diff --git a/bin/syncqt.pl b/bin/syncqt.pl index ff4cafa7b9..c6aced4412 100755 --- a/bin/syncqt.pl +++ b/bin/syncqt.pl @@ -98,14 +98,11 @@ my $showonly = 0; my $verbose_level = 1; my $remove_stale = 1; my $force_win = 0; -my $force_relative = 0; my $check_includes = 0; my $copy_headers = 0; -my $create_private_headers = 1; my $minimal = 0; my $module_version = 0; my @modules_to_sync ; -$force_relative = 1 if ( -d "/System/Library/Frameworks" ); # functions ---------------------------------------------------------- @@ -124,7 +121,6 @@ sub showUsage print " -copy Copy headers instead of include-fwd(default: " . ($copy_headers ? "yes" : "no") . ")\n"; print " -remove-stale Removes stale headers (default: " . ($remove_stale ? "yes" : "no") . ")\n"; - print " -relative Force relative symlinks (default: " . ($force_relative ? "yes" : "no") . ")\n"; print " -windows Force platform to Windows (default: " . ($force_win ? "yes" : "no") . ")\n"; print " -showonly Show action but not perform (default: " . ($showonly ? "yes" : "no") . ")\n"; print " -minimal Do not create CamelCase headers (default: " . ($minimal ? "yes" : "no") . ")\n"; @@ -137,7 +133,6 @@ sub showUsage print " -separate-module ::\n"; print " Create headers for with original headers in\n"; print " relative to \n"; - print " -private Force copy private headers (default: " . ($create_private_headers ? "yes" : "no") . ")\n"; print " -help This help\n"; exit 0; } @@ -782,9 +777,6 @@ while ( @ARGV ) { } elsif($arg eq "-minimal") { $var = "minimal"; $val = "yes"; - } elsif($arg eq "-private") { - $var = "create_private_headers"; - $val = "yes"; } elsif($arg eq "-version") { $var = "version"; $val = shift @ARGV; @@ -841,12 +833,6 @@ while ( @ARGV ) { } elsif($force_win) { $force_win--; } - } elsif ($var eq "relative") { - if($val eq "yes") { - $force_relative++; - } elsif($force_relative) { - $force_relative--; - } } elsif ($var eq "minimal") { if($val eq "yes") { $minimal++; @@ -934,7 +920,7 @@ foreach my $lib (@modules_to_sync) { $allheadersprivate = 1 if $allmoduleheadersprivate{$lib}; #information used after the syncing - my $pri_install_classes = ""; + my $pri_install_gfiles = ""; my $pri_install_files = ""; my $pri_install_ifiles = ""; my $pri_install_pfiles = ""; @@ -1084,9 +1070,9 @@ foreach my $lib (@modules_to_sync) { $header_copies++ if (!$shadow && syncHeader($lib, "$out_basedir/include/$lib/$class", "$out_basedir/include/$lib/$header", 0, $ts)); } - } elsif ($create_private_headers && !$qpa_header) { + } elsif (!$qpa_header) { $oheader = "$out_basedir/include/$lib/$module_version/$lib/private/$header"; - } elsif ($create_private_headers) { + } else { $oheader = "$out_basedir/include/$lib/$module_version/$lib/qpa/$header"; } $header_copies++ if (!$shadow && syncHeader($lib, $oheader, $iheader, $copy_headers, $ts)); @@ -1100,9 +1086,9 @@ foreach my $lib (@modules_to_sync) { # if ($class =~ m/::/) { # $class =~ s,::,/,g; # } - my $class_header = fixPaths("$out_basedir/include/$lib/$class", $dir) . " "; - $pri_install_classes .= $class_header - unless($pri_install_classes =~ $class_header); + my $class_header = "$class "; + $pri_install_gfiles .= $class_header + unless($pri_install_gfiles =~ $class_header); $injection .= ":$class"; } @@ -1175,16 +1161,10 @@ foreach my $lib (@modules_to_sync) { # create deprecated headers my $first = 1; while (my ($header, $include) = each %{$deprecatedheaders{$lib}}) { - my $public_header = 0; - $public_header = 1 unless ($allheadersprivate || ($header =~ /_p\.h$/)); - next unless ($public_header || $create_private_headers); - - my $header_path = "$out_basedir/include/$lib/"; - unless ($public_header) { - $header_path .= "$module_version/$lib/private/"; - } - $header_path .= "$header"; + die "Attempting unsupported aliasing of private header $header.\n" + if ($allheadersprivate || ($header =~ /_p\.h$/)); + my $header_path = "$out_basedir/include/$lib/$header"; unless (-e $header_path) { my $guard = "DEPRECATED_HEADER_" . $lib . "_" . $header; $guard =~ s/([^a-zA-Z0-9_])/_/g; @@ -1192,26 +1172,19 @@ foreach my $lib (@modules_to_sync) { my $header_dir = dirname($header_path); make_path($header_dir, $lib, $verbose_level); + my $warning = "Header <$lib/$header> is deprecated. Please include <$include> instead."; my $hdrcont = "#ifndef $guard\n" . - "#define $guard\n"; - my $warning = "Header <$lib/"; - $warning .= "private/" unless ($public_header); - $warning .= "$header> is deprecated. Please include <$include> instead."; - $hdrcont .= + "#define $guard\n" . "#if defined(__GNUC__)\n" . "# warning $warning\n" . "#elif defined(_MSC_VER)\n" . "# pragma message (\"$warning\")\n" . "#endif\n" . - "#include <$include>\n"; - if ($public_header) { - $hdrcont .= - "#if 0\n" . - "#pragma qt_no_master_include\n" . - "#endif\n"; - } - $hdrcont .= + "#include <$include>\n" . + "#if 0\n" . + "#pragma qt_no_master_include\n" . + "#endif\n" . "#endif\n"; if (writeFile($header_path, $hdrcont)) { if ($verbose_level < 3) { @@ -1225,12 +1198,7 @@ foreach my $lib (@modules_to_sync) { } } - my $addendum = fixPaths($header_path, $dir) . " "; - if ($public_header) { - $pri_install_files .= $addendum; - } else { - $pri_install_pfiles .= $addendum; - } + $pri_install_gfiles .= "$header "; } if ($verbose_level < 3) { print " }\n" unless ($first); @@ -1240,8 +1208,7 @@ foreach my $lib (@modules_to_sync) { my $vheader = "$out_basedir/include/$lib/".lc($lib)."version.h"; my $VHeader = "$out_basedir/include/$lib/${lib}Version"; syncHeader($lib, $VHeader, $vheader, 0); - $pri_install_files .= fixPaths($vheader, $dir) . " "; - $pri_install_classes .= fixPaths($VHeader, $dir) . " "; + $pri_install_gfiles .= lc($lib)."version.h ${lib}Version "; my @versions = split(/\./, $module_version); my $modulehexstring = sprintf("0x%02X%02X%02X", $versions[0], $versions[1], $versions[2]); my $vhdrcont = @@ -1257,7 +1224,7 @@ foreach my $lib (@modules_to_sync) { writeFile($vheader, $vhdrcont, $lib, "version header"); my $master_include = "$out_basedir/include/$lib/$lib"; - $pri_install_files .= fixPaths($master_include, $dir) . " "; + $pri_install_gfiles .= "$lib "; writeFile($master_include, $master_contents, $lib, "master header"); } @@ -1266,7 +1233,7 @@ foreach my $lib (@modules_to_sync) { my $headers_pri_contents = ""; $headers_pri_contents .= "SYNCQT.HEADER_FILES = $pri_install_files\n"; $headers_pri_contents .= "SYNCQT.INJECTED_HEADER_FILES = $pri_install_ifiles\n"; - $headers_pri_contents .= "SYNCQT.HEADER_CLASSES = $pri_install_classes\n"; + $headers_pri_contents .= "SYNCQT.GENERATED_HEADER_FILES = $pri_install_gfiles\n"; $headers_pri_contents .= "SYNCQT.PRIVATE_HEADER_FILES = $pri_install_pfiles\n"; $headers_pri_contents .= "SYNCQT.INJECTED_PRIVATE_HEADER_FILES = $pri_install_ipfiles\n"; $headers_pri_contents .= "SYNCQT.QPA_HEADER_FILES = $pri_install_qpafiles\n"; diff --git a/examples/widgets/doc/src/eventtransitions.qdoc b/examples/widgets/doc/src/eventtransitions.qdoc index 4d332c0e00..e74831b14b 100644 --- a/examples/widgets/doc/src/eventtransitions.qdoc +++ b/examples/widgets/doc/src/eventtransitions.qdoc @@ -46,7 +46,7 @@ The \c Window class's constructors begins by creating a button. This button is added to \c layout, which is a QVBoxLayout object. - Then two states are created: \s1 is the state + Then two states are created: \c s1 is the state "Outside", and \c s2 is the state "Inside". \snippet statemachine/eventtransitions/main.cpp 1 diff --git a/mkspecs/features/qt_installs.prf b/mkspecs/features/qt_installs.prf index 90d84cc535..8f98987b99 100644 --- a/mkspecs/features/qt_installs.prf +++ b/mkspecs/features/qt_installs.prf @@ -28,9 +28,9 @@ #headers qt_install_headers { - class_headers.files = $$SYNCQT.HEADER_CLASSES - class_headers.path = $$[QT_INSTALL_HEADERS]/$$MODULE_INCNAME - INSTALLS += class_headers + gen_headers.files = $$SYNCQT.GENERATED_HEADER_FILES + gen_headers.path = $$[QT_INSTALL_HEADERS]/$$MODULE_INCNAME + INSTALLS += gen_headers targ_headers.files = $$SYNCQT.HEADER_FILES $$SYNCQT.INJECTED_HEADER_FILES targ_headers.path = $$[QT_INSTALL_HEADERS]/$$MODULE_INCNAME diff --git a/mkspecs/features/qt_module.prf b/mkspecs/features/qt_module.prf index e6a0d97f1a..f8729de947 100644 --- a/mkspecs/features/qt_module.prf +++ b/mkspecs/features/qt_module.prf @@ -136,7 +136,7 @@ lib_bundle { if(if(!debug_and_release|CONFIG(release, debug|release))) { FRAMEWORK_HEADERS.version = Versions FRAMEWORK_HEADERS.files = \ - $$SYNCQT.HEADER_FILES $$SYNCQT.HEADER_CLASSES $$SYNCQT.INJECTED_HEADER_FILES + $$SYNCQT.HEADER_FILES $$SYNCQT.GENERATED_HEADER_FILES $$SYNCQT.INJECTED_HEADER_FILES FRAMEWORK_HEADERS.path = Headers FRAMEWORK_PRIVATE_HEADERS.version = Versions FRAMEWORK_PRIVATE_HEADERS.files = \ @@ -224,7 +224,7 @@ android: CONFIG += qt_android_deps no_linker_version_script private_api_headers = $$SYNCQT.PRIVATE_HEADER_FILES $$SYNCQT.QPA_HEADER_FILES for(header, private_api_headers): \ - verscript_content += " @FILE:$${_PRO_FILE_PWD_}/$$header@" + verscript_content += " @FILE:$$header@" verscript_content += "};" current = Qt_$$QT_MAJOR_VERSION @@ -244,8 +244,7 @@ android: CONFIG += qt_android_deps no_linker_version_script verscriptprocess.name = linker version script ${QMAKE_FILE_BASE} verscriptprocess.input = verscript_in verscriptprocess.CONFIG += no_link target_predeps - for(header, private_api_headers): \ - verscriptprocess.depends += $${_PRO_FILE_PWD_}/$$header + verscriptprocess.depends = $$private_api_headers verscriptprocess.output = $$verscript verscriptprocess.commands = perl $${PWD}/data/unix/findclasslist.pl < ${QMAKE_FILE_IN} > $@ silent:verscriptprocess.commands = @echo creating linker version script ${QMAKE_FILE_BASE} && $$verscriptprocess.commands diff --git a/mkspecs/features/qt_module_headers.prf b/mkspecs/features/qt_module_headers.prf index 62b88c6fe2..38e293db9e 100644 --- a/mkspecs/features/qt_module_headers.prf +++ b/mkspecs/features/qt_module_headers.prf @@ -96,12 +96,26 @@ MODULE_PRIVATE_INCLUDES += $$MODULE_PRIVATE_AUX_INCLUDES minimal_syncqt: return() +defineTest(syncQtResolve) { + out = + for (f, SYNCQT.$$1): \ + out += $$absolute_path($$f, $$2) + SYNCQT.$$1 = $$out + export(SYNCQT.$$1) +} + #load up the headers info git_build: \ INC_PATH = $$MODULE_BASE_OUTDIR else: \ INC_PATH = $$MODULE_BASE_INDIR include($$INC_PATH/include/$$MODULE_INCNAME/headers.pri, "", true) +syncQtResolve(HEADER_FILES, $$_PRO_FILE_PWD_) +syncQtResolve(PRIVATE_HEADER_FILES, $$_PRO_FILE_PWD_) +syncQtResolve(QPA_HEADER_FILES, $$_PRO_FILE_PWD_) +syncQtResolve(GENERATED_HEADER_FILES, $$INC_PATH/include/$$MODULE_INCNAME) +syncQtResolve(INJECTED_HEADER_FILES, $$OUT_PWD) +syncQtResolve(INJECTED_PRIVATE_HEADER_FILES, $$OUT_PWD) !lib_bundle: \ # Headers are embedded into the bundle, so don't install them separately. CONFIG += qt_install_headers @@ -114,9 +128,8 @@ exists($$OUT_PWD/qt$${MODULE}-config.h) { SYNCQT.INJECTIONS += \ $$fwd_rel/qt$${MODULE}-config.h:qt$${MODULE}-config.h \ $$fwd_rel/qt$${MODULE}-config_p.h:$$MODULE_VERSION/$$MODULE_INCNAME/private/qt$${MODULE}-config_p.h - inst_rel = $$relative_path($$OUT_PWD, $$_PRO_FILE_PWD_) - SYNCQT.HEADER_FILES += $$inst_rel/qt$${MODULE}-config.h - SYNCQT.INJECTED_PRIVATE_HEADER_FILES += $$inst_rel/qt$${MODULE}-config_p.h + SYNCQT.INJECTED_HEADER_FILES += $$OUT_PWD/qt$${MODULE}-config.h + SYNCQT.INJECTED_PRIVATE_HEADER_FILES += $$OUT_PWD/qt$${MODULE}-config_p.h } for (injection, SYNCQT.INJECTIONS) { diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp index 8ecfa0bf31..5468285c2e 100644 --- a/qmake/generators/unix/unixmake2.cpp +++ b/qmake/generators/unix/unixmake2.cpp @@ -943,7 +943,9 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) QString fn = files.at(file).toQString(); QString src = fileFixify(fn, FileFixifyAbsolute); if (!QFile::exists(src)) - src = fn; + src = fileFixify(fn, FileFixifyFromOutdir); + else + src = fileFixify(fn); QString dst = path + Option::dir_sep + fileInfo(fn).fileName(); bundledFiles << dst; alldeps << dst; diff --git a/src/3rdparty/sqlite/qt_attribution.json b/src/3rdparty/sqlite/qt_attribution.json index 3800477239..b470e7e38c 100644 --- a/src/3rdparty/sqlite/qt_attribution.json +++ b/src/3rdparty/sqlite/qt_attribution.json @@ -6,7 +6,7 @@ "Description": "SQLite is a small C library that implements a self-contained, embeddable, zero-configuration SQL database engine.", "Homepage": "http://www.sqlite.org/", - "Version": "3.22.0", + "Version": "3.23.1", "License": "Public Domain", "Copyright": "The authors disclaim copyright to the source code. However, a license can be obtained if needed." } diff --git a/src/3rdparty/sqlite/sqlite3.c b/src/3rdparty/sqlite/sqlite3.c index 73c69efbd5..c49f89c923 100644 --- a/src/3rdparty/sqlite/sqlite3.c +++ b/src/3rdparty/sqlite/sqlite3.c @@ -1,6 +1,6 @@ /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.22.0. By combining all the individual C code files into this +** version 3.23.1. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a single translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements @@ -213,7 +213,7 @@ static const char * const sqlite3azCompileOpt[] = { "ENABLE_BATCH_ATOMIC_WRITE", #endif #if SQLITE_ENABLE_CEROD - "ENABLE_CEROD", + "ENABLE_CEROD=" CTIMEOPT_VAL(SQLITE_ENABLE_CEROD), #endif #if SQLITE_ENABLE_COLUMN_METADATA "ENABLE_COLUMN_METADATA", @@ -1147,9 +1147,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.22.0" -#define SQLITE_VERSION_NUMBER 3022000 -#define SQLITE_SOURCE_ID "2018-01-22 18:45:57 0c55d179733b46d8d0ba4d88e01a25e10677046ee3da1d5b1581e86726f2171d" +#define SQLITE_VERSION "3.23.1" +#define SQLITE_VERSION_NUMBER 3023001 +#define SQLITE_SOURCE_ID "2018-04-10 17:39:29 4bb2294022060e61de7da5c227a69ccd846ba330e31626ebcd59a94efd148b3b" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -2088,6 +2088,12 @@ struct sqlite3_io_methods { ** so that all subsequent write operations are independent. ** ^SQLite will never invoke SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE without ** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE]. +** +**
  • [[SQLITE_FCNTL_LOCK_TIMEOUT]] +** The [SQLITE_FCNTL_LOCK_TIMEOUT] opcode causes attempts to obtain +** a file lock using the xLock or xShmLock methods of the VFS to wait +** for up to M milliseconds before failing, where M is the single +** unsigned integer parameter. ** */ #define SQLITE_FCNTL_LOCKSTATE 1 @@ -2122,6 +2128,7 @@ struct sqlite3_io_methods { #define SQLITE_FCNTL_BEGIN_ATOMIC_WRITE 31 #define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE 32 #define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33 +#define SQLITE_FCNTL_LOCK_TIMEOUT 34 /* deprecated names */ #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE @@ -3078,11 +3085,13 @@ struct sqlite3_mem_methods { ** connections at all to the database. If so, it performs a checkpoint ** operation before closing the connection. This option may be used to ** override this behaviour. The first parameter passed to this operation -** is an integer - non-zero to disable checkpoints-on-close, or zero (the -** default) to enable them. The second parameter is a pointer to an integer +** is an integer - positive to disable checkpoints-on-close, or zero (the +** default) to enable them, and negative to leave the setting unchanged. +** The second parameter is a pointer to an integer ** into which is written 0 or 1 to indicate whether checkpoints-on-close ** have been disabled - 0 if they are not disabled, 1 if they are. ** +** **
    SQLITE_DBCONFIG_ENABLE_QPSG
    **
    ^(The SQLITE_DBCONFIG_ENABLE_QPSG option activates or deactivates ** the [query planner stability guarantee] (QPSG). When the QPSG is active, @@ -3092,13 +3101,20 @@ struct sqlite3_mem_methods { ** slower. But the QPSG has the advantage of more predictable behavior. With ** the QPSG active, SQLite will always use the same query plan in the field as ** was used during testing in the lab. +** The first argument to this setting is an integer which is 0 to disable +** the QPSG, positive to enable QPSG, or negative to leave the setting +** unchanged. The second parameter is a pointer to an integer into which +** is written 0 or 1 to indicate whether the QPSG is disabled or enabled +** following this call. **
    +** **
    SQLITE_DBCONFIG_TRIGGER_EQP
    **
    By default, the output of EXPLAIN QUERY PLAN commands does not ** include output for any operations performed by trigger programs. This ** option is used to set or clear (the default) a flag that governs this ** behavior. The first parameter passed to this operation is an integer - -** non-zero to enable output for trigger programs, or zero to disable it. +** positive to enable output for trigger programs, or zero to disable it, +** or negative to leave the setting unchanged. ** The second parameter is a pointer to an integer into which is written ** 0 or 1 to indicate whether output-for-triggers has been disabled - 0 if ** it is not disabled, 1 if it is. @@ -3520,16 +3536,16 @@ SQLITE_API void sqlite3_free_table(char **result); ** ** These routines are work-alikes of the "printf()" family of functions ** from the standard C library. -** These routines understand most of the common K&R formatting options, -** plus some additional non-standard formats, detailed below. -** Note that some of the more obscure formatting options from recent -** C-library standards are omitted from this implementation. +** These routines understand most of the common formatting options from +** the standard library printf() +** plus some additional non-standard formats ([%q], [%Q], [%w], and [%z]). +** See the [built-in printf()] documentation for details. ** ** ^The sqlite3_mprintf() and sqlite3_vmprintf() routines write their -** results into memory obtained from [sqlite3_malloc()]. +** results into memory obtained from [sqlite3_malloc64()]. ** The strings returned by these two routines should be ** released by [sqlite3_free()]. ^Both routines return a -** NULL pointer if [sqlite3_malloc()] is unable to allocate enough +** NULL pointer if [sqlite3_malloc64()] is unable to allocate enough ** memory to hold the resulting string. ** ** ^(The sqlite3_snprintf() routine is similar to "snprintf()" from @@ -3553,71 +3569,7 @@ SQLITE_API void sqlite3_free_table(char **result); ** ** ^The sqlite3_vsnprintf() routine is a varargs version of sqlite3_snprintf(). ** -** These routines all implement some additional formatting -** options that are useful for constructing SQL statements. -** All of the usual printf() formatting options apply. In addition, there -** is are "%q", "%Q", "%w" and "%z" options. -** -** ^(The %q option works like %s in that it substitutes a nul-terminated -** string from the argument list. But %q also doubles every '\'' character. -** %q is designed for use inside a string literal.)^ By doubling each '\'' -** character it escapes that character and allows it to be inserted into -** the string. -** -** For example, assume the string variable zText contains text as follows: -** -**
    -**  char *zText = "It's a happy day!";
    -** 
    -** -** One can use this text in an SQL statement as follows: -** -**
    -**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES('%q')", zText);
    -**  sqlite3_exec(db, zSQL, 0, 0, 0);
    -**  sqlite3_free(zSQL);
    -** 
    -** -** Because the %q format string is used, the '\'' character in zText -** is escaped and the SQL generated is as follows: -** -**
    -**  INSERT INTO table1 VALUES('It''s a happy day!')
    -** 
    -** -** This is correct. Had we used %s instead of %q, the generated SQL -** would have looked like this: -** -**
    -**  INSERT INTO table1 VALUES('It's a happy day!');
    -** 
    -** -** This second example is an SQL syntax error. As a general rule you should -** always use %q instead of %s when inserting text into a string literal. -** -** ^(The %Q option works like %q except it also adds single quotes around -** the outside of the total string. Additionally, if the parameter in the -** argument list is a NULL pointer, %Q substitutes the text "NULL" (without -** single quotes).)^ So, for example, one could say: -** -**
    -**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES(%Q)", zText);
    -**  sqlite3_exec(db, zSQL, 0, 0, 0);
    -**  sqlite3_free(zSQL);
    -** 
    -** -** The code above will render a correct SQL statement in the zSQL -** variable even if the zText variable is a NULL pointer. -** -** ^(The "%w" formatting option is like "%q" except that it expects to -** be contained within double-quotes instead of single quotes, and it -** escapes the double-quote character instead of the single-quote -** character.)^ The "%w" formatting option is intended for safely inserting -** table and column names into a constructed SQL statement. -** -** ^(The "%z" formatting option works like "%s" but with the -** addition that after the string has been read and copied into -** the result, [sqlite3_free()] is called on the input string.)^ +** See also: [built-in printf()], [printf() SQL function] */ SQLITE_API char *sqlite3_mprintf(const char*,...); SQLITE_API char *sqlite3_vmprintf(const char*, va_list); @@ -4683,13 +4635,13 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); ** or [GLOB] operator or if the parameter is compared to an indexed column ** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled. **
  • +** ** **

    ^sqlite3_prepare_v3() differs from sqlite3_prepare_v2() only in having ** the extra prepFlags parameter, which is a bit array consisting of zero or ** more of the [SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_*] flags. ^The ** sqlite3_prepare_v2() interface works exactly the same as ** sqlite3_prepare_v3() with a zero prepFlags parameter. -** */ SQLITE_API int sqlite3_prepare( sqlite3 *db, /* Database handle */ @@ -8318,6 +8270,15 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r ** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0. ** ** +** [[SQLITE_DBSTATUS_CACHE_SPILL]] ^(

    SQLITE_DBSTATUS_CACHE_SPILL
    +**
    This parameter returns the number of dirty cache entries that have +** been written to disk in the middle of a transaction due to the page +** cache overflowing. Transactions are more efficient if they are written +** to disk all at once. When pages spill mid-transaction, that introduces +** additional overhead. This parameter can be used help identify +** inefficiencies that can be resolve by increasing the cache size. +**
    +** ** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(
    SQLITE_DBSTATUS_DEFERRED_FKS
    **
    This parameter returns zero for the current value if and only if ** all foreign key constraints (deferred or immediate) have been @@ -8337,7 +8298,8 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r #define SQLITE_DBSTATUS_CACHE_WRITE 9 #define SQLITE_DBSTATUS_DEFERRED_FKS 10 #define SQLITE_DBSTATUS_CACHE_USED_SHARED 11 -#define SQLITE_DBSTATUS_MAX 11 /* Largest defined DBSTATUS */ +#define SQLITE_DBSTATUS_CACHE_SPILL 12 +#define SQLITE_DBSTATUS_MAX 12 /* Largest defined DBSTATUS */ /* @@ -9817,6 +9779,128 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp( */ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb); +/* +** CAPI3REF: Serialize a database +** +** The sqlite3_serialize(D,S,P,F) interface returns a pointer to memory +** that is a serialization of the S database on [database connection] D. +** If P is not a NULL pointer, then the size of the database in bytes +** is written into *P. +** +** For an ordinary on-disk database file, the serialization is just a +** copy of the disk file. For an in-memory database or a "TEMP" database, +** the serialization is the same sequence of bytes which would be written +** to disk if that database where backed up to disk. +** +** The usual case is that sqlite3_serialize() copies the serialization of +** the database into memory obtained from [sqlite3_malloc64()] and returns +** a pointer to that memory. The caller is responsible for freeing the +** returned value to avoid a memory leak. However, if the F argument +** contains the SQLITE_SERIALIZE_NOCOPY bit, then no memory allocations +** are made, and the sqlite3_serialize() function will return a pointer +** to the contiguous memory representation of the database that SQLite +** is currently using for that database, or NULL if the no such contiguous +** memory representation of the database exists. A contiguous memory +** representation of the database will usually only exist if there has +** been a prior call to [sqlite3_deserialize(D,S,...)] with the same +** values of D and S. +** The size of the database is written into *P even if the +** SQLITE_SERIALIZE_NOCOPY bit is set but no contigious copy +** of the database exists. +** +** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the +** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory +** allocation error occurs. +** +** This interface is only available if SQLite is compiled with the +** [SQLITE_ENABLE_DESERIALIZE] option. +*/ +SQLITE_API unsigned char *sqlite3_serialize( + sqlite3 *db, /* The database connection */ + const char *zSchema, /* Which DB to serialize. ex: "main", "temp", ... */ + sqlite3_int64 *piSize, /* Write size of the DB here, if not NULL */ + unsigned int mFlags /* Zero or more SQLITE_SERIALIZE_* flags */ +); + +/* +** CAPI3REF: Flags for sqlite3_serialize +** +** Zero or more of the following constants can be OR-ed together for +** the F argument to [sqlite3_serialize(D,S,P,F)]. +** +** SQLITE_SERIALIZE_NOCOPY means that [sqlite3_serialize()] will return +** a pointer to contiguous in-memory database that it is currently using, +** without making a copy of the database. If SQLite is not currently using +** a contiguous in-memory database, then this option causes +** [sqlite3_serialize()] to return a NULL pointer. SQLite will only be +** using a contiguous in-memory database if it has been initialized by a +** prior call to [sqlite3_deserialize()]. +*/ +#define SQLITE_SERIALIZE_NOCOPY 0x001 /* Do no memory allocations */ + +/* +** CAPI3REF: Deserialize a database +** +** The sqlite3_deserialize(D,S,P,N,M,F) interface causes the +** [database connection] D to disconnect from database S and then +** reopen S as an in-memory database based on the serialization contained +** in P. The serialized database P is N bytes in size. M is the size of +** the buffer P, which might be larger than N. If M is larger than N, and +** the SQLITE_DESERIALIZE_READONLY bit is not set in F, then SQLite is +** permitted to add content to the in-memory database as long as the total +** size does not exceed M bytes. +** +** If the SQLITE_DESERIALIZE_FREEONCLOSE bit is set in F, then SQLite will +** invoke sqlite3_free() on the serialization buffer when the database +** connection closes. If the SQLITE_DESERIALIZE_RESIZEABLE bit is set, then +** SQLite will try to increase the buffer size using sqlite3_realloc64() +** if writes on the database cause it to grow larger than M bytes. +** +** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the +** database is currently in a read transaction or is involved in a backup +** operation. +** +** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the +** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then +** [sqlite3_free()] is invoked on argument P prior to returning. +** +** This interface is only available if SQLite is compiled with the +** [SQLITE_ENABLE_DESERIALIZE] option. +*/ +SQLITE_API int sqlite3_deserialize( + sqlite3 *db, /* The database connection */ + const char *zSchema, /* Which DB to reopen with the deserialization */ + unsigned char *pData, /* The serialized database content */ + sqlite3_int64 szDb, /* Number bytes in the deserialization */ + sqlite3_int64 szBuf, /* Total size of buffer pData[] */ + unsigned mFlags /* Zero or more SQLITE_DESERIALIZE_* flags */ +); + +/* +** CAPI3REF: Flags for sqlite3_deserialize() +** +** The following are allowed values for 6th argument (the F argument) to +** the [sqlite3_deserialize(D,S,P,N,M,F)] interface. +** +** The SQLITE_DESERIALIZE_FREEONCLOSE means that the database serialization +** in the P argument is held in memory obtained from [sqlite3_malloc64()] +** and that SQLite should take ownership of this memory and automatically +** free it when it has finished using it. Without this flag, the caller +** is resposible for freeing any dynamically allocated memory. +** +** The SQLITE_DESERIALIZE_RESIZEABLE flag means that SQLite is allowed to +** grow the size of the database using calls to [sqlite3_realloc64()]. This +** flag should only be used if SQLITE_DESERIALIZE_FREEONCLOSE is also used. +** Without this flag, the deserialized database cannot increase in size beyond +** the number of bytes specified by the M parameter. +** +** The SQLITE_DESERIALIZE_READONLY flag means that the deserialized database +** should be treated as read-only. +*/ +#define SQLITE_DESERIALIZE_FREEONCLOSE 1 /* Call sqlite3_free() on close */ +#define SQLITE_DESERIALIZE_RESIZEABLE 2 /* Resize using sqlite3_realloc64() */ +#define SQLITE_DESERIALIZE_READONLY 4 /* Database is read-only */ + /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. @@ -9964,16 +10048,23 @@ extern "C" { /* ** CAPI3REF: Session Object Handle +** +** An instance of this object is a [session] that can be used to +** record changes to a database. */ typedef struct sqlite3_session sqlite3_session; /* ** CAPI3REF: Changeset Iterator Handle +** +** An instance of this object acts as a cursor for iterating +** over the elements of a [changeset] or [patchset]. */ typedef struct sqlite3_changeset_iter sqlite3_changeset_iter; /* ** CAPI3REF: Create A New Session Object +** CONSTRUCTOR: sqlite3_session ** ** Create a new session object attached to database handle db. If successful, ** a pointer to the new object is written to *ppSession and SQLITE_OK is @@ -10010,6 +10101,7 @@ SQLITE_API int sqlite3session_create( /* ** CAPI3REF: Delete A Session Object +** DESTRUCTOR: sqlite3_session ** ** Delete a session object previously allocated using ** [sqlite3session_create()]. Once a session object has been deleted, the @@ -10025,6 +10117,7 @@ SQLITE_API void sqlite3session_delete(sqlite3_session *pSession); /* ** CAPI3REF: Enable Or Disable A Session Object +** METHOD: sqlite3_session ** ** Enable or disable the recording of changes by a session object. When ** enabled, a session object records changes made to the database. When @@ -10044,6 +10137,7 @@ SQLITE_API int sqlite3session_enable(sqlite3_session *pSession, int bEnable); /* ** CAPI3REF: Set Or Clear the Indirect Change Flag +** METHOD: sqlite3_session ** ** Each change recorded by a session object is marked as either direct or ** indirect. A change is marked as indirect if either: @@ -10073,6 +10167,7 @@ SQLITE_API int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect) /* ** CAPI3REF: Attach A Table To A Session Object +** METHOD: sqlite3_session ** ** If argument zTab is not NULL, then it is the name of a table to attach ** to the session object passed as the first argument. All subsequent changes @@ -10135,6 +10230,7 @@ SQLITE_API int sqlite3session_attach( /* ** CAPI3REF: Set a table filter on a Session Object. +** METHOD: sqlite3_session ** ** The second argument (xFilter) is the "filter callback". For changes to rows ** in tables that are not attached to the Session object, the filter is called @@ -10153,6 +10249,7 @@ SQLITE_API void sqlite3session_table_filter( /* ** CAPI3REF: Generate A Changeset From A Session Object +** METHOD: sqlite3_session ** ** Obtain a changeset containing changes to the tables attached to the ** session object passed as the first argument. If successful, @@ -10262,7 +10359,8 @@ SQLITE_API int sqlite3session_changeset( ); /* -** CAPI3REF: Load The Difference Between Tables Into A Session +** CAPI3REF: Load The Difference Between Tables Into A Session +** METHOD: sqlite3_session ** ** If it is not already attached to the session object passed as the first ** argument, this function attaches table zTbl in the same manner as the @@ -10327,6 +10425,7 @@ SQLITE_API int sqlite3session_diff( /* ** CAPI3REF: Generate A Patchset From A Session Object +** METHOD: sqlite3_session ** ** The differences between a patchset and a changeset are that: ** @@ -10378,6 +10477,7 @@ SQLITE_API int sqlite3session_isempty(sqlite3_session *pSession); /* ** CAPI3REF: Create An Iterator To Traverse A Changeset +** CONSTRUCTOR: sqlite3_changeset_iter ** ** Create an iterator used to iterate through the contents of a changeset. ** If successful, *pp is set to point to the iterator handle and SQLITE_OK @@ -10418,6 +10518,7 @@ SQLITE_API int sqlite3changeset_start( /* ** CAPI3REF: Advance A Changeset Iterator +** METHOD: sqlite3_changeset_iter ** ** This function may only be used with iterators created by function ** [sqlite3changeset_start()]. If it is called on an iterator passed to @@ -10442,6 +10543,7 @@ SQLITE_API int sqlite3changeset_next(sqlite3_changeset_iter *pIter); /* ** CAPI3REF: Obtain The Current Operation From A Changeset Iterator +** METHOD: sqlite3_changeset_iter ** ** The pIter argument passed to this function may either be an iterator ** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator @@ -10476,6 +10578,7 @@ SQLITE_API int sqlite3changeset_op( /* ** CAPI3REF: Obtain The Primary Key Definition Of A Table +** METHOD: sqlite3_changeset_iter ** ** For each modified table, a changeset includes the following: ** @@ -10507,6 +10610,7 @@ SQLITE_API int sqlite3changeset_pk( /* ** CAPI3REF: Obtain old.* Values From A Changeset Iterator +** METHOD: sqlite3_changeset_iter ** ** The pIter argument passed to this function may either be an iterator ** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator @@ -10537,6 +10641,7 @@ SQLITE_API int sqlite3changeset_old( /* ** CAPI3REF: Obtain new.* Values From A Changeset Iterator +** METHOD: sqlite3_changeset_iter ** ** The pIter argument passed to this function may either be an iterator ** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator @@ -10570,6 +10675,7 @@ SQLITE_API int sqlite3changeset_new( /* ** CAPI3REF: Obtain Conflicting Row Values From A Changeset Iterator +** METHOD: sqlite3_changeset_iter ** ** This function should only be used with iterator objects passed to a ** conflict-handler callback by [sqlite3changeset_apply()] with either @@ -10597,6 +10703,7 @@ SQLITE_API int sqlite3changeset_conflict( /* ** CAPI3REF: Determine The Number Of Foreign Key Constraint Violations +** METHOD: sqlite3_changeset_iter ** ** This function may only be called with an iterator passed to an ** SQLITE_CHANGESET_FOREIGN_KEY conflict handler callback. In this case @@ -10613,6 +10720,7 @@ SQLITE_API int sqlite3changeset_fk_conflicts( /* ** CAPI3REF: Finalize A Changeset Iterator +** METHOD: sqlite3_changeset_iter ** ** This function is used to finalize an iterator allocated with ** [sqlite3changeset_start()]. @@ -10629,6 +10737,7 @@ SQLITE_API int sqlite3changeset_fk_conflicts( ** to that error is returned by this function. Otherwise, SQLITE_OK is ** returned. This is to allow the following pattern (pseudo-code): ** +**
     **   sqlite3changeset_start();
     **   while( SQLITE_ROW==sqlite3changeset_next() ){
     **     // Do something with change.
    @@ -10637,6 +10746,7 @@ SQLITE_API int sqlite3changeset_fk_conflicts(
     **   if( rc!=SQLITE_OK ){
     **     // An error has occurred 
     **   }
    +** 
    */ SQLITE_API int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter); @@ -10684,6 +10794,7 @@ SQLITE_API int sqlite3changeset_invert( ** sqlite3_changegroup object. Calling it produces similar results as the ** following code fragment: ** +**
     **   sqlite3_changegroup *pGrp;
     **   rc = sqlite3_changegroup_new(&pGrp);
     **   if( rc==SQLITE_OK ) rc = sqlite3changegroup_add(pGrp, nA, pA);
    @@ -10694,6 +10805,7 @@ SQLITE_API int sqlite3changeset_invert(
     **     *ppOut = 0;
     **     *pnOut = 0;
     **   }
    +** 
    ** ** Refer to the sqlite3_changegroup documentation below for details. */ @@ -10709,11 +10821,15 @@ SQLITE_API int sqlite3changeset_concat( /* ** CAPI3REF: Changegroup Handle +** +** A changegroup is an object used to combine two or more +** [changesets] or [patchsets] */ typedef struct sqlite3_changegroup sqlite3_changegroup; /* ** CAPI3REF: Create A New Changegroup Object +** CONSTRUCTOR: sqlite3_changegroup ** ** An sqlite3_changegroup object is used to combine two or more changesets ** (or patchsets) into a single changeset (or patchset). A single changegroup @@ -10751,6 +10867,7 @@ SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp); /* ** CAPI3REF: Add A Changeset To A Changegroup +** METHOD: sqlite3_changegroup ** ** Add all changes within the changeset (or patchset) in buffer pData (size ** nData bytes) to the changegroup. @@ -10828,6 +10945,7 @@ SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pDa /* ** CAPI3REF: Obtain A Composite Changeset From A Changegroup +** METHOD: sqlite3_changegroup ** ** Obtain a buffer containing a changeset (or patchset) representing the ** current contents of the changegroup. If the inputs to the changegroup @@ -10858,25 +10976,25 @@ SQLITE_API int sqlite3changegroup_output( /* ** CAPI3REF: Delete A Changegroup Object +** DESTRUCTOR: sqlite3_changegroup */ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*); /* ** CAPI3REF: Apply A Changeset To A Database ** -** Apply a changeset to a database. This function attempts to update the -** "main" database attached to handle db with the changes found in the -** changeset passed via the second and third arguments. +** Apply a changeset or patchset to a database. These functions attempt to +** update the "main" database attached to handle db with the changes found in +** the changeset passed via the second and third arguments. ** -** The fourth argument (xFilter) passed to this function is the "filter +** The fourth argument (xFilter) passed to these functions is the "filter ** callback". If it is not NULL, then for each table affected by at least one ** change in the changeset, the filter callback is invoked with ** the table name as the second argument, and a copy of the context pointer -** passed as the sixth argument to this function as the first. If the "filter -** callback" returns zero, then no attempt is made to apply any changes to -** the table. Otherwise, if the return value is non-zero or the xFilter -** argument to this function is NULL, all changes related to the table are -** attempted. +** passed as the sixth argument as the first. If the "filter callback" +** returns zero, then no attempt is made to apply any changes to the table. +** Otherwise, if the return value is non-zero or the xFilter argument to +** is NULL, all changes related to the table are attempted. ** ** For each table that is not excluded by the filter callback, this function ** tests that the target database contains a compatible table. A table is @@ -10921,7 +11039,7 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*); ** **
    **
    DELETE Changes
    -** For each DELETE change, this function checks if the target database +** For each DELETE change, the function checks if the target database ** contains a row with the same primary key value (or values) as the ** original row values stored in the changeset. If it does, and the values ** stored in all non-primary key columns also match the values stored in @@ -10966,7 +11084,7 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*); ** [SQLITE_CHANGESET_REPLACE]. ** **
    UPDATE Changes
    -** For each UPDATE change, this function checks if the target database +** For each UPDATE change, the function checks if the target database ** contains a row with the same primary key value (or values) as the ** original row values stored in the changeset. If it does, and the values ** stored in all modified non-primary key columns also match the values @@ -10997,11 +11115,28 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*); ** This can be used to further customize the applications conflict ** resolution strategy. ** -** All changes made by this function are enclosed in a savepoint transaction. +** All changes made by these functions are enclosed in a savepoint transaction. ** If any other error (aside from a constraint failure when attempting to ** write to the target database) occurs, then the savepoint transaction is ** rolled back, restoring the target database to its original state, and an ** SQLite error code returned. +** +** If the output parameters (ppRebase) and (pnRebase) are non-NULL and +** the input is a changeset (not a patchset), then sqlite3changeset_apply_v2() +** may set (*ppRebase) to point to a "rebase" that may be used with the +** sqlite3_rebaser APIs buffer before returning. In this case (*pnRebase) +** is set to the size of the buffer in bytes. It is the responsibility of the +** caller to eventually free any such buffer using sqlite3_free(). The buffer +** is only allocated and populated if one or more conflicts were encountered +** while applying the patchset. See comments surrounding the sqlite3_rebaser +** APIs for further details. +** +** The behavior of sqlite3changeset_apply_v2() and its streaming equivalent +** may be modified by passing a combination of +** [SQLITE_CHANGESETAPPLY_NOSAVEPOINT | supported flags] as the 9th parameter. +** +** Note that the sqlite3changeset_apply_v2() API is still experimental +** and therefore subject to change. */ SQLITE_API int sqlite3changeset_apply( sqlite3 *db, /* Apply change to "main" db of this handle */ @@ -11018,6 +11153,41 @@ SQLITE_API int sqlite3changeset_apply( ), void *pCtx /* First argument passed to xConflict */ ); +SQLITE_API int sqlite3changeset_apply_v2( + sqlite3 *db, /* Apply change to "main" db of this handle */ + int nChangeset, /* Size of changeset in bytes */ + void *pChangeset, /* Changeset blob */ + int(*xFilter)( + void *pCtx, /* Copy of sixth arg to _apply() */ + const char *zTab /* Table name */ + ), + int(*xConflict)( + void *pCtx, /* Copy of sixth arg to _apply() */ + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ + sqlite3_changeset_iter *p /* Handle describing change and conflict */ + ), + void *pCtx, /* First argument passed to xConflict */ + void **ppRebase, int *pnRebase, /* OUT: Rebase data */ + int flags /* Combination of SESSION_APPLY_* flags */ +); + +/* +** CAPI3REF: Flags for sqlite3changeset_apply_v2 +** +** The following flags may passed via the 9th parameter to +** [sqlite3changeset_apply_v2] and [sqlite3changeset_apply_v2_strm]: +** +**
    +**
    SQLITE_CHANGESETAPPLY_NOSAVEPOINT
    +** Usually, the sessions module encloses all operations performed by +** a single call to apply_v2() or apply_v2_strm() in a [SAVEPOINT]. The +** SAVEPOINT is committed if the changeset or patchset is successfully +** applied, or rolled back if an error occurs. Specifying this flag +** causes the sessions module to omit this savepoint. In this case, if the +** caller has an open transaction or savepoint when apply_v2() is called, +** it may revert the partially applied changeset by rolling it back. +*/ +#define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001 /* ** CAPI3REF: Constants Passed To The Conflict Handler @@ -11115,6 +11285,161 @@ SQLITE_API int sqlite3changeset_apply( #define SQLITE_CHANGESET_REPLACE 1 #define SQLITE_CHANGESET_ABORT 2 +/* +** CAPI3REF: Rebasing changesets +** EXPERIMENTAL +** +** Suppose there is a site hosting a database in state S0. And that +** modifications are made that move that database to state S1 and a +** changeset recorded (the "local" changeset). Then, a changeset based +** on S0 is received from another site (the "remote" changeset) and +** applied to the database. The database is then in state +** (S1+"remote"), where the exact state depends on any conflict +** resolution decisions (OMIT or REPLACE) made while applying "remote". +** Rebasing a changeset is to update it to take those conflict +** resolution decisions into account, so that the same conflicts +** do not have to be resolved elsewhere in the network. +** +** For example, if both the local and remote changesets contain an +** INSERT of the same key on "CREATE TABLE t1(a PRIMARY KEY, b)": +** +** local: INSERT INTO t1 VALUES(1, 'v1'); +** remote: INSERT INTO t1 VALUES(1, 'v2'); +** +** and the conflict resolution is REPLACE, then the INSERT change is +** removed from the local changeset (it was overridden). Or, if the +** conflict resolution was "OMIT", then the local changeset is modified +** to instead contain: +** +** UPDATE t1 SET b = 'v2' WHERE a=1; +** +** Changes within the local changeset are rebased as follows: +** +**
    +**
    Local INSERT
    +** This may only conflict with a remote INSERT. If the conflict +** resolution was OMIT, then add an UPDATE change to the rebased +** changeset. Or, if the conflict resolution was REPLACE, add +** nothing to the rebased changeset. +** +**
    Local DELETE
    +** This may conflict with a remote UPDATE or DELETE. In both cases the +** only possible resolution is OMIT. If the remote operation was a +** DELETE, then add no change to the rebased changeset. If the remote +** operation was an UPDATE, then the old.* fields of change are updated +** to reflect the new.* values in the UPDATE. +** +**
    Local UPDATE
    +** This may conflict with a remote UPDATE or DELETE. If it conflicts +** with a DELETE, and the conflict resolution was OMIT, then the update +** is changed into an INSERT. Any undefined values in the new.* record +** from the update change are filled in using the old.* values from +** the conflicting DELETE. Or, if the conflict resolution was REPLACE, +** the UPDATE change is simply omitted from the rebased changeset. +** +** If conflict is with a remote UPDATE and the resolution is OMIT, then +** the old.* values are rebased using the new.* values in the remote +** change. Or, if the resolution is REPLACE, then the change is copied +** into the rebased changeset with updates to columns also updated by +** the conflicting remote UPDATE removed. If this means no columns would +** be updated, the change is omitted. +**
    +** +** A local change may be rebased against multiple remote changes +** simultaneously. If a single key is modified by multiple remote +** changesets, they are combined as follows before the local changeset +** is rebased: +** +**
      +**
    • If there has been one or more REPLACE resolutions on a +** key, it is rebased according to a REPLACE. +** +**
    • If there have been no REPLACE resolutions on a key, then +** the local changeset is rebased according to the most recent +** of the OMIT resolutions. +**
    +** +** Note that conflict resolutions from multiple remote changesets are +** combined on a per-field basis, not per-row. This means that in the +** case of multiple remote UPDATE operations, some fields of a single +** local change may be rebased for REPLACE while others are rebased for +** OMIT. +** +** In order to rebase a local changeset, the remote changeset must first +** be applied to the local database using sqlite3changeset_apply_v2() and +** the buffer of rebase information captured. Then: +** +**
      +**
    1. An sqlite3_rebaser object is created by calling +** sqlite3rebaser_create(). +**
    2. The new object is configured with the rebase buffer obtained from +** sqlite3changeset_apply_v2() by calling sqlite3rebaser_configure(). +** If the local changeset is to be rebased against multiple remote +** changesets, then sqlite3rebaser_configure() should be called +** multiple times, in the same order that the multiple +** sqlite3changeset_apply_v2() calls were made. +**
    3. Each local changeset is rebased by calling sqlite3rebaser_rebase(). +**
    4. The sqlite3_rebaser object is deleted by calling +** sqlite3rebaser_delete(). +**
    +*/ +typedef struct sqlite3_rebaser sqlite3_rebaser; + +/* +** CAPI3REF: Create a changeset rebaser object. +** EXPERIMENTAL +** +** Allocate a new changeset rebaser object. If successful, set (*ppNew) to +** point to the new object and return SQLITE_OK. Otherwise, if an error +** occurs, return an SQLite error code (e.g. SQLITE_NOMEM) and set (*ppNew) +** to NULL. +*/ +SQLITE_API int sqlite3rebaser_create(sqlite3_rebaser **ppNew); + +/* +** CAPI3REF: Configure a changeset rebaser object. +** EXPERIMENTAL +** +** Configure the changeset rebaser object to rebase changesets according +** to the conflict resolutions described by buffer pRebase (size nRebase +** bytes), which must have been obtained from a previous call to +** sqlite3changeset_apply_v2(). +*/ +SQLITE_API int sqlite3rebaser_configure( + sqlite3_rebaser*, + int nRebase, const void *pRebase +); + +/* +** CAPI3REF: Rebase a changeset +** EXPERIMENTAL +** +** Argument pIn must point to a buffer containing a changeset nIn bytes +** in size. This function allocates and populates a buffer with a copy +** of the changeset rebased rebased according to the configuration of the +** rebaser object passed as the first argument. If successful, (*ppOut) +** is set to point to the new buffer containing the rebased changset and +** (*pnOut) to its size in bytes and SQLITE_OK returned. It is the +** responsibility of the caller to eventually free the new buffer using +** sqlite3_free(). Otherwise, if an error occurs, (*ppOut) and (*pnOut) +** are set to zero and an SQLite error code returned. +*/ +SQLITE_API int sqlite3rebaser_rebase( + sqlite3_rebaser*, + int nIn, const void *pIn, + int *pnOut, void **ppOut +); + +/* +** CAPI3REF: Delete a changeset rebaser object. +** EXPERIMENTAL +** +** Delete the changeset rebaser object and all associated resources. There +** should be one call to this function for each successful invocation +** of sqlite3rebaser_create(). +*/ +SQLITE_API void sqlite3rebaser_delete(sqlite3_rebaser *p); + /* ** CAPI3REF: Streaming Versions of API functions. ** @@ -11124,6 +11449,7 @@ SQLITE_API int sqlite3changeset_apply( ** ** **
    Streaming functionNon-streaming equivalent
    sqlite3changeset_apply_strm[sqlite3changeset_apply] +**
    sqlite3changeset_apply_strm_v2[sqlite3changeset_apply_v2] **
    sqlite3changeset_concat_strm[sqlite3changeset_concat] **
    sqlite3changeset_invert_strm[sqlite3changeset_invert] **
    sqlite3changeset_start_strm[sqlite3changeset_start] @@ -11219,6 +11545,23 @@ SQLITE_API int sqlite3changeset_apply_strm( ), void *pCtx /* First argument passed to xConflict */ ); +SQLITE_API int sqlite3changeset_apply_v2_strm( + sqlite3 *db, /* Apply change to "main" db of this handle */ + int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ + void *pIn, /* First arg for xInput */ + int(*xFilter)( + void *pCtx, /* Copy of sixth arg to _apply() */ + const char *zTab /* Table name */ + ), + int(*xConflict)( + void *pCtx, /* Copy of sixth arg to _apply() */ + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ + sqlite3_changeset_iter *p /* Handle describing change and conflict */ + ), + void *pCtx, /* First argument passed to xConflict */ + void **ppRebase, int *pnRebase, + int flags +); SQLITE_API int sqlite3changeset_concat_strm( int (*xInputA)(void *pIn, void *pData, int *pnData), void *pInA, @@ -11256,6 +11599,13 @@ SQLITE_API int sqlite3changegroup_output_strm(sqlite3_changegroup*, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut ); +SQLITE_API int sqlite3rebaser_rebase_strm( + sqlite3_rebaser *pRebaser, + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +); /* @@ -12673,23 +13023,25 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*); #define TK_INDEX 140 #define TK_ALTER 141 #define TK_ADD 142 -#define TK_ISNOT 143 -#define TK_FUNCTION 144 -#define TK_COLUMN 145 -#define TK_AGG_FUNCTION 146 -#define TK_AGG_COLUMN 147 -#define TK_UMINUS 148 -#define TK_UPLUS 149 -#define TK_REGISTER 150 -#define TK_VECTOR 151 -#define TK_SELECT_COLUMN 152 -#define TK_IF_NULL_ROW 153 -#define TK_ASTERISK 154 -#define TK_SPAN 155 -#define TK_END_OF_FILE 156 -#define TK_UNCLOSED_STRING 157 -#define TK_SPACE 158 -#define TK_ILLEGAL 159 +#define TK_TRUEFALSE 143 +#define TK_ISNOT 144 +#define TK_FUNCTION 145 +#define TK_COLUMN 146 +#define TK_AGG_FUNCTION 147 +#define TK_AGG_COLUMN 148 +#define TK_UMINUS 149 +#define TK_UPLUS 150 +#define TK_TRUTH 151 +#define TK_REGISTER 152 +#define TK_VECTOR 153 +#define TK_SELECT_COLUMN 154 +#define TK_IF_NULL_ROW 155 +#define TK_ASTERISK 156 +#define TK_SPAN 157 +#define TK_END_OF_FILE 158 +#define TK_UNCLOSED_STRING 159 +#define TK_SPACE 160 +#define TK_ILLEGAL 161 /* The token codes above must all fit in 8 bits */ #define TKFLG_MASK 0xff @@ -13133,9 +13485,10 @@ typedef INT16_TYPE LogEst; */ typedef struct BusyHandler BusyHandler; struct BusyHandler { - int (*xFunc)(void *,int); /* The busy callback */ - void *pArg; /* First arg to busy callback */ - int nBusy; /* Incremented with each busy call */ + int (*xBusyHandler)(void *,int); /* The busy callback */ + void *pBusyArg; /* First arg to busy callback */ + int nBusy; /* Incremented with each busy call */ + u8 bExtraFileArg; /* Include sqlite3_file as callback arg */ }; /* @@ -13935,80 +14288,81 @@ typedef struct VdbeOpList VdbeOpList; #define OP_Concat 93 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */ #define OP_Compare 94 /* synopsis: r[P1@P3] <-> r[P2@P3] */ #define OP_BitNot 95 /* same as TK_BITNOT, synopsis: r[P1]= ~r[P1] */ -#define OP_Offset 96 /* synopsis: r[P3] = sqlite_offset(P1) */ +#define OP_IsTrue 96 /* synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 */ #define OP_String8 97 /* same as TK_STRING, synopsis: r[P2]='P4' */ -#define OP_Column 98 /* synopsis: r[P3]=PX */ -#define OP_Affinity 99 /* synopsis: affinity(r[P1@P2]) */ -#define OP_MakeRecord 100 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ -#define OP_Count 101 /* synopsis: r[P2]=count() */ -#define OP_ReadCookie 102 -#define OP_SetCookie 103 -#define OP_ReopenIdx 104 /* synopsis: root=P2 iDb=P3 */ -#define OP_OpenRead 105 /* synopsis: root=P2 iDb=P3 */ -#define OP_OpenWrite 106 /* synopsis: root=P2 iDb=P3 */ -#define OP_OpenDup 107 -#define OP_OpenAutoindex 108 /* synopsis: nColumn=P2 */ -#define OP_OpenEphemeral 109 /* synopsis: nColumn=P2 */ -#define OP_SorterOpen 110 -#define OP_SequenceTest 111 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */ -#define OP_OpenPseudo 112 /* synopsis: P3 columns in r[P2] */ -#define OP_Close 113 -#define OP_ColumnsUsed 114 -#define OP_Sequence 115 /* synopsis: r[P2]=cursor[P1].ctr++ */ -#define OP_NewRowid 116 /* synopsis: r[P2]=rowid */ -#define OP_Insert 117 /* synopsis: intkey=r[P3] data=r[P2] */ -#define OP_InsertInt 118 /* synopsis: intkey=P3 data=r[P2] */ -#define OP_Delete 119 -#define OP_ResetCount 120 -#define OP_SorterCompare 121 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */ -#define OP_SorterData 122 /* synopsis: r[P2]=data */ -#define OP_RowData 123 /* synopsis: r[P2]=data */ -#define OP_Rowid 124 /* synopsis: r[P2]=rowid */ -#define OP_NullRow 125 -#define OP_SeekEnd 126 -#define OP_SorterInsert 127 /* synopsis: key=r[P2] */ -#define OP_IdxInsert 128 /* synopsis: key=r[P2] */ -#define OP_IdxDelete 129 /* synopsis: key=r[P2@P3] */ -#define OP_DeferredSeek 130 /* synopsis: Move P3 to P1.rowid if needed */ -#define OP_IdxRowid 131 /* synopsis: r[P2]=rowid */ +#define OP_Offset 98 /* synopsis: r[P3] = sqlite_offset(P1) */ +#define OP_Column 99 /* synopsis: r[P3]=PX */ +#define OP_Affinity 100 /* synopsis: affinity(r[P1@P2]) */ +#define OP_MakeRecord 101 /* synopsis: r[P3]=mkrec(r[P1@P2]) */ +#define OP_Count 102 /* synopsis: r[P2]=count() */ +#define OP_ReadCookie 103 +#define OP_SetCookie 104 +#define OP_ReopenIdx 105 /* synopsis: root=P2 iDb=P3 */ +#define OP_OpenRead 106 /* synopsis: root=P2 iDb=P3 */ +#define OP_OpenWrite 107 /* synopsis: root=P2 iDb=P3 */ +#define OP_OpenDup 108 +#define OP_OpenAutoindex 109 /* synopsis: nColumn=P2 */ +#define OP_OpenEphemeral 110 /* synopsis: nColumn=P2 */ +#define OP_SorterOpen 111 +#define OP_SequenceTest 112 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */ +#define OP_OpenPseudo 113 /* synopsis: P3 columns in r[P2] */ +#define OP_Close 114 +#define OP_ColumnsUsed 115 +#define OP_Sequence 116 /* synopsis: r[P2]=cursor[P1].ctr++ */ +#define OP_NewRowid 117 /* synopsis: r[P2]=rowid */ +#define OP_Insert 118 /* synopsis: intkey=r[P3] data=r[P2] */ +#define OP_InsertInt 119 /* synopsis: intkey=P3 data=r[P2] */ +#define OP_Delete 120 +#define OP_ResetCount 121 +#define OP_SorterCompare 122 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */ +#define OP_SorterData 123 /* synopsis: r[P2]=data */ +#define OP_RowData 124 /* synopsis: r[P2]=data */ +#define OP_Rowid 125 /* synopsis: r[P2]=rowid */ +#define OP_NullRow 126 +#define OP_SeekEnd 127 +#define OP_SorterInsert 128 /* synopsis: key=r[P2] */ +#define OP_IdxInsert 129 /* synopsis: key=r[P2] */ +#define OP_IdxDelete 130 /* synopsis: key=r[P2@P3] */ +#define OP_DeferredSeek 131 /* synopsis: Move P3 to P1.rowid if needed */ #define OP_Real 132 /* same as TK_FLOAT, synopsis: r[P2]=P4 */ -#define OP_Destroy 133 -#define OP_Clear 134 -#define OP_ResetSorter 135 -#define OP_CreateBtree 136 /* synopsis: r[P2]=root iDb=P1 flags=P3 */ -#define OP_SqlExec 137 -#define OP_ParseSchema 138 -#define OP_LoadAnalysis 139 -#define OP_DropTable 140 -#define OP_DropIndex 141 -#define OP_DropTrigger 142 -#define OP_IntegrityCk 143 -#define OP_RowSetAdd 144 /* synopsis: rowset(P1)=r[P2] */ -#define OP_Param 145 -#define OP_FkCounter 146 /* synopsis: fkctr[P1]+=P2 */ -#define OP_MemMax 147 /* synopsis: r[P1]=max(r[P1],r[P2]) */ -#define OP_OffsetLimit 148 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */ -#define OP_AggStep0 149 /* synopsis: accum=r[P3] step(r[P2@P5]) */ -#define OP_AggStep 150 /* synopsis: accum=r[P3] step(r[P2@P5]) */ -#define OP_AggFinal 151 /* synopsis: accum=r[P1] N=P2 */ -#define OP_Expire 152 -#define OP_TableLock 153 /* synopsis: iDb=P1 root=P2 write=P3 */ -#define OP_VBegin 154 -#define OP_VCreate 155 -#define OP_VDestroy 156 -#define OP_VOpen 157 -#define OP_VColumn 158 /* synopsis: r[P3]=vcolumn(P2) */ -#define OP_VRename 159 -#define OP_Pagecount 160 -#define OP_MaxPgcnt 161 -#define OP_PureFunc0 162 -#define OP_Function0 163 /* synopsis: r[P3]=func(r[P2@P5]) */ -#define OP_PureFunc 164 -#define OP_Function 165 /* synopsis: r[P3]=func(r[P2@P5]) */ -#define OP_Trace 166 -#define OP_CursorHint 167 -#define OP_Noop 168 -#define OP_Explain 169 +#define OP_IdxRowid 133 /* synopsis: r[P2]=rowid */ +#define OP_Destroy 134 +#define OP_Clear 135 +#define OP_ResetSorter 136 +#define OP_CreateBtree 137 /* synopsis: r[P2]=root iDb=P1 flags=P3 */ +#define OP_SqlExec 138 +#define OP_ParseSchema 139 +#define OP_LoadAnalysis 140 +#define OP_DropTable 141 +#define OP_DropIndex 142 +#define OP_DropTrigger 143 +#define OP_IntegrityCk 144 +#define OP_RowSetAdd 145 /* synopsis: rowset(P1)=r[P2] */ +#define OP_Param 146 +#define OP_FkCounter 147 /* synopsis: fkctr[P1]+=P2 */ +#define OP_MemMax 148 /* synopsis: r[P1]=max(r[P1],r[P2]) */ +#define OP_OffsetLimit 149 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */ +#define OP_AggStep0 150 /* synopsis: accum=r[P3] step(r[P2@P5]) */ +#define OP_AggStep 151 /* synopsis: accum=r[P3] step(r[P2@P5]) */ +#define OP_AggFinal 152 /* synopsis: accum=r[P1] N=P2 */ +#define OP_Expire 153 +#define OP_TableLock 154 /* synopsis: iDb=P1 root=P2 write=P3 */ +#define OP_VBegin 155 +#define OP_VCreate 156 +#define OP_VDestroy 157 +#define OP_VOpen 158 +#define OP_VColumn 159 /* synopsis: r[P3]=vcolumn(P2) */ +#define OP_VRename 160 +#define OP_Pagecount 161 +#define OP_MaxPgcnt 162 +#define OP_PureFunc0 163 +#define OP_Function0 164 /* synopsis: r[P3]=func(r[P2@P5]) */ +#define OP_PureFunc 165 +#define OP_Function 166 /* synopsis: r[P3]=func(r[P2@P5]) */ +#define OP_Trace 167 +#define OP_CursorHint 168 +#define OP_Noop 169 +#define OP_Explain 170 /* Properties such as "out2" or "jump" that are specified in ** comments following the "case" for each opcode in the vdbe.c @@ -14033,16 +14387,16 @@ typedef struct VdbeOpList VdbeOpList; /* 72 */ 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\ /* 80 */ 0x02, 0x02, 0x02, 0x00, 0x26, 0x26, 0x26, 0x26,\ /* 88 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x00, 0x12,\ -/* 96 */ 0x20, 0x10, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00,\ +/* 96 */ 0x12, 0x10, 0x20, 0x00, 0x00, 0x00, 0x10, 0x10,\ /* 104 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ -/* 112 */ 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00,\ -/* 120 */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x04,\ -/* 128 */ 0x04, 0x00, 0x00, 0x10, 0x10, 0x10, 0x00, 0x00,\ -/* 136 */ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ -/* 144 */ 0x06, 0x10, 0x00, 0x04, 0x1a, 0x00, 0x00, 0x00,\ +/* 112 */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\ +/* 120 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,\ +/* 128 */ 0x04, 0x04, 0x00, 0x00, 0x10, 0x10, 0x10, 0x00,\ +/* 136 */ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ +/* 144 */ 0x00, 0x06, 0x10, 0x00, 0x04, 0x1a, 0x00, 0x00,\ /* 152 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ -/* 160 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ -/* 168 */ 0x00, 0x00,} +/* 160 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\ +/* 168 */ 0x00, 0x00, 0x00,} /* The sqlite3P2Values() routine is able to run faster if it knows ** the value of the largest JUMP opcode. The smaller the maximum @@ -14343,7 +14697,7 @@ SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3*); SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); /* Functions used to configure a Pager object. */ -SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *); +SQLITE_PRIVATE void sqlite3PagerSetBusyHandler(Pager*, int(*)(void *), void *); SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int); #ifdef SQLITE_HAS_CODEC SQLITE_PRIVATE void sqlite3PagerAlignReserve(Pager*,Pager*); @@ -14429,6 +14783,11 @@ SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*); SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, int *); SQLITE_PRIVATE void sqlite3PagerClearCache(Pager*); SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *); +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT +SQLITE_PRIVATE void sqlite3PagerResetLockTimeout(Pager *pPager); +#else +# define sqlite3PagerResetLockTimeout(X) +#endif /* Functions used to truncate the database file. */ SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno); @@ -15248,8 +15607,9 @@ struct sqlite3 { int newTnum; /* Rootpage of table being initialized */ u8 iDb; /* Which db file is being initialized */ u8 busy; /* TRUE if currently initializing */ - u8 orphanTrigger; /* Last statement is orphaned TEMP trigger */ - u8 imposterTable; /* Building an imposter table */ + unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */ + unsigned imposterTable : 1; /* Building an imposter table */ + unsigned reopenMemdb : 1; /* ATTACH is really a reopen using MemDB */ } init; int nVdbeActive; /* Number of VDBEs currently running */ int nVdbeRead; /* Number of active VDBEs that read or write */ @@ -15414,6 +15774,8 @@ struct sqlite3 { #define SQLITE_CursorHints 0x0400 /* Add OP_CursorHint opcodes */ #define SQLITE_Stat34 0x0800 /* Use STAT3 or STAT4 data */ /* TH3 expects the Stat34 ^^^^^^ value to be 0x0800. Don't change it */ +#define SQLITE_PushDown 0x1000 /* The push-down optimization */ +#define SQLITE_SimplifyJoin 0x2000 /* Convert LEFT JOIN to JOIN */ #define SQLITE_AllOpts 0xffff /* All optimizations */ /* @@ -15637,6 +15999,7 @@ struct Column { #define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */ #define COLFLAG_HIDDEN 0x0002 /* A hidden column in a virtual table */ #define COLFLAG_HASTYPE 0x0004 /* Type name follows column name */ +#define COLFLAG_UNIQUE 0x0008 /* Column def contains "UNIQUE" or "PK" */ /* ** A "Collating Sequence" is defined by an instance of the following @@ -16874,7 +17237,6 @@ struct Parse { int nMaxArg; /* Max args passed to user function by sub-program */ #if SELECTTRACE_ENABLED int nSelect; /* Number of SELECT statements seen */ - int nSelectIndent; /* How far to indent SELECTTRACE() output */ #endif #ifndef SQLITE_OMIT_SHARED_CACHE int nTableLock; /* Number of locks in aTableLock */ @@ -17238,9 +17600,9 @@ struct Walker { struct CCurHint *pCCurHint; /* Used by codeCursorHint() */ int *aiCol; /* array of column indexes */ struct IdxCover *pIdxCover; /* Check for index coverage */ - struct IdxExprTrans *pIdxTrans; /* Convert indexed expr to column */ + struct IdxExprTrans *pIdxTrans; /* Convert idxed expr to column */ ExprList *pGroupBy; /* GROUP BY clause */ - struct HavingToWhereCtx *pHavingCtx; /* HAVING to WHERE clause ctx */ + Select *pSelect; /* HAVING to WHERE clause ctx */ } u; }; @@ -17704,6 +18066,7 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Parse*,Expr*, Expr*, int); SQLITE_PRIVATE int sqlite3ExprCompareSkip(Expr*, Expr*, int); SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList*, ExprList*, int); SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Parse*,Expr*, Expr*, int); +SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr*,int); SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*); SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*); SQLITE_PRIVATE int sqlite3ExprCoveredByIndex(Expr*, int iCur, Index *pIdx); @@ -17721,6 +18084,8 @@ SQLITE_PRIVATE void sqlite3EndTransaction(Parse*,int); SQLITE_PRIVATE void sqlite3Savepoint(Parse*, int, Token*); SQLITE_PRIVATE void sqlite3CloseSavepoints(sqlite3 *); SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3*); +SQLITE_PRIVATE int sqlite3ExprIdToTrueFalse(Expr*); +SQLITE_PRIVATE int sqlite3ExprTruthValue(const Expr*); SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr*); SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr*); SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr*, u8); @@ -17903,6 +18268,10 @@ SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **); SQLITE_PRIVATE const char *sqlite3ErrName(int); #endif +#ifdef SQLITE_ENABLE_DESERIALIZE +SQLITE_PRIVATE int sqlite3MemdbInit(void); +#endif + SQLITE_PRIVATE const char *sqlite3ErrStr(int); SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse); SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int); @@ -17951,6 +18320,9 @@ SQLITE_PRIVATE FuncDefHash sqlite3BuiltinFunctions; SQLITE_PRIVATE int sqlite3PendingByte; #endif #endif +#ifdef VDBE_PROFILE +SQLITE_PRIVATE sqlite3_uint64 sqlite3NProfileCnt; +#endif SQLITE_PRIVATE void sqlite3RootPageMoved(sqlite3*, int, int, int); SQLITE_PRIVATE void sqlite3Reindex(Parse*, Token*, Token*); SQLITE_PRIVATE void sqlite3AlterFunctions(void); @@ -17973,7 +18345,7 @@ SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *); SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*); SQLITE_PRIVATE char sqlite3AffinityType(const char*, u8*); SQLITE_PRIVATE void sqlite3Analyze(Parse*, Token*, Token*); -SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*); +SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*, sqlite3_file*); SQLITE_PRIVATE int sqlite3FindDb(sqlite3*, Token*); SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *, const char *); SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3*,int iDB); @@ -18574,6 +18946,13 @@ SQLITE_PRIVATE const Token sqlite3IntTokens[] = { { "1", 1 } }; +#ifdef VDBE_PROFILE +/* +** The following performance counter can be used in place of +** sqlite3Hwtime() for profiling. This is a no-op on standard builds. +*/ +SQLITE_PRIVATE sqlite3_uint64 sqlite3NProfileCnt = 0; +#endif /* ** The value of the "pending" byte must be 0x40000000 (1 byte past the @@ -18857,8 +19236,6 @@ struct sqlite3_value { ** If the MEM_Null flag is set, then the value is an SQL NULL value. ** For a pointer type created using sqlite3_bind_pointer() or ** sqlite3_result_pointer() the MEM_Term and MEM_Subtype flags are also set. -** If both MEM_Null and MEM_Zero are set, that means that the value is -** an unchanging column value from VColumn. ** ** If the MEM_Str flag is set then Mem.z points at a string representation. ** Usually this is encoded in the same unicode encoding as the main @@ -18952,7 +19329,6 @@ struct sqlite3_context { int iOp; /* Instruction number of OP_Function */ int isError; /* Error code returned by the function. */ u8 skipFlag; /* Skip accumulator loading if true */ - u8 fErrorOrAux; /* isError!=0 or pVdbe->pAuxData modified */ u8 argc; /* Number of arguments */ sqlite3_value *argv[1]; /* Argument set */ }; @@ -19122,6 +19498,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, u8, u8); SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem*); SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem*); +SQLITE_PRIVATE int sqlite3VdbeBooleanValue(Mem*, int ifNull); SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*); SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*); @@ -19515,6 +19892,9 @@ SQLITE_API int sqlite3_db_status( ** pagers the database handle is connected to. *pHighwater is always set ** to zero. */ + case SQLITE_DBSTATUS_CACHE_SPILL: + op = SQLITE_DBSTATUS_CACHE_WRITE+1; + /* Fall through into the next case */ case SQLITE_DBSTATUS_CACHE_HIT: case SQLITE_DBSTATUS_CACHE_MISS: case SQLITE_DBSTATUS_CACHE_WRITE:{ @@ -20935,8 +21315,11 @@ SQLITE_PRIVATE int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut){ ** routine has no return value since the return value would be meaningless. */ SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){ + if( id->pMethods==0 ) return SQLITE_NOTFOUND; #ifdef SQLITE_TEST - if( op!=SQLITE_FCNTL_COMMIT_PHASETWO ){ + if( op!=SQLITE_FCNTL_COMMIT_PHASETWO + && op!=SQLITE_FCNTL_LOCK_TIMEOUT + ){ /* Faults are not injected into COMMIT_PHASETWO because, assuming SQLite ** is using a regular VFS, it is called after the corresponding ** transaction has been committed. Injecting a fault at this point @@ -20953,7 +21336,7 @@ SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){ return id->pMethods->xFileControl(id, op, pArg); } SQLITE_PRIVATE void sqlite3OsFileControlHint(sqlite3_file *id, int op, void *pArg){ - (void)id->pMethods->xFileControl(id, op, pArg); + if( id->pMethods ) (void)id->pMethods->xFileControl(id, op, pArg); } SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id){ @@ -24108,11 +24491,12 @@ struct sqlite3_mutex { #endif }; #if SQLITE_MUTEX_NREF -#define SQLITE3_MUTEX_INITIALIZER {PTHREAD_MUTEX_INITIALIZER,0,0,(pthread_t)0,0} +# define SQLITE3_MUTEX_INITIALIZER(id) \ + {PTHREAD_MUTEX_INITIALIZER,id,0,(pthread_t)0,0} #elif defined(SQLITE_ENABLE_API_ARMOR) -#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, 0 } +# define SQLITE3_MUTEX_INITIALIZER(id) { PTHREAD_MUTEX_INITIALIZER, id } #else -#define SQLITE3_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER } +#define SQLITE3_MUTEX_INITIALIZER(id) { PTHREAD_MUTEX_INITIALIZER } #endif /* @@ -24209,18 +24593,18 @@ static int pthreadMutexEnd(void){ return SQLITE_OK; } */ static sqlite3_mutex *pthreadMutexAlloc(int iType){ static sqlite3_mutex staticMutexes[] = { - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER + SQLITE3_MUTEX_INITIALIZER(2), + SQLITE3_MUTEX_INITIALIZER(3), + SQLITE3_MUTEX_INITIALIZER(4), + SQLITE3_MUTEX_INITIALIZER(5), + SQLITE3_MUTEX_INITIALIZER(6), + SQLITE3_MUTEX_INITIALIZER(7), + SQLITE3_MUTEX_INITIALIZER(8), + SQLITE3_MUTEX_INITIALIZER(9), + SQLITE3_MUTEX_INITIALIZER(10), + SQLITE3_MUTEX_INITIALIZER(11), + SQLITE3_MUTEX_INITIALIZER(12), + SQLITE3_MUTEX_INITIALIZER(13) }; sqlite3_mutex *p; switch( iType ){ @@ -24238,6 +24622,9 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){ pthread_mutexattr_settype(&recursiveAttr, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(&p->mutex, &recursiveAttr); pthread_mutexattr_destroy(&recursiveAttr); +#endif +#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR) + p->id = SQLITE_MUTEX_RECURSIVE; #endif } break; @@ -24246,6 +24633,9 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){ p = sqlite3MallocZero( sizeof(*p) ); if( p ){ pthread_mutex_init(&p->mutex, 0); +#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR) + p->id = SQLITE_MUTEX_FAST; +#endif } break; } @@ -24261,7 +24651,7 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){ } } #if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR) - if( p ) p->id = iType; + assert( p==0 || p->id==iType ); #endif return p; } @@ -24778,7 +25168,7 @@ struct sqlite3_mutex { #ifdef SQLITE_DEBUG volatile int nRef; /* Number of enterances */ volatile DWORD owner; /* Thread holding this mutex */ - volatile int trace; /* True to trace changes */ + volatile LONG trace; /* True to trace changes */ #endif }; @@ -24790,10 +25180,10 @@ struct sqlite3_mutex { #define SQLITE_W32_MUTEX_INITIALIZER { 0 } #ifdef SQLITE_DEBUG -#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0, \ +#define SQLITE3_MUTEX_INITIALIZER(id) { SQLITE_W32_MUTEX_INITIALIZER, id, \ 0L, (DWORD)0, 0 } #else -#define SQLITE3_MUTEX_INITIALIZER { SQLITE_W32_MUTEX_INITIALIZER, 0 } +#define SQLITE3_MUTEX_INITIALIZER(id) { SQLITE_W32_MUTEX_INITIALIZER, id } #endif #ifdef SQLITE_DEBUG @@ -24836,18 +25226,18 @@ SQLITE_PRIVATE void sqlite3MemoryBarrier(void){ ** Initialize and deinitialize the mutex subsystem. */ static sqlite3_mutex winMutex_staticMutexes[] = { - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER, - SQLITE3_MUTEX_INITIALIZER + SQLITE3_MUTEX_INITIALIZER(2), + SQLITE3_MUTEX_INITIALIZER(3), + SQLITE3_MUTEX_INITIALIZER(4), + SQLITE3_MUTEX_INITIALIZER(5), + SQLITE3_MUTEX_INITIALIZER(6), + SQLITE3_MUTEX_INITIALIZER(7), + SQLITE3_MUTEX_INITIALIZER(8), + SQLITE3_MUTEX_INITIALIZER(9), + SQLITE3_MUTEX_INITIALIZER(10), + SQLITE3_MUTEX_INITIALIZER(11), + SQLITE3_MUTEX_INITIALIZER(12), + SQLITE3_MUTEX_INITIALIZER(13) }; static int winMutex_isInit = 0; @@ -24977,15 +25367,15 @@ static sqlite3_mutex *winMutexAlloc(int iType){ } #endif p = &winMutex_staticMutexes[iType-2]; - p->id = iType; #ifdef SQLITE_DEBUG #ifdef SQLITE_WIN32_MUTEX_TRACE_STATIC - p->trace = 1; + InterlockedCompareExchange(&p->trace, 1, 0); #endif #endif break; } } + assert( p==0 || p->id==iType ); return p; } @@ -26064,6 +26454,11 @@ SQLITE_PRIVATE void sqlite3VXPrintf( PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */ char buf[etBUFSIZE]; /* Conversion buffer */ + /* pAccum never starts out with an empty buffer that was obtained from + ** malloc(). This precondition is required by the mprintf("%z...") + ** optimization. */ + assert( pAccum->nChar>0 || (pAccum->printfFlags&SQLITE_PRINTF_MALLOCED)==0 ); + bufpt = 0; if( (pAccum->printfFlags & SQLITE_PRINTF_SQLFUNC)!=0 ){ pArgList = va_arg(ap, PrintfArguments*); @@ -26482,9 +26877,38 @@ SQLITE_PRIVATE void sqlite3VXPrintf( case etCHARX: if( bArgList ){ bufpt = getTextArg(pArgList); - c = bufpt ? bufpt[0] : 0; + length = 1; + if( bufpt ){ + buf[0] = c = *(bufpt++); + if( (c&0xc0)==0xc0 ){ + while( length<4 && (bufpt[0]&0xc0)==0x80 ){ + buf[length++] = *(bufpt++); + } + } + }else{ + buf[0] = 0; + } }else{ - c = va_arg(ap,int); + unsigned int ch = va_arg(ap,unsigned int); + if( ch<0x00080 ){ + buf[0] = ch & 0xff; + length = 1; + }else if( ch<0x00800 ){ + buf[0] = 0xc0 + (u8)((ch>>6)&0x1f); + buf[1] = 0x80 + (u8)(ch & 0x3f); + length = 2; + }else if( ch<0x10000 ){ + buf[0] = 0xe0 + (u8)((ch>>12)&0x0f); + buf[1] = 0x80 + (u8)((ch>>6) & 0x3f); + buf[2] = 0x80 + (u8)(ch & 0x3f); + length = 3; + }else{ + buf[0] = 0xf0 + (u8)((ch>>18) & 0x07); + buf[1] = 0x80 + (u8)((ch>>12) & 0x3f); + buf[2] = 0x80 + (u8)((ch>>6) & 0x3f); + buf[3] = 0x80 + (u8)(ch & 0x3f); + length = 4; + } } if( precision>1 ){ width -= precision-1; @@ -26492,12 +26916,13 @@ SQLITE_PRIVATE void sqlite3VXPrintf( sqlite3AppendChar(pAccum, width-1, ' '); width = 0; } - sqlite3AppendChar(pAccum, precision-1, c); + while( precision-- > 1 ){ + sqlite3StrAccumAppend(pAccum, buf, length); + } } - length = 1; - buf[0] = c; bufpt = buf; - break; + flag_altform2 = 1; + goto adjust_width_for_utf8; case etSTRING: case etDYNSTRING: if( bArgList ){ @@ -26509,17 +26934,45 @@ SQLITE_PRIVATE void sqlite3VXPrintf( if( bufpt==0 ){ bufpt = ""; }else if( xtype==etDYNSTRING ){ + if( pAccum->nChar==0 && pAccum->mxAlloc && width==0 && precision<0 ){ + /* Special optimization for sqlite3_mprintf("%z..."): + ** Extend an existing memory allocation rather than creating + ** a new one. */ + assert( (pAccum->printfFlags&SQLITE_PRINTF_MALLOCED)==0 ); + pAccum->zText = bufpt; + pAccum->nAlloc = sqlite3DbMallocSize(pAccum->db, bufpt); + pAccum->nChar = 0x7fffffff & (int)strlen(bufpt); + pAccum->printfFlags |= SQLITE_PRINTF_MALLOCED; + length = 0; + break; + } zExtra = bufpt; } if( precision>=0 ){ - for(length=0; length 0 && z[0] ){ + SQLITE_SKIP_UTF8(z); + } + length = (int)(z - (unsigned char*)bufpt); + }else{ + for(length=0; length0 ){ + /* Adjust width to account for extra bytes in UTF-8 characters */ + int ii = length - 1; + while( ii>=0 ) if( (bufpt[ii--] & 0xc0)==0x80 ) width++; + } break; - case etSQLESCAPE: /* Escape ' characters */ - case etSQLESCAPE2: /* Escape ' and enclose in '...' */ - case etSQLESCAPE3: { /* Escape " characters */ + case etSQLESCAPE: /* %q: Escape ' characters */ + case etSQLESCAPE2: /* %Q: Escape ' and enclose in '...' */ + case etSQLESCAPE3: { /* %w: Escape " characters */ int i, j, k, n, isnull; int needQuote; char ch; @@ -26533,9 +26986,17 @@ SQLITE_PRIVATE void sqlite3VXPrintf( } isnull = escarg==0; if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)"); + /* For %q, %Q, and %w, the precision is the number of byte (or + ** characters if the ! flags is present) to use from the input. + ** Because of the extra quoting characters inserted, the number + ** of output characters may be larger than the precision. + */ k = precision; for(i=n=0; k!=0 && (ch=escarg[i])!=0; i++, k--){ if( ch==q ) n++; + if( flag_altform2 && (ch&0xc0)==0xc0 ){ + while( (escarg[i+1]&0xc0)==0x80 ){ i++; } + } } needQuote = !isnull && xtype==etSQLESCAPE2; n += i + 3; @@ -26558,10 +27019,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf( if( needQuote ) bufpt[j++] = q; bufpt[j] = 0; length = j; - /* The precision in %q and %Q means how many input characters to - ** consume, not the length of the output... - ** if( precision>=0 && precision0 ){ @@ -27115,11 +27576,21 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m sqlite3TreeViewPush(pView, 1); } do{ +#if SELECTTRACE_ENABLED + sqlite3TreeViewLine(pView, + "SELECT%s%s (%s/%p) selFlags=0x%x nSelectRow=%d", + ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""), + ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), + p->zSelName, p, p->selFlags, + (int)p->nSelectRow + ); +#else sqlite3TreeViewLine(pView, "SELECT%s%s (0x%p) selFlags=0x%x nSelectRow=%d", ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""), ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), p, p->selFlags, (int)p->nSelectRow ); +#endif if( cnt++ ) sqlite3TreeViewPop(pView); if( p->pPrior ){ n = 1000; @@ -27270,6 +27741,11 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m sqlite3TreeViewLine(pView,"NULL"); break; } + case TK_TRUEFALSE: { + sqlite3TreeViewLine(pView, + sqlite3ExprTruthValue(pExpr) ? "TRUE" : "FALSE"); + break; + } #ifndef SQLITE_OMIT_BLOB_LITERAL case TK_BLOB: { sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken); @@ -27326,6 +27802,19 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m case TK_ISNULL: zUniOp = "ISNULL"; break; case TK_NOTNULL: zUniOp = "NOTNULL"; break; + case TK_TRUTH: { + int x; + const char *azOp[] = { + "IS-FALSE", "IS-TRUE", "IS-NOT-FALSE", "IS-NOT-TRUE" + }; + assert( pExpr->op2==TK_IS || pExpr->op2==TK_ISNOT ); + assert( pExpr->pRight ); + assert( pExpr->pRight->op==TK_TRUEFALSE ); + x = (pExpr->op2==TK_ISNOT)*2 + sqlite3ExprTruthValue(pExpr->pRight); + zUniOp = azOp[x]; + break; + } + case TK_SPAN: { sqlite3TreeViewLine(pView, "SPAN %Q", pExpr->u.zToken); sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); @@ -29063,7 +29552,7 @@ static int compare2pow63(const char *zNum, int incr){ ** Returns: ** ** 0 Successful transformation. Fits in a 64-bit signed integer. -** 1 Excess text after the integer value +** 1 Excess non-space text after the integer value ** 2 Integer too large for a 64-bit signed integer or is malformed ** 3 Special case of 9223372036854775808 ** @@ -29106,47 +29595,57 @@ SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc for(i=0; &zNum[i]='0' && c<='9'; i+=incr){ u = u*10 + c - '0'; } + testcase( i==18*incr ); + testcase( i==19*incr ); + testcase( i==20*incr ); if( u>LARGEST_INT64 ){ + /* This test and assignment is needed only to suppress UB warnings + ** from clang and -fsanitize=undefined. This test and assignment make + ** the code a little larger and slower, and no harm comes from omitting + ** them, but we must appaise the undefined-behavior pharisees. */ *pNum = neg ? SMALLEST_INT64 : LARGEST_INT64; }else if( neg ){ *pNum = -(i64)u; }else{ *pNum = (i64)u; } - testcase( i==18 ); - testcase( i==19 ); - testcase( i==20 ); - if( &zNum[i]19*incr ){ /* Too many digits */ - /* zNum is empty or contains non-numeric text or is longer - ** than 19 digits (thus guaranteeing that it is too large) */ - return 2; - }else if( i<19*incr ){ + if( i<19*incr ){ /* Less than 19 digits, so we know that it fits in 64 bits */ assert( u<=LARGEST_INT64 ); return rc; }else{ /* zNum is a 19-digit numbers. Compare it against 9223372036854775808. */ - c = compare2pow63(zNum, incr); + c = i>19*incr ? 1 : compare2pow63(zNum, incr); if( c<0 ){ /* zNum is less than 9223372036854775808 so it fits */ assert( u<=LARGEST_INT64 ); return rc; - }else if( c>0 ){ - /* zNum is greater than 9223372036854775808 so it overflows */ - return 2; }else{ - /* zNum is exactly 9223372036854775808. Fits if negative. The - ** special case 2 overflow if positive */ - assert( u-1==LARGEST_INT64 ); - return neg ? rc : 3; + *pNum = neg ? SMALLEST_INT64 : LARGEST_INT64; + if( c>0 ){ + /* zNum is greater than 9223372036854775808 so it overflows */ + return 2; + }else{ + /* zNum is exactly 9223372036854775808. Fits if negative. The + ** special case 2 overflow if positive */ + assert( u-1==LARGEST_INT64 ); + return neg ? rc : 3; + } } } } @@ -30463,80 +30962,81 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ /* 93 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"), /* 94 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"), /* 95 */ "BitNot" OpHelp("r[P1]= ~r[P1]"), - /* 96 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"), + /* 96 */ "IsTrue" OpHelp("r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4"), /* 97 */ "String8" OpHelp("r[P2]='P4'"), - /* 98 */ "Column" OpHelp("r[P3]=PX"), - /* 99 */ "Affinity" OpHelp("affinity(r[P1@P2])"), - /* 100 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), - /* 101 */ "Count" OpHelp("r[P2]=count()"), - /* 102 */ "ReadCookie" OpHelp(""), - /* 103 */ "SetCookie" OpHelp(""), - /* 104 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"), - /* 105 */ "OpenRead" OpHelp("root=P2 iDb=P3"), - /* 106 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), - /* 107 */ "OpenDup" OpHelp(""), - /* 108 */ "OpenAutoindex" OpHelp("nColumn=P2"), - /* 109 */ "OpenEphemeral" OpHelp("nColumn=P2"), - /* 110 */ "SorterOpen" OpHelp(""), - /* 111 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"), - /* 112 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), - /* 113 */ "Close" OpHelp(""), - /* 114 */ "ColumnsUsed" OpHelp(""), - /* 115 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"), - /* 116 */ "NewRowid" OpHelp("r[P2]=rowid"), - /* 117 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), - /* 118 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"), - /* 119 */ "Delete" OpHelp(""), - /* 120 */ "ResetCount" OpHelp(""), - /* 121 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"), - /* 122 */ "SorterData" OpHelp("r[P2]=data"), - /* 123 */ "RowData" OpHelp("r[P2]=data"), - /* 124 */ "Rowid" OpHelp("r[P2]=rowid"), - /* 125 */ "NullRow" OpHelp(""), - /* 126 */ "SeekEnd" OpHelp(""), - /* 127 */ "SorterInsert" OpHelp("key=r[P2]"), - /* 128 */ "IdxInsert" OpHelp("key=r[P2]"), - /* 129 */ "IdxDelete" OpHelp("key=r[P2@P3]"), - /* 130 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"), - /* 131 */ "IdxRowid" OpHelp("r[P2]=rowid"), + /* 98 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"), + /* 99 */ "Column" OpHelp("r[P3]=PX"), + /* 100 */ "Affinity" OpHelp("affinity(r[P1@P2])"), + /* 101 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"), + /* 102 */ "Count" OpHelp("r[P2]=count()"), + /* 103 */ "ReadCookie" OpHelp(""), + /* 104 */ "SetCookie" OpHelp(""), + /* 105 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"), + /* 106 */ "OpenRead" OpHelp("root=P2 iDb=P3"), + /* 107 */ "OpenWrite" OpHelp("root=P2 iDb=P3"), + /* 108 */ "OpenDup" OpHelp(""), + /* 109 */ "OpenAutoindex" OpHelp("nColumn=P2"), + /* 110 */ "OpenEphemeral" OpHelp("nColumn=P2"), + /* 111 */ "SorterOpen" OpHelp(""), + /* 112 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"), + /* 113 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"), + /* 114 */ "Close" OpHelp(""), + /* 115 */ "ColumnsUsed" OpHelp(""), + /* 116 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"), + /* 117 */ "NewRowid" OpHelp("r[P2]=rowid"), + /* 118 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"), + /* 119 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"), + /* 120 */ "Delete" OpHelp(""), + /* 121 */ "ResetCount" OpHelp(""), + /* 122 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"), + /* 123 */ "SorterData" OpHelp("r[P2]=data"), + /* 124 */ "RowData" OpHelp("r[P2]=data"), + /* 125 */ "Rowid" OpHelp("r[P2]=rowid"), + /* 126 */ "NullRow" OpHelp(""), + /* 127 */ "SeekEnd" OpHelp(""), + /* 128 */ "SorterInsert" OpHelp("key=r[P2]"), + /* 129 */ "IdxInsert" OpHelp("key=r[P2]"), + /* 130 */ "IdxDelete" OpHelp("key=r[P2@P3]"), + /* 131 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"), /* 132 */ "Real" OpHelp("r[P2]=P4"), - /* 133 */ "Destroy" OpHelp(""), - /* 134 */ "Clear" OpHelp(""), - /* 135 */ "ResetSorter" OpHelp(""), - /* 136 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"), - /* 137 */ "SqlExec" OpHelp(""), - /* 138 */ "ParseSchema" OpHelp(""), - /* 139 */ "LoadAnalysis" OpHelp(""), - /* 140 */ "DropTable" OpHelp(""), - /* 141 */ "DropIndex" OpHelp(""), - /* 142 */ "DropTrigger" OpHelp(""), - /* 143 */ "IntegrityCk" OpHelp(""), - /* 144 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), - /* 145 */ "Param" OpHelp(""), - /* 146 */ "FkCounter" OpHelp("fkctr[P1]+=P2"), - /* 147 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), - /* 148 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"), - /* 149 */ "AggStep0" OpHelp("accum=r[P3] step(r[P2@P5])"), - /* 150 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"), - /* 151 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), - /* 152 */ "Expire" OpHelp(""), - /* 153 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), - /* 154 */ "VBegin" OpHelp(""), - /* 155 */ "VCreate" OpHelp(""), - /* 156 */ "VDestroy" OpHelp(""), - /* 157 */ "VOpen" OpHelp(""), - /* 158 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), - /* 159 */ "VRename" OpHelp(""), - /* 160 */ "Pagecount" OpHelp(""), - /* 161 */ "MaxPgcnt" OpHelp(""), - /* 162 */ "PureFunc0" OpHelp(""), - /* 163 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"), - /* 164 */ "PureFunc" OpHelp(""), - /* 165 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"), - /* 166 */ "Trace" OpHelp(""), - /* 167 */ "CursorHint" OpHelp(""), - /* 168 */ "Noop" OpHelp(""), - /* 169 */ "Explain" OpHelp(""), + /* 133 */ "IdxRowid" OpHelp("r[P2]=rowid"), + /* 134 */ "Destroy" OpHelp(""), + /* 135 */ "Clear" OpHelp(""), + /* 136 */ "ResetSorter" OpHelp(""), + /* 137 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"), + /* 138 */ "SqlExec" OpHelp(""), + /* 139 */ "ParseSchema" OpHelp(""), + /* 140 */ "LoadAnalysis" OpHelp(""), + /* 141 */ "DropTable" OpHelp(""), + /* 142 */ "DropIndex" OpHelp(""), + /* 143 */ "DropTrigger" OpHelp(""), + /* 144 */ "IntegrityCk" OpHelp(""), + /* 145 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"), + /* 146 */ "Param" OpHelp(""), + /* 147 */ "FkCounter" OpHelp("fkctr[P1]+=P2"), + /* 148 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"), + /* 149 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"), + /* 150 */ "AggStep0" OpHelp("accum=r[P3] step(r[P2@P5])"), + /* 151 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"), + /* 152 */ "AggFinal" OpHelp("accum=r[P1] N=P2"), + /* 153 */ "Expire" OpHelp(""), + /* 154 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"), + /* 155 */ "VBegin" OpHelp(""), + /* 156 */ "VCreate" OpHelp(""), + /* 157 */ "VDestroy" OpHelp(""), + /* 158 */ "VOpen" OpHelp(""), + /* 159 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"), + /* 160 */ "VRename" OpHelp(""), + /* 161 */ "Pagecount" OpHelp(""), + /* 162 */ "MaxPgcnt" OpHelp(""), + /* 163 */ "PureFunc0" OpHelp(""), + /* 164 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"), + /* 165 */ "PureFunc" OpHelp(""), + /* 166 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"), + /* 167 */ "Trace" OpHelp(""), + /* 168 */ "CursorHint" OpHelp(""), + /* 169 */ "Noop" OpHelp(""), + /* 170 */ "Explain" OpHelp(""), }; return azName[i]; } @@ -30775,6 +31275,9 @@ struct unixFile { #if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__) unsigned fsFlags; /* cached details from statfs() */ #endif +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT + unsigned iBusyTimeout; /* Wait this many millisec on locks */ +#endif #if OS_VXWORKS struct vxworksFileId *pId; /* Unique file ID */ #endif @@ -31212,7 +31715,11 @@ static struct unix_syscall { #endif #define osFchown ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent) +#if defined(HAVE_FCHOWN) { "geteuid", (sqlite3_syscall_ptr)geteuid, 0 }, +#else + { "geteuid", (sqlite3_syscall_ptr)0, 0 }, +#endif #define osGeteuid ((uid_t(*)(void))aSyscall[21].pCurrent) #if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 @@ -31440,15 +31947,16 @@ static int robust_open(const char *z, int f, mode_t m){ ** assert( unixMutexHeld() ); ** unixEnterLeave() */ +static sqlite3_mutex *unixBigLock = 0; static void unixEnterMutex(void){ - sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); + sqlite3_mutex_enter(unixBigLock); } static void unixLeaveMutex(void){ - sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); + sqlite3_mutex_leave(unixBigLock); } #ifdef SQLITE_DEBUG static int unixMutexHeld(void) { - return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); + return sqlite3_mutex_held(unixBigLock); } #endif @@ -32204,6 +32712,43 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){ return rc; } +/* +** Set a posix-advisory-lock. +** +** There are two versions of this routine. If compiled with +** SQLITE_ENABLE_SETLK_TIMEOUT then the routine has an extra parameter +** which is a pointer to a unixFile. If the unixFile->iBusyTimeout +** value is set, then it is the number of milliseconds to wait before +** failing the lock. The iBusyTimeout value is always reset back to +** zero on each call. +** +** If SQLITE_ENABLE_SETLK_TIMEOUT is not defined, then do a non-blocking +** attempt to set the lock. +*/ +#ifndef SQLITE_ENABLE_SETLK_TIMEOUT +# define osSetPosixAdvisoryLock(h,x,t) osFcntl(h,F_SETLK,x) +#else +static int osSetPosixAdvisoryLock( + int h, /* The file descriptor on which to take the lock */ + struct flock *pLock, /* The description of the lock */ + unixFile *pFile /* Structure holding timeout value */ +){ + int rc = osFcntl(h,F_SETLK,pLock); + while( rc<0 && pFile->iBusyTimeout>0 ){ + /* On systems that support some kind of blocking file lock with a timeout, + ** make appropriate changes here to invoke that blocking file lock. On + ** generic posix, however, there is no such API. So we simply try the + ** lock once every millisecond until either the timeout expires, or until + ** the lock is obtained. */ + usleep(1000); + rc = osFcntl(h,F_SETLK,pLock); + pFile->iBusyTimeout--; + } + return rc; +} +#endif /* SQLITE_ENABLE_SETLK_TIMEOUT */ + + /* ** Attempt to set a system-lock on the file pFile. The lock is ** described by pLock. @@ -32236,7 +32781,7 @@ static int unixFileLock(unixFile *pFile, struct flock *pLock){ lock.l_start = SHARED_FIRST; lock.l_len = SHARED_SIZE; lock.l_type = F_WRLCK; - rc = osFcntl(pFile->h, F_SETLK, &lock); + rc = osSetPosixAdvisoryLock(pFile->h, &lock, pFile); if( rc<0 ) return rc; pInode->bProcessLock = 1; pInode->nLock++; @@ -32244,7 +32789,7 @@ static int unixFileLock(unixFile *pFile, struct flock *pLock){ rc = 0; } }else{ - rc = osFcntl(pFile->h, F_SETLK, pLock); + rc = osSetPosixAdvisoryLock(pFile->h, pLock, pFile); } return rc; } @@ -34604,6 +35149,12 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){ *(int*)pArg = fileHasMoved(pFile); return SQLITE_OK; } +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT + case SQLITE_FCNTL_LOCK_TIMEOUT: { + pFile->iBusyTimeout = *(int*)pArg; + return SQLITE_OK; + } +#endif #if SQLITE_MAX_MMAP_SIZE>0 case SQLITE_FCNTL_MMAP_SIZE: { i64 newLimit = *(i64*)pArg; @@ -34919,13 +35470,11 @@ static int unixShmSystemLock( if( pShmNode->h>=0 ){ /* Initialize the locking parameters */ - memset(&f, 0, sizeof(f)); f.l_type = lockType; f.l_whence = SEEK_SET; f.l_start = ofst; f.l_len = n; - - rc = osFcntl(pShmNode->h, F_SETLK, &f); + rc = osSetPosixAdvisoryLock(pShmNode->h, &f, pFile); rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY; } @@ -36590,7 +37139,6 @@ static int unixOpen( randomnessPid = osGetpid(0); sqlite3_randomness(0,0); } - memset(p, 0, sizeof(unixFile)); if( eType==SQLITE_OPEN_MAIN_DB ){ @@ -38465,6 +39013,7 @@ SQLITE_API int sqlite3_os_init(void){ for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ sqlite3_vfs_register(&aVfs[i], i==0); } + unixBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1); return SQLITE_OK; } @@ -38476,6 +39025,7 @@ SQLITE_API int sqlite3_os_init(void){ ** This routine is a no-op for unix. */ SQLITE_API int sqlite3_os_end(void){ + unixBigLock = 0; return SQLITE_OK; } @@ -42314,15 +42864,16 @@ static SYSTEM_INFO winSysInfo; ** assert( winShmMutexHeld() ); ** winShmLeaveMutex() */ +static sqlite3_mutex *winBigLock = 0; static void winShmEnterMutex(void){ - sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); + sqlite3_mutex_enter(winBigLock); } static void winShmLeaveMutex(void){ - sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); + sqlite3_mutex_leave(winBigLock); } #ifndef NDEBUG static int winShmMutexHeld(void) { - return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); + return sqlite3_mutex_held(winBigLock); } #endif @@ -44745,6 +45296,10 @@ SQLITE_API int sqlite3_os_init(void){ sqlite3_vfs_register(&winLongPathNolockVfs, 0); #endif +#ifndef SQLITE_OMIT_WAL + winBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1); +#endif + return SQLITE_OK; } @@ -44755,12 +45310,609 @@ SQLITE_API int sqlite3_os_end(void){ sleepObj = NULL; } #endif + +#ifndef SQLITE_OMIT_WAL + winBigLock = 0; +#endif + return SQLITE_OK; } #endif /* SQLITE_OS_WIN */ /************** End of os_win.c **********************************************/ +/************** Begin file memdb.c *******************************************/ +/* +** 2016-09-07 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** This file implements an in-memory VFS. A database is held as a contiguous +** block of memory. +** +** This file also implements interface sqlite3_serialize() and +** sqlite3_deserialize(). +*/ +#ifdef SQLITE_ENABLE_DESERIALIZE +/* #include "sqliteInt.h" */ + +/* +** Forward declaration of objects used by this utility +*/ +typedef struct sqlite3_vfs MemVfs; +typedef struct MemFile MemFile; + +/* Access to a lower-level VFS that (might) implement dynamic loading, +** access to randomness, etc. +*/ +#define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData)) + +/* An open file */ +struct MemFile { + sqlite3_file base; /* IO methods */ + sqlite3_int64 sz; /* Size of the file */ + sqlite3_int64 szMax; /* Space allocated to aData */ + unsigned char *aData; /* content of the file */ + int nMmap; /* Number of memory mapped pages */ + unsigned mFlags; /* Flags */ + int eLock; /* Most recent lock against this file */ +}; + +/* +** Methods for MemFile +*/ +static int memdbClose(sqlite3_file*); +static int memdbRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst); +static int memdbWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst); +static int memdbTruncate(sqlite3_file*, sqlite3_int64 size); +static int memdbSync(sqlite3_file*, int flags); +static int memdbFileSize(sqlite3_file*, sqlite3_int64 *pSize); +static int memdbLock(sqlite3_file*, int); +/* static int memdbCheckReservedLock(sqlite3_file*, int *pResOut);// not used */ +static int memdbFileControl(sqlite3_file*, int op, void *pArg); +/* static int memdbSectorSize(sqlite3_file*); // not used */ +static int memdbDeviceCharacteristics(sqlite3_file*); +static int memdbFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp); +static int memdbUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p); + +/* +** Methods for MemVfs +*/ +static int memdbOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *); +/* static int memdbDelete(sqlite3_vfs*, const char *zName, int syncDir); */ +static int memdbAccess(sqlite3_vfs*, const char *zName, int flags, int *); +static int memdbFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut); +static void *memdbDlOpen(sqlite3_vfs*, const char *zFilename); +static void memdbDlError(sqlite3_vfs*, int nByte, char *zErrMsg); +static void (*memdbDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void); +static void memdbDlClose(sqlite3_vfs*, void*); +static int memdbRandomness(sqlite3_vfs*, int nByte, char *zOut); +static int memdbSleep(sqlite3_vfs*, int microseconds); +/* static int memdbCurrentTime(sqlite3_vfs*, double*); */ +static int memdbGetLastError(sqlite3_vfs*, int, char *); +static int memdbCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*); + +static sqlite3_vfs memdb_vfs = { + 2, /* iVersion */ + 0, /* szOsFile (set when registered) */ + 1024, /* mxPathname */ + 0, /* pNext */ + "memdb", /* zName */ + 0, /* pAppData (set when registered) */ + memdbOpen, /* xOpen */ + 0, /* memdbDelete, */ /* xDelete */ + memdbAccess, /* xAccess */ + memdbFullPathname, /* xFullPathname */ + memdbDlOpen, /* xDlOpen */ + memdbDlError, /* xDlError */ + memdbDlSym, /* xDlSym */ + memdbDlClose, /* xDlClose */ + memdbRandomness, /* xRandomness */ + memdbSleep, /* xSleep */ + 0, /* memdbCurrentTime, */ /* xCurrentTime */ + memdbGetLastError, /* xGetLastError */ + memdbCurrentTimeInt64 /* xCurrentTimeInt64 */ +}; + +static const sqlite3_io_methods memdb_io_methods = { + 3, /* iVersion */ + memdbClose, /* xClose */ + memdbRead, /* xRead */ + memdbWrite, /* xWrite */ + memdbTruncate, /* xTruncate */ + memdbSync, /* xSync */ + memdbFileSize, /* xFileSize */ + memdbLock, /* xLock */ + memdbLock, /* xUnlock - same as xLock in this case */ + 0, /* memdbCheckReservedLock, */ /* xCheckReservedLock */ + memdbFileControl, /* xFileControl */ + 0, /* memdbSectorSize,*/ /* xSectorSize */ + memdbDeviceCharacteristics, /* xDeviceCharacteristics */ + 0, /* xShmMap */ + 0, /* xShmLock */ + 0, /* xShmBarrier */ + 0, /* xShmUnmap */ + memdbFetch, /* xFetch */ + memdbUnfetch /* xUnfetch */ +}; + + + +/* +** Close an memdb-file. +** +** The pData pointer is owned by the application, so there is nothing +** to free. +*/ +static int memdbClose(sqlite3_file *pFile){ + MemFile *p = (MemFile *)pFile; + if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ) sqlite3_free(p->aData); + return SQLITE_OK; +} + +/* +** Read data from an memdb-file. +*/ +static int memdbRead( + sqlite3_file *pFile, + void *zBuf, + int iAmt, + sqlite_int64 iOfst +){ + MemFile *p = (MemFile *)pFile; + if( iOfst+iAmt>p->sz ){ + memset(zBuf, 0, iAmt); + if( iOfstsz ) memcpy(zBuf, p->aData+iOfst, p->sz - iOfst); + return SQLITE_IOERR_SHORT_READ; + } + memcpy(zBuf, p->aData+iOfst, iAmt); + return SQLITE_OK; +} + +/* +** Try to enlarge the memory allocation to hold at least sz bytes +*/ +static int memdbEnlarge(MemFile *p, sqlite3_int64 newSz){ + unsigned char *pNew; + if( (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)==0 || p->nMmap>0 ){ + return SQLITE_FULL; + } + pNew = sqlite3_realloc64(p->aData, newSz); + if( pNew==0 ) return SQLITE_NOMEM; + p->aData = pNew; + p->szMax = newSz; + return SQLITE_OK; +} + +/* +** Write data to an memdb-file. +*/ +static int memdbWrite( + sqlite3_file *pFile, + const void *z, + int iAmt, + sqlite_int64 iOfst +){ + MemFile *p = (MemFile *)pFile; + if( iOfst+iAmt>p->sz ){ + int rc; + if( iOfst+iAmt>p->szMax + && (rc = memdbEnlarge(p, (iOfst+iAmt)*2))!=SQLITE_OK + ){ + return rc; + } + if( iOfst>p->sz ) memset(p->aData+p->sz, 0, iOfst-p->sz); + p->sz = iOfst+iAmt; + } + memcpy(p->aData+iOfst, z, iAmt); + return SQLITE_OK; +} + +/* +** Truncate an memdb-file. +** +** In rollback mode (which is always the case for memdb, as it does not +** support WAL mode) the truncate() method is only used to reduce +** the size of a file, never to increase the size. +*/ +static int memdbTruncate(sqlite3_file *pFile, sqlite_int64 size){ + MemFile *p = (MemFile *)pFile; + if( NEVER(size>p->sz) ) return SQLITE_FULL; + p->sz = size; + return SQLITE_OK; +} + +/* +** Sync an memdb-file. +*/ +static int memdbSync(sqlite3_file *pFile, int flags){ + return SQLITE_OK; +} + +/* +** Return the current file-size of an memdb-file. +*/ +static int memdbFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){ + MemFile *p = (MemFile *)pFile; + *pSize = p->sz; + return SQLITE_OK; +} + +/* +** Lock an memdb-file. +*/ +static int memdbLock(sqlite3_file *pFile, int eLock){ + MemFile *p = (MemFile *)pFile; + p->eLock = eLock; + return SQLITE_OK; +} + +#if 0 /* Never used because memdbAccess() always returns false */ +/* +** Check if another file-handle holds a RESERVED lock on an memdb-file. +*/ +static int memdbCheckReservedLock(sqlite3_file *pFile, int *pResOut){ + *pResOut = 0; + return SQLITE_OK; +} +#endif + +/* +** File control method. For custom operations on an memdb-file. +*/ +static int memdbFileControl(sqlite3_file *pFile, int op, void *pArg){ + MemFile *p = (MemFile *)pFile; + int rc = SQLITE_NOTFOUND; + if( op==SQLITE_FCNTL_VFSNAME ){ + *(char**)pArg = sqlite3_mprintf("memdb(%p,%lld)", p->aData, p->sz); + rc = SQLITE_OK; + } + return rc; +} + +#if 0 /* Not used because of SQLITE_IOCAP_POWERSAFE_OVERWRITE */ +/* +** Return the sector-size in bytes for an memdb-file. +*/ +static int memdbSectorSize(sqlite3_file *pFile){ + return 1024; +} +#endif + +/* +** Return the device characteristic flags supported by an memdb-file. +*/ +static int memdbDeviceCharacteristics(sqlite3_file *pFile){ + return SQLITE_IOCAP_ATOMIC | + SQLITE_IOCAP_POWERSAFE_OVERWRITE | + SQLITE_IOCAP_SAFE_APPEND | + SQLITE_IOCAP_SEQUENTIAL; +} + +/* Fetch a page of a memory-mapped file */ +static int memdbFetch( + sqlite3_file *pFile, + sqlite3_int64 iOfst, + int iAmt, + void **pp +){ + MemFile *p = (MemFile *)pFile; + p->nMmap++; + *pp = (void*)(p->aData + iOfst); + return SQLITE_OK; +} + +/* Release a memory-mapped page */ +static int memdbUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){ + MemFile *p = (MemFile *)pFile; + p->nMmap--; + return SQLITE_OK; +} + +/* +** Open an mem file handle. +*/ +static int memdbOpen( + sqlite3_vfs *pVfs, + const char *zName, + sqlite3_file *pFile, + int flags, + int *pOutFlags +){ + MemFile *p = (MemFile*)pFile; + if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){ + return ORIGVFS(pVfs)->xOpen(ORIGVFS(pVfs), zName, pFile, flags, pOutFlags); + } + memset(p, 0, sizeof(*p)); + p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE; + assert( pOutFlags!=0 ); /* True because flags==SQLITE_OPEN_MAIN_DB */ + *pOutFlags = flags | SQLITE_OPEN_MEMORY; + p->base.pMethods = &memdb_io_methods; + return SQLITE_OK; +} + +#if 0 /* Only used to delete rollback journals, master journals, and WAL + ** files, none of which exist in memdb. So this routine is never used */ +/* +** Delete the file located at zPath. If the dirSync argument is true, +** ensure the file-system modifications are synced to disk before +** returning. +*/ +static int memdbDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ + return SQLITE_IOERR_DELETE; +} +#endif + +/* +** Test for access permissions. Return true if the requested permission +** is available, or false otherwise. +** +** With memdb, no files ever exist on disk. So always return false. +*/ +static int memdbAccess( + sqlite3_vfs *pVfs, + const char *zPath, + int flags, + int *pResOut +){ + *pResOut = 0; + return SQLITE_OK; +} + +/* +** Populate buffer zOut with the full canonical pathname corresponding +** to the pathname in zPath. zOut is guaranteed to point to a buffer +** of at least (INST_MAX_PATHNAME+1) bytes. +*/ +static int memdbFullPathname( + sqlite3_vfs *pVfs, + const char *zPath, + int nOut, + char *zOut +){ + sqlite3_snprintf(nOut, zOut, "%s", zPath); + return SQLITE_OK; +} + +/* +** Open the dynamic library located at zPath and return a handle. +*/ +static void *memdbDlOpen(sqlite3_vfs *pVfs, const char *zPath){ + return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath); +} + +/* +** Populate the buffer zErrMsg (size nByte bytes) with a human readable +** utf-8 string describing the most recent error encountered associated +** with dynamic libraries. +*/ +static void memdbDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){ + ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg); +} + +/* +** Return a pointer to the symbol zSymbol in the dynamic library pHandle. +*/ +static void (*memdbDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){ + return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym); +} + +/* +** Close the dynamic library handle pHandle. +*/ +static void memdbDlClose(sqlite3_vfs *pVfs, void *pHandle){ + ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle); +} + +/* +** Populate the buffer pointed to by zBufOut with nByte bytes of +** random data. +*/ +static int memdbRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){ + return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut); +} + +/* +** Sleep for nMicro microseconds. Return the number of microseconds +** actually slept. +*/ +static int memdbSleep(sqlite3_vfs *pVfs, int nMicro){ + return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro); +} + +#if 0 /* Never used. Modern cores only call xCurrentTimeInt64() */ +/* +** Return the current time as a Julian Day number in *pTimeOut. +*/ +static int memdbCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){ + return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut); +} +#endif + +static int memdbGetLastError(sqlite3_vfs *pVfs, int a, char *b){ + return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b); +} +static int memdbCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){ + return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p); +} + +/* +** Translate a database connection pointer and schema name into a +** MemFile pointer. +*/ +static MemFile *memdbFromDbSchema(sqlite3 *db, const char *zSchema){ + MemFile *p = 0; + int rc = sqlite3_file_control(db, zSchema, SQLITE_FCNTL_FILE_POINTER, &p); + if( rc ) return 0; + if( p->base.pMethods!=&memdb_io_methods ) return 0; + return p; +} + +/* +** Return the serialization of a database +*/ +SQLITE_API unsigned char *sqlite3_serialize( + sqlite3 *db, /* The database connection */ + const char *zSchema, /* Which database within the connection */ + sqlite3_int64 *piSize, /* Write size here, if not NULL */ + unsigned int mFlags /* Maybe SQLITE_SERIALIZE_NOCOPY */ +){ + MemFile *p; + int iDb; + Btree *pBt; + sqlite3_int64 sz; + int szPage = 0; + sqlite3_stmt *pStmt = 0; + unsigned char *pOut; + char *zSql; + int rc; + +#ifdef SQLITE_ENABLE_API_ARMOR + if( !sqlite3SafetyCheckOk(db) ){ + (void)SQLITE_MISUSE_BKPT; + return 0; + } +#endif + + if( zSchema==0 ) zSchema = db->aDb[0].zDbSName; + p = memdbFromDbSchema(db, zSchema); + iDb = sqlite3FindDbName(db, zSchema); + if( piSize ) *piSize = -1; + if( iDb<0 ) return 0; + if( p ){ + if( piSize ) *piSize = p->sz; + if( mFlags & SQLITE_SERIALIZE_NOCOPY ){ + pOut = p->aData; + }else{ + pOut = sqlite3_malloc64( p->sz ); + if( pOut ) memcpy(pOut, p->aData, p->sz); + } + return pOut; + } + pBt = db->aDb[iDb].pBt; + if( pBt==0 ) return 0; + szPage = sqlite3BtreeGetPageSize(pBt); + zSql = sqlite3_mprintf("PRAGMA \"%w\".page_count", zSchema); + rc = zSql ? sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0) : SQLITE_NOMEM; + sqlite3_free(zSql); + if( rc ) return 0; + rc = sqlite3_step(pStmt); + if( rc!=SQLITE_ROW ){ + pOut = 0; + }else{ + sz = sqlite3_column_int64(pStmt, 0)*szPage; + if( piSize ) *piSize = sz; + if( mFlags & SQLITE_SERIALIZE_NOCOPY ){ + pOut = 0; + }else{ + pOut = sqlite3_malloc64( sz ); + if( pOut ){ + int nPage = sqlite3_column_int(pStmt, 0); + Pager *pPager = sqlite3BtreePager(pBt); + int pgno; + for(pgno=1; pgno<=nPage; pgno++){ + DbPage *pPage = 0; + unsigned char *pTo = pOut + szPage*(sqlite3_int64)(pgno-1); + rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pPage, 0); + if( rc==SQLITE_OK ){ + memcpy(pTo, sqlite3PagerGetData(pPage), szPage); + }else{ + memset(pTo, 0, szPage); + } + sqlite3PagerUnref(pPage); + } + } + } + } + sqlite3_finalize(pStmt); + return pOut; +} + +/* Convert zSchema to a MemDB and initialize its content. +*/ +SQLITE_API int sqlite3_deserialize( + sqlite3 *db, /* The database connection */ + const char *zSchema, /* Which DB to reopen with the deserialization */ + unsigned char *pData, /* The serialized database content */ + sqlite3_int64 szDb, /* Number bytes in the deserialization */ + sqlite3_int64 szBuf, /* Total size of buffer pData[] */ + unsigned mFlags /* Zero or more SQLITE_DESERIALIZE_* flags */ +){ + MemFile *p; + char *zSql; + sqlite3_stmt *pStmt = 0; + int rc; + int iDb; + +#ifdef SQLITE_ENABLE_API_ARMOR + if( !sqlite3SafetyCheckOk(db) ){ + return SQLITE_MISUSE_BKPT; + } + if( szDb<0 ) return SQLITE_MISUSE_BKPT; + if( szBuf<0 ) return SQLITE_MISUSE_BKPT; +#endif + + sqlite3_mutex_enter(db->mutex); + if( zSchema==0 ) zSchema = db->aDb[0].zDbSName; + iDb = sqlite3FindDbName(db, zSchema); + if( iDb<0 ){ + rc = SQLITE_ERROR; + goto end_deserialize; + } + zSql = sqlite3_mprintf("ATTACH x AS %Q", zSchema); + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); + sqlite3_free(zSql); + if( rc ) goto end_deserialize; + db->init.iDb = (u8)iDb; + db->init.reopenMemdb = 1; + rc = sqlite3_step(pStmt); + db->init.reopenMemdb = 0; + if( rc!=SQLITE_DONE ){ + rc = SQLITE_ERROR; + goto end_deserialize; + } + p = memdbFromDbSchema(db, zSchema); + if( p==0 ){ + rc = SQLITE_ERROR; + }else{ + p->aData = pData; + p->sz = szDb; + p->szMax = szBuf; + p->mFlags = mFlags; + rc = SQLITE_OK; + } + +end_deserialize: + sqlite3_finalize(pStmt); + sqlite3_mutex_leave(db->mutex); + return rc; +} + +/* +** This routine is called when the extension is loaded. +** Register the new VFS. +*/ +SQLITE_PRIVATE int sqlite3MemdbInit(void){ + sqlite3_vfs *pLower = sqlite3_vfs_find(0); + int sz = pLower->szOsFile; + memdb_vfs.pAppData = pLower; + /* In all known configurations of SQLite, the size of a default + ** sqlite3_file is greater than the size of a memdb sqlite3_file. + ** Should that ever change, remove the following NEVER() */ + if( NEVER(szpgno, pgno, - sqlite3GlobalConfig.pcache.xPagecount(pCache->pCache), + sqlite3GlobalConfig.pcache2.xPagecount(pCache->pCache), numberOfCachePages(pCache)); #endif pcacheTrace(("%p.SPILL %d\n",pCache,pPg->pgno)); @@ -48665,7 +49817,7 @@ struct Pager { char *zJournal; /* Name of the journal file */ int (*xBusyHandler)(void*); /* Function to call when busy */ void *pBusyHandlerArg; /* Context argument for xBusyHandler */ - int aStat[3]; /* Total cache hits, misses and writes */ + int aStat[4]; /* Total cache hits, misses, writes, spills */ #ifdef SQLITE_TEST int nRead; /* Database pages read */ #endif @@ -48693,6 +49845,7 @@ struct Pager { #define PAGER_STAT_HIT 0 #define PAGER_STAT_MISS 1 #define PAGER_STAT_WRITE 2 +#define PAGER_STAT_SPILL 3 /* ** The following global variables hold counters used for @@ -49179,7 +50332,7 @@ static int jrnlBufferSize(Pager *pPager){ #endif #ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE - if( dc&SQLITE_IOCAP_BATCH_ATOMIC ){ + if( pPager->dbSize>0 && (dc&SQLITE_IOCAP_BATCH_ATOMIC) ){ return -1; } #endif @@ -50095,7 +51248,7 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){ rc = pager_truncate(pPager, pPager->dbSize); } - if( rc==SQLITE_OK && bCommit && isOpen(pPager->fd) ){ + if( rc==SQLITE_OK && bCommit ){ rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_COMMIT_PHASETWO, 0); if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK; } @@ -50914,9 +52067,7 @@ end_playback: ** assertion that the transaction counter was modified. */ #ifdef SQLITE_DEBUG - if( pPager->fd->pMethods ){ - sqlite3OsFileControlHint(pPager->fd,SQLITE_FCNTL_DB_UNCHANGED,0); - } + sqlite3OsFileControlHint(pPager->fd,SQLITE_FCNTL_DB_UNCHANGED,0); #endif /* If this playback is happening automatically as a result of an IO or @@ -51669,20 +52820,18 @@ static int pagerOpentemp( ** retried. If it returns zero, then the SQLITE_BUSY error is ** returned to the caller of the pager API function. */ -SQLITE_PRIVATE void sqlite3PagerSetBusyhandler( +SQLITE_PRIVATE void sqlite3PagerSetBusyHandler( Pager *pPager, /* Pager object */ int (*xBusyHandler)(void *), /* Pointer to busy-handler function */ void *pBusyHandlerArg /* Argument to pass to xBusyHandler */ ){ + void **ap; pPager->xBusyHandler = xBusyHandler; pPager->pBusyHandlerArg = pBusyHandlerArg; - - if( isOpen(pPager->fd) ){ - void **ap = (void **)&pPager->xBusyHandler; - assert( ((int(*)(void *))(ap[0]))==xBusyHandler ); - assert( ap[1]==pBusyHandlerArg ); - sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_BUSYHANDLER, (void *)ap); - } + ap = (void **)&pPager->xBusyHandler; + assert( ((int(*)(void *))(ap[0]))==xBusyHandler ); + assert( ap[1]==pBusyHandlerArg ); + sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_BUSYHANDLER, (void *)ap); } /* @@ -52068,6 +53217,30 @@ static void pagerFreeMapHdrs(Pager *pPager){ } } +/* Verify that the database file has not be deleted or renamed out from +** under the pager. Return SQLITE_OK if the database is still where it ought +** to be on disk. Return non-zero (SQLITE_READONLY_DBMOVED or some other error +** code from sqlite3OsAccess()) if the database has gone missing. +*/ +static int databaseIsUnmoved(Pager *pPager){ + int bHasMoved = 0; + int rc; + + if( pPager->tempFile ) return SQLITE_OK; + if( pPager->dbSize==0 ) return SQLITE_OK; + assert( pPager->zFilename && pPager->zFilename[0] ); + rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_HAS_MOVED, &bHasMoved); + if( rc==SQLITE_NOTFOUND ){ + /* If the HAS_MOVED file-control is unimplemented, assume that the file + ** has not been moved. That is the historical behavior of SQLite: prior to + ** version 3.8.3, it never checked */ + rc = SQLITE_OK; + }else if( rc==SQLITE_OK && bHasMoved ){ + rc = SQLITE_READONLY_DBMOVED; + } + return rc; +} + /* ** Shutdown the page cache. Free all memory and close all files. @@ -52084,8 +53257,7 @@ static void pagerFreeMapHdrs(Pager *pPager){ ** to the caller. */ SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3 *db){ - u8 *pTmp = (u8 *)pPager->pTmpSpace; - + u8 *pTmp = (u8*)pPager->pTmpSpace; assert( db || pagerUseWal(pPager)==0 ); assert( assert_pager_state(pPager) ); disable_simulated_io_errors(); @@ -52094,11 +53266,17 @@ SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3 *db){ /* pPager->errCode = 0; */ pPager->exclusiveMode = 0; #ifndef SQLITE_OMIT_WAL - assert( db || pPager->pWal==0 ); - sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags, pPager->pageSize, - (db && (db->flags & SQLITE_NoCkptOnClose) ? 0 : pTmp) - ); - pPager->pWal = 0; + { + u8 *a = 0; + assert( db || pPager->pWal==0 ); + if( db && 0==(db->flags & SQLITE_NoCkptOnClose) + && SQLITE_OK==databaseIsUnmoved(pPager) + ){ + a = pTmp; + } + sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags, pPager->pageSize,a); + pPager->pWal = 0; + } #endif pager_reset(pPager); if( MEMDB ){ @@ -52555,6 +53733,7 @@ static int pagerStress(void *p, PgHdr *pPg){ return SQLITE_OK; } + pPager->aStat[PAGER_STAT_SPILL]++; pPg->pDirty = 0; if( pagerUseWal(pPager) ){ /* Write a single frame for this page to the log. */ @@ -52660,6 +53839,11 @@ SQLITE_PRIVATE int sqlite3PagerOpen( int rc = SQLITE_OK; /* Return code */ int tempFile = 0; /* True for temp files (incl. in-memory files) */ int memDb = 0; /* True if this is an in-memory file */ +#ifdef SQLITE_ENABLE_DESERIALIZE + int memJM = 0; /* Memory journal mode */ +#else +# define memJM 0 +#endif int readOnly = 0; /* True if this is a read-only file */ int journalFileSize; /* Bytes to allocate for each journal fd */ char *zPathname = 0; /* Full path to database file */ @@ -52787,7 +53971,10 @@ SQLITE_PRIVATE int sqlite3PagerOpen( int fout = 0; /* VFS flags returned by xOpen() */ rc = sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout); assert( !memDb ); - readOnly = (fout&SQLITE_OPEN_READONLY); +#ifdef SQLITE_ENABLE_DESERIALIZE + memJM = (fout&SQLITE_OPEN_MEMORY)!=0; +#endif + readOnly = (fout&SQLITE_OPEN_READONLY)!=0; /* If the file was successfully opened for read/write access, ** choose a default page size in case we have to create the @@ -52918,7 +54105,7 @@ act_like_temp_file: setSectorSize(pPager); if( !useJournal ){ pPager->journalMode = PAGER_JOURNALMODE_OFF; - }else if( memDb ){ + }else if( memDb || memJM ){ pPager->journalMode = PAGER_JOURNALMODE_MEMORY; } /* pPager->xBusyHandler = 0; */ @@ -52933,30 +54120,6 @@ act_like_temp_file: } -/* Verify that the database file has not be deleted or renamed out from -** under the pager. Return SQLITE_OK if the database is still were it ought -** to be on disk. Return non-zero (SQLITE_READONLY_DBMOVED or some other error -** code from sqlite3OsAccess()) if the database has gone missing. -*/ -static int databaseIsUnmoved(Pager *pPager){ - int bHasMoved = 0; - int rc; - - if( pPager->tempFile ) return SQLITE_OK; - if( pPager->dbSize==0 ) return SQLITE_OK; - assert( pPager->zFilename && pPager->zFilename[0] ); - rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_HAS_MOVED, &bHasMoved); - if( rc==SQLITE_NOTFOUND ){ - /* If the HAS_MOVED file-control is unimplemented, assume that the file - ** has not been moved. That is the historical behavior of SQLite: prior to - ** version 3.8.3, it never checked */ - rc = SQLITE_OK; - }else if( rc==SQLITE_OK && bHasMoved ){ - rc = SQLITE_READONLY_DBMOVED; - } - return rc; -} - /* ** This function is called after transitioning from PAGER_UNLOCK to @@ -53644,6 +54807,7 @@ SQLITE_PRIVATE void sqlite3PagerUnrefPageOne(DbPage *pPg){ assert( pPg->pgno==1 ); assert( (pPg->flags & PGHDR_MMAP)==0 ); /* Page1 is never memory mapped */ pPager = pPg->pPager; + sqlite3PagerResetLockTimeout(pPager); sqlite3PcacheRelease(pPg); pagerUnlockIfUnused(pPager); } @@ -54239,12 +55403,9 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){ */ SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager, const char *zMaster){ int rc = SQLITE_OK; - - if( isOpen(pPager->fd) ){ - void *pArg = (void*)zMaster; - rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC, pArg); - if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK; - } + void *pArg = (void*)zMaster; + rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC, pArg); + if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK; if( rc==SQLITE_OK && !pPager->noSync ){ assert( !MEMDB ); rc = sqlite3OsSync(pPager->fd, pPager->syncFlags); @@ -54465,8 +55626,9 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne( if( bBatch ){ if( rc==SQLITE_OK ){ rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_COMMIT_ATOMIC_WRITE, 0); - }else{ - sqlite3OsFileControl(fd, SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE, 0); + } + if( rc!=SQLITE_OK ){ + sqlite3OsFileControlHint(fd, SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE, 0); } } @@ -54690,8 +55852,12 @@ SQLITE_PRIVATE int *sqlite3PagerStats(Pager *pPager){ #endif /* -** Parameter eStat must be either SQLITE_DBSTATUS_CACHE_HIT or -** SQLITE_DBSTATUS_CACHE_MISS. Before returning, *pnVal is incremented by the +** Parameter eStat must be one of SQLITE_DBSTATUS_CACHE_HIT, _MISS, _WRITE, +** or _WRITE+1. The SQLITE_DBSTATUS_CACHE_WRITE+1 case is a translation +** of SQLITE_DBSTATUS_CACHE_SPILL. The _SPILL case is not contiguous because +** it was added later. +** +** Before returning, *pnVal is incremented by the ** current cache hit or miss count, according to the value of eStat. If the ** reset parameter is non-zero, the cache hit or miss count is zeroed before ** returning. @@ -54701,15 +55867,18 @@ SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, i assert( eStat==SQLITE_DBSTATUS_CACHE_HIT || eStat==SQLITE_DBSTATUS_CACHE_MISS || eStat==SQLITE_DBSTATUS_CACHE_WRITE + || eStat==SQLITE_DBSTATUS_CACHE_WRITE+1 ); assert( SQLITE_DBSTATUS_CACHE_HIT+1==SQLITE_DBSTATUS_CACHE_MISS ); assert( SQLITE_DBSTATUS_CACHE_HIT+2==SQLITE_DBSTATUS_CACHE_WRITE ); - assert( PAGER_STAT_HIT==0 && PAGER_STAT_MISS==1 && PAGER_STAT_WRITE==2 ); + assert( PAGER_STAT_HIT==0 && PAGER_STAT_MISS==1 + && PAGER_STAT_WRITE==2 && PAGER_STAT_SPILL==3 ); - *pnVal += pPager->aStat[eStat - SQLITE_DBSTATUS_CACHE_HIT]; + eStat -= SQLITE_DBSTATUS_CACHE_HIT; + *pnVal += pPager->aStat[eStat]; if( reset ){ - pPager->aStat[eStat - SQLITE_DBSTATUS_CACHE_HIT] = 0; + pPager->aStat[eStat] = 0; } } @@ -54913,6 +56082,16 @@ SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager *pPager){ return pPager->fd; } +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT +/* +** Reset the lock timeout for pager. +*/ +SQLITE_PRIVATE void sqlite3PagerResetLockTimeout(Pager *pPager){ + int x = 0; + sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_LOCK_TIMEOUT, &x); +} +#endif + /* ** Return the file handle for the journal file (if it exists). ** This will be either the rollback journal or the WAL file. @@ -55373,6 +56552,7 @@ SQLITE_PRIVATE int sqlite3PagerCheckpoint( pPager->walSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace, pnLog, pnCkpt ); + sqlite3PagerResetLockTimeout(pPager); } return rc; } @@ -56155,7 +57335,11 @@ struct WalIterator { ** page and SQLITE_OK is returned. If an error (an OOM or VFS error) occurs, ** then an SQLite error code is returned and *ppPage is set to 0. */ -static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){ +static SQLITE_NOINLINE int walIndexPageRealloc( + Wal *pWal, /* The WAL context */ + int iPage, /* The page we seek */ + volatile u32 **ppPage /* Write the page pointer here */ +){ int rc = SQLITE_OK; /* Enlarge the pWal->apWiData[] array if required */ @@ -56174,21 +57358,20 @@ static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){ } /* Request a pointer to the required page from the VFS */ - if( pWal->apWiData[iPage]==0 ){ - if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){ - pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ); - if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM_BKPT; - }else{ - rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ, - pWal->writeLock, (void volatile **)&pWal->apWiData[iPage] - ); - assert( pWal->apWiData[iPage]!=0 || rc!=SQLITE_OK || pWal->writeLock==0 ); - testcase( pWal->apWiData[iPage]==0 && rc==SQLITE_OK ); - if( (rc&0xff)==SQLITE_READONLY ){ - pWal->readOnly |= WAL_SHM_RDONLY; - if( rc==SQLITE_READONLY ){ - rc = SQLITE_OK; - } + assert( pWal->apWiData[iPage]==0 ); + if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){ + pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ); + if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM_BKPT; + }else{ + rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ, + pWal->writeLock, (void volatile **)&pWal->apWiData[iPage] + ); + assert( pWal->apWiData[iPage]!=0 || rc!=SQLITE_OK || pWal->writeLock==0 ); + testcase( pWal->apWiData[iPage]==0 && rc==SQLITE_OK ); + if( (rc&0xff)==SQLITE_READONLY ){ + pWal->readOnly |= WAL_SHM_RDONLY; + if( rc==SQLITE_READONLY ){ + rc = SQLITE_OK; } } } @@ -56197,6 +57380,16 @@ static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){ assert( iPage==0 || *ppPage || rc!=SQLITE_OK ); return rc; } +static int walIndexPage( + Wal *pWal, /* The WAL context */ + int iPage, /* The page we seek */ + volatile u32 **ppPage /* Write the page pointer here */ +){ + if( pWal->nWiData<=iPage || (*ppPage = pWal->apWiData[iPage])==0 ){ + return walIndexPageRealloc(pWal, iPage, ppPage); + } + return SQLITE_OK; +} /* ** Return a pointer to the WalCkptInfo structure in the wal-index. @@ -57173,8 +58366,9 @@ static void walIteratorFree(WalIterator *p){ /* ** Construct a WalInterator object that can be used to loop over all -** pages in the WAL in ascending order. The caller must hold the checkpoint -** lock. +** pages in the WAL following frame nBackfill in ascending order. Frames +** nBackfill or earlier may be included - excluding them is an optimization +** only. The caller must hold the checkpoint lock. ** ** On success, make *pp point to the newly allocated WalInterator object ** return SQLITE_OK. Otherwise, return an error code. If this routine @@ -57183,7 +58377,7 @@ static void walIteratorFree(WalIterator *p){ ** The calling routine should invoke walIteratorFree() to destroy the ** WalIterator object when it has finished with it. */ -static int walIteratorInit(Wal *pWal, WalIterator **pp){ +static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){ WalIterator *p; /* Return value */ int nSegment; /* Number of segments to merge */ u32 iLast; /* Last frame in log */ @@ -57220,7 +58414,7 @@ static int walIteratorInit(Wal *pWal, WalIterator **pp){ rc = SQLITE_NOMEM_BKPT; } - for(i=0; rc==SQLITE_OK && inBackfillhdr.mxFrame ){ - /* Allocate the iterator */ - rc = walIteratorInit(pWal, &pIter); - if( rc!=SQLITE_OK ){ - return rc; - } - assert( pIter ); - /* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked ** in the SQLITE_CHECKPOINT_PASSIVE mode. */ assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 ); @@ -57419,7 +58607,13 @@ static int walCheckpoint( } } - if( pInfo->nBackfillnBackfillnBackfill, &pIter); + assert( rc==SQLITE_OK || pIter==0 ); + } + + if( pIter && (rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(0),1))==SQLITE_OK ){ i64 nSize; /* Current size of database file */ @@ -58469,7 +59663,7 @@ SQLITE_PRIVATE int sqlite3WalFindFrame( ** table after the current read-transaction had started. */ iMinHash = walFramePage(pWal->minFrame); - for(iHash=walFramePage(iLast); iHash>=iMinHash && iRead==0; iHash--){ + for(iHash=walFramePage(iLast); iHash>=iMinHash; iHash--){ volatile ht_slot *aHash; /* Pointer to hash table */ volatile u32 *aPgno; /* Pointer to array of page numbers */ u32 iZero; /* Frame number corresponding to aPgno[0] */ @@ -58492,6 +59686,7 @@ SQLITE_PRIVATE int sqlite3WalFindFrame( return SQLITE_CORRUPT_BKPT; } } + if( iRead ) break; } #ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT @@ -59906,20 +61101,20 @@ struct BtCursor { u8 curFlags; /* zero or more BTCF_* flags defined below */ u8 curPagerFlags; /* Flags to send to sqlite3PagerGet() */ u8 hints; /* As configured by CursorSetHints() */ - int nOvflAlloc; /* Allocated size of aOverflow[] array */ - Btree *pBtree; /* The Btree to which this cursor belongs */ - BtShared *pBt; /* The BtShared this cursor points to */ - BtCursor *pNext; /* Forms a linked list of all cursors */ - Pgno *aOverflow; /* Cache of overflow page locations */ - CellInfo info; /* A parse of the cell we are pointing at */ - i64 nKey; /* Size of pKey, or last integer key */ - void *pKey; /* Saved key that was cursor last known position */ - Pgno pgnoRoot; /* The root page of this tree */ int skipNext; /* Prev() is noop if negative. Next() is noop if positive. ** Error code if eState==CURSOR_FAULT */ + Btree *pBtree; /* The Btree to which this cursor belongs */ + Pgno *aOverflow; /* Cache of overflow page locations */ + void *pKey; /* Saved key that was cursor last known position */ /* All fields above are zeroed when the cursor is allocated. See ** sqlite3BtreeCursorZero(). Fields that follow must be manually ** initialized. */ +#define BTCURSOR_FIRST_UNINIT pBt /* Name of first uninitialized field */ + BtShared *pBt; /* The BtShared this cursor points to */ + BtCursor *pNext; /* Forms a linked list of all cursors */ + CellInfo info; /* A parse of the cell we are pointing at */ + i64 nKey; /* Size of pKey, or last integer key */ + Pgno pgnoRoot; /* The root page of this tree */ i8 iPage; /* Index of current page in apPage */ u8 curIntKey; /* Value of apPage[0]->intKey */ u16 ix; /* Current index for apPage[iPage] */ @@ -59969,8 +61164,8 @@ struct BtCursor { ** Do nothing else with this cursor. Any attempt to use the cursor ** should return the error code stored in BtCursor.skipNext */ -#define CURSOR_INVALID 0 -#define CURSOR_VALID 1 +#define CURSOR_VALID 0 +#define CURSOR_INVALID 1 #define CURSOR_SKIPNEXT 2 #define CURSOR_REQUIRESEEK 3 #define CURSOR_FAULT 4 @@ -62634,7 +63829,8 @@ static int btreeInvokeBusyHandler(void *pArg){ BtShared *pBt = (BtShared*)pArg; assert( pBt->db ); assert( sqlite3_mutex_held(pBt->db->mutex) ); - return sqlite3InvokeBusyHandler(&pBt->db->busyHandler); + return sqlite3InvokeBusyHandler(&pBt->db->busyHandler, + sqlite3PagerFile(pBt->pPager)); } /* @@ -62812,7 +64008,7 @@ SQLITE_PRIVATE int sqlite3BtreeOpen( } pBt->openFlags = (u8)flags; pBt->db = db; - sqlite3PagerSetBusyhandler(pBt->pPager, btreeInvokeBusyHandler, pBt); + sqlite3PagerSetBusyHandler(pBt->pPager, btreeInvokeBusyHandler, pBt); p->pBt = pBt; pBt->pCursor = 0; @@ -63775,6 +64971,7 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){ } }while( (rc&0xFF)==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE && btreeInvokeBusyHandler(pBt) ); + sqlite3PagerResetLockTimeout(pBt->pPager); if( rc==SQLITE_OK ){ if( p->inTrans==TRANS_NONE ){ @@ -64748,7 +65945,7 @@ SQLITE_PRIVATE int sqlite3BtreeCursorSize(void){ ** of run-time by skipping the initialization of those elements. */ SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor *p){ - memset(p, 0, offsetof(BtCursor, iPage)); + memset(p, 0, offsetof(BtCursor, BTCURSOR_FIRST_UNINIT)); } /* @@ -64791,11 +65988,19 @@ SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){ ** Using this cache reduces the number of calls to btreeParseCell(). */ #ifndef NDEBUG + static int cellInfoEqual(CellInfo *a, CellInfo *b){ + if( a->nKey!=b->nKey ) return 0; + if( a->pPayload!=b->pPayload ) return 0; + if( a->nPayload!=b->nPayload ) return 0; + if( a->nLocal!=b->nLocal ) return 0; + if( a->nSize!=b->nSize ) return 0; + return 1; + } static void assertCellInfo(BtCursor *pCur){ CellInfo info; memset(&info, 0, sizeof(info)); btreeParseCell(pCur->pPage, pCur->ix, &info); - assert( CORRUPT_DB || memcmp(&info, &pCur->info, sizeof(info))==0 ); + assert( CORRUPT_DB || cellInfoEqual(&info, &pCur->info) ); } #else #define assertCellInfo(x) @@ -65071,14 +66276,15 @@ static int accessPayload( */ if( (pCur->curFlags & BTCF_ValidOvfl)==0 ){ int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize; - if( nOvfl>pCur->nOvflAlloc ){ + if( pCur->aOverflow==0 + || nOvfl*(int)sizeof(Pgno) > sqlite3MallocSize(pCur->aOverflow) + ){ Pgno *aNew = (Pgno*)sqlite3Realloc( pCur->aOverflow, nOvfl*2*sizeof(Pgno) ); if( aNew==0 ){ return SQLITE_NOMEM_BKPT; }else{ - pCur->nOvflAlloc = nOvfl*2; pCur->aOverflow = aNew; } } @@ -66592,9 +67798,8 @@ static void freePage(MemPage *pPage, int *pRC){ } /* -** Free any overflow pages associated with the given Cell. Write the -** local Cell size (the number of bytes on the original page, omitting -** overflow) into *pnSize. +** Free any overflow pages associated with the given Cell. Store +** size information about the cell in pInfo. */ static int clearCell( MemPage *pPage, /* The page that contains the Cell */ @@ -67798,7 +69003,7 @@ static int balance_nonroot( } /* Load b.apCell[] with pointers to all cells in pOld. If pOld - ** constains overflow cells, include them in the b.apCell[] array + ** contains overflow cells, include them in the b.apCell[] array ** in the correct spot. ** ** Note that when there are multiple overflow cells, it is always the @@ -71283,6 +72488,51 @@ SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem *p){ } #endif +#ifdef SQLITE_DEBUG +/* +** Check that string value of pMem agrees with its integer or real value. +** +** A single int or real value always converts to the same strings. But +** many different strings can be converted into the same int or real. +** If a table contains a numeric value and an index is based on the +** corresponding string value, then it is important that the string be +** derived from the numeric value, not the other way around, to ensure +** that the index and table are consistent. See ticket +** https://www.sqlite.org/src/info/343634942dd54ab (2018-01-31) for +** an example. +** +** This routine looks at pMem to verify that if it has both a numeric +** representation and a string representation then the string rep has +** been derived from the numeric and not the other way around. It returns +** true if everything is ok and false if there is a problem. +** +** This routine is for use inside of assert() statements only. +*/ +SQLITE_PRIVATE int sqlite3VdbeMemConsistentDualRep(Mem *p){ + char zBuf[100]; + char *z; + int i, j, incr; + if( (p->flags & MEM_Str)==0 ) return 1; + if( (p->flags & (MEM_Int|MEM_Real))==0 ) return 1; + if( p->flags & MEM_Int ){ + sqlite3_snprintf(sizeof(zBuf),zBuf,"%lld",p->u.i); + }else{ + sqlite3_snprintf(sizeof(zBuf),zBuf,"%!.15g",p->u.r); + } + z = p->z; + i = j = 0; + incr = 1; + if( p->enc!=SQLITE_UTF8 ){ + incr = 2; + if( p->enc==SQLITE_UTF16BE ) z++; + } + while( zBuf[j] ){ + if( zBuf[j++]!=z[i] ) return 0; + i += incr; + } + return 1; +} +#endif /* SQLITE_DEBUG */ /* ** If pMem is an object with a valid string representation, this routine @@ -71717,6 +72967,16 @@ SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem *pMem){ } } +/* +** Return 1 if pMem represents true, and return 0 if pMem represents false. +** Return the value ifNull if pMem is NULL. +*/ +SQLITE_PRIVATE int sqlite3VdbeBooleanValue(Mem *pMem, int ifNull){ + if( pMem->flags & MEM_Int ) return pMem->u.i!=0; + if( pMem->flags & MEM_Null ) return ifNull; + return sqlite3VdbeRealValue(pMem)!=0.0; +} + /* ** The MEM structure is already a MEM_Real. Try to also make it a ** MEM_Int if we can. @@ -71772,6 +73032,18 @@ SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem *pMem){ return SQLITE_OK; } +/* Compare a floating point value to an integer. Return true if the two +** values are the same within the precision of the floating point value. +** +** For some versions of GCC on 32-bit machines, if you do the more obvious +** comparison of "r1==(double)i" you sometimes get an answer of false even +** though the r1 and (double)i values are bit-for-bit the same. +*/ +static int sqlite3RealSameAsInt(double r1, sqlite3_int64 i){ + double r2 = (double)i; + return memcmp(&r1, &r2, sizeof(r1))==0; +} + /* ** Convert pMem so that it has types MEM_Real or MEM_Int or both. ** Invalidate any prior representations. @@ -71791,7 +73063,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){ }else{ i64 i = pMem->u.i; sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc); - if( rc==1 && pMem->u.r==(double)i ){ + if( rc==1 && sqlite3RealSameAsInt(pMem->u.r, i) ){ pMem->u.i = i; MemSetTypeFlag(pMem, MEM_Int); }else{ @@ -72274,6 +73546,7 @@ static SQLITE_NOINLINE const void *valueToText(sqlite3_value* pVal, u8 enc){ assert(pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) || pVal->db==0 || pVal->db->mallocFailed ); if( pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) ){ + assert( sqlite3VdbeMemConsistentDualRep(pVal) ); return pVal->z; }else{ return 0; @@ -72296,6 +73569,7 @@ SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){ assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) ); assert( (pVal->flags & MEM_RowSet)==0 ); if( (pVal->flags&(MEM_Str|MEM_Term))==(MEM_Str|MEM_Term) && pVal->enc==enc ){ + assert( sqlite3VdbeMemConsistentDualRep(pVal) ); return pVal->z; } if( pVal->flags&MEM_Null ){ @@ -78077,14 +79351,12 @@ SQLITE_API void sqlite3_result_double(sqlite3_context *pCtx, double rVal){ SQLITE_API void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); pCtx->isError = SQLITE_ERROR; - pCtx->fErrorOrAux = 1; sqlite3VdbeMemSetStr(pCtx->pOut, z, n, SQLITE_UTF8, SQLITE_TRANSIENT); } #ifndef SQLITE_OMIT_UTF16 SQLITE_API void sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); pCtx->isError = SQLITE_ERROR; - pCtx->fErrorOrAux = 1; sqlite3VdbeMemSetStr(pCtx->pOut, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT); } #endif @@ -78190,8 +79462,7 @@ SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context *pCtx, u64 n){ return SQLITE_OK; } SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){ - pCtx->isError = errCode; - pCtx->fErrorOrAux = 1; + pCtx->isError = errCode ? errCode : -1; #ifdef SQLITE_DEBUG if( pCtx->pVdbe ) pCtx->pVdbe->rcApp = errCode; #endif @@ -78205,7 +79476,6 @@ SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){ SQLITE_API void sqlite3_result_error_toobig(sqlite3_context *pCtx){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); pCtx->isError = SQLITE_TOOBIG; - pCtx->fErrorOrAux = 1; sqlite3VdbeMemSetStr(pCtx->pOut, "string or blob too big", -1, SQLITE_UTF8, SQLITE_STATIC); } @@ -78215,7 +79485,6 @@ SQLITE_API void sqlite3_result_error_nomem(sqlite3_context *pCtx){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetNull(pCtx->pOut); pCtx->isError = SQLITE_NOMEM_BKPT; - pCtx->fErrorOrAux = 1; sqlite3OomFault(pCtx->pOut->db); } @@ -78622,10 +79891,7 @@ SQLITE_API void sqlite3_set_auxdata( pAuxData->iAuxArg = iArg; pAuxData->pNextAux = pVdbe->pAuxData; pVdbe->pAuxData = pAuxData; - if( pCtx->fErrorOrAux==0 ){ - pCtx->isError = 0; - pCtx->fErrorOrAux = 1; - } + if( pCtx->isError==0 ) pCtx->isError = -1; }else if( pAuxData->xDeleteAux ){ pAuxData->xDeleteAux(pAuxData->pAux); } @@ -79381,7 +80647,9 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){ Vdbe *pVdbe = (Vdbe*)pStmt; u32 v; #ifdef SQLITE_ENABLE_API_ARMOR - if( !pStmt ){ + if( !pStmt + || (op!=SQLITE_STMTSTATUS_MEMUSED && (op<0||op>=ArraySize(pVdbe->aCounter))) + ){ (void)SQLITE_MISUSE_BKPT; return 0; } @@ -80155,6 +81423,11 @@ static void applyNumericAffinity(Mem *pRec, int bTryForInt){ pRec->flags |= MEM_Real; if( bTryForInt ) sqlite3VdbeIntegerAffinity(pRec); } + /* TEXT->NUMERIC is many->one. Hence, it is important to invalidate the + ** string representation after computing a numeric equivalent, because the + ** string representation might not be the canonical representation for the + ** numeric value. Ticket [343634942dd54ab57b7024] 2018-01-31. */ + pRec->flags &= ~MEM_Str; } /* @@ -80623,7 +81896,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec( assert( pOp>=aOp && pOp<&aOp[p->nOp]); #ifdef VDBE_PROFILE - start = sqlite3Hwtime(); + start = sqlite3NProfileCnt ? sqlite3NProfileCnt : sqlite3Hwtime(); #endif nVmStep++; #ifdef SQLITE_ENABLE_STMT_SCANSTATUS @@ -82147,18 +83420,8 @@ case OP_Or: { /* same as TK_OR, in1, in2, out3 */ int v1; /* Left operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */ int v2; /* Right operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */ - pIn1 = &aMem[pOp->p1]; - if( pIn1->flags & MEM_Null ){ - v1 = 2; - }else{ - v1 = sqlite3VdbeIntValue(pIn1)!=0; - } - pIn2 = &aMem[pOp->p2]; - if( pIn2->flags & MEM_Null ){ - v2 = 2; - }else{ - v2 = sqlite3VdbeIntValue(pIn2)!=0; - } + v1 = sqlite3VdbeBooleanValue(&aMem[pOp->p1], 2); + v2 = sqlite3VdbeBooleanValue(&aMem[pOp->p2], 2); if( pOp->opcode==OP_And ){ static const unsigned char and_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 }; v1 = and_logic[v1*3+v2]; @@ -82176,6 +83439,35 @@ case OP_Or: { /* same as TK_OR, in1, in2, out3 */ break; } +/* Opcode: IsTrue P1 P2 P3 P4 * +** Synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 +** +** This opcode implements the IS TRUE, IS FALSE, IS NOT TRUE, and +** IS NOT FALSE operators. +** +** Interpret the value in register P1 as a boolean value. Store that +** boolean (a 0 or 1) in register P2. Or if the value in register P1 is +** NULL, then the P3 is stored in register P2. Invert the answer if P4 +** is 1. +** +** The logic is summarized like this: +** +**
      +**
    • If P3==0 and P4==0 then r[P2] := r[P1] IS TRUE +**
    • If P3==1 and P4==1 then r[P2] := r[P1] IS FALSE +**
    • If P3==0 and P4==1 then r[P2] := r[P1] IS NOT TRUE +**
    • If P3==1 and P4==0 then r[P2] := r[P1] IS NOT FALSE +**
    +*/ +case OP_IsTrue: { /* in1, out2 */ + assert( pOp->p4type==P4_INT32 ); + assert( pOp->p4.i==0 || pOp->p4.i==1 ); + assert( pOp->p3==0 || pOp->p3==1 ); + sqlite3VdbeMemSetInt64(&aMem[pOp->p2], + sqlite3VdbeBooleanValue(&aMem[pOp->p1], pOp->p3) ^ pOp->p4.i); + break; +} + /* Opcode: Not P1 P2 * * * ** Synopsis: r[P2]= !r[P1] ** @@ -82186,10 +83478,10 @@ case OP_Or: { /* same as TK_OR, in1, in2, out3 */ case OP_Not: { /* same as TK_NOT, in1, out2 */ pIn1 = &aMem[pOp->p1]; pOut = &aMem[pOp->p2]; - sqlite3VdbeMemSetNull(pOut); if( (pIn1->flags & MEM_Null)==0 ){ - pOut->flags = MEM_Int; - pOut->u.i = !sqlite3VdbeIntValue(pIn1); + sqlite3VdbeMemSetInt64(pOut, !sqlite3VdbeBooleanValue(pIn1,0)); + }else{ + sqlite3VdbeMemSetNull(pOut); } break; } @@ -82256,30 +83548,25 @@ case OP_Once: { /* jump */ ** is considered true if it is numeric and non-zero. If the value ** in P1 is NULL then take the jump if and only if P3 is non-zero. */ +case OP_If: { /* jump, in1 */ + int c; + c = sqlite3VdbeBooleanValue(&aMem[pOp->p1], pOp->p3); + VdbeBranchTaken(c!=0, 2); + if( c ) goto jump_to_p2; + break; +} + /* Opcode: IfNot P1 P2 P3 * * ** ** Jump to P2 if the value in register P1 is False. The value ** is considered false if it has a numeric value of zero. If the value ** in P1 is NULL then take the jump if and only if P3 is non-zero. */ -case OP_If: /* jump, in1 */ case OP_IfNot: { /* jump, in1 */ int c; - pIn1 = &aMem[pOp->p1]; - if( pIn1->flags & MEM_Null ){ - c = pOp->p3; - }else{ -#ifdef SQLITE_OMIT_FLOATING_POINT - c = sqlite3VdbeIntValue(pIn1)!=0; -#else - c = sqlite3VdbeRealValue(pIn1)!=0.0; -#endif - if( pOp->opcode==OP_IfNot ) c = !c; - } + c = !sqlite3VdbeBooleanValue(&aMem[pOp->p1], !pOp->p3); VdbeBranchTaken(c!=0, 2); - if( c ){ - goto jump_to_p2; - } + if( c ) goto jump_to_p2; break; } @@ -82340,7 +83627,7 @@ case OP_IfNullRow: { /* jump */ ** P2 is the column number for the argument to the sqlite_offset() function. ** This opcode does not use P2 itself, but the P2 value is used by the ** code generator. The P1, P2, and P3 operands to this opcode are the -** as as for OP_Column. +** same as for OP_Column. ** ** This opcode is only available if SQLite is compiled with the ** -DSQLITE_ENABLE_OFFSET_SQL_FUNC option. @@ -84248,6 +85535,10 @@ case OP_NewRowid: { /* out2 */ pOut = out2Prerelease(p, pOp); assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; + if( !pC->isTable ){ + rc = SQLITE_CORRUPT_BKPT; + goto abort_due_to_error; + } assert( pC!=0 ); assert( pC->eCurType==CURTYPE_BTREE ); assert( pC->uc.pCursor!=0 ); @@ -86184,12 +87475,17 @@ case OP_AggStep0: { assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) ); assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem+1 - p->nCursor)+1) ); assert( pOp->p3p2 || pOp->p3>=pOp->p2+n ); - pCtx = sqlite3DbMallocRawNN(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*)); + pCtx = sqlite3DbMallocRawNN(db, n*sizeof(sqlite3_value*) + + (sizeof(pCtx[0]) + sizeof(Mem) - sizeof(sqlite3_value*))); if( pCtx==0 ) goto no_mem; pCtx->pMem = 0; + pCtx->pOut = (Mem*)&(pCtx->argv[n]); + sqlite3VdbeMemInit(pCtx->pOut, db, MEM_Null); pCtx->pFunc = pOp->p4.pFunc; pCtx->iOp = (int)(pOp - aOp); pCtx->pVdbe = p; + pCtx->skipFlag = 0; + pCtx->isError = 0; pCtx->argc = n; pOp->p4type = P4_FUNCCTX; pOp->p4.pCtx = pCtx; @@ -86200,7 +87496,6 @@ case OP_AggStep: { int i; sqlite3_context *pCtx; Mem *pMem; - Mem t; assert( pOp->p4type==P4_FUNCCTX ); pCtx = pOp->p4.pCtx; @@ -86223,26 +87518,28 @@ case OP_AggStep: { #endif pMem->n++; - sqlite3VdbeMemInit(&t, db, MEM_Null); - pCtx->pOut = &t; - pCtx->fErrorOrAux = 0; - pCtx->skipFlag = 0; + assert( pCtx->pOut->flags==MEM_Null ); + assert( pCtx->isError==0 ); + assert( pCtx->skipFlag==0 ); (pCtx->pFunc->xSFunc)(pCtx,pCtx->argc,pCtx->argv); /* IMP: R-24505-23230 */ - if( pCtx->fErrorOrAux ){ - if( pCtx->isError ){ - sqlite3VdbeError(p, "%s", sqlite3_value_text(&t)); + if( pCtx->isError ){ + if( pCtx->isError>0 ){ + sqlite3VdbeError(p, "%s", sqlite3_value_text(pCtx->pOut)); rc = pCtx->isError; } - sqlite3VdbeMemRelease(&t); + if( pCtx->skipFlag ){ + assert( pOp[-1].opcode==OP_CollSeq ); + i = pOp[-1].p1; + if( i ) sqlite3VdbeMemSetInt64(&aMem[i], 1); + pCtx->skipFlag = 0; + } + sqlite3VdbeMemRelease(pCtx->pOut); + pCtx->pOut->flags = MEM_Null; + pCtx->isError = 0; if( rc ) goto abort_due_to_error; - }else{ - assert( t.flags==MEM_Null ); - } - if( pCtx->skipFlag ){ - assert( pOp[-1].opcode==OP_CollSeq ); - i = pOp[-1].p1; - if( i ) sqlite3VdbeMemSetInt64(&aMem[i], 1); } + assert( pCtx->pOut->flags==MEM_Null ); + assert( pCtx->skipFlag==0 ); break; } @@ -86729,7 +88026,8 @@ case OP_VColumn: { } rc = pModule->xColumn(pCur->uc.pVCur, &sContext, pOp->p2); sqlite3VtabImportErrmsg(p, pVtab); - if( sContext.isError ){ + if( sContext.isError>0 ){ + sqlite3VdbeError(p, "%s", sqlite3_value_text(pDest)); rc = sContext.isError; } sqlite3VdbeChangeEncoding(pDest, encoding); @@ -86994,6 +88292,7 @@ case OP_Function0: { pCtx->pFunc = pOp->p4.pFunc; pCtx->iOp = (int)(pOp - aOp); pCtx->pVdbe = p; + pCtx->isError = 0; pCtx->argc = n; pOp->p4type = P4_FUNCCTX; pOp->p4.pCtx = pCtx; @@ -87028,16 +88327,17 @@ case OP_Function: { } #endif MemSetTypeFlag(pOut, MEM_Null); - pCtx->fErrorOrAux = 0; + assert( pCtx->isError==0 ); (*pCtx->pFunc->xSFunc)(pCtx, pCtx->argc, pCtx->argv);/* IMP: R-24505-23230 */ /* If the function returned an error, throw an exception */ - if( pCtx->fErrorOrAux ){ - if( pCtx->isError ){ + if( pCtx->isError ){ + if( pCtx->isError>0 ){ sqlite3VdbeError(p, "%s", sqlite3_value_text(pOut)); rc = pCtx->isError; } sqlite3VdbeDeleteAuxData(db, &p->pAuxData, pCtx->iOp, pOp->p1); + pCtx->isError = 0; if( rc ) goto abort_due_to_error; } @@ -87079,8 +88379,10 @@ case OP_Function: { */ case OP_Trace: case OP_Init: { /* jump */ - char *zTrace; int i; +#ifndef SQLITE_OMIT_TRACE + char *zTrace; +#endif /* If the P4 argument is not NULL, then it must be an SQL comment string. ** The "--" string is broken up to prevent false-positives with srcck1.c. @@ -87197,7 +88499,7 @@ default: { /* This is really OP_Noop and OP_Explain */ #ifdef VDBE_PROFILE { - u64 endTime = sqlite3Hwtime(); + u64 endTime = sqlite3NProfileCnt ? sqlite3NProfileCnt : sqlite3Hwtime(); if( endTime>start ) pOrigOp->cycles += endTime - start; pOrigOp->cnt++; } @@ -91584,10 +92886,16 @@ static int lookupName( ** Because no reference was made to outer contexts, the pNC->nRef ** fields are not changed in any context. */ - if( cnt==0 && zTab==0 && ExprHasProperty(pExpr,EP_DblQuoted) ){ - pExpr->op = TK_STRING; - pExpr->pTab = 0; - return WRC_Prune; + if( cnt==0 && zTab==0 ){ + assert( pExpr->op==TK_ID ); + if( ExprHasProperty(pExpr,EP_DblQuoted) ){ + pExpr->op = TK_STRING; + pExpr->pTab = 0; + return WRC_Prune; + } + if( sqlite3ExprIdToTrueFalse(pExpr) ){ + return WRC_Prune; + } } /* @@ -91936,15 +93244,30 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ notValid(pParse, pNC, "parameters", NC_IsCheck|NC_PartIdx|NC_IdxExpr); break; } + case TK_IS: + case TK_ISNOT: { + Expr *pRight; + assert( !ExprHasProperty(pExpr, EP_Reduced) ); + /* Handle special cases of "x IS TRUE", "x IS FALSE", "x IS NOT TRUE", + ** and "x IS NOT FALSE". */ + if( (pRight = pExpr->pRight)->op==TK_ID ){ + int rc = resolveExprStep(pWalker, pRight); + if( rc==WRC_Abort ) return WRC_Abort; + if( pRight->op==TK_TRUEFALSE ){ + pExpr->op2 = pExpr->op; + pExpr->op = TK_TRUTH; + return WRC_Continue; + } + } + /* Fall thru */ + } case TK_BETWEEN: case TK_EQ: case TK_NE: case TK_LT: case TK_LE: case TK_GT: - case TK_GE: - case TK_IS: - case TK_ISNOT: { + case TK_GE: { int nLeft, nRight; if( pParse->db->mallocFailed ) break; assert( pExpr->pLeft!=0 ); @@ -94419,6 +95742,34 @@ SQLITE_PRIVATE int sqlite3SelectWalkFail(Walker *pWalker, Select *NotUsed){ return WRC_Abort; } +/* +** If the input expression is an ID with the name "true" or "false" +** then convert it into an TK_TRUEFALSE term. Return non-zero if +** the conversion happened, and zero if the expression is unaltered. +*/ +SQLITE_PRIVATE int sqlite3ExprIdToTrueFalse(Expr *pExpr){ + assert( pExpr->op==TK_ID || pExpr->op==TK_STRING ); + if( sqlite3StrICmp(pExpr->u.zToken, "true")==0 + || sqlite3StrICmp(pExpr->u.zToken, "false")==0 + ){ + pExpr->op = TK_TRUEFALSE; + return 1; + } + return 0; +} + +/* +** The argument must be a TK_TRUEFALSE Expr node. Return 1 if it is TRUE +** and 0 if it is FALSE. +*/ +SQLITE_PRIVATE int sqlite3ExprTruthValue(const Expr *pExpr){ + assert( pExpr->op==TK_TRUEFALSE ); + assert( sqlite3StrICmp(pExpr->u.zToken,"true")==0 + || sqlite3StrICmp(pExpr->u.zToken,"false")==0 ); + return pExpr->u.zToken[4]==0; +} + + /* ** These routines are Walker callbacks used to check expressions to ** see if they are "constant" for some definition of constant. The @@ -94466,6 +95817,12 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){ return WRC_Abort; } case TK_ID: + /* Convert "true" or "false" in a DEFAULT clause into the + ** appropriate TK_TRUEFALSE operator */ + if( sqlite3ExprIdToTrueFalse(pExpr) ){ + return WRC_Prune; + } + /* Fall thru */ case TK_COLUMN: case TK_AGG_FUNCTION: case TK_AGG_COLUMN: @@ -96230,6 +97587,10 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) codeInteger(pParse, pExpr, 0, target); return target; } + case TK_TRUEFALSE: { + sqlite3VdbeAddOp2(v, OP_Integer, sqlite3ExprTruthValue(pExpr), target); + return target; + } #ifndef SQLITE_OMIT_FLOATING_POINT case TK_FLOAT: { assert( !ExprHasProperty(pExpr, EP_IntValue) ); @@ -96385,6 +97746,18 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) sqlite3VdbeAddOp2(v, op, r1, inReg); break; } + case TK_TRUTH: { + int isTrue; /* IS TRUE or IS NOT TRUE */ + int bNormal; /* IS TRUE or IS FALSE */ + r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + testcase( regFree1==0 ); + isTrue = sqlite3ExprTruthValue(pExpr->pRight); + bNormal = pExpr->op2==TK_IS; + testcase( isTrue && bNormal); + testcase( !isTrue && bNormal); + sqlite3VdbeAddOp4Int(v, OP_IsTrue, r1, inReg, !isTrue, isTrue ^ bNormal); + break; + } case TK_ISNULL: case TK_NOTNULL: { int addr; @@ -97160,6 +98533,23 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); break; } + case TK_TRUTH: { + int isNot; /* IS NOT TRUE or IS NOT FALSE */ + int isTrue; /* IS TRUE or IS NOT TRUE */ + testcase( jumpIfNull==0 ); + isNot = pExpr->op2==TK_ISNOT; + isTrue = sqlite3ExprTruthValue(pExpr->pRight); + testcase( isTrue && isNot ); + testcase( !isTrue && isNot ); + if( isTrue ^ isNot ){ + sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, + isNot ? SQLITE_JUMPIFNULL : 0); + }else{ + sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, + isNot ? SQLITE_JUMPIFNULL : 0); + } + break; + } case TK_IS: case TK_ISNOT: testcase( op==TK_IS ); @@ -97314,6 +98704,26 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); break; } + case TK_TRUTH: { + int isNot; /* IS NOT TRUE or IS NOT FALSE */ + int isTrue; /* IS TRUE or IS NOT TRUE */ + testcase( jumpIfNull==0 ); + isNot = pExpr->op2==TK_ISNOT; + isTrue = sqlite3ExprTruthValue(pExpr->pRight); + testcase( isTrue && isNot ); + testcase( !isTrue && isNot ); + if( isTrue ^ isNot ){ + /* IS TRUE and IS NOT FALSE */ + sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, + isNot ? 0 : SQLITE_JUMPIFNULL); + + }else{ + /* IS FALSE and IS NOT TRUE */ + sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, + isNot ? 0 : SQLITE_JUMPIFNULL); + } + break; + } case TK_IS: case TK_ISNOT: testcase( pExpr->op==TK_IS ); @@ -97601,6 +99011,105 @@ SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Parse *pParse, Expr *pE1, Expr *pE2, i return 0; } +/* +** This is the Expr node callback for sqlite3ExprImpliesNotNullRow(). +** If the expression node requires that the table at pWalker->iCur +** have a non-NULL column, then set pWalker->eCode to 1 and abort. +*/ +static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ + /* This routine is only called for WHERE clause expressions and so it + ** cannot have any TK_AGG_COLUMN entries because those are only found + ** in HAVING clauses. We can get a TK_AGG_FUNCTION in a WHERE clause, + ** but that is an illegal construct and the query will be rejected at + ** a later stage of processing, so the TK_AGG_FUNCTION case does not + ** need to be considered here. */ + assert( pExpr->op!=TK_AGG_COLUMN ); + testcase( pExpr->op==TK_AGG_FUNCTION ); + + if( ExprHasProperty(pExpr, EP_FromJoin) ) return WRC_Prune; + switch( pExpr->op ){ + case TK_ISNOT: + case TK_NOT: + case TK_ISNULL: + case TK_IS: + case TK_OR: + case TK_CASE: + case TK_IN: + case TK_FUNCTION: + testcase( pExpr->op==TK_ISNOT ); + testcase( pExpr->op==TK_NOT ); + testcase( pExpr->op==TK_ISNULL ); + testcase( pExpr->op==TK_IS ); + testcase( pExpr->op==TK_OR ); + testcase( pExpr->op==TK_CASE ); + testcase( pExpr->op==TK_IN ); + testcase( pExpr->op==TK_FUNCTION ); + return WRC_Prune; + case TK_COLUMN: + if( pWalker->u.iCur==pExpr->iTable ){ + pWalker->eCode = 1; + return WRC_Abort; + } + return WRC_Prune; + + /* Virtual tables are allowed to use constraints like x=NULL. So + ** a term of the form x=y does not prove that y is not null if x + ** is the column of a virtual table */ + case TK_EQ: + case TK_NE: + case TK_LT: + case TK_LE: + case TK_GT: + case TK_GE: + testcase( pExpr->op==TK_EQ ); + testcase( pExpr->op==TK_NE ); + testcase( pExpr->op==TK_LT ); + testcase( pExpr->op==TK_LE ); + testcase( pExpr->op==TK_GT ); + testcase( pExpr->op==TK_GE ); + if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->pTab)) + || (pExpr->pRight->op==TK_COLUMN && IsVirtual(pExpr->pRight->pTab)) + ){ + return WRC_Prune; + } + default: + return WRC_Continue; + } +} + +/* +** Return true (non-zero) if expression p can only be true if at least +** one column of table iTab is non-null. In other words, return true +** if expression p will always be NULL or false if every column of iTab +** is NULL. +** +** False negatives are acceptable. In other words, it is ok to return +** zero even if expression p will never be true of every column of iTab +** is NULL. A false negative is merely a missed optimization opportunity. +** +** False positives are not allowed, however. A false positive may result +** in an incorrect answer. +** +** Terms of p that are marked with EP_FromJoin (and hence that come from +** the ON or USING clauses of LEFT JOINS) are excluded from the analysis. +** +** This routine is used to check if a LEFT JOIN can be converted into +** an ordinary JOIN. The p argument is the WHERE clause. If the WHERE +** clause requires that some column of the right table of the LEFT JOIN +** be non-NULL, then the LEFT JOIN can be safely converted into an +** ordinary join. +*/ +SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr *p, int iTab){ + Walker w; + w.xExprCallback = impliesNotNullRow; + w.xSelectCallback = 0; + w.xSelectCallback2 = 0; + w.eCode = 0; + w.u.iCur = iTab; + sqlite3WalkExpr(&w, p); + return w.eCode; +} + /* ** An instance of the following structure is used by the tree walker ** to determine if an expression can be evaluated by reference to the @@ -99845,7 +101354,7 @@ static void analyzeOneTable( /* Do not gather statistics on views or virtual tables */ return; } - if( sqlite3_strlike("sqlite_%", pTab->zName, 0)==0 ){ + if( sqlite3_strlike("sqlite\\_%", pTab->zName, '\\')==0 ){ /* Do not gather statistics on system tables */ return; } @@ -100824,6 +102333,10 @@ static int resolveAttachExpr(NameContext *pName, Expr *pExpr) ** ** If the optional "KEY z" syntax is omitted, an SQL NULL is passed as the ** third argument. +** +** If the db->init.reopenMemdb flags is set, then instead of attaching a +** new database, close the database on db->init.iDb and reopen it as an +** empty MemDB. */ static void attachFunc( sqlite3_context *context, @@ -100844,65 +102357,85 @@ static void attachFunc( sqlite3_vfs *pVfs; UNUSED_PARAMETER(NotUsed); - zFile = (const char *)sqlite3_value_text(argv[0]); zName = (const char *)sqlite3_value_text(argv[1]); if( zFile==0 ) zFile = ""; if( zName==0 ) zName = ""; - /* Check for the following errors: - ** - ** * Too many attached databases, - ** * Transaction currently open - ** * Specified database name already being used. - */ - if( db->nDb>=db->aLimit[SQLITE_LIMIT_ATTACHED]+2 ){ - zErrDyn = sqlite3MPrintf(db, "too many attached databases - max %d", - db->aLimit[SQLITE_LIMIT_ATTACHED] - ); - goto attach_error; - } - for(i=0; inDb; i++){ - char *z = db->aDb[i].zDbSName; - assert( z && zName ); - if( sqlite3StrICmp(z, zName)==0 ){ - zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName); +#ifdef SQLITE_ENABLE_DESERIALIZE +# define REOPEN_AS_MEMDB(db) (db->init.reopenMemdb) +#else +# define REOPEN_AS_MEMDB(db) (0) +#endif + + if( REOPEN_AS_MEMDB(db) ){ + /* This is not a real ATTACH. Instead, this routine is being called + ** from sqlite3_deserialize() to close database db->init.iDb and + ** reopen it as a MemDB */ + pVfs = sqlite3_vfs_find("memdb"); + if( pVfs==0 ) return; + pNew = &db->aDb[db->init.iDb]; + if( pNew->pBt ) sqlite3BtreeClose(pNew->pBt); + pNew->pBt = 0; + pNew->pSchema = 0; + rc = sqlite3BtreeOpen(pVfs, "x", db, &pNew->pBt, 0, SQLITE_OPEN_MAIN_DB); + }else{ + /* This is a real ATTACH + ** + ** Check for the following errors: + ** + ** * Too many attached databases, + ** * Transaction currently open + ** * Specified database name already being used. + */ + if( db->nDb>=db->aLimit[SQLITE_LIMIT_ATTACHED]+2 ){ + zErrDyn = sqlite3MPrintf(db, "too many attached databases - max %d", + db->aLimit[SQLITE_LIMIT_ATTACHED] + ); goto attach_error; } + for(i=0; inDb; i++){ + char *z = db->aDb[i].zDbSName; + assert( z && zName ); + if( sqlite3StrICmp(z, zName)==0 ){ + zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName); + goto attach_error; + } + } + + /* Allocate the new entry in the db->aDb[] array and initialize the schema + ** hash tables. + */ + if( db->aDb==db->aDbStatic ){ + aNew = sqlite3DbMallocRawNN(db, sizeof(db->aDb[0])*3 ); + if( aNew==0 ) return; + memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2); + }else{ + aNew = sqlite3DbRealloc(db, db->aDb, sizeof(db->aDb[0])*(db->nDb+1) ); + if( aNew==0 ) return; + } + db->aDb = aNew; + pNew = &db->aDb[db->nDb]; + memset(pNew, 0, sizeof(*pNew)); + + /* Open the database file. If the btree is successfully opened, use + ** it to obtain the database schema. At this point the schema may + ** or may not be initialized. + */ + flags = db->openFlags; + rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr); + if( rc!=SQLITE_OK ){ + if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); + sqlite3_result_error(context, zErr, -1); + sqlite3_free(zErr); + return; + } + assert( pVfs ); + flags |= SQLITE_OPEN_MAIN_DB; + rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags); + sqlite3_free( zPath ); + db->nDb++; } - - /* Allocate the new entry in the db->aDb[] array and initialize the schema - ** hash tables. - */ - if( db->aDb==db->aDbStatic ){ - aNew = sqlite3DbMallocRawNN(db, sizeof(db->aDb[0])*3 ); - if( aNew==0 ) return; - memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2); - }else{ - aNew = sqlite3DbRealloc(db, db->aDb, sizeof(db->aDb[0])*(db->nDb+1) ); - if( aNew==0 ) return; - } - db->aDb = aNew; - pNew = &db->aDb[db->nDb]; - memset(pNew, 0, sizeof(*pNew)); - - /* Open the database file. If the btree is successfully opened, use - ** it to obtain the database schema. At this point the schema may - ** or may not be initialized. - */ - flags = db->openFlags; - rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr); - if( rc!=SQLITE_OK ){ - if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); - sqlite3_result_error(context, zErr, -1); - sqlite3_free(zErr); - return; - } - assert( pVfs ); - flags |= SQLITE_OPEN_MAIN_DB; - rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags); - sqlite3_free( zPath ); - db->nDb++; db->skipBtreeMutex = 0; if( rc==SQLITE_CONSTRAINT ){ rc = SQLITE_ERROR; @@ -100929,7 +102462,7 @@ static void attachFunc( sqlite3BtreeLeave(pNew->pBt); } pNew->safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1; - pNew->zDbSName = sqlite3DbStrDup(db, zName); + if( !REOPEN_AS_MEMDB(db) ) pNew->zDbSName = sqlite3DbStrDup(db, zName); if( rc==SQLITE_OK && pNew->zDbSName==0 ){ rc = SQLITE_NOMEM_BKPT; } @@ -100969,13 +102502,15 @@ static void attachFunc( /* If the file was opened successfully, read the schema for the new database. ** If this fails, or if opening the file failed, then close the file and - ** remove the entry from the db->aDb[] array. i.e. put everything back the way - ** we found it. + ** remove the entry from the db->aDb[] array. i.e. put everything back the + ** way we found it. */ if( rc==SQLITE_OK ){ sqlite3BtreeEnterAll(db); + db->init.iDb = 0; rc = sqlite3Init(db, &zErrDyn); sqlite3BtreeLeaveAll(db); + assert( zErrDyn==0 || rc!=SQLITE_OK ); } #ifdef SQLITE_USER_AUTHENTICATION if( rc==SQLITE_OK ){ @@ -100987,21 +102522,23 @@ static void attachFunc( } #endif if( rc ){ - int iDb = db->nDb - 1; - assert( iDb>=2 ); - if( db->aDb[iDb].pBt ){ - sqlite3BtreeClose(db->aDb[iDb].pBt); - db->aDb[iDb].pBt = 0; - db->aDb[iDb].pSchema = 0; - } - sqlite3ResetAllSchemasOfConnection(db); - db->nDb = iDb; - if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ - sqlite3OomFault(db); - sqlite3DbFree(db, zErrDyn); - zErrDyn = sqlite3MPrintf(db, "out of memory"); - }else if( zErrDyn==0 ){ - zErrDyn = sqlite3MPrintf(db, "unable to open database: %s", zFile); + if( !REOPEN_AS_MEMDB(db) ){ + int iDb = db->nDb - 1; + assert( iDb>=2 ); + if( db->aDb[iDb].pBt ){ + sqlite3BtreeClose(db->aDb[iDb].pBt); + db->aDb[iDb].pBt = 0; + db->aDb[iDb].pSchema = 0; + } + sqlite3ResetAllSchemasOfConnection(db); + db->nDb = iDb; + if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ + sqlite3OomFault(db); + sqlite3DbFree(db, zErrDyn); + zErrDyn = sqlite3MPrintf(db, "out of memory"); + }else if( zErrDyn==0 ){ + zErrDyn = sqlite3MPrintf(db, "unable to open database: %s", zFile); + } } goto attach_error; } @@ -101273,6 +102810,14 @@ SQLITE_PRIVATE int sqlite3FixSelect( if( sqlite3FixExpr(pFix, pSelect->pLimit) ){ return 1; } + if( pSelect->pWith ){ + int i; + for(i=0; ipWith->nCte; i++){ + if( sqlite3FixSelect(pFix, pSelect->pWith->a[i].pSelect) ){ + return 1; + } + } + } pSelect = pSelect->pPrior; } return 0; @@ -102736,10 +104281,24 @@ SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){ */ SQLITE_PRIVATE void sqlite3AddNotNull(Parse *pParse, int onError){ Table *p; + Column *pCol; p = pParse->pNewTable; if( p==0 || NEVER(p->nCol<1) ) return; - p->aCol[p->nCol-1].notNull = (u8)onError; + pCol = &p->aCol[p->nCol-1]; + pCol->notNull = (u8)onError; p->tabFlags |= TF_HasNotNull; + + /* Set the uniqNotNull flag on any UNIQUE or PK indexes already created + ** on this column. */ + if( pCol->colFlags & COLFLAG_UNIQUE ){ + Index *pIdx; + for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){ + assert( pIdx->nKeyCol==1 && pIdx->onError!=OE_None ); + if( pIdx->aiColumn[0]==p->nCol-1 ){ + pIdx->uniqNotNull = 1; + } + } + } } /* @@ -102856,7 +104415,7 @@ SQLITE_PRIVATE void sqlite3AddDefaultValue( pCol->zName); }else{ /* A copy of pExpr is used instead of the original, as pExpr contains - ** tokens that point to volatile memory. + ** tokens that point to volatile memory. */ Expr x; sqlite3ExprDelete(db, pCol->pDflt); @@ -103100,7 +104659,7 @@ SQLITE_PRIVATE void sqlite3ChangeCookie(Parse *pParse, int iDb){ Vdbe *v = pParse->pVdbe; assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_SCHEMA_VERSION, - db->aDb[iDb].pSchema->schema_cookie+1); + (int)(1+(unsigned)db->aDb[iDb].pSchema->schema_cookie)); } /* @@ -103474,8 +105033,6 @@ SQLITE_PRIVATE void sqlite3EndTable( p = pParse->pNewTable; if( p==0 ) return; - assert( !db->init.busy || !pSelect ); - /* If the db->init.busy is 1 it means we are reading the SQL off the ** "sqlite_master" or "sqlite_temp_master" table on the disk. ** So do not write to the disk again. Extract the root page number @@ -103486,6 +105043,10 @@ SQLITE_PRIVATE void sqlite3EndTable( ** table itself. So mark it read-only. */ if( db->init.busy ){ + if( pSelect ){ + sqlite3ErrorMsg(pParse, ""); + return; + } p->tnum = db->init.newTnum; if( p->tnum==1 ) p->tabFlags |= TF_Readonly; } @@ -103776,7 +105337,7 @@ SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ int nErr = 0; /* Number of errors encountered */ int n; /* Temporarily holds the number of cursors assigned */ sqlite3 *db = pParse->db; /* Database connection for malloc errors */ -#ifndef SQLITE_OMIT_VIRTUALTABLE +#ifndef SQLITE_OMIT_VIRTUALTABLE int rc; #endif #ifndef SQLITE_OMIT_AUTHORIZATION @@ -104703,7 +106264,9 @@ SQLITE_PRIVATE void sqlite3CreateIndex( */ if( pList==0 ){ Token prevCol; - sqlite3TokenInit(&prevCol, pTab->aCol[pTab->nCol-1].zName); + Column *pCol = &pTab->aCol[pTab->nCol-1]; + pCol->colFlags |= COLFLAG_UNIQUE; + sqlite3TokenInit(&prevCol, pCol->zName); pList = sqlite3ExprListAppend(pParse, 0, sqlite3ExprAlloc(db, TK_ID, &prevCol, 0)); if( pList==0 ) goto exit_create_index; @@ -107548,6 +109111,8 @@ static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){ ** iteration of the aggregate loop. */ static void sqlite3SkipAccumulatorLoad(sqlite3_context *context){ + assert( context->isError<=0 ); + context->isError = -1; context->skipFlag = 1; } @@ -107614,8 +109179,6 @@ static void lengthFunc( int argc, sqlite3_value **argv ){ - int len; - assert( argc==1 ); UNUSED_PARAMETER(argc); switch( sqlite3_value_type(argv[0]) ){ @@ -107627,13 +109190,17 @@ static void lengthFunc( } case SQLITE_TEXT: { const unsigned char *z = sqlite3_value_text(argv[0]); + const unsigned char *z0; + unsigned char c; if( z==0 ) return; - len = 0; - while( *z ){ - len++; - SQLITE_SKIP_UTF8(z); + z0 = z; + while( (c = *z)!=0 ){ + z++; + if( c>=0xc0 ){ + while( (*z & 0xc0)==0x80 ){ z++; z0++; } + } } - sqlite3_result_int(context, len); + sqlite3_result_int(context, (int)(z-z0)); break; } default: { @@ -108708,6 +110275,8 @@ static void replaceFunc( i64 nOut; /* Maximum size of zOut */ int loopLimit; /* Last zStr[] that might match zPattern[] */ int i, j; /* Loop counters */ + unsigned cntExpand; /* Number zOut expansions */ + sqlite3 *db = sqlite3_context_db_handle(context); assert( argc==3 ); UNUSED_PARAMETER(argc); @@ -108739,33 +110308,40 @@ static void replaceFunc( return; } loopLimit = nStr - nPattern; + cntExpand = 0; for(i=j=0; i<=loopLimit; i++){ if( zStr[i]!=zPattern[0] || memcmp(&zStr[i], zPattern, nPattern) ){ zOut[j++] = zStr[i]; }else{ - u8 *zOld; - sqlite3 *db = sqlite3_context_db_handle(context); - nOut += nRep - nPattern; - testcase( nOut-1==db->aLimit[SQLITE_LIMIT_LENGTH] ); - testcase( nOut-2==db->aLimit[SQLITE_LIMIT_LENGTH] ); - if( nOut-1>db->aLimit[SQLITE_LIMIT_LENGTH] ){ - sqlite3_result_error_toobig(context); - sqlite3_free(zOut); - return; - } - zOld = zOut; - zOut = sqlite3_realloc64(zOut, (int)nOut); - if( zOut==0 ){ - sqlite3_result_error_nomem(context); - sqlite3_free(zOld); - return; + if( nRep>nPattern ){ + nOut += nRep - nPattern; + testcase( nOut-1==db->aLimit[SQLITE_LIMIT_LENGTH] ); + testcase( nOut-2==db->aLimit[SQLITE_LIMIT_LENGTH] ); + if( nOut-1>db->aLimit[SQLITE_LIMIT_LENGTH] ){ + sqlite3_result_error_toobig(context); + sqlite3_free(zOut); + return; + } + cntExpand++; + if( (cntExpand&(cntExpand-1))==0 ){ + /* Grow the size of the output buffer only on substitutions + ** whose index is a power of two: 1, 2, 4, 8, 16, 32, ... */ + u8 *zOld; + zOld = zOut; + zOut = sqlite3_realloc64(zOut, (int)nOut + (nOut - nStr - 1)); + if( zOut==0 ){ + sqlite3_result_error_nomem(context); + sqlite3_free(zOld); + return; + } + } } memcpy(&zOut[j], zRep, nRep); j += nRep; i += nPattern-1; } } - assert( j+nStr-i+1==nOut ); + assert( j+nStr-i+1<=nOut ); memcpy(&zOut[j], &zStr[i], nStr-i); j += nStr - i; assert( j<=nOut ); @@ -111047,11 +112623,12 @@ static int readsTable(Parse *p, int iDb, Table *pTab){ ** first use of table pTab. On 2nd and subsequent uses, the original ** AutoincInfo structure is used. ** -** Three memory locations are allocated: +** Four consecutive registers are allocated: ** -** (1) Register to hold the name of the pTab table. -** (2) Register to hold the maximum ROWID of pTab. -** (3) Register to hold the rowid in sqlite_sequence of pTab +** (1) The name of the pTab table. +** (2) The maximum ROWID of pTab. +** (3) The rowid in sqlite_sequence of pTab +** (4) The original value of the max ROWID in pTab, or NULL if none ** ** The 2nd register is the one that is returned. That is all the ** insert routine needs to know about. @@ -111079,7 +112656,7 @@ static int autoIncBegin( pInfo->iDb = iDb; pToplevel->nMem++; /* Register to hold name of table */ pInfo->regCtr = ++pToplevel->nMem; /* Max rowid register */ - pToplevel->nMem++; /* Rowid in sqlite_sequence */ + pToplevel->nMem +=2; /* Rowid in sqlite_sequence + orig max val */ } memId = pInfo->regCtr; } @@ -111107,15 +112684,17 @@ SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse){ static const int iLn = VDBE_OFFSET_LINENO(2); static const VdbeOpList autoInc[] = { /* 0 */ {OP_Null, 0, 0, 0}, - /* 1 */ {OP_Rewind, 0, 9, 0}, + /* 1 */ {OP_Rewind, 0, 10, 0}, /* 2 */ {OP_Column, 0, 0, 0}, - /* 3 */ {OP_Ne, 0, 7, 0}, + /* 3 */ {OP_Ne, 0, 9, 0}, /* 4 */ {OP_Rowid, 0, 0, 0}, /* 5 */ {OP_Column, 0, 1, 0}, - /* 6 */ {OP_Goto, 0, 9, 0}, - /* 7 */ {OP_Next, 0, 2, 0}, - /* 8 */ {OP_Integer, 0, 0, 0}, - /* 9 */ {OP_Close, 0, 0, 0} + /* 6 */ {OP_AddImm, 0, 0, 0}, + /* 7 */ {OP_Copy, 0, 0, 0}, + /* 8 */ {OP_Goto, 0, 11, 0}, + /* 9 */ {OP_Next, 0, 2, 0}, + /* 10 */ {OP_Integer, 0, 0, 0}, + /* 11 */ {OP_Close, 0, 0, 0} }; VdbeOp *aOp; pDb = &db->aDb[p->iDb]; @@ -111126,14 +112705,17 @@ SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse){ aOp = sqlite3VdbeAddOpList(v, ArraySize(autoInc), autoInc, iLn); if( aOp==0 ) break; aOp[0].p2 = memId; - aOp[0].p3 = memId+1; + aOp[0].p3 = memId+2; aOp[2].p3 = memId; aOp[3].p1 = memId-1; aOp[3].p3 = memId; aOp[3].p5 = SQLITE_JUMPIFNULL; aOp[4].p2 = memId+1; aOp[5].p3 = memId; - aOp[8].p2 = memId; + aOp[6].p1 = memId; + aOp[7].p2 = memId+2; + aOp[7].p1 = memId; + aOp[10].p2 = memId; } } @@ -111180,6 +112762,8 @@ static SQLITE_NOINLINE void autoIncrementEnd(Parse *pParse){ iRec = sqlite3GetTempReg(pParse); assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) ); + sqlite3VdbeAddOp3(v, OP_Le, memId+2, sqlite3VdbeCurrentAddr(v)+7, memId); + VdbeCoverage(v); sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenWrite); aOp = sqlite3VdbeAddOpList(v, ArraySize(autoIncEnd), autoIncEnd, iLn); if( aOp==0 ) break; @@ -113828,8 +115412,8 @@ typedef int (*sqlite3_loadext_entry)( #define sqlite3_value_pointer sqlite3_api->value_pointer /* Version 3.22.0 and later */ #define sqlite3_vtab_nochange sqlite3_api->vtab_nochange -#define sqlite3_value_nochange sqltie3_api->value_nochange -#define sqlite3_vtab_collation sqltie3_api->vtab_collation +#define sqlite3_value_nochange sqlite3_api->value_nochange +#define sqlite3_vtab_collation sqlite3_api->vtab_collation #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) @@ -117813,7 +119397,7 @@ static void corruptSchema( char *z; if( zObj==0 ) zObj = "?"; z = sqlite3MPrintf(db, "malformed database schema (%s)", zObj); - if( zExtra ) z = sqlite3MPrintf(db, "%z - %s", z, zExtra); + if( zExtra && zExtra[0] ) z = sqlite3MPrintf(db, "%z - %s", z, zExtra); sqlite3DbFree(db, *pData->pzErrMsg); *pData->pzErrMsg = z; } @@ -118707,8 +120291,7 @@ SQLITE_API int sqlite3_prepare16_v3( /***/ int sqlite3SelectTrace = 0; # define SELECTTRACE(K,P,S,X) \ if(sqlite3SelectTrace&(K)) \ - sqlite3DebugPrintf("%*s%s.%p: ",(P)->nSelectIndent*2-2,"",\ - (S)->zSelName,(S)),\ + sqlite3DebugPrintf("%s/%p: ",(S)->zSelName,(S)),\ sqlite3DebugPrintf X #else # define SELECTTRACE(K,P,S,X) @@ -119069,6 +120652,29 @@ static void setJoinExpr(Expr *p, int iTable){ } } +/* Undo the work of setJoinExpr(). In the expression tree p, convert every +** term that is marked with EP_FromJoin and iRightJoinTable==iTable into +** an ordinary term that omits the EP_FromJoin mark. +** +** This happens when a LEFT JOIN is simplified into an ordinary JOIN. +*/ +static void unsetJoinExpr(Expr *p, int iTable){ + while( p ){ + if( ExprHasProperty(p, EP_FromJoin) + && (iTable<0 || p->iRightJoinTable==iTable) ){ + ExprClearProperty(p, EP_FromJoin); + } + if( p->op==TK_FUNCTION && p->x.pList ){ + int i; + for(i=0; ix.pList->nExpr; i++){ + unsetJoinExpr(p->x.pList->a[i].pExpr, iTable); + } + } + unsetJoinExpr(p->pLeft, iTable); + p = p->pRight; + } +} + /* ** This routine processes the join information for a SELECT statement. ** ON and USING clauses are converted into extra terms of the WHERE clause. @@ -119952,12 +121558,15 @@ static void generateSortTail( iSortTab = iTab; bSeq = 1; } - for(i=0, iCol=nKey+bSeq; i=0; i--){ int iRead; if( aOutEx[i].u.x.iOrderByCol ){ iRead = aOutEx[i].u.x.iOrderByCol-1; }else{ - iRead = iCol++; + iRead = iCol--; } sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iRead, regRow+i); VdbeComment((v, "%s", aOutEx[i].zName ? aOutEx[i].zName : aOutEx[i].zSpan)); @@ -122434,7 +124043,6 @@ static int flattenSubquery( pOrderBy->a[i].u.x.iOrderByCol = 0; } assert( pParent->pOrderBy==0 ); - assert( pSub->pPrior==0 ); pParent->pOrderBy = pOrderBy; pSub->pOrderBy = 0; } @@ -122518,12 +124126,22 @@ static int flattenSubquery( ** (3) The inner query has a LIMIT clause (since the changes to the WHERE ** close would change the meaning of the LIMIT). ** -** (4) The inner query is the right operand of a LEFT JOIN. (The caller -** enforces this restriction since this routine does not have enough -** information to know.) +** (4) The inner query is the right operand of a LEFT JOIN and the +** expression to be pushed down does not come from the ON clause +** on that LEFT JOIN. ** ** (5) The WHERE clause expression originates in the ON or USING clause -** of a LEFT JOIN. +** of a LEFT JOIN where iCursor is not the right-hand table of that +** left join. An example: +** +** SELECT * +** FROM (SELECT 1 AS a1 UNION ALL SELECT 2) AS aa +** JOIN (SELECT 1 AS b2 UNION ALL SELECT 2) AS bb ON (a1=b2) +** LEFT JOIN (SELECT 8 AS c3 UNION ALL SELECT 9) AS cc ON (b2=2); +** +** The correct answer is three rows: (1,1,NULL),(2,2,8),(2,2,9). +** But if the (b2=2) term were to be pushed down into the bb subquery, +** then the (1,1,NULL) row would be suppressed. ** ** Return 0 if no changes are made and non-zero if one or more WHERE clause ** terms are duplicated into the subquery. @@ -122532,7 +124150,8 @@ static int pushDownWhereTerms( Parse *pParse, /* Parse context (for malloc() and error reporting) */ Select *pSubq, /* The subquery whose WHERE clause is to be augmented */ Expr *pWhere, /* The WHERE clause of the outer query */ - int iCursor /* Cursor number of the subquery */ + int iCursor, /* Cursor number of the subquery */ + int isLeftJoin /* True if pSubq is the right term of a LEFT JOIN */ ){ Expr *pNew; int nChng = 0; @@ -122556,15 +124175,25 @@ static int pushDownWhereTerms( return 0; /* restriction (3) */ } while( pWhere->op==TK_AND ){ - nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, iCursor); + nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, + iCursor, isLeftJoin); pWhere = pWhere->pLeft; } - if( ExprHasProperty(pWhere,EP_FromJoin) ) return 0; /* restriction (5) */ + if( isLeftJoin + && (ExprHasProperty(pWhere,EP_FromJoin)==0 + || pWhere->iRightJoinTable!=iCursor) + ){ + return 0; /* restriction (4) */ + } + if( ExprHasProperty(pWhere,EP_FromJoin) && pWhere->iRightJoinTable!=iCursor ){ + return 0; /* restriction (5) */ + } if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){ nChng++; while( pSubq ){ SubstContext x; pNew = sqlite3ExprDup(pParse->db, pWhere, 0); + unsetJoinExpr(pNew, -1); x.pParse = pParse; x.iTable = iCursor; x.iNewTable = iCursor; @@ -123019,9 +124648,7 @@ static int selectExpander(Walker *pWalker, Select *p){ } pTabList = p->pSrc; pEList = p->pEList; - if( OK_IF_ALWAYS_TRUE(p->pWith) ){ - sqlite3WithPush(pParse, p->pWith, 0); - } + sqlite3WithPush(pParse, p->pWith, 0); /* Make sure cursor numbers have been assigned to all entries in ** the FROM clause of the SELECT statement. @@ -123596,14 +125223,6 @@ static void explainSimpleCount( # define explainSimpleCount(a,b,c) #endif -/* -** Context object for havingToWhereExprCb(). -*/ -struct HavingToWhereCtx { - Expr **ppWhere; - ExprList *pGroupBy; -}; - /* ** sqlite3WalkExpr() callback used by havingToWhere(). ** @@ -123617,15 +125236,16 @@ struct HavingToWhereCtx { */ static int havingToWhereExprCb(Walker *pWalker, Expr *pExpr){ if( pExpr->op!=TK_AND ){ - struct HavingToWhereCtx *p = pWalker->u.pHavingCtx; - if( sqlite3ExprIsConstantOrGroupBy(pWalker->pParse, pExpr, p->pGroupBy) ){ + Select *pS = pWalker->u.pSelect; + if( sqlite3ExprIsConstantOrGroupBy(pWalker->pParse, pExpr, pS->pGroupBy) ){ sqlite3 *db = pWalker->pParse->db; Expr *pNew = sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[1], 0); if( pNew ){ - Expr *pWhere = *(p->ppWhere); + Expr *pWhere = pS->pWhere; SWAP(Expr, *pNew, *pExpr); pNew = sqlite3ExprAnd(db, pWhere, pNew); - *(p->ppWhere) = pNew; + pS->pWhere = pNew; + pWalker->eCode = 1; } } return WRC_Prune; @@ -123648,23 +125268,19 @@ static int havingToWhereExprCb(Walker *pWalker, Expr *pExpr){ ** entirely of constants and expressions that are also GROUP BY terms that ** use the "BINARY" collation sequence. */ -static void havingToWhere( - Parse *pParse, - ExprList *pGroupBy, - Expr *pHaving, - Expr **ppWhere -){ - struct HavingToWhereCtx sCtx; +static void havingToWhere(Parse *pParse, Select *p){ Walker sWalker; - - sCtx.ppWhere = ppWhere; - sCtx.pGroupBy = pGroupBy; - memset(&sWalker, 0, sizeof(sWalker)); sWalker.pParse = pParse; sWalker.xExprCallback = havingToWhereExprCb; - sWalker.u.pHavingCtx = &sCtx; - sqlite3WalkExpr(&sWalker, pHaving); + sWalker.u.pSelect = p; + sqlite3WalkExpr(&sWalker, p->pHaving); +#if SELECTTRACE_ENABLED + if( sWalker.eCode && (sqlite3SelectTrace & 0x100)!=0 ){ + SELECTTRACE(0x100,pParse,p,("Move HAVING terms into WHERE:\n")); + sqlite3TreeViewSelect(0, p, 0); + } +#endif } /* @@ -123825,7 +125441,6 @@ SQLITE_PRIVATE int sqlite3Select( if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1; memset(&sAggInfo, 0, sizeof(sAggInfo)); #if SELECTTRACE_ENABLED - pParse->nSelectIndent++; SELECTTRACE(1,pParse,p, ("begin processing:\n")); if( sqlite3SelectTrace & 0x100 ){ sqlite3TreeViewSelect(0, p, 0); @@ -123871,13 +125486,29 @@ SQLITE_PRIVATE int sqlite3Select( generateColumnNames(pParse, p); } - /* Try to flatten subqueries in the FROM clause up into the main query + /* Try to various optimizations (flattening subqueries, and strength + ** reduction of join operators) in the FROM clause up into the main query */ #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) for(i=0; !p->pPrior && inSrc; i++){ struct SrcList_item *pItem = &pTabList->a[i]; Select *pSub = pItem->pSelect; Table *pTab = pItem->pTab; + + /* Convert LEFT JOIN into JOIN if there are terms of the right table + ** of the LEFT JOIN used in the WHERE clause. + */ + if( (pItem->fg.jointype & JT_LEFT)!=0 + && sqlite3ExprImpliesNonNullRow(p->pWhere, pItem->iCursor) + && OptimizationEnabled(db, SQLITE_SimplifyJoin) + ){ + SELECTTRACE(0x100,pParse,p, + ("LEFT-JOIN simplifies to JOIN on term %d\n",i)); + pItem->fg.jointype &= ~(JT_LEFT|JT_OUTER); + unsetJoinExpr(p->pWhere, pItem->iCursor); + } + + /* No futher action if this term of the FROM clause is no a subquery */ if( pSub==0 ) continue; /* Catch mismatch in the declared columns of a view and the number of @@ -123946,7 +125577,6 @@ SQLITE_PRIVATE int sqlite3Select( explainSetInteger(pParse->iSelectId, iRestoreSelectId); #if SELECTTRACE_ENABLED SELECTTRACE(1,pParse,p,("end compound-select processing\n")); - pParse->nSelectIndent--; #endif return rc; } @@ -124019,8 +125649,9 @@ SQLITE_PRIVATE int sqlite3Select( /* Make copies of constant WHERE-clause terms in the outer query down ** inside the subquery. This can help the subquery to run more efficiently. */ - if( (pItem->fg.jointype & JT_OUTER)==0 - && pushDownWhereTerms(pParse, pSub, p->pWhere, pItem->iCursor) + if( OptimizationEnabled(db, SQLITE_PushDown) + && pushDownWhereTerms(pParse, pSub, p->pWhere, pItem->iCursor, + (pItem->fg.jointype & JT_OUTER)!=0) ){ #if SELECTTRACE_ENABLED if( sqlite3SelectTrace & 0x100 ){ @@ -124028,6 +125659,8 @@ SQLITE_PRIVATE int sqlite3Select( sqlite3TreeViewSelect(0, p, 0); } #endif + }else{ + SELECTTRACE(0x100,pParse,p,("Push-down not possible\n")); } zSavedAuthContext = pParse->zAuthContext; @@ -124230,6 +125863,7 @@ SQLITE_PRIVATE int sqlite3Select( wctrlFlags |= p->selFlags & SF_FixedLimit; /* Begin the database scan. */ + SELECTTRACE(1,pParse,p,("WhereBegin\n")); pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, sSort.pOrderBy, p->pEList, wctrlFlags, p->nSelectRow); if( pWInfo==0 ) goto select_end; @@ -124331,7 +125965,9 @@ SQLITE_PRIVATE int sqlite3Select( if( pHaving ){ if( pGroupBy ){ assert( pWhere==p->pWhere ); - havingToWhere(pParse, pGroupBy, pHaving, &p->pWhere); + assert( pHaving==p->pHaving ); + assert( pGroupBy==p->pGroupBy ); + havingToWhere(pParse, p); pWhere = p->pWhere; } sqlite3ExprAnalyzeAggregates(&sNC, pHaving); @@ -124418,6 +126054,7 @@ SQLITE_PRIVATE int sqlite3Select( ** in the right order to begin with. */ sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset); + SELECTTRACE(1,pParse,p,("WhereBegin\n")); pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0, WHERE_GROUPBY | (orderByGrp ? WHERE_SORTBYGROUP : 0), 0 ); @@ -124673,6 +126310,7 @@ SQLITE_PRIVATE int sqlite3Select( assert( minMaxFlag==WHERE_ORDERBY_NORMAL || pMinMaxOrderBy!=0 ); assert( pMinMaxOrderBy==0 || pMinMaxOrderBy->nExpr==1 ); + SELECTTRACE(1,pParse,p,("WhereBegin\n")); pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMaxOrderBy, 0, minMaxFlag, 0); if( pWInfo==0 ){ @@ -124728,7 +126366,6 @@ select_end: sqlite3DbFree(db, sAggInfo.aFunc); #if SELECTTRACE_ENABLED SELECTTRACE(1,pParse,p,("end processing\n")); - pParse->nSelectIndent--; #endif return rc; } @@ -126474,7 +128111,7 @@ SQLITE_PRIVATE void sqlite3Update( regKey = ++pParse->nMem; iEph = pParse->nTab++; - sqlite3VdbeAddOp2(v, OP_Null, 0, iPk); + sqlite3VdbeAddOp3(v, OP_Null, 0, iPk, iPk+nPk-1); addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nPk); sqlite3VdbeSetP4KeyInfo(pParse, pPk); } @@ -127024,8 +128661,8 @@ static int execSql(sqlite3 *db, char **pzErrMsg, const char *zSql){ while( SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){ const char *zSubSql = (const char*)sqlite3_column_text(pStmt,0); assert( sqlite3_strnicmp(zSql,"SELECT",6)==0 ); - if( zSubSql ){ - assert( zSubSql[0]!='S' ); + assert( sqlite3_strnicmp(zSubSql,"SELECT",6)!=0 || CORRUPT_DB ); + if( zSubSql && zSubSql[0]!='S' ){ rc = execSql(db, pzErrMsg, zSubSql); if( rc!=SQLITE_OK ) break; } @@ -128646,7 +130283,7 @@ SQLITE_API int sqlite3_vtab_config(sqlite3 *db, int op, ...){ ** Trace output macros */ #if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) -/***/ int sqlite3WhereTrace; +/***/ extern int sqlite3WhereTrace; #endif #if defined(SQLITE_DEBUG) \ && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE)) @@ -130563,7 +132200,15 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( if( sqlite3ExprIsVector(pX->pRight) ){ r1 = rTemp = sqlite3GetTempReg(pParse); codeExprOrVector(pParse, pX->pRight, r1, 1); - op = aMoveOp[(pX->op - TK_GT) | 0x0001]; + testcase( pX->op==TK_GT ); + testcase( pX->op==TK_GE ); + testcase( pX->op==TK_LT ); + testcase( pX->op==TK_LE ); + op = aMoveOp[((pX->op - TK_GT - 1) & 0x3) | 0x1]; + assert( pX->op!=TK_GT || op==OP_SeekGE ); + assert( pX->op!=TK_GE || op==OP_SeekGE ); + assert( pX->op!=TK_LT || op==OP_SeekLE ); + assert( pX->op!=TK_LE || op==OP_SeekLE ); }else{ r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, &rTemp); disableTerm(pLevel, pStart); @@ -131287,7 +132932,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( continue; } - if( pTerm->wtFlags & TERM_LIKECOND ){ + if( (pTerm->wtFlags & TERM_LIKECOND)!=0 ){ /* If the TERM_LIKECOND flag is set, that means that the range search ** is sufficient to guarantee that the LIKE operator is true, so we ** can skip the call to the like(A,B) function. But this only works @@ -131297,8 +132942,9 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( continue; #else u32 x = pLevel->iLikeRepCntr; - assert( x>0 ); - skipLikeAddr = sqlite3VdbeAddOp1(v, (x&1)?OP_IfNot:OP_If, (int)(x>>1)); + if( x>0 ){ + skipLikeAddr = sqlite3VdbeAddOp1(v, (x&1)?OP_IfNot:OP_If,(int)(x>>1)); + } VdbeCoverage(v); #endif } @@ -131338,6 +132984,12 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart( WO_EQ|WO_IN|WO_IS, 0); if( pAlt==0 ) continue; if( pAlt->wtFlags & (TERM_CODED) ) continue; + if( (pAlt->eOperator & WO_IN) + && (pAlt->pExpr->flags & EP_xIsSelect) + && (pAlt->pExpr->x.pSelect->pEList->nExpr>1) + ){ + continue; + } testcase( pAlt->eOperator & WO_EQ ); testcase( pAlt->eOperator & WO_IS ); testcase( pAlt->eOperator & WO_IN ); @@ -132252,6 +133904,9 @@ static Bitmask exprSelectUsage(WhereMaskSet *pMaskSet, Select *pS){ for(i=0; inSrc; i++){ mask |= exprSelectUsage(pMaskSet, pSrc->a[i].pSelect); mask |= sqlite3WhereExprUsage(pMaskSet, pSrc->a[i].pOn); + if( pSrc->a[i].fg.isTabFunc ){ + mask |= sqlite3WhereExprListUsage(pMaskSet, pSrc->a[i].u1.pFuncArg); + } } } pS = pS->pPrior; @@ -132664,7 +134319,7 @@ static void exprAnalyze( exprAnalyze(pSrc, pWC, idxNew); } pTerm = &pWC->a[idxTerm]; - pTerm->wtFlags = TERM_CODED|TERM_VIRTUAL; /* Disable the original */ + pTerm->wtFlags |= TERM_CODED|TERM_VIRTUAL; /* Disable the original */ pTerm->eOperator = 0; } @@ -135281,8 +136936,8 @@ static int whereLoopAddBtreeIndex( pNew = pBuilder->pNew; if( db->mallocFailed ) return SQLITE_NOMEM_BKPT; - WHERETRACE(0x800, ("BEGIN addBtreeIdx(%s), nEq=%d\n", - pProbe->zName, pNew->u.btree.nEq)); + WHERETRACE(0x800, ("BEGIN %s.addBtreeIdx(%s), nEq=%d\n", + pProbe->pTable->zName,pProbe->zName, pNew->u.btree.nEq)); assert( (pNew->wsFlags & WHERE_VIRTUALTABLE)==0 ); assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 ); @@ -135389,10 +137044,12 @@ static int whereLoopAddBtreeIndex( if( iCol==XN_ROWID || (iCol>=0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1) ){ - if( iCol>=0 && pProbe->uniqNotNull==0 ){ - pNew->wsFlags |= WHERE_UNQ_WANTED; - }else{ + if( iCol==XN_ROWID || pProbe->uniqNotNull + || (pProbe->nKeyCol==1 && pProbe->onError && eOp==WO_EQ) + ){ pNew->wsFlags |= WHERE_ONEROW; + }else{ + pNew->wsFlags |= WHERE_UNQ_WANTED; } } }else if( eOp & WO_ISNULL ){ @@ -135566,8 +137223,8 @@ static int whereLoopAddBtreeIndex( pNew->wsFlags = saved_wsFlags; } - WHERETRACE(0x800, ("END addBtreeIdx(%s), nEq=%d, rc=%d\n", - pProbe->zName, saved_nEq, rc)); + WHERETRACE(0x800, ("END %s.addBtreeIdx(%s), nEq=%d, rc=%d\n", + pProbe->pTable->zName, pProbe->zName, saved_nEq, rc)); return rc; } @@ -136005,9 +137662,9 @@ static int whereLoopAddVirtualOne( || pNew->aLTerm[iTerm]!=0 || pIdxCons->usable==0 ){ - rc = SQLITE_ERROR; sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName); - return rc; + testcase( pIdxInfo->needToFreeIdxStr ); + return SQLITE_ERROR; } testcase( iTerm==nConstraint-1 ); testcase( j==0 ); @@ -136035,6 +137692,15 @@ static int whereLoopAddVirtualOne( pNew->u.vtab.omitMask &= ~mNoOmit; pNew->nLTerm = mxTerm+1; + for(i=0; i<=mxTerm; i++){ + if( pNew->aLTerm[i]==0 ){ + /* The non-zero argvIdx values must be contiguous. Raise an + ** error if they are not */ + sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName); + testcase( pIdxInfo->needToFreeIdxStr ); + return SQLITE_ERROR; + } + } assert( pNew->nLTerm<=pNew->nLSlot ); pNew->u.vtab.idxNum = pIdxInfo->idxNum; pNew->u.vtab.needFree = pIdxInfo->needToFreeIdxStr; @@ -136150,6 +137816,7 @@ static int whereLoopAddVirtual( } /* First call xBestIndex() with all constraints usable. */ + WHERETRACE(0x800, ("BEGIN %s.addVirtual()\n", pSrc->pTab->zName)); WHERETRACE(0x40, (" VirtualOne: all usable\n")); rc = whereLoopAddVirtualOne(pBuilder, mPrereq, ALLBITS, 0, p, mNoOmit, &bIn); @@ -136225,6 +137892,7 @@ static int whereLoopAddVirtual( if( p->needToFreeIdxStr ) sqlite3_free(p->idxStr); sqlite3DbFreeNN(pParse->db, p); + WHERETRACE(0x800, ("END %s.addVirtual(), rc=%d\n", pSrc->pTab->zName, rc)); return rc; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -137539,6 +139207,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( */ for(ii=0; iinTerm; ii++){ WhereTerm *pT = &sWLB.pWC->a[ii]; + if( pT->wtFlags & TERM_VIRTUAL ) continue; if( pT->prereqAll==0 && (nTabList==0 || exprIsDeterministic(pT->pExpr)) ){ sqlite3ExprIfFalse(pParse, pT->pExpr, pWInfo->iBreak, SQLITE_JUMPIFNULL); pT->wtFlags |= TERM_CODED; @@ -138364,17 +140033,17 @@ typedef union { #define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse #define sqlite3ParserARG_STORE yypParser->pParse = pParse #define YYFALLBACK 1 -#define YYNSTATE 466 -#define YYNRULE 330 +#define YYNSTATE 472 +#define YYNRULE 333 #define YYNTOKEN 143 -#define YY_MAX_SHIFT 465 -#define YY_MIN_SHIFTREDUCE 675 -#define YY_MAX_SHIFTREDUCE 1004 -#define YY_ERROR_ACTION 1005 -#define YY_ACCEPT_ACTION 1006 -#define YY_NO_ACTION 1007 -#define YY_MIN_REDUCE 1008 -#define YY_MAX_REDUCE 1337 +#define YY_MAX_SHIFT 471 +#define YY_MIN_SHIFTREDUCE 681 +#define YY_MAX_SHIFTREDUCE 1013 +#define YY_ERROR_ACTION 1014 +#define YY_ACCEPT_ACTION 1015 +#define YY_NO_ACTION 1016 +#define YY_MIN_REDUCE 1017 +#define YY_MAX_REDUCE 1349 /************* End control #defines *******************************************/ /* Define the yytestcase() macro to be a no-op if is not already defined @@ -138440,322 +140109,324 @@ typedef union { ** yy_default[] Default action for each state. ** *********** Begin parsing tables **********************************************/ -#define YY_ACTTAB_COUNT (1541) +#define YY_ACTTAB_COUNT (1566) static const YYACTIONTYPE yy_action[] = { - /* 0 */ 1006, 156, 156, 2, 1302, 90, 87, 179, 90, 87, - /* 10 */ 179, 460, 1048, 460, 465, 1010, 460, 333, 1130, 335, - /* 20 */ 246, 330, 112, 303, 439, 1258, 304, 419, 1129, 1087, - /* 30 */ 72, 798, 50, 50, 50, 50, 331, 30, 30, 799, - /* 40 */ 951, 364, 371, 97, 98, 88, 983, 983, 859, 862, - /* 50 */ 851, 851, 95, 95, 96, 96, 96, 96, 120, 371, - /* 60 */ 370, 120, 348, 22, 90, 87, 179, 438, 423, 438, - /* 70 */ 440, 335, 420, 385, 90, 87, 179, 116, 73, 163, - /* 80 */ 848, 848, 860, 863, 94, 94, 94, 94, 93, 93, - /* 90 */ 92, 92, 92, 91, 361, 97, 98, 88, 983, 983, - /* 100 */ 859, 862, 851, 851, 95, 95, 96, 96, 96, 96, - /* 110 */ 718, 365, 339, 93, 93, 92, 92, 92, 91, 361, - /* 120 */ 99, 371, 453, 335, 94, 94, 94, 94, 93, 93, - /* 130 */ 92, 92, 92, 91, 361, 852, 94, 94, 94, 94, - /* 140 */ 93, 93, 92, 92, 92, 91, 361, 97, 98, 88, - /* 150 */ 983, 983, 859, 862, 851, 851, 95, 95, 96, 96, - /* 160 */ 96, 96, 92, 92, 92, 91, 361, 838, 132, 195, - /* 170 */ 58, 244, 412, 409, 408, 335, 457, 457, 457, 304, - /* 180 */ 59, 332, 831, 407, 394, 962, 830, 391, 94, 94, - /* 190 */ 94, 94, 93, 93, 92, 92, 92, 91, 361, 97, - /* 200 */ 98, 88, 983, 983, 859, 862, 851, 851, 95, 95, - /* 210 */ 96, 96, 96, 96, 426, 357, 460, 830, 830, 832, - /* 220 */ 91, 361, 962, 963, 964, 195, 459, 335, 412, 409, - /* 230 */ 408, 280, 361, 820, 132, 11, 11, 50, 50, 407, - /* 240 */ 94, 94, 94, 94, 93, 93, 92, 92, 92, 91, - /* 250 */ 361, 97, 98, 88, 983, 983, 859, 862, 851, 851, - /* 260 */ 95, 95, 96, 96, 96, 96, 460, 221, 460, 264, - /* 270 */ 375, 254, 438, 428, 1276, 1276, 383, 1074, 1053, 335, - /* 280 */ 245, 422, 299, 713, 271, 271, 1074, 50, 50, 50, - /* 290 */ 50, 962, 94, 94, 94, 94, 93, 93, 92, 92, - /* 300 */ 92, 91, 361, 97, 98, 88, 983, 983, 859, 862, - /* 310 */ 851, 851, 95, 95, 96, 96, 96, 96, 90, 87, - /* 320 */ 179, 1306, 438, 437, 438, 418, 368, 253, 962, 963, - /* 330 */ 964, 335, 360, 360, 360, 706, 359, 358, 324, 962, - /* 340 */ 1281, 951, 364, 230, 94, 94, 94, 94, 93, 93, - /* 350 */ 92, 92, 92, 91, 361, 97, 98, 88, 983, 983, - /* 360 */ 859, 862, 851, 851, 95, 95, 96, 96, 96, 96, - /* 370 */ 769, 460, 120, 226, 226, 366, 962, 963, 964, 1089, - /* 380 */ 990, 900, 990, 335, 1057, 425, 421, 839, 759, 759, - /* 390 */ 425, 427, 50, 50, 432, 381, 94, 94, 94, 94, - /* 400 */ 93, 93, 92, 92, 92, 91, 361, 97, 98, 88, - /* 410 */ 983, 983, 859, 862, 851, 851, 95, 95, 96, 96, - /* 420 */ 96, 96, 460, 259, 460, 120, 117, 354, 942, 1332, - /* 430 */ 942, 1333, 1332, 278, 1333, 335, 680, 681, 682, 825, - /* 440 */ 201, 176, 303, 50, 50, 49, 49, 404, 94, 94, - /* 450 */ 94, 94, 93, 93, 92, 92, 92, 91, 361, 97, - /* 460 */ 98, 88, 983, 983, 859, 862, 851, 851, 95, 95, - /* 470 */ 96, 96, 96, 96, 199, 460, 380, 265, 433, 380, - /* 480 */ 265, 383, 256, 158, 258, 319, 1003, 335, 155, 940, - /* 490 */ 177, 940, 273, 379, 276, 322, 34, 34, 302, 962, - /* 500 */ 94, 94, 94, 94, 93, 93, 92, 92, 92, 91, - /* 510 */ 361, 97, 98, 88, 983, 983, 859, 862, 851, 851, - /* 520 */ 95, 95, 96, 96, 96, 96, 905, 905, 397, 460, - /* 530 */ 301, 158, 101, 319, 941, 340, 962, 963, 964, 313, - /* 540 */ 283, 449, 335, 327, 146, 1266, 1004, 257, 234, 248, - /* 550 */ 35, 35, 94, 94, 94, 94, 93, 93, 92, 92, - /* 560 */ 92, 91, 361, 709, 785, 1227, 97, 98, 88, 983, - /* 570 */ 983, 859, 862, 851, 851, 95, 95, 96, 96, 96, - /* 580 */ 96, 962, 1227, 1229, 245, 422, 838, 198, 197, 196, - /* 590 */ 1079, 1079, 1077, 1077, 1004, 1334, 320, 335, 172, 171, - /* 600 */ 709, 831, 159, 271, 271, 830, 76, 94, 94, 94, - /* 610 */ 94, 93, 93, 92, 92, 92, 91, 361, 962, 963, - /* 620 */ 964, 97, 98, 88, 983, 983, 859, 862, 851, 851, - /* 630 */ 95, 95, 96, 96, 96, 96, 830, 830, 832, 1157, - /* 640 */ 1157, 199, 1157, 173, 1227, 231, 232, 1282, 2, 335, - /* 650 */ 271, 764, 271, 820, 271, 271, 763, 389, 389, 389, - /* 660 */ 132, 79, 94, 94, 94, 94, 93, 93, 92, 92, - /* 670 */ 92, 91, 361, 97, 98, 88, 983, 983, 859, 862, - /* 680 */ 851, 851, 95, 95, 96, 96, 96, 96, 460, 264, - /* 690 */ 223, 460, 1257, 783, 1223, 1157, 1086, 1082, 80, 271, - /* 700 */ 78, 335, 340, 1031, 341, 344, 345, 902, 346, 10, - /* 710 */ 10, 902, 25, 25, 94, 94, 94, 94, 93, 93, - /* 720 */ 92, 92, 92, 91, 361, 97, 86, 88, 983, 983, - /* 730 */ 859, 862, 851, 851, 95, 95, 96, 96, 96, 96, - /* 740 */ 1157, 270, 395, 117, 233, 263, 235, 70, 456, 341, - /* 750 */ 225, 176, 335, 1305, 342, 133, 736, 966, 980, 249, - /* 760 */ 1150, 396, 325, 1085, 1028, 178, 94, 94, 94, 94, - /* 770 */ 93, 93, 92, 92, 92, 91, 361, 98, 88, 983, - /* 780 */ 983, 859, 862, 851, 851, 95, 95, 96, 96, 96, - /* 790 */ 96, 783, 783, 132, 120, 966, 120, 120, 120, 798, - /* 800 */ 252, 937, 335, 353, 321, 429, 355, 799, 822, 692, - /* 810 */ 390, 203, 446, 450, 372, 716, 454, 94, 94, 94, - /* 820 */ 94, 93, 93, 92, 92, 92, 91, 361, 88, 983, - /* 830 */ 983, 859, 862, 851, 851, 95, 95, 96, 96, 96, - /* 840 */ 96, 84, 455, 1225, 3, 1209, 120, 120, 382, 387, - /* 850 */ 120, 203, 1271, 716, 384, 168, 266, 203, 458, 72, - /* 860 */ 260, 1246, 84, 455, 178, 3, 378, 94, 94, 94, - /* 870 */ 94, 93, 93, 92, 92, 92, 91, 361, 350, 458, - /* 880 */ 1245, 362, 430, 213, 228, 290, 415, 285, 414, 200, - /* 890 */ 783, 882, 444, 726, 725, 405, 283, 921, 209, 921, - /* 900 */ 281, 132, 362, 72, 838, 289, 147, 733, 734, 392, - /* 910 */ 81, 82, 922, 444, 922, 267, 288, 83, 362, 462, - /* 920 */ 461, 272, 132, 830, 23, 838, 388, 923, 1216, 923, - /* 930 */ 1056, 81, 82, 84, 455, 899, 3, 899, 83, 362, - /* 940 */ 462, 461, 761, 962, 830, 75, 1, 443, 275, 747, - /* 950 */ 458, 5, 962, 204, 830, 830, 832, 833, 18, 748, - /* 960 */ 229, 962, 277, 19, 153, 317, 317, 316, 216, 314, - /* 970 */ 279, 460, 689, 362, 1055, 830, 830, 832, 833, 18, - /* 980 */ 962, 963, 964, 962, 444, 181, 460, 251, 981, 962, - /* 990 */ 963, 964, 8, 8, 20, 250, 838, 1070, 962, 963, - /* 1000 */ 964, 417, 81, 82, 768, 204, 347, 36, 36, 83, - /* 1010 */ 362, 462, 461, 1054, 284, 830, 84, 455, 1123, 3, - /* 1020 */ 962, 963, 964, 460, 183, 962, 981, 764, 889, 1107, - /* 1030 */ 460, 184, 763, 458, 132, 182, 74, 455, 460, 3, - /* 1040 */ 981, 898, 834, 898, 8, 8, 830, 830, 832, 833, - /* 1050 */ 18, 8, 8, 458, 219, 1156, 362, 1103, 349, 8, - /* 1060 */ 8, 240, 962, 963, 964, 236, 889, 444, 792, 336, - /* 1070 */ 158, 203, 885, 435, 700, 209, 362, 114, 981, 838, - /* 1080 */ 834, 227, 334, 1114, 441, 81, 82, 444, 442, 305, - /* 1090 */ 784, 306, 83, 362, 462, 461, 369, 1162, 830, 838, - /* 1100 */ 460, 1037, 237, 1030, 237, 81, 82, 7, 96, 96, - /* 1110 */ 96, 96, 83, 362, 462, 461, 1019, 1018, 830, 1020, - /* 1120 */ 1289, 37, 37, 400, 96, 96, 96, 96, 89, 830, - /* 1130 */ 830, 832, 833, 18, 1100, 318, 962, 292, 94, 94, - /* 1140 */ 94, 94, 93, 93, 92, 92, 92, 91, 361, 830, - /* 1150 */ 830, 832, 833, 18, 94, 94, 94, 94, 93, 93, - /* 1160 */ 92, 92, 92, 91, 361, 359, 358, 226, 226, 727, - /* 1170 */ 294, 296, 460, 962, 963, 964, 460, 989, 160, 425, - /* 1180 */ 170, 1295, 262, 460, 987, 374, 988, 386, 1145, 255, - /* 1190 */ 326, 460, 373, 38, 38, 410, 174, 39, 39, 413, - /* 1200 */ 460, 287, 460, 1053, 40, 40, 298, 728, 1220, 990, - /* 1210 */ 445, 990, 26, 26, 1219, 460, 311, 460, 169, 1292, - /* 1220 */ 460, 27, 27, 29, 29, 998, 460, 206, 135, 995, - /* 1230 */ 1265, 1263, 460, 57, 60, 460, 41, 41, 42, 42, - /* 1240 */ 460, 43, 43, 460, 343, 351, 460, 9, 9, 460, - /* 1250 */ 144, 460, 130, 44, 44, 460, 103, 103, 460, 137, - /* 1260 */ 70, 45, 45, 460, 46, 46, 460, 31, 31, 1142, - /* 1270 */ 47, 47, 48, 48, 460, 376, 32, 32, 460, 122, - /* 1280 */ 122, 460, 157, 460, 123, 123, 139, 124, 124, 460, - /* 1290 */ 186, 460, 377, 460, 115, 54, 54, 460, 403, 33, - /* 1300 */ 33, 460, 104, 104, 51, 51, 460, 161, 460, 140, - /* 1310 */ 105, 105, 106, 106, 102, 102, 460, 141, 121, 121, - /* 1320 */ 460, 142, 119, 119, 190, 460, 1152, 110, 110, 109, - /* 1330 */ 109, 702, 460, 148, 393, 65, 460, 107, 107, 460, - /* 1340 */ 323, 108, 108, 399, 460, 1234, 53, 53, 1214, 269, - /* 1350 */ 154, 416, 1115, 55, 55, 220, 401, 52, 52, 191, - /* 1360 */ 24, 24, 274, 192, 193, 28, 28, 1021, 328, 702, - /* 1370 */ 1073, 352, 1072, 718, 1071, 431, 1111, 1064, 329, 1045, - /* 1380 */ 69, 205, 6, 291, 1044, 286, 1112, 1043, 1304, 1110, - /* 1390 */ 293, 300, 295, 297, 1063, 1200, 1109, 77, 241, 448, - /* 1400 */ 356, 452, 436, 100, 214, 71, 434, 1027, 1093, 21, - /* 1410 */ 463, 242, 243, 957, 215, 217, 218, 464, 309, 307, - /* 1420 */ 308, 310, 1016, 125, 1250, 1251, 1011, 1249, 126, 127, - /* 1430 */ 1248, 113, 676, 337, 238, 338, 134, 363, 167, 1041, - /* 1440 */ 1040, 56, 247, 367, 180, 897, 111, 895, 136, 1038, - /* 1450 */ 818, 128, 138, 750, 261, 911, 185, 143, 145, 61, - /* 1460 */ 62, 63, 64, 129, 914, 187, 188, 910, 118, 12, - /* 1470 */ 189, 903, 268, 992, 203, 162, 398, 150, 149, 691, - /* 1480 */ 402, 288, 194, 406, 151, 411, 66, 13, 729, 239, - /* 1490 */ 282, 14, 67, 131, 837, 836, 865, 758, 15, 4, - /* 1500 */ 68, 762, 175, 222, 224, 424, 152, 869, 791, 202, - /* 1510 */ 786, 75, 72, 880, 866, 864, 16, 17, 920, 207, - /* 1520 */ 919, 208, 447, 946, 164, 211, 947, 210, 165, 451, - /* 1530 */ 868, 166, 315, 835, 701, 85, 212, 1297, 312, 952, - /* 1540 */ 1296, + /* 0 */ 1169, 1015, 167, 167, 1, 168, 466, 1313, 466, 1083, + /* 10 */ 1062, 466, 97, 94, 183, 1057, 466, 329, 1083, 342, + /* 20 */ 97, 94, 183, 459, 459, 459, 436, 57, 57, 57, + /* 30 */ 57, 807, 57, 57, 367, 367, 367, 57, 57, 808, + /* 40 */ 1270, 1088, 1088, 104, 105, 95, 991, 991, 868, 871, + /* 50 */ 860, 860, 102, 102, 103, 103, 103, 103, 233, 233, + /* 60 */ 326, 1011, 449, 437, 449, 446, 351, 449, 461, 1142, + /* 70 */ 463, 342, 449, 426, 1316, 209, 180, 742, 80, 299, + /* 80 */ 857, 857, 869, 872, 101, 101, 101, 101, 100, 100, + /* 90 */ 99, 99, 99, 98, 368, 104, 105, 95, 991, 991, + /* 100 */ 868, 871, 860, 860, 102, 102, 103, 103, 103, 103, + /* 110 */ 99, 99, 99, 98, 368, 355, 97, 94, 183, 228, + /* 120 */ 106, 1012, 407, 342, 101, 101, 101, 101, 100, 100, + /* 130 */ 99, 99, 99, 98, 368, 861, 101, 101, 101, 101, + /* 140 */ 100, 100, 99, 99, 99, 98, 368, 104, 105, 95, + /* 150 */ 991, 991, 868, 871, 860, 860, 102, 102, 103, 103, + /* 160 */ 103, 103, 201, 368, 375, 420, 417, 416, 387, 273, + /* 170 */ 65, 97, 94, 183, 168, 342, 415, 951, 1343, 396, + /* 180 */ 66, 1343, 320, 959, 371, 970, 334, 340, 101, 101, + /* 190 */ 101, 101, 100, 100, 99, 99, 99, 98, 368, 104, + /* 200 */ 105, 95, 991, 991, 868, 871, 860, 860, 102, 102, + /* 210 */ 103, 103, 103, 103, 373, 100, 100, 99, 99, 99, + /* 220 */ 98, 368, 970, 971, 972, 201, 1100, 342, 420, 417, + /* 230 */ 416, 287, 366, 365, 337, 970, 1162, 463, 949, 415, + /* 240 */ 101, 101, 101, 101, 100, 100, 99, 99, 99, 98, + /* 250 */ 368, 104, 105, 95, 991, 991, 868, 871, 860, 860, + /* 260 */ 102, 102, 103, 103, 103, 103, 777, 241, 233, 233, + /* 270 */ 9, 847, 970, 971, 972, 390, 998, 1141, 998, 342, + /* 280 */ 463, 252, 829, 719, 98, 368, 840, 298, 338, 142, + /* 290 */ 839, 339, 101, 101, 101, 101, 100, 100, 99, 99, + /* 300 */ 99, 98, 368, 104, 105, 95, 991, 991, 868, 871, + /* 310 */ 860, 860, 102, 102, 103, 103, 103, 103, 272, 466, + /* 320 */ 392, 839, 839, 841, 97, 94, 183, 390, 1317, 253, + /* 330 */ 456, 342, 125, 166, 807, 712, 208, 407, 386, 970, + /* 340 */ 57, 57, 808, 238, 101, 101, 101, 101, 100, 100, + /* 350 */ 99, 99, 99, 98, 368, 104, 105, 95, 991, 991, + /* 360 */ 868, 871, 860, 860, 102, 102, 103, 103, 103, 103, + /* 370 */ 466, 108, 466, 267, 465, 442, 970, 971, 972, 261, + /* 380 */ 951, 1344, 909, 342, 1344, 142, 829, 848, 1292, 959, + /* 390 */ 371, 55, 55, 57, 57, 242, 101, 101, 101, 101, + /* 400 */ 100, 100, 99, 99, 99, 98, 368, 104, 105, 95, + /* 410 */ 991, 991, 868, 871, 860, 860, 102, 102, 103, 103, + /* 420 */ 103, 103, 272, 382, 262, 253, 456, 310, 364, 253, + /* 430 */ 456, 86, 264, 84, 266, 342, 441, 176, 175, 834, + /* 440 */ 464, 949, 767, 767, 332, 313, 1094, 396, 101, 101, + /* 450 */ 101, 101, 100, 100, 99, 99, 99, 98, 368, 104, + /* 460 */ 105, 95, 991, 991, 868, 871, 860, 860, 102, 102, + /* 470 */ 103, 103, 103, 103, 227, 227, 233, 233, 233, 233, + /* 480 */ 387, 273, 234, 234, 326, 950, 463, 342, 463, 298, + /* 490 */ 463, 914, 914, 404, 463, 1037, 123, 265, 27, 970, + /* 500 */ 101, 101, 101, 101, 100, 100, 99, 99, 99, 98, + /* 510 */ 368, 104, 105, 95, 991, 991, 868, 871, 860, 860, + /* 520 */ 102, 102, 103, 103, 103, 103, 435, 233, 233, 466, + /* 530 */ 285, 686, 687, 688, 127, 271, 970, 971, 972, 463, + /* 540 */ 1345, 327, 342, 407, 157, 1012, 988, 13, 13, 181, + /* 550 */ 41, 41, 101, 101, 101, 101, 100, 100, 99, 99, + /* 560 */ 99, 98, 368, 715, 794, 378, 104, 105, 95, 991, + /* 570 */ 991, 868, 871, 860, 860, 102, 102, 103, 103, 103, + /* 580 */ 103, 970, 378, 377, 346, 239, 847, 1086, 1086, 280, + /* 590 */ 1169, 283, 204, 203, 202, 177, 298, 342, 407, 298, + /* 600 */ 715, 840, 169, 299, 407, 839, 82, 101, 101, 101, + /* 610 */ 101, 100, 100, 99, 99, 99, 98, 368, 970, 971, + /* 620 */ 972, 104, 105, 95, 991, 991, 868, 871, 860, 860, + /* 630 */ 102, 102, 103, 103, 103, 103, 839, 839, 841, 362, + /* 640 */ 240, 124, 1169, 172, 126, 378, 1269, 1169, 1066, 342, + /* 650 */ 253, 456, 407, 407, 407, 396, 352, 401, 407, 429, + /* 660 */ 398, 85, 101, 101, 101, 101, 100, 100, 99, 99, + /* 670 */ 99, 98, 368, 104, 105, 95, 991, 991, 868, 871, + /* 680 */ 860, 860, 102, 102, 103, 103, 103, 103, 1169, 466, + /* 690 */ 230, 233, 233, 792, 1235, 1095, 1091, 1293, 1, 77, + /* 700 */ 278, 342, 205, 463, 974, 911, 1040, 348, 353, 911, + /* 710 */ 42, 42, 79, 403, 101, 101, 101, 101, 100, 100, + /* 720 */ 99, 99, 99, 98, 368, 104, 93, 95, 991, 991, + /* 730 */ 868, 871, 860, 860, 102, 102, 103, 103, 103, 103, + /* 740 */ 402, 9, 974, 243, 772, 458, 348, 232, 180, 771, + /* 750 */ 946, 312, 342, 328, 363, 349, 143, 831, 389, 1278, + /* 760 */ 211, 211, 21, 347, 432, 182, 101, 101, 101, 101, + /* 770 */ 100, 100, 99, 99, 99, 98, 368, 105, 95, 991, + /* 780 */ 991, 868, 871, 860, 860, 102, 102, 103, 103, 103, + /* 790 */ 103, 792, 724, 22, 732, 731, 233, 233, 1239, 256, + /* 800 */ 391, 274, 342, 211, 79, 360, 257, 413, 463, 397, + /* 810 */ 207, 288, 260, 450, 79, 1239, 1241, 101, 101, 101, + /* 820 */ 101, 100, 100, 99, 99, 99, 98, 368, 95, 991, + /* 830 */ 991, 868, 871, 860, 860, 102, 102, 103, 103, 103, + /* 840 */ 103, 91, 457, 296, 3, 233, 233, 5, 438, 212, + /* 850 */ 331, 394, 739, 740, 295, 898, 894, 463, 460, 207, + /* 860 */ 801, 1237, 722, 211, 698, 843, 1283, 101, 101, 101, + /* 870 */ 101, 100, 100, 99, 99, 99, 98, 368, 1239, 380, + /* 880 */ 357, 369, 233, 233, 989, 219, 236, 297, 423, 292, + /* 890 */ 422, 206, 454, 898, 463, 970, 91, 457, 290, 3, + /* 900 */ 722, 142, 268, 843, 847, 466, 1258, 149, 388, 425, + /* 910 */ 88, 89, 769, 460, 930, 87, 447, 90, 369, 468, + /* 920 */ 467, 385, 989, 839, 1257, 439, 57, 57, 395, 931, + /* 930 */ 1065, 158, 970, 971, 972, 772, 369, 471, 1019, 399, + /* 940 */ 771, 253, 456, 254, 932, 119, 891, 454, 233, 233, + /* 950 */ 4, 970, 1096, 275, 839, 839, 841, 842, 19, 847, + /* 960 */ 463, 449, 448, 163, 453, 88, 89, 776, 970, 1127, + /* 970 */ 279, 930, 90, 369, 468, 467, 91, 457, 839, 3, + /* 980 */ 235, 1064, 466, 1228, 233, 233, 931, 970, 970, 971, + /* 990 */ 972, 970, 908, 460, 908, 2, 463, 81, 457, 212, + /* 1000 */ 3, 932, 282, 10, 10, 970, 971, 972, 189, 839, + /* 1010 */ 839, 841, 842, 19, 460, 284, 369, 354, 907, 286, + /* 1020 */ 907, 753, 466, 1079, 970, 971, 972, 454, 970, 971, + /* 1030 */ 972, 754, 970, 1063, 989, 372, 792, 369, 1118, 847, + /* 1040 */ 291, 452, 466, 10, 10, 88, 89, 142, 454, 168, + /* 1050 */ 300, 412, 90, 369, 468, 467, 793, 356, 839, 706, + /* 1060 */ 847, 341, 121, 10, 10, 301, 88, 89, 379, 970, + /* 1070 */ 971, 972, 989, 90, 369, 468, 467, 244, 205, 839, + /* 1080 */ 1306, 245, 1135, 245, 250, 1168, 1114, 253, 456, 839, + /* 1090 */ 839, 841, 842, 19, 1125, 237, 122, 451, 1174, 733, + /* 1100 */ 324, 324, 323, 222, 321, 466, 1046, 695, 182, 225, + /* 1110 */ 839, 839, 841, 842, 19, 103, 103, 103, 103, 96, + /* 1120 */ 185, 466, 259, 1039, 1028, 170, 10, 10, 1027, 421, + /* 1130 */ 258, 1029, 1300, 708, 792, 466, 408, 734, 8, 347, + /* 1140 */ 444, 174, 12, 12, 290, 101, 101, 101, 101, 100, + /* 1150 */ 100, 99, 99, 99, 98, 368, 32, 32, 466, 187, + /* 1160 */ 466, 1111, 103, 103, 103, 103, 188, 466, 325, 138, + /* 1170 */ 186, 708, 303, 305, 307, 358, 970, 270, 393, 43, + /* 1180 */ 43, 44, 44, 1157, 333, 178, 418, 294, 45, 45, + /* 1190 */ 1232, 318, 101, 101, 101, 101, 100, 100, 99, 99, + /* 1200 */ 99, 98, 368, 381, 343, 366, 365, 466, 263, 253, + /* 1210 */ 456, 466, 1062, 970, 971, 972, 1231, 997, 309, 466, + /* 1220 */ 455, 466, 427, 466, 995, 173, 996, 1303, 46, 46, + /* 1230 */ 145, 376, 37, 37, 1006, 1277, 466, 214, 1275, 64, + /* 1240 */ 47, 47, 33, 33, 34, 34, 1003, 67, 466, 998, + /* 1250 */ 350, 998, 466, 155, 233, 233, 466, 36, 36, 24, + /* 1260 */ 140, 77, 1154, 466, 383, 466, 463, 428, 466, 48, + /* 1270 */ 48, 466, 147, 49, 49, 466, 150, 50, 50, 466, + /* 1280 */ 151, 152, 466, 384, 11, 11, 51, 51, 466, 110, + /* 1290 */ 110, 153, 52, 52, 411, 466, 38, 38, 466, 191, + /* 1300 */ 53, 53, 466, 54, 54, 466, 400, 466, 330, 39, + /* 1310 */ 39, 466, 1164, 466, 25, 466, 56, 56, 466, 131, + /* 1320 */ 131, 72, 466, 132, 132, 159, 133, 133, 61, 61, + /* 1330 */ 1226, 195, 40, 40, 111, 111, 58, 58, 406, 112, + /* 1340 */ 112, 466, 277, 113, 113, 466, 226, 466, 1246, 466, + /* 1350 */ 197, 466, 164, 466, 409, 466, 198, 466, 199, 466, + /* 1360 */ 335, 281, 109, 109, 466, 1030, 130, 130, 129, 129, + /* 1370 */ 117, 117, 116, 116, 114, 114, 115, 115, 60, 60, + /* 1380 */ 62, 62, 466, 359, 466, 59, 59, 424, 1082, 1081, + /* 1390 */ 1080, 724, 1073, 1054, 336, 293, 1053, 1052, 1315, 431, + /* 1400 */ 361, 76, 248, 31, 31, 35, 35, 1072, 249, 440, + /* 1410 */ 302, 434, 213, 1122, 6, 311, 1212, 107, 83, 251, + /* 1420 */ 78, 1123, 445, 220, 443, 1036, 304, 23, 1121, 469, + /* 1430 */ 965, 221, 223, 1104, 314, 224, 344, 317, 315, 316, + /* 1440 */ 470, 306, 1025, 1120, 308, 1262, 1020, 134, 120, 246, + /* 1450 */ 682, 370, 171, 255, 1263, 135, 184, 1261, 1260, 374, + /* 1460 */ 118, 906, 904, 827, 1050, 146, 136, 137, 148, 1049, + /* 1470 */ 63, 1047, 756, 190, 269, 920, 154, 156, 68, 69, + /* 1480 */ 70, 71, 139, 923, 192, 193, 144, 919, 345, 128, + /* 1490 */ 14, 194, 276, 211, 1000, 405, 196, 161, 912, 160, + /* 1500 */ 26, 697, 410, 295, 200, 289, 414, 162, 419, 73, + /* 1510 */ 15, 16, 141, 74, 28, 247, 846, 845, 735, 874, + /* 1520 */ 954, 75, 430, 955, 29, 433, 179, 229, 231, 800, + /* 1530 */ 165, 795, 87, 210, 889, 79, 875, 17, 873, 877, + /* 1540 */ 929, 18, 928, 216, 215, 878, 20, 30, 462, 844, + /* 1550 */ 707, 92, 766, 770, 7, 322, 217, 218, 319, 1308, + /* 1560 */ 960, 1016, 1016, 1016, 1016, 1307, }; static const YYCODETYPE yy_lookahead[] = { - /* 0 */ 144, 145, 146, 147, 172, 222, 223, 224, 222, 223, - /* 10 */ 224, 152, 180, 152, 148, 149, 152, 173, 176, 19, - /* 20 */ 154, 173, 156, 152, 163, 242, 152, 163, 176, 163, - /* 30 */ 26, 31, 173, 174, 173, 174, 173, 173, 174, 39, - /* 40 */ 1, 2, 152, 43, 44, 45, 46, 47, 48, 49, - /* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 197, 169, - /* 60 */ 170, 197, 188, 197, 222, 223, 224, 208, 209, 208, - /* 70 */ 209, 19, 208, 152, 222, 223, 224, 22, 26, 24, + /* 0 */ 152, 144, 145, 146, 147, 152, 152, 172, 152, 180, + /* 10 */ 181, 152, 223, 224, 225, 180, 152, 164, 189, 19, + /* 20 */ 223, 224, 225, 168, 169, 170, 163, 173, 174, 173, + /* 30 */ 174, 31, 173, 174, 168, 169, 170, 173, 174, 39, + /* 40 */ 243, 191, 192, 43, 44, 45, 46, 47, 48, 49, + /* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 195, 196, + /* 60 */ 22, 23, 208, 209, 208, 209, 218, 208, 209, 176, + /* 70 */ 207, 19, 208, 209, 23, 212, 213, 26, 26, 152, /* 80 */ 46, 47, 48, 49, 84, 85, 86, 87, 88, 89, /* 90 */ 90, 91, 92, 93, 94, 43, 44, 45, 46, 47, /* 100 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - /* 110 */ 106, 245, 157, 88, 89, 90, 91, 92, 93, 94, - /* 120 */ 68, 231, 251, 19, 84, 85, 86, 87, 88, 89, + /* 110 */ 90, 91, 92, 93, 94, 188, 223, 224, 225, 171, + /* 120 */ 68, 83, 152, 19, 84, 85, 86, 87, 88, 89, /* 130 */ 90, 91, 92, 93, 94, 101, 84, 85, 86, 87, /* 140 */ 88, 89, 90, 91, 92, 93, 94, 43, 44, 45, /* 150 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - /* 160 */ 56, 57, 90, 91, 92, 93, 94, 82, 79, 99, - /* 170 */ 66, 200, 102, 103, 104, 19, 168, 169, 170, 152, - /* 180 */ 24, 210, 97, 113, 229, 59, 101, 232, 84, 85, + /* 160 */ 56, 57, 99, 94, 194, 102, 103, 104, 109, 110, + /* 170 */ 66, 223, 224, 225, 152, 19, 113, 22, 23, 152, + /* 180 */ 24, 26, 160, 1, 2, 59, 164, 173, 84, 85, /* 190 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 43, /* 200 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - /* 210 */ 54, 55, 56, 57, 152, 188, 152, 132, 133, 134, - /* 220 */ 93, 94, 96, 97, 98, 99, 152, 19, 102, 103, - /* 230 */ 104, 23, 94, 72, 79, 173, 174, 173, 174, 113, + /* 210 */ 54, 55, 56, 57, 244, 88, 89, 90, 91, 92, + /* 220 */ 93, 94, 96, 97, 98, 99, 196, 19, 102, 103, + /* 230 */ 104, 23, 88, 89, 173, 59, 163, 207, 83, 113, /* 240 */ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, /* 250 */ 94, 43, 44, 45, 46, 47, 48, 49, 50, 51, - /* 260 */ 52, 53, 54, 55, 56, 57, 152, 171, 152, 108, - /* 270 */ 109, 110, 208, 209, 119, 120, 152, 180, 181, 19, - /* 280 */ 119, 120, 152, 23, 152, 152, 189, 173, 174, 173, - /* 290 */ 174, 59, 84, 85, 86, 87, 88, 89, 90, 91, + /* 260 */ 52, 53, 54, 55, 56, 57, 90, 240, 195, 196, + /* 270 */ 171, 82, 96, 97, 98, 152, 132, 176, 134, 19, + /* 280 */ 207, 200, 72, 23, 93, 94, 97, 152, 173, 79, + /* 290 */ 101, 210, 84, 85, 86, 87, 88, 89, 90, 91, /* 300 */ 92, 93, 94, 43, 44, 45, 46, 47, 48, 49, - /* 310 */ 50, 51, 52, 53, 54, 55, 56, 57, 222, 223, - /* 320 */ 224, 186, 208, 209, 208, 209, 194, 194, 96, 97, - /* 330 */ 98, 19, 168, 169, 170, 23, 88, 89, 163, 59, - /* 340 */ 0, 1, 2, 219, 84, 85, 86, 87, 88, 89, + /* 310 */ 50, 51, 52, 53, 54, 55, 56, 57, 108, 152, + /* 320 */ 152, 132, 133, 134, 223, 224, 225, 152, 186, 119, + /* 330 */ 120, 19, 197, 234, 31, 23, 26, 152, 239, 59, + /* 340 */ 173, 174, 39, 220, 84, 85, 86, 87, 88, 89, /* 350 */ 90, 91, 92, 93, 94, 43, 44, 45, 46, 47, /* 360 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - /* 370 */ 90, 152, 197, 195, 196, 243, 96, 97, 98, 196, - /* 380 */ 132, 11, 134, 19, 182, 207, 115, 23, 117, 118, - /* 390 */ 207, 163, 173, 174, 152, 220, 84, 85, 86, 87, + /* 370 */ 152, 22, 152, 16, 152, 208, 96, 97, 98, 194, + /* 380 */ 22, 23, 11, 19, 26, 79, 72, 23, 0, 1, + /* 390 */ 2, 173, 174, 173, 174, 220, 84, 85, 86, 87, /* 400 */ 88, 89, 90, 91, 92, 93, 94, 43, 44, 45, /* 410 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - /* 420 */ 56, 57, 152, 16, 152, 197, 171, 208, 22, 23, - /* 430 */ 22, 23, 26, 16, 26, 19, 7, 8, 9, 23, - /* 440 */ 212, 213, 152, 173, 174, 173, 174, 19, 84, 85, + /* 420 */ 56, 57, 108, 109, 110, 119, 120, 152, 208, 119, + /* 430 */ 120, 137, 75, 139, 77, 19, 152, 88, 89, 23, + /* 440 */ 115, 83, 117, 118, 163, 227, 163, 152, 84, 85, /* 450 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 43, /* 460 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - /* 470 */ 54, 55, 56, 57, 46, 152, 109, 110, 208, 109, - /* 480 */ 110, 152, 75, 152, 77, 22, 23, 19, 233, 83, - /* 490 */ 152, 83, 75, 238, 77, 164, 173, 174, 226, 59, + /* 470 */ 54, 55, 56, 57, 195, 196, 195, 196, 195, 196, + /* 480 */ 109, 110, 195, 196, 22, 23, 207, 19, 207, 152, + /* 490 */ 207, 108, 109, 110, 207, 163, 22, 140, 24, 59, /* 500 */ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, /* 510 */ 94, 43, 44, 45, 46, 47, 48, 49, 50, 51, - /* 520 */ 52, 53, 54, 55, 56, 57, 108, 109, 110, 152, - /* 530 */ 152, 152, 22, 22, 23, 107, 96, 97, 98, 160, - /* 540 */ 112, 251, 19, 164, 22, 152, 83, 140, 219, 152, + /* 520 */ 52, 53, 54, 55, 56, 57, 152, 195, 196, 152, + /* 530 */ 16, 7, 8, 9, 197, 240, 96, 97, 98, 207, + /* 540 */ 249, 250, 19, 152, 22, 83, 26, 173, 174, 152, /* 550 */ 173, 174, 84, 85, 86, 87, 88, 89, 90, 91, /* 560 */ 92, 93, 94, 59, 124, 152, 43, 44, 45, 46, /* 570 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - /* 580 */ 57, 59, 169, 170, 119, 120, 82, 108, 109, 110, - /* 590 */ 191, 192, 191, 192, 83, 248, 249, 19, 88, 89, + /* 580 */ 57, 59, 169, 170, 157, 194, 82, 191, 192, 75, + /* 590 */ 152, 77, 108, 109, 110, 26, 152, 19, 152, 152, /* 600 */ 96, 97, 24, 152, 152, 101, 138, 84, 85, 86, /* 610 */ 87, 88, 89, 90, 91, 92, 93, 94, 96, 97, /* 620 */ 98, 43, 44, 45, 46, 47, 48, 49, 50, 51, - /* 630 */ 52, 53, 54, 55, 56, 57, 132, 133, 134, 152, - /* 640 */ 152, 46, 152, 26, 231, 194, 194, 146, 147, 19, - /* 650 */ 152, 116, 152, 72, 152, 152, 121, 152, 152, 152, - /* 660 */ 79, 138, 84, 85, 86, 87, 88, 89, 90, 91, + /* 630 */ 52, 53, 54, 55, 56, 57, 132, 133, 134, 188, + /* 640 */ 194, 197, 152, 123, 197, 232, 194, 152, 182, 19, + /* 650 */ 119, 120, 152, 152, 152, 152, 218, 230, 152, 163, + /* 660 */ 233, 138, 84, 85, 86, 87, 88, 89, 90, 91, /* 670 */ 92, 93, 94, 43, 44, 45, 46, 47, 48, 49, - /* 680 */ 50, 51, 52, 53, 54, 55, 56, 57, 152, 108, - /* 690 */ 23, 152, 194, 26, 194, 152, 194, 194, 137, 152, - /* 700 */ 139, 19, 107, 166, 167, 218, 218, 29, 218, 173, - /* 710 */ 174, 33, 173, 174, 84, 85, 86, 87, 88, 89, + /* 680 */ 50, 51, 52, 53, 54, 55, 56, 57, 152, 152, + /* 690 */ 23, 195, 196, 26, 194, 194, 194, 146, 147, 130, + /* 700 */ 194, 19, 46, 207, 59, 29, 166, 167, 218, 33, + /* 710 */ 173, 174, 26, 218, 84, 85, 86, 87, 88, 89, /* 720 */ 90, 91, 92, 93, 94, 43, 44, 45, 46, 47, /* 730 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - /* 740 */ 152, 194, 64, 171, 239, 239, 239, 130, 166, 167, - /* 750 */ 212, 213, 19, 23, 246, 247, 26, 59, 26, 152, - /* 760 */ 163, 218, 163, 163, 163, 98, 84, 85, 86, 87, + /* 740 */ 64, 171, 97, 240, 116, 166, 167, 212, 213, 121, + /* 750 */ 23, 152, 19, 26, 218, 247, 248, 23, 23, 152, + /* 760 */ 26, 26, 22, 107, 163, 98, 84, 85, 86, 87, /* 770 */ 88, 89, 90, 91, 92, 93, 94, 44, 45, 46, /* 780 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - /* 790 */ 57, 124, 26, 79, 197, 97, 197, 197, 197, 31, - /* 800 */ 152, 23, 19, 19, 26, 19, 218, 39, 23, 21, - /* 810 */ 238, 26, 163, 163, 100, 59, 163, 84, 85, 86, + /* 790 */ 57, 124, 106, 53, 100, 101, 195, 196, 152, 152, + /* 800 */ 23, 23, 19, 26, 26, 19, 152, 23, 207, 239, + /* 810 */ 26, 23, 152, 163, 26, 169, 170, 84, 85, 86, /* 820 */ 87, 88, 89, 90, 91, 92, 93, 94, 45, 46, /* 830 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - /* 840 */ 57, 19, 20, 152, 22, 23, 197, 197, 23, 19, - /* 850 */ 197, 26, 152, 97, 23, 123, 23, 26, 36, 26, - /* 860 */ 152, 152, 19, 20, 98, 22, 78, 84, 85, 86, - /* 870 */ 87, 88, 89, 90, 91, 92, 93, 94, 94, 36, - /* 880 */ 152, 59, 96, 99, 100, 101, 102, 103, 104, 105, - /* 890 */ 124, 103, 70, 100, 101, 23, 112, 12, 26, 12, - /* 900 */ 23, 79, 59, 26, 82, 101, 22, 7, 8, 152, - /* 910 */ 88, 89, 27, 70, 27, 152, 112, 95, 96, 97, - /* 920 */ 98, 152, 79, 101, 22, 82, 96, 42, 140, 42, - /* 930 */ 182, 88, 89, 19, 20, 132, 22, 134, 95, 96, - /* 940 */ 97, 98, 23, 59, 101, 26, 22, 62, 152, 62, - /* 950 */ 36, 22, 59, 24, 132, 133, 134, 135, 136, 72, - /* 960 */ 5, 59, 152, 22, 71, 10, 11, 12, 13, 14, - /* 970 */ 152, 152, 17, 59, 182, 132, 133, 134, 135, 136, - /* 980 */ 96, 97, 98, 59, 70, 30, 152, 32, 59, 96, - /* 990 */ 97, 98, 173, 174, 53, 40, 82, 152, 96, 97, - /* 1000 */ 98, 90, 88, 89, 90, 24, 187, 173, 174, 95, - /* 1010 */ 96, 97, 98, 152, 152, 101, 19, 20, 152, 22, - /* 1020 */ 96, 97, 98, 152, 69, 59, 97, 116, 59, 214, - /* 1030 */ 152, 76, 121, 36, 79, 80, 19, 20, 152, 22, - /* 1040 */ 59, 132, 59, 134, 173, 174, 132, 133, 134, 135, - /* 1050 */ 136, 173, 174, 36, 234, 152, 59, 152, 187, 173, - /* 1060 */ 174, 211, 96, 97, 98, 187, 97, 70, 23, 114, - /* 1070 */ 152, 26, 23, 187, 23, 26, 59, 26, 97, 82, - /* 1080 */ 97, 22, 164, 152, 152, 88, 89, 70, 192, 152, - /* 1090 */ 124, 152, 95, 96, 97, 98, 141, 152, 101, 82, - /* 1100 */ 152, 152, 184, 152, 186, 88, 89, 199, 54, 55, - /* 1110 */ 56, 57, 95, 96, 97, 98, 152, 152, 101, 152, - /* 1120 */ 152, 173, 174, 235, 54, 55, 56, 57, 58, 132, - /* 1130 */ 133, 134, 135, 136, 211, 150, 59, 211, 84, 85, - /* 1140 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 132, - /* 1150 */ 133, 134, 135, 136, 84, 85, 86, 87, 88, 89, - /* 1160 */ 90, 91, 92, 93, 94, 88, 89, 195, 196, 35, - /* 1170 */ 211, 211, 152, 96, 97, 98, 152, 100, 198, 207, - /* 1180 */ 171, 122, 240, 152, 107, 215, 109, 240, 202, 215, - /* 1190 */ 202, 152, 220, 173, 174, 177, 185, 173, 174, 65, - /* 1200 */ 152, 176, 152, 181, 173, 174, 215, 73, 176, 132, - /* 1210 */ 228, 134, 173, 174, 176, 152, 201, 152, 199, 155, - /* 1220 */ 152, 173, 174, 173, 174, 60, 152, 122, 244, 38, - /* 1230 */ 159, 159, 152, 241, 241, 152, 173, 174, 173, 174, - /* 1240 */ 152, 173, 174, 152, 159, 111, 152, 173, 174, 152, - /* 1250 */ 22, 152, 43, 173, 174, 152, 173, 174, 152, 190, - /* 1260 */ 130, 173, 174, 152, 173, 174, 152, 173, 174, 202, - /* 1270 */ 173, 174, 173, 174, 152, 18, 173, 174, 152, 173, - /* 1280 */ 174, 152, 221, 152, 173, 174, 193, 173, 174, 152, - /* 1290 */ 158, 152, 159, 152, 22, 173, 174, 152, 18, 173, - /* 1300 */ 174, 152, 173, 174, 173, 174, 152, 221, 152, 193, - /* 1310 */ 173, 174, 173, 174, 173, 174, 152, 193, 173, 174, - /* 1320 */ 152, 193, 173, 174, 158, 152, 190, 173, 174, 173, - /* 1330 */ 174, 59, 152, 190, 159, 137, 152, 173, 174, 152, - /* 1340 */ 202, 173, 174, 61, 152, 237, 173, 174, 202, 236, - /* 1350 */ 22, 107, 159, 173, 174, 159, 178, 173, 174, 158, - /* 1360 */ 173, 174, 159, 158, 158, 173, 174, 159, 178, 97, - /* 1370 */ 175, 63, 175, 106, 175, 125, 217, 183, 178, 175, - /* 1380 */ 107, 159, 22, 216, 177, 175, 217, 175, 175, 217, - /* 1390 */ 216, 159, 216, 216, 183, 225, 217, 137, 227, 178, - /* 1400 */ 94, 178, 126, 129, 25, 128, 127, 162, 206, 26, - /* 1410 */ 161, 230, 230, 13, 153, 153, 6, 151, 203, 205, - /* 1420 */ 204, 202, 151, 165, 171, 171, 151, 171, 165, 165, - /* 1430 */ 171, 179, 4, 250, 179, 250, 247, 3, 22, 171, - /* 1440 */ 171, 171, 142, 81, 15, 23, 16, 23, 131, 171, - /* 1450 */ 120, 111, 123, 20, 16, 1, 125, 123, 131, 53, - /* 1460 */ 53, 53, 53, 111, 96, 34, 122, 1, 5, 22, - /* 1470 */ 107, 67, 140, 74, 26, 24, 41, 107, 67, 20, - /* 1480 */ 19, 112, 105, 66, 22, 66, 22, 22, 28, 66, - /* 1490 */ 23, 22, 22, 37, 23, 23, 23, 116, 22, 22, - /* 1500 */ 26, 23, 122, 23, 23, 26, 22, 11, 96, 34, - /* 1510 */ 124, 26, 26, 23, 23, 23, 34, 34, 23, 26, - /* 1520 */ 23, 22, 24, 23, 22, 122, 23, 26, 22, 24, - /* 1530 */ 23, 22, 15, 23, 23, 22, 122, 122, 23, 1, - /* 1540 */ 122, 252, 252, 252, 252, 252, 252, 252, 252, 252, - /* 1550 */ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, - /* 1560 */ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, + /* 840 */ 57, 19, 20, 101, 22, 195, 196, 22, 19, 24, + /* 850 */ 163, 19, 7, 8, 112, 59, 23, 207, 36, 26, + /* 860 */ 23, 152, 59, 26, 21, 59, 152, 84, 85, 86, + /* 870 */ 87, 88, 89, 90, 91, 92, 93, 94, 232, 221, + /* 880 */ 94, 59, 195, 196, 59, 99, 100, 101, 102, 103, + /* 890 */ 104, 105, 70, 97, 207, 59, 19, 20, 112, 22, + /* 900 */ 97, 79, 152, 97, 82, 152, 152, 71, 221, 90, + /* 910 */ 88, 89, 23, 36, 12, 26, 163, 95, 96, 97, + /* 920 */ 98, 78, 97, 101, 152, 96, 173, 174, 96, 27, + /* 930 */ 182, 22, 96, 97, 98, 116, 59, 148, 149, 152, + /* 940 */ 121, 119, 120, 154, 42, 156, 103, 70, 195, 196, + /* 950 */ 22, 59, 163, 152, 132, 133, 134, 135, 136, 82, + /* 960 */ 207, 208, 209, 71, 62, 88, 89, 90, 59, 152, + /* 970 */ 152, 12, 95, 96, 97, 98, 19, 20, 101, 22, + /* 980 */ 22, 182, 152, 140, 195, 196, 27, 59, 96, 97, + /* 990 */ 98, 59, 132, 36, 134, 22, 207, 19, 20, 24, + /* 1000 */ 22, 42, 152, 173, 174, 96, 97, 98, 219, 132, + /* 1010 */ 133, 134, 135, 136, 36, 152, 59, 187, 132, 152, + /* 1020 */ 134, 62, 152, 152, 96, 97, 98, 70, 96, 97, + /* 1030 */ 98, 72, 59, 152, 59, 246, 26, 59, 214, 82, + /* 1040 */ 152, 192, 152, 173, 174, 88, 89, 79, 70, 152, + /* 1050 */ 152, 19, 95, 96, 97, 98, 124, 187, 101, 23, + /* 1060 */ 82, 164, 26, 173, 174, 152, 88, 89, 100, 96, + /* 1070 */ 97, 98, 97, 95, 96, 97, 98, 187, 46, 101, + /* 1080 */ 122, 184, 152, 186, 211, 152, 152, 119, 120, 132, + /* 1090 */ 133, 134, 135, 136, 152, 5, 22, 152, 152, 35, + /* 1100 */ 10, 11, 12, 13, 14, 152, 152, 17, 98, 235, + /* 1110 */ 132, 133, 134, 135, 136, 54, 55, 56, 57, 58, + /* 1120 */ 30, 152, 32, 152, 152, 198, 173, 174, 152, 65, + /* 1130 */ 40, 152, 152, 59, 124, 152, 236, 73, 199, 107, + /* 1140 */ 187, 171, 173, 174, 112, 84, 85, 86, 87, 88, + /* 1150 */ 89, 90, 91, 92, 93, 94, 173, 174, 152, 69, + /* 1160 */ 152, 211, 54, 55, 56, 57, 76, 152, 150, 79, + /* 1170 */ 80, 97, 211, 211, 211, 111, 59, 241, 241, 173, + /* 1180 */ 174, 173, 174, 202, 202, 185, 177, 176, 173, 174, + /* 1190 */ 176, 201, 84, 85, 86, 87, 88, 89, 90, 91, + /* 1200 */ 92, 93, 94, 215, 114, 88, 89, 152, 215, 119, + /* 1210 */ 120, 152, 181, 96, 97, 98, 176, 100, 215, 152, + /* 1220 */ 229, 152, 163, 152, 107, 199, 109, 155, 173, 174, + /* 1230 */ 245, 141, 173, 174, 60, 159, 152, 122, 159, 242, + /* 1240 */ 173, 174, 173, 174, 173, 174, 38, 242, 152, 132, + /* 1250 */ 159, 134, 152, 22, 195, 196, 152, 173, 174, 222, + /* 1260 */ 43, 130, 202, 152, 18, 152, 207, 208, 152, 173, + /* 1270 */ 174, 152, 190, 173, 174, 152, 193, 173, 174, 152, + /* 1280 */ 193, 193, 152, 159, 173, 174, 173, 174, 152, 173, + /* 1290 */ 174, 193, 173, 174, 18, 152, 173, 174, 152, 158, + /* 1300 */ 173, 174, 152, 173, 174, 152, 159, 152, 202, 173, + /* 1310 */ 174, 152, 190, 152, 222, 152, 173, 174, 152, 173, + /* 1320 */ 174, 137, 152, 173, 174, 190, 173, 174, 173, 174, + /* 1330 */ 202, 158, 173, 174, 173, 174, 173, 174, 61, 173, + /* 1340 */ 174, 152, 237, 173, 174, 152, 159, 152, 238, 152, + /* 1350 */ 158, 152, 22, 152, 178, 152, 158, 152, 158, 152, + /* 1360 */ 178, 159, 173, 174, 152, 159, 173, 174, 173, 174, + /* 1370 */ 173, 174, 173, 174, 173, 174, 173, 174, 173, 174, + /* 1380 */ 173, 174, 152, 63, 152, 173, 174, 107, 175, 175, + /* 1390 */ 175, 106, 183, 175, 178, 175, 177, 175, 175, 178, + /* 1400 */ 94, 107, 231, 173, 174, 173, 174, 183, 231, 125, + /* 1410 */ 216, 178, 159, 217, 22, 159, 226, 129, 137, 228, + /* 1420 */ 128, 217, 126, 25, 127, 162, 216, 26, 217, 161, + /* 1430 */ 13, 153, 153, 206, 205, 6, 251, 202, 204, 203, + /* 1440 */ 151, 216, 151, 217, 216, 171, 151, 165, 179, 179, + /* 1450 */ 4, 3, 22, 142, 171, 165, 15, 171, 171, 81, + /* 1460 */ 16, 23, 23, 120, 171, 131, 165, 111, 123, 171, + /* 1470 */ 171, 171, 20, 125, 16, 1, 123, 131, 53, 53, + /* 1480 */ 53, 53, 111, 96, 34, 122, 248, 1, 251, 5, + /* 1490 */ 22, 107, 140, 26, 74, 41, 122, 107, 67, 67, + /* 1500 */ 24, 20, 19, 112, 105, 23, 66, 22, 66, 22, + /* 1510 */ 22, 22, 37, 22, 22, 66, 23, 23, 28, 23, + /* 1520 */ 23, 26, 24, 23, 22, 24, 122, 23, 23, 96, + /* 1530 */ 22, 124, 26, 34, 23, 26, 23, 34, 23, 23, + /* 1540 */ 23, 34, 23, 22, 26, 11, 22, 22, 26, 23, + /* 1550 */ 23, 22, 116, 23, 22, 15, 122, 122, 23, 122, + /* 1560 */ 1, 252, 252, 252, 252, 122, 252, 252, 252, 252, /* 1570 */ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, /* 1580 */ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, /* 1590 */ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, @@ -138767,147 +140438,152 @@ static const YYCODETYPE yy_lookahead[] = { /* 1650 */ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, /* 1660 */ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, /* 1670 */ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, - /* 1680 */ 252, 252, 252, 252, + /* 1680 */ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, + /* 1690 */ 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, + /* 1700 */ 252, 252, 252, 252, 252, 252, 252, 252, 252, }; -#define YY_SHIFT_COUNT (465) +#define YY_SHIFT_COUNT (471) #define YY_SHIFT_MIN (0) -#define YY_SHIFT_MAX (1538) +#define YY_SHIFT_MAX (1559) static const unsigned short int yy_shift_ofst[] = { - /* 0 */ 39, 822, 955, 843, 997, 997, 997, 997, 0, 0, - /* 10 */ 104, 630, 997, 997, 997, 997, 997, 997, 997, 1077, - /* 20 */ 1077, 126, 161, 155, 52, 156, 208, 260, 312, 364, - /* 30 */ 416, 468, 523, 578, 630, 630, 630, 630, 630, 630, - /* 40 */ 630, 630, 630, 630, 630, 630, 630, 630, 630, 630, - /* 50 */ 630, 682, 630, 733, 783, 783, 914, 997, 997, 997, - /* 60 */ 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, - /* 70 */ 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, - /* 80 */ 997, 997, 997, 997, 997, 997, 997, 997, 1017, 997, - /* 90 */ 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, - /* 100 */ 997, 997, 1070, 1054, 1054, 1054, 1054, 1054, 40, 25, - /* 110 */ 72, 232, 788, 428, 248, 248, 232, 581, 367, 127, - /* 120 */ 465, 138, 1541, 1541, 1541, 784, 784, 784, 522, 522, - /* 130 */ 887, 887, 893, 406, 408, 232, 232, 232, 232, 232, - /* 140 */ 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, - /* 150 */ 232, 232, 232, 232, 232, 370, 340, 714, 698, 698, - /* 160 */ 465, 89, 89, 89, 89, 89, 89, 1541, 1541, 1541, - /* 170 */ 504, 85, 85, 884, 70, 280, 902, 440, 966, 924, - /* 180 */ 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, - /* 190 */ 232, 232, 232, 232, 232, 232, 1134, 1134, 1134, 232, - /* 200 */ 232, 667, 232, 232, 232, 929, 232, 232, 885, 232, - /* 210 */ 232, 232, 232, 232, 232, 232, 232, 232, 232, 418, - /* 220 */ 678, 981, 981, 981, 981, 766, 271, 911, 510, 429, - /* 230 */ 617, 786, 786, 830, 617, 830, 4, 730, 595, 768, - /* 240 */ 786, 561, 768, 768, 732, 535, 55, 1165, 1105, 1105, - /* 250 */ 1191, 1191, 1105, 1228, 1209, 1130, 1257, 1257, 1257, 1257, - /* 260 */ 1105, 1280, 1130, 1228, 1209, 1209, 1130, 1105, 1280, 1198, - /* 270 */ 1282, 1105, 1105, 1280, 1328, 1105, 1280, 1105, 1280, 1328, - /* 280 */ 1244, 1244, 1244, 1308, 1328, 1244, 1267, 1244, 1308, 1244, - /* 290 */ 1244, 1250, 1273, 1250, 1273, 1250, 1273, 1250, 1273, 1105, - /* 300 */ 1360, 1105, 1260, 1328, 1306, 1306, 1328, 1274, 1276, 1277, - /* 310 */ 1279, 1130, 1379, 1383, 1400, 1400, 1410, 1410, 1410, 1541, - /* 320 */ 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, 1541, - /* 330 */ 1541, 1541, 1541, 1541, 1541, 34, 407, 463, 511, 417, - /* 340 */ 479, 1272, 778, 941, 785, 825, 831, 833, 872, 877, - /* 350 */ 756, 793, 900, 804, 919, 1045, 969, 1049, 803, 909, - /* 360 */ 1051, 983, 1059, 1428, 1434, 1416, 1300, 1429, 1362, 1430, - /* 370 */ 1422, 1424, 1330, 1317, 1340, 1329, 1433, 1331, 1438, 1454, - /* 380 */ 1334, 1327, 1406, 1407, 1408, 1409, 1352, 1368, 1431, 1344, - /* 390 */ 1466, 1463, 1447, 1363, 1332, 1404, 1448, 1411, 1399, 1435, - /* 400 */ 1370, 1451, 1459, 1461, 1369, 1377, 1462, 1417, 1464, 1465, - /* 410 */ 1467, 1469, 1419, 1460, 1470, 1423, 1456, 1471, 1472, 1473, - /* 420 */ 1474, 1381, 1476, 1478, 1477, 1479, 1380, 1480, 1481, 1412, - /* 430 */ 1475, 1484, 1386, 1485, 1482, 1486, 1483, 1490, 1485, 1491, - /* 440 */ 1492, 1495, 1493, 1497, 1499, 1496, 1500, 1502, 1498, 1501, - /* 450 */ 1503, 1506, 1505, 1501, 1507, 1509, 1510, 1511, 1513, 1403, - /* 460 */ 1414, 1415, 1418, 1515, 1517, 1538, + /* 0 */ 182, 1090, 822, 822, 306, 957, 957, 957, 957, 210, + /* 10 */ 0, 0, 104, 630, 957, 957, 957, 957, 957, 957, + /* 20 */ 957, 1117, 1117, 126, 968, 306, 306, 306, 306, 306, + /* 30 */ 306, 52, 156, 208, 260, 312, 364, 416, 468, 523, + /* 40 */ 578, 630, 630, 630, 630, 630, 630, 630, 630, 630, + /* 50 */ 630, 630, 630, 630, 630, 630, 630, 630, 682, 630, + /* 60 */ 733, 783, 783, 877, 957, 957, 957, 957, 957, 957, + /* 70 */ 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, + /* 80 */ 957, 957, 957, 957, 957, 957, 957, 957, 957, 957, + /* 90 */ 957, 957, 957, 957, 957, 978, 957, 957, 957, 957, + /* 100 */ 957, 957, 957, 957, 957, 957, 957, 957, 957, 1061, + /* 110 */ 1108, 1108, 1108, 1108, 1108, 40, 127, 20, 280, 843, + /* 120 */ 1032, 144, 144, 280, 310, 310, 310, 310, 59, 191, + /* 130 */ 69, 1566, 1566, 1566, 786, 786, 786, 522, 836, 522, + /* 140 */ 959, 959, 892, 155, 358, 280, 280, 280, 280, 280, + /* 150 */ 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + /* 160 */ 280, 280, 280, 280, 280, 280, 371, 388, 645, 645, + /* 170 */ 531, 1566, 1566, 1566, 504, 189, 189, 909, 63, 176, + /* 180 */ 928, 440, 932, 973, 280, 280, 280, 280, 280, 314, + /* 190 */ 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + /* 200 */ 280, 280, 1064, 1064, 1064, 280, 280, 280, 280, 667, + /* 210 */ 280, 280, 280, 825, 280, 280, 902, 280, 280, 280, + /* 220 */ 280, 280, 280, 280, 280, 383, 676, 325, 975, 975, + /* 230 */ 975, 975, 1010, 325, 325, 819, 349, 524, 569, 829, + /* 240 */ 829, 832, 569, 832, 686, 51, 656, 303, 303, 303, + /* 250 */ 829, 294, 520, 628, 474, 1174, 1115, 1115, 1208, 1208, + /* 260 */ 1115, 1231, 1217, 1131, 1246, 1246, 1246, 1246, 1115, 1276, + /* 270 */ 1131, 1231, 1217, 1217, 1131, 1115, 1276, 1184, 1277, 1115, + /* 280 */ 1276, 1330, 1115, 1276, 1115, 1276, 1330, 1280, 1280, 1280, + /* 290 */ 1320, 1330, 1280, 1285, 1280, 1320, 1280, 1280, 1330, 1306, + /* 300 */ 1306, 1330, 1284, 1294, 1284, 1294, 1284, 1294, 1284, 1294, + /* 310 */ 1115, 1392, 1115, 1281, 1288, 1296, 1292, 1297, 1131, 1398, + /* 320 */ 1401, 1417, 1417, 1429, 1429, 1429, 1566, 1566, 1566, 1566, + /* 330 */ 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, 1566, + /* 340 */ 1566, 1566, 34, 357, 38, 462, 514, 484, 1074, 727, + /* 350 */ 740, 734, 735, 777, 778, 784, 788, 803, 694, 845, + /* 360 */ 742, 796, 833, 837, 889, 860, 886, 1036, 806, 958, + /* 370 */ 1446, 1448, 1430, 1311, 1441, 1378, 1444, 1438, 1439, 1343, + /* 380 */ 1334, 1356, 1345, 1452, 1348, 1458, 1474, 1353, 1346, 1425, + /* 390 */ 1426, 1427, 1428, 1371, 1387, 1450, 1363, 1486, 1484, 1468, + /* 400 */ 1384, 1352, 1431, 1467, 1432, 1420, 1454, 1374, 1390, 1476, + /* 410 */ 1481, 1483, 1391, 1399, 1485, 1440, 1487, 1488, 1482, 1489, + /* 420 */ 1442, 1490, 1491, 1449, 1475, 1493, 1494, 1496, 1495, 1497, + /* 430 */ 1492, 1498, 1500, 1502, 1501, 1404, 1504, 1505, 1433, 1499, + /* 440 */ 1508, 1407, 1506, 1503, 1509, 1507, 1511, 1513, 1515, 1506, + /* 450 */ 1516, 1517, 1518, 1519, 1521, 1534, 1524, 1525, 1526, 1527, + /* 460 */ 1529, 1530, 1532, 1522, 1436, 1434, 1435, 1437, 1443, 1535, + /* 470 */ 1540, 1559, }; -#define YY_REDUCE_COUNT (334) -#define YY_REDUCE_MIN (-217) -#define YY_REDUCE_MAX (1278) +#define YY_REDUCE_COUNT (341) +#define YY_REDUCE_MIN (-211) +#define YY_REDUCE_MAX (1301) static const short yy_reduce_ofst[] = { - /* 0 */ -144, -139, -134, -136, -141, 64, 114, 116, -158, -148, - /* 10 */ -217, 96, 819, 871, 878, 219, 270, 886, 272, -110, - /* 20 */ 413, 918, 972, 228, -214, -214, -214, -214, -214, -214, - /* 30 */ -214, -214, -214, -214, -214, -214, -214, -214, -214, -214, - /* 40 */ -214, -214, -214, -214, -214, -214, -214, -214, -214, -214, - /* 50 */ -214, -214, -214, -214, -214, -214, 62, 323, 377, 536, - /* 60 */ 539, 834, 948, 1020, 1024, 1031, 1039, 1048, 1050, 1063, - /* 70 */ 1065, 1068, 1074, 1080, 1083, 1088, 1091, 1094, 1097, 1099, - /* 80 */ 1103, 1106, 1111, 1114, 1122, 1126, 1129, 1131, 1137, 1139, - /* 90 */ 1141, 1145, 1149, 1154, 1156, 1164, 1168, 1173, 1180, 1184, - /* 100 */ 1187, 1192, -214, -214, -214, -214, -214, -214, -214, -214, - /* 110 */ -214, 132, -45, 97, 8, 164, 379, 175, 255, -214, - /* 120 */ 178, -214, -214, -214, -214, -168, -168, -168, 124, 329, - /* 130 */ 399, 401, -129, 347, 347, 331, 133, 451, 452, 498, - /* 140 */ 500, 502, 503, 505, 487, 506, 488, 490, 507, 543, - /* 150 */ 547, -126, 588, 290, 27, 572, 501, 597, 537, 582, - /* 160 */ 183, 599, 600, 601, 649, 650, 653, 508, 538, -29, - /* 170 */ -156, -152, -137, -79, 135, 74, 130, 242, 338, 378, - /* 180 */ 393, 397, 607, 648, 691, 700, 708, 709, 728, 757, - /* 190 */ 763, 769, 796, 810, 818, 845, 202, 748, 792, 861, - /* 200 */ 862, 815, 866, 903, 905, 850, 931, 932, 896, 937, - /* 210 */ 939, 945, 74, 949, 951, 964, 965, 967, 968, 888, - /* 220 */ 820, 923, 926, 959, 960, 815, 980, 908, 1009, 985, - /* 230 */ 986, 970, 974, 942, 988, 947, 1018, 1011, 1022, 1025, - /* 240 */ 991, 982, 1032, 1038, 1015, 1019, 1064, 984, 1071, 1072, - /* 250 */ 992, 993, 1085, 1061, 1069, 1067, 1093, 1116, 1124, 1128, - /* 260 */ 1133, 1132, 1138, 1086, 1136, 1143, 1146, 1175, 1166, 1108, - /* 270 */ 1113, 1193, 1196, 1201, 1178, 1203, 1205, 1208, 1206, 1190, - /* 280 */ 1195, 1197, 1199, 1194, 1200, 1204, 1207, 1210, 1211, 1212, - /* 290 */ 1213, 1159, 1167, 1169, 1174, 1172, 1176, 1179, 1177, 1222, - /* 300 */ 1170, 1232, 1171, 1221, 1181, 1182, 1223, 1202, 1214, 1216, - /* 310 */ 1215, 1219, 1245, 1249, 1261, 1262, 1266, 1271, 1275, 1183, - /* 320 */ 1185, 1189, 1258, 1253, 1254, 1256, 1259, 1263, 1252, 1255, - /* 330 */ 1268, 1269, 1270, 1278, 1264, + /* 0 */ -143, 789, 753, 1059, -137, -146, -144, -141, -136, 687, + /* 10 */ -107, 101, -203, -52, 830, 870, 890, 167, 953, 218, + /* 20 */ 220, 413, 646, 897, 73, 281, 283, 332, 496, 601, + /* 30 */ 650, -211, -211, -211, -211, -211, -211, -211, -211, -211, + /* 40 */ -211, -211, -211, -211, -211, -211, -211, -211, -211, -211, + /* 50 */ -211, -211, -211, -211, -211, -211, -211, -211, -211, -211, + /* 60 */ -211, -211, -211, 374, 377, 537, 969, 983, 1006, 1008, + /* 70 */ 1015, 1055, 1067, 1069, 1071, 1084, 1096, 1100, 1104, 1111, + /* 80 */ 1113, 1116, 1119, 1123, 1127, 1130, 1136, 1143, 1146, 1150, + /* 90 */ 1153, 1155, 1159, 1161, 1163, 1166, 1170, 1189, 1193, 1195, + /* 100 */ 1197, 1199, 1201, 1203, 1205, 1207, 1212, 1230, 1232, -211, + /* 110 */ -211, -211, -211, -211, -211, -211, -211, -211, -30, 427, + /* 120 */ -171, -145, -134, 22, 279, 287, 279, 287, 99, -211, + /* 130 */ -211, -211, -211, -211, -165, -165, -165, 123, 135, 175, + /* 140 */ -150, 396, 337, 291, 291, -147, 185, 391, 446, 444, + /* 150 */ 452, 500, 501, 502, 27, -152, 295, 438, 490, 503, + /* 160 */ 495, 506, -73, 447, 451, 536, 570, 551, 540, 579, + /* 170 */ 30, 508, 535, 81, 14, 61, 115, 168, 142, 222, + /* 180 */ 275, 284, 397, 599, 607, 647, 654, 660, 709, 658, + /* 190 */ 714, 750, 754, 772, 787, 801, 817, 818, 850, 863, + /* 200 */ 867, 871, 466, 748, 799, 881, 888, 898, 913, 824, + /* 210 */ 930, 933, 934, 873, 942, 945, 849, 946, 222, 954, + /* 220 */ 971, 972, 976, 979, 980, 900, 874, 927, 950, 961, + /* 230 */ 962, 963, 824, 927, 927, 939, 970, 1018, 981, 988, + /* 240 */ 993, 936, 982, 937, 1009, 1000, 1031, 1011, 1014, 1040, + /* 250 */ 1003, 991, 990, 1026, 1072, 985, 1076, 1079, 997, 1005, + /* 260 */ 1091, 1037, 1082, 1060, 1083, 1087, 1088, 1098, 1124, 1141, + /* 270 */ 1106, 1092, 1122, 1135, 1128, 1147, 1173, 1110, 1105, 1187, + /* 280 */ 1192, 1176, 1202, 1198, 1206, 1200, 1182, 1213, 1214, 1215, + /* 290 */ 1209, 1216, 1218, 1219, 1220, 1224, 1222, 1223, 1221, 1171, + /* 300 */ 1177, 1233, 1196, 1194, 1204, 1210, 1211, 1225, 1226, 1228, + /* 310 */ 1253, 1190, 1256, 1191, 1227, 1229, 1234, 1236, 1235, 1263, + /* 320 */ 1268, 1278, 1279, 1289, 1291, 1295, 1185, 1237, 1238, 1282, + /* 330 */ 1274, 1283, 1286, 1287, 1290, 1269, 1270, 1293, 1298, 1299, + /* 340 */ 1300, 1301, }; static const YYACTIONTYPE yy_default[] = { - /* 0 */ 1286, 1276, 1276, 1276, 1209, 1209, 1209, 1209, 1133, 1133, - /* 10 */ 1260, 1036, 1005, 1005, 1005, 1005, 1005, 1005, 1208, 1005, - /* 20 */ 1005, 1005, 1005, 1108, 1139, 1005, 1005, 1005, 1005, 1210, - /* 30 */ 1211, 1005, 1005, 1005, 1259, 1261, 1149, 1148, 1147, 1146, - /* 40 */ 1242, 1120, 1144, 1137, 1141, 1210, 1204, 1205, 1203, 1207, - /* 50 */ 1211, 1005, 1140, 1174, 1188, 1173, 1005, 1005, 1005, 1005, - /* 60 */ 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, - /* 70 */ 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, - /* 80 */ 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, - /* 90 */ 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, - /* 100 */ 1005, 1005, 1182, 1187, 1194, 1186, 1183, 1176, 1175, 1177, - /* 110 */ 1178, 1005, 1026, 1075, 1005, 1005, 1005, 1276, 1036, 1179, - /* 120 */ 1005, 1180, 1191, 1190, 1189, 1267, 1294, 1293, 1005, 1005, - /* 130 */ 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, - /* 140 */ 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, - /* 150 */ 1005, 1005, 1005, 1005, 1005, 1036, 1286, 1276, 1032, 1032, - /* 160 */ 1005, 1276, 1276, 1276, 1276, 1276, 1276, 1272, 1108, 1099, - /* 170 */ 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, - /* 180 */ 1005, 1264, 1262, 1005, 1224, 1005, 1005, 1005, 1005, 1005, - /* 190 */ 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, - /* 200 */ 1005, 1005, 1005, 1005, 1005, 1104, 1005, 1005, 1005, 1005, - /* 210 */ 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1288, 1005, - /* 220 */ 1237, 1104, 1104, 1104, 1104, 1106, 1088, 1098, 1036, 1012, - /* 230 */ 1143, 1122, 1122, 1327, 1143, 1327, 1050, 1308, 1047, 1133, - /* 240 */ 1122, 1206, 1133, 1133, 1105, 1098, 1005, 1330, 1113, 1113, - /* 250 */ 1329, 1329, 1113, 1154, 1078, 1143, 1084, 1084, 1084, 1084, - /* 260 */ 1113, 1023, 1143, 1154, 1078, 1078, 1143, 1113, 1023, 1241, - /* 270 */ 1324, 1113, 1113, 1023, 1217, 1113, 1023, 1113, 1023, 1217, - /* 280 */ 1076, 1076, 1076, 1065, 1217, 1076, 1050, 1076, 1065, 1076, - /* 290 */ 1076, 1126, 1121, 1126, 1121, 1126, 1121, 1126, 1121, 1113, - /* 300 */ 1212, 1113, 1005, 1217, 1221, 1221, 1217, 1138, 1127, 1136, - /* 310 */ 1134, 1143, 1029, 1068, 1291, 1291, 1287, 1287, 1287, 1335, - /* 320 */ 1335, 1272, 1303, 1036, 1036, 1036, 1036, 1303, 1052, 1052, - /* 330 */ 1036, 1036, 1036, 1036, 1303, 1005, 1005, 1005, 1005, 1005, - /* 340 */ 1005, 1298, 1005, 1226, 1005, 1005, 1005, 1005, 1005, 1005, - /* 350 */ 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, - /* 360 */ 1005, 1005, 1159, 1005, 1008, 1269, 1005, 1005, 1268, 1005, - /* 370 */ 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, - /* 380 */ 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1326, - /* 390 */ 1005, 1005, 1005, 1005, 1005, 1005, 1240, 1239, 1005, 1005, - /* 400 */ 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, - /* 410 */ 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, - /* 420 */ 1005, 1090, 1005, 1005, 1005, 1312, 1005, 1005, 1005, 1005, - /* 430 */ 1005, 1005, 1005, 1135, 1005, 1128, 1005, 1005, 1317, 1005, - /* 440 */ 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1005, 1278, - /* 450 */ 1005, 1005, 1005, 1277, 1005, 1005, 1005, 1005, 1005, 1161, - /* 460 */ 1005, 1160, 1164, 1005, 1017, 1005, + /* 0 */ 1297, 1349, 1221, 1014, 1119, 1221, 1221, 1221, 1221, 1014, + /* 10 */ 1145, 1145, 1272, 1045, 1014, 1014, 1014, 1014, 1014, 1220, + /* 20 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, + /* 30 */ 1014, 1151, 1014, 1014, 1014, 1014, 1222, 1223, 1014, 1014, + /* 40 */ 1014, 1271, 1273, 1161, 1160, 1159, 1158, 1254, 1132, 1156, + /* 50 */ 1149, 1153, 1216, 1217, 1215, 1219, 1222, 1223, 1014, 1152, + /* 60 */ 1186, 1200, 1185, 1014, 1014, 1014, 1014, 1014, 1014, 1014, + /* 70 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, + /* 80 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, + /* 90 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, + /* 100 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1194, + /* 110 */ 1199, 1206, 1198, 1195, 1188, 1187, 1189, 1190, 1014, 1035, + /* 120 */ 1084, 1014, 1014, 1014, 1289, 1288, 1014, 1014, 1045, 1191, + /* 130 */ 1192, 1203, 1202, 1201, 1279, 1305, 1304, 1014, 1014, 1014, + /* 140 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, + /* 150 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, + /* 160 */ 1014, 1014, 1014, 1014, 1014, 1014, 1045, 1297, 1041, 1041, + /* 170 */ 1014, 1284, 1119, 1110, 1014, 1014, 1014, 1014, 1014, 1014, + /* 180 */ 1014, 1014, 1014, 1014, 1014, 1276, 1274, 1014, 1236, 1014, + /* 190 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, + /* 200 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, + /* 210 */ 1014, 1014, 1014, 1115, 1014, 1014, 1014, 1014, 1014, 1014, + /* 220 */ 1014, 1014, 1014, 1014, 1299, 1014, 1249, 1098, 1115, 1115, + /* 230 */ 1115, 1115, 1117, 1099, 1097, 1109, 1045, 1021, 1155, 1134, + /* 240 */ 1134, 1338, 1155, 1338, 1059, 1319, 1056, 1145, 1145, 1145, + /* 250 */ 1134, 1218, 1116, 1109, 1014, 1341, 1124, 1124, 1340, 1340, + /* 260 */ 1124, 1166, 1087, 1155, 1093, 1093, 1093, 1093, 1124, 1032, + /* 270 */ 1155, 1166, 1087, 1087, 1155, 1124, 1032, 1253, 1335, 1124, + /* 280 */ 1032, 1229, 1124, 1032, 1124, 1032, 1229, 1085, 1085, 1085, + /* 290 */ 1074, 1229, 1085, 1059, 1085, 1074, 1085, 1085, 1229, 1233, + /* 300 */ 1233, 1229, 1138, 1133, 1138, 1133, 1138, 1133, 1138, 1133, + /* 310 */ 1124, 1224, 1124, 1014, 1150, 1139, 1148, 1146, 1155, 1038, + /* 320 */ 1077, 1302, 1302, 1298, 1298, 1298, 1346, 1346, 1284, 1314, + /* 330 */ 1045, 1045, 1045, 1045, 1314, 1061, 1061, 1045, 1045, 1045, + /* 340 */ 1045, 1314, 1014, 1014, 1014, 1014, 1014, 1014, 1309, 1014, + /* 350 */ 1238, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, + /* 360 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1171, + /* 370 */ 1014, 1017, 1281, 1014, 1014, 1280, 1014, 1014, 1014, 1014, + /* 380 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, + /* 390 */ 1014, 1014, 1014, 1014, 1014, 1014, 1337, 1014, 1014, 1014, + /* 400 */ 1014, 1014, 1014, 1252, 1251, 1014, 1014, 1126, 1014, 1014, + /* 410 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, + /* 420 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, + /* 430 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, + /* 440 */ 1014, 1014, 1147, 1014, 1140, 1014, 1014, 1014, 1014, 1328, + /* 450 */ 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, 1014, + /* 460 */ 1014, 1014, 1014, 1323, 1101, 1173, 1014, 1172, 1176, 1014, + /* 470 */ 1026, 1014, }; /********** End of lemon-generated parsing tables *****************************/ @@ -139293,7 +140969,7 @@ static const char *const yyTokenName[] = { /* 194 */ "fullname", /* 195 */ "selectnowith", /* 196 */ "oneselect", - /* 197 */ "with", + /* 197 */ "wqlist", /* 198 */ "multiselect_op", /* 199 */ "distinct", /* 200 */ "selcollist", @@ -139315,39 +140991,39 @@ static const char *const yyTokenName[] = { /* 216 */ "on_opt", /* 217 */ "using_opt", /* 218 */ "idlist", - /* 219 */ "setlist", - /* 220 */ "insert_cmd", - /* 221 */ "idlist_opt", - /* 222 */ "likeop", - /* 223 */ "between_op", - /* 224 */ "in_op", - /* 225 */ "paren_exprlist", - /* 226 */ "case_operand", - /* 227 */ "case_exprlist", - /* 228 */ "case_else", - /* 229 */ "uniqueflag", - /* 230 */ "collate", - /* 231 */ "nmnum", - /* 232 */ "trigger_decl", - /* 233 */ "trigger_cmd_list", - /* 234 */ "trigger_time", - /* 235 */ "trigger_event", - /* 236 */ "foreach_clause", - /* 237 */ "when_clause", - /* 238 */ "trigger_cmd", - /* 239 */ "trnm", - /* 240 */ "tridxby", - /* 241 */ "database_kw_opt", - /* 242 */ "key_opt", - /* 243 */ "add_column_fullname", - /* 244 */ "kwcolumn_opt", - /* 245 */ "create_vtab", - /* 246 */ "vtabarglist", - /* 247 */ "vtabarg", - /* 248 */ "vtabargtoken", - /* 249 */ "lp", - /* 250 */ "anylist", - /* 251 */ "wqlist", + /* 219 */ "with", + /* 220 */ "setlist", + /* 221 */ "insert_cmd", + /* 222 */ "idlist_opt", + /* 223 */ "likeop", + /* 224 */ "between_op", + /* 225 */ "in_op", + /* 226 */ "paren_exprlist", + /* 227 */ "case_operand", + /* 228 */ "case_exprlist", + /* 229 */ "case_else", + /* 230 */ "uniqueflag", + /* 231 */ "collate", + /* 232 */ "nmnum", + /* 233 */ "trigger_decl", + /* 234 */ "trigger_cmd_list", + /* 235 */ "trigger_time", + /* 236 */ "trigger_event", + /* 237 */ "foreach_clause", + /* 238 */ "when_clause", + /* 239 */ "trigger_cmd", + /* 240 */ "trnm", + /* 241 */ "tridxby", + /* 242 */ "database_kw_opt", + /* 243 */ "key_opt", + /* 244 */ "add_column_fullname", + /* 245 */ "kwcolumn_opt", + /* 246 */ "create_vtab", + /* 247 */ "vtabarglist", + /* 248 */ "vtabarg", + /* 249 */ "vtabargtoken", + /* 250 */ "lp", + /* 251 */ "anylist", }; #endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */ @@ -139435,256 +141111,259 @@ static const char *const yyRuleName[] = { /* 77 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select", /* 78 */ "cmd ::= DROP VIEW ifexists fullname", /* 79 */ "cmd ::= select", - /* 80 */ "select ::= with selectnowith", - /* 81 */ "selectnowith ::= selectnowith multiselect_op oneselect", - /* 82 */ "multiselect_op ::= UNION", - /* 83 */ "multiselect_op ::= UNION ALL", - /* 84 */ "multiselect_op ::= EXCEPT|INTERSECT", - /* 85 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt", - /* 86 */ "values ::= VALUES LP nexprlist RP", - /* 87 */ "values ::= values COMMA LP exprlist RP", - /* 88 */ "distinct ::= DISTINCT", - /* 89 */ "distinct ::= ALL", - /* 90 */ "distinct ::=", - /* 91 */ "sclp ::=", - /* 92 */ "selcollist ::= sclp scanpt expr scanpt as", - /* 93 */ "selcollist ::= sclp scanpt STAR", - /* 94 */ "selcollist ::= sclp scanpt nm DOT STAR", - /* 95 */ "as ::= AS nm", - /* 96 */ "as ::=", - /* 97 */ "from ::=", - /* 98 */ "from ::= FROM seltablist", - /* 99 */ "stl_prefix ::= seltablist joinop", - /* 100 */ "stl_prefix ::=", - /* 101 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt", - /* 102 */ "seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt", - /* 103 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt", - /* 104 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt", - /* 105 */ "dbnm ::=", - /* 106 */ "dbnm ::= DOT nm", - /* 107 */ "fullname ::= nm dbnm", - /* 108 */ "joinop ::= COMMA|JOIN", - /* 109 */ "joinop ::= JOIN_KW JOIN", - /* 110 */ "joinop ::= JOIN_KW nm JOIN", - /* 111 */ "joinop ::= JOIN_KW nm nm JOIN", - /* 112 */ "on_opt ::= ON expr", - /* 113 */ "on_opt ::=", - /* 114 */ "indexed_opt ::=", - /* 115 */ "indexed_opt ::= INDEXED BY nm", - /* 116 */ "indexed_opt ::= NOT INDEXED", - /* 117 */ "using_opt ::= USING LP idlist RP", - /* 118 */ "using_opt ::=", - /* 119 */ "orderby_opt ::=", - /* 120 */ "orderby_opt ::= ORDER BY sortlist", - /* 121 */ "sortlist ::= sortlist COMMA expr sortorder", - /* 122 */ "sortlist ::= expr sortorder", - /* 123 */ "sortorder ::= ASC", - /* 124 */ "sortorder ::= DESC", - /* 125 */ "sortorder ::=", - /* 126 */ "groupby_opt ::=", - /* 127 */ "groupby_opt ::= GROUP BY nexprlist", - /* 128 */ "having_opt ::=", - /* 129 */ "having_opt ::= HAVING expr", - /* 130 */ "limit_opt ::=", - /* 131 */ "limit_opt ::= LIMIT expr", - /* 132 */ "limit_opt ::= LIMIT expr OFFSET expr", - /* 133 */ "limit_opt ::= LIMIT expr COMMA expr", - /* 134 */ "cmd ::= with DELETE FROM fullname indexed_opt where_opt", - /* 135 */ "where_opt ::=", - /* 136 */ "where_opt ::= WHERE expr", - /* 137 */ "cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt", - /* 138 */ "setlist ::= setlist COMMA nm EQ expr", - /* 139 */ "setlist ::= setlist COMMA LP idlist RP EQ expr", - /* 140 */ "setlist ::= nm EQ expr", - /* 141 */ "setlist ::= LP idlist RP EQ expr", - /* 142 */ "cmd ::= with insert_cmd INTO fullname idlist_opt select", - /* 143 */ "cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES", - /* 144 */ "insert_cmd ::= INSERT orconf", - /* 145 */ "insert_cmd ::= REPLACE", - /* 146 */ "idlist_opt ::=", - /* 147 */ "idlist_opt ::= LP idlist RP", - /* 148 */ "idlist ::= idlist COMMA nm", - /* 149 */ "idlist ::= nm", - /* 150 */ "expr ::= LP expr RP", - /* 151 */ "expr ::= ID|INDEXED", - /* 152 */ "expr ::= JOIN_KW", - /* 153 */ "expr ::= nm DOT nm", - /* 154 */ "expr ::= nm DOT nm DOT nm", - /* 155 */ "term ::= NULL|FLOAT|BLOB", - /* 156 */ "term ::= STRING", - /* 157 */ "term ::= INTEGER", - /* 158 */ "expr ::= VARIABLE", - /* 159 */ "expr ::= expr COLLATE ID|STRING", - /* 160 */ "expr ::= CAST LP expr AS typetoken RP", - /* 161 */ "expr ::= ID|INDEXED LP distinct exprlist RP", - /* 162 */ "expr ::= ID|INDEXED LP STAR RP", - /* 163 */ "term ::= CTIME_KW", - /* 164 */ "expr ::= LP nexprlist COMMA expr RP", - /* 165 */ "expr ::= expr AND expr", - /* 166 */ "expr ::= expr OR expr", - /* 167 */ "expr ::= expr LT|GT|GE|LE expr", - /* 168 */ "expr ::= expr EQ|NE expr", - /* 169 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", - /* 170 */ "expr ::= expr PLUS|MINUS expr", - /* 171 */ "expr ::= expr STAR|SLASH|REM expr", - /* 172 */ "expr ::= expr CONCAT expr", - /* 173 */ "likeop ::= NOT LIKE_KW|MATCH", - /* 174 */ "expr ::= expr likeop expr", - /* 175 */ "expr ::= expr likeop expr ESCAPE expr", - /* 176 */ "expr ::= expr ISNULL|NOTNULL", - /* 177 */ "expr ::= expr NOT NULL", - /* 178 */ "expr ::= expr IS expr", - /* 179 */ "expr ::= expr IS NOT expr", - /* 180 */ "expr ::= NOT expr", - /* 181 */ "expr ::= BITNOT expr", - /* 182 */ "expr ::= MINUS expr", - /* 183 */ "expr ::= PLUS expr", - /* 184 */ "between_op ::= BETWEEN", - /* 185 */ "between_op ::= NOT BETWEEN", - /* 186 */ "expr ::= expr between_op expr AND expr", - /* 187 */ "in_op ::= IN", - /* 188 */ "in_op ::= NOT IN", - /* 189 */ "expr ::= expr in_op LP exprlist RP", - /* 190 */ "expr ::= LP select RP", - /* 191 */ "expr ::= expr in_op LP select RP", - /* 192 */ "expr ::= expr in_op nm dbnm paren_exprlist", - /* 193 */ "expr ::= EXISTS LP select RP", - /* 194 */ "expr ::= CASE case_operand case_exprlist case_else END", - /* 195 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", - /* 196 */ "case_exprlist ::= WHEN expr THEN expr", - /* 197 */ "case_else ::= ELSE expr", - /* 198 */ "case_else ::=", - /* 199 */ "case_operand ::= expr", - /* 200 */ "case_operand ::=", - /* 201 */ "exprlist ::=", - /* 202 */ "nexprlist ::= nexprlist COMMA expr", - /* 203 */ "nexprlist ::= expr", - /* 204 */ "paren_exprlist ::=", - /* 205 */ "paren_exprlist ::= LP exprlist RP", - /* 206 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt", - /* 207 */ "uniqueflag ::= UNIQUE", - /* 208 */ "uniqueflag ::=", - /* 209 */ "eidlist_opt ::=", - /* 210 */ "eidlist_opt ::= LP eidlist RP", - /* 211 */ "eidlist ::= eidlist COMMA nm collate sortorder", - /* 212 */ "eidlist ::= nm collate sortorder", - /* 213 */ "collate ::=", - /* 214 */ "collate ::= COLLATE ID|STRING", - /* 215 */ "cmd ::= DROP INDEX ifexists fullname", - /* 216 */ "cmd ::= VACUUM", - /* 217 */ "cmd ::= VACUUM nm", - /* 218 */ "cmd ::= PRAGMA nm dbnm", - /* 219 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", - /* 220 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", - /* 221 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", - /* 222 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", - /* 223 */ "plus_num ::= PLUS INTEGER|FLOAT", - /* 224 */ "minus_num ::= MINUS INTEGER|FLOAT", - /* 225 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", - /* 226 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", - /* 227 */ "trigger_time ::= BEFORE|AFTER", - /* 228 */ "trigger_time ::= INSTEAD OF", - /* 229 */ "trigger_time ::=", - /* 230 */ "trigger_event ::= DELETE|INSERT", - /* 231 */ "trigger_event ::= UPDATE", - /* 232 */ "trigger_event ::= UPDATE OF idlist", - /* 233 */ "when_clause ::=", - /* 234 */ "when_clause ::= WHEN expr", - /* 235 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", - /* 236 */ "trigger_cmd_list ::= trigger_cmd SEMI", - /* 237 */ "trnm ::= nm DOT nm", - /* 238 */ "tridxby ::= INDEXED BY nm", - /* 239 */ "tridxby ::= NOT INDEXED", - /* 240 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt", - /* 241 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select scanpt", - /* 242 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt", - /* 243 */ "trigger_cmd ::= scanpt select scanpt", - /* 244 */ "expr ::= RAISE LP IGNORE RP", - /* 245 */ "expr ::= RAISE LP raisetype COMMA nm RP", - /* 246 */ "raisetype ::= ROLLBACK", - /* 247 */ "raisetype ::= ABORT", - /* 248 */ "raisetype ::= FAIL", - /* 249 */ "cmd ::= DROP TRIGGER ifexists fullname", - /* 250 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", - /* 251 */ "cmd ::= DETACH database_kw_opt expr", - /* 252 */ "key_opt ::=", - /* 253 */ "key_opt ::= KEY expr", - /* 254 */ "cmd ::= REINDEX", - /* 255 */ "cmd ::= REINDEX nm dbnm", - /* 256 */ "cmd ::= ANALYZE", - /* 257 */ "cmd ::= ANALYZE nm dbnm", - /* 258 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", - /* 259 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist", - /* 260 */ "add_column_fullname ::= fullname", - /* 261 */ "cmd ::= create_vtab", - /* 262 */ "cmd ::= create_vtab LP vtabarglist RP", - /* 263 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", - /* 264 */ "vtabarg ::=", - /* 265 */ "vtabargtoken ::= ANY", - /* 266 */ "vtabargtoken ::= lp anylist RP", - /* 267 */ "lp ::= LP", - /* 268 */ "with ::=", - /* 269 */ "with ::= WITH wqlist", - /* 270 */ "with ::= WITH RECURSIVE wqlist", - /* 271 */ "wqlist ::= nm eidlist_opt AS LP select RP", - /* 272 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP", - /* 273 */ "input ::= cmdlist", - /* 274 */ "cmdlist ::= cmdlist ecmd", - /* 275 */ "cmdlist ::= ecmd", - /* 276 */ "ecmd ::= SEMI", - /* 277 */ "ecmd ::= explain cmdx SEMI", - /* 278 */ "explain ::=", - /* 279 */ "trans_opt ::=", - /* 280 */ "trans_opt ::= TRANSACTION", - /* 281 */ "trans_opt ::= TRANSACTION nm", - /* 282 */ "savepoint_opt ::= SAVEPOINT", - /* 283 */ "savepoint_opt ::=", - /* 284 */ "cmd ::= create_table create_table_args", - /* 285 */ "columnlist ::= columnlist COMMA columnname carglist", - /* 286 */ "columnlist ::= columnname carglist", - /* 287 */ "nm ::= ID|INDEXED", - /* 288 */ "nm ::= STRING", - /* 289 */ "nm ::= JOIN_KW", - /* 290 */ "typetoken ::= typename", - /* 291 */ "typename ::= ID|STRING", - /* 292 */ "signed ::= plus_num", - /* 293 */ "signed ::= minus_num", - /* 294 */ "carglist ::= carglist ccons", - /* 295 */ "carglist ::=", - /* 296 */ "ccons ::= NULL onconf", - /* 297 */ "conslist_opt ::= COMMA conslist", - /* 298 */ "conslist ::= conslist tconscomma tcons", - /* 299 */ "conslist ::= tcons", - /* 300 */ "tconscomma ::=", - /* 301 */ "defer_subclause_opt ::= defer_subclause", - /* 302 */ "resolvetype ::= raisetype", - /* 303 */ "selectnowith ::= oneselect", - /* 304 */ "oneselect ::= values", - /* 305 */ "sclp ::= selcollist COMMA", - /* 306 */ "as ::= ID|STRING", - /* 307 */ "expr ::= term", - /* 308 */ "likeop ::= LIKE_KW|MATCH", - /* 309 */ "exprlist ::= nexprlist", - /* 310 */ "nmnum ::= plus_num", - /* 311 */ "nmnum ::= nm", - /* 312 */ "nmnum ::= ON", - /* 313 */ "nmnum ::= DELETE", - /* 314 */ "nmnum ::= DEFAULT", - /* 315 */ "plus_num ::= INTEGER|FLOAT", - /* 316 */ "foreach_clause ::=", - /* 317 */ "foreach_clause ::= FOR EACH ROW", - /* 318 */ "trnm ::= nm", - /* 319 */ "tridxby ::=", - /* 320 */ "database_kw_opt ::= DATABASE", - /* 321 */ "database_kw_opt ::=", - /* 322 */ "kwcolumn_opt ::=", - /* 323 */ "kwcolumn_opt ::= COLUMNKW", - /* 324 */ "vtabarglist ::= vtabarg", - /* 325 */ "vtabarglist ::= vtabarglist COMMA vtabarg", - /* 326 */ "vtabarg ::= vtabarg vtabargtoken", - /* 327 */ "anylist ::=", - /* 328 */ "anylist ::= anylist LP anylist RP", - /* 329 */ "anylist ::= anylist ANY", + /* 80 */ "select ::= WITH wqlist selectnowith", + /* 81 */ "select ::= WITH RECURSIVE wqlist selectnowith", + /* 82 */ "select ::= selectnowith", + /* 83 */ "selectnowith ::= selectnowith multiselect_op oneselect", + /* 84 */ "multiselect_op ::= UNION", + /* 85 */ "multiselect_op ::= UNION ALL", + /* 86 */ "multiselect_op ::= EXCEPT|INTERSECT", + /* 87 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt", + /* 88 */ "values ::= VALUES LP nexprlist RP", + /* 89 */ "values ::= values COMMA LP exprlist RP", + /* 90 */ "distinct ::= DISTINCT", + /* 91 */ "distinct ::= ALL", + /* 92 */ "distinct ::=", + /* 93 */ "sclp ::=", + /* 94 */ "selcollist ::= sclp scanpt expr scanpt as", + /* 95 */ "selcollist ::= sclp scanpt STAR", + /* 96 */ "selcollist ::= sclp scanpt nm DOT STAR", + /* 97 */ "as ::= AS nm", + /* 98 */ "as ::=", + /* 99 */ "from ::=", + /* 100 */ "from ::= FROM seltablist", + /* 101 */ "stl_prefix ::= seltablist joinop", + /* 102 */ "stl_prefix ::=", + /* 103 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt", + /* 104 */ "seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt", + /* 105 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt", + /* 106 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt", + /* 107 */ "dbnm ::=", + /* 108 */ "dbnm ::= DOT nm", + /* 109 */ "fullname ::= nm", + /* 110 */ "fullname ::= nm DOT nm", + /* 111 */ "joinop ::= COMMA|JOIN", + /* 112 */ "joinop ::= JOIN_KW JOIN", + /* 113 */ "joinop ::= JOIN_KW nm JOIN", + /* 114 */ "joinop ::= JOIN_KW nm nm JOIN", + /* 115 */ "on_opt ::= ON expr", + /* 116 */ "on_opt ::=", + /* 117 */ "indexed_opt ::=", + /* 118 */ "indexed_opt ::= INDEXED BY nm", + /* 119 */ "indexed_opt ::= NOT INDEXED", + /* 120 */ "using_opt ::= USING LP idlist RP", + /* 121 */ "using_opt ::=", + /* 122 */ "orderby_opt ::=", + /* 123 */ "orderby_opt ::= ORDER BY sortlist", + /* 124 */ "sortlist ::= sortlist COMMA expr sortorder", + /* 125 */ "sortlist ::= expr sortorder", + /* 126 */ "sortorder ::= ASC", + /* 127 */ "sortorder ::= DESC", + /* 128 */ "sortorder ::=", + /* 129 */ "groupby_opt ::=", + /* 130 */ "groupby_opt ::= GROUP BY nexprlist", + /* 131 */ "having_opt ::=", + /* 132 */ "having_opt ::= HAVING expr", + /* 133 */ "limit_opt ::=", + /* 134 */ "limit_opt ::= LIMIT expr", + /* 135 */ "limit_opt ::= LIMIT expr OFFSET expr", + /* 136 */ "limit_opt ::= LIMIT expr COMMA expr", + /* 137 */ "cmd ::= with DELETE FROM fullname indexed_opt where_opt", + /* 138 */ "where_opt ::=", + /* 139 */ "where_opt ::= WHERE expr", + /* 140 */ "cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt", + /* 141 */ "setlist ::= setlist COMMA nm EQ expr", + /* 142 */ "setlist ::= setlist COMMA LP idlist RP EQ expr", + /* 143 */ "setlist ::= nm EQ expr", + /* 144 */ "setlist ::= LP idlist RP EQ expr", + /* 145 */ "cmd ::= with insert_cmd INTO fullname idlist_opt select", + /* 146 */ "cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES", + /* 147 */ "insert_cmd ::= INSERT orconf", + /* 148 */ "insert_cmd ::= REPLACE", + /* 149 */ "idlist_opt ::=", + /* 150 */ "idlist_opt ::= LP idlist RP", + /* 151 */ "idlist ::= idlist COMMA nm", + /* 152 */ "idlist ::= nm", + /* 153 */ "expr ::= LP expr RP", + /* 154 */ "expr ::= ID|INDEXED", + /* 155 */ "expr ::= JOIN_KW", + /* 156 */ "expr ::= nm DOT nm", + /* 157 */ "expr ::= nm DOT nm DOT nm", + /* 158 */ "term ::= NULL|FLOAT|BLOB", + /* 159 */ "term ::= STRING", + /* 160 */ "term ::= INTEGER", + /* 161 */ "expr ::= VARIABLE", + /* 162 */ "expr ::= expr COLLATE ID|STRING", + /* 163 */ "expr ::= CAST LP expr AS typetoken RP", + /* 164 */ "expr ::= ID|INDEXED LP distinct exprlist RP", + /* 165 */ "expr ::= ID|INDEXED LP STAR RP", + /* 166 */ "term ::= CTIME_KW", + /* 167 */ "expr ::= LP nexprlist COMMA expr RP", + /* 168 */ "expr ::= expr AND expr", + /* 169 */ "expr ::= expr OR expr", + /* 170 */ "expr ::= expr LT|GT|GE|LE expr", + /* 171 */ "expr ::= expr EQ|NE expr", + /* 172 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", + /* 173 */ "expr ::= expr PLUS|MINUS expr", + /* 174 */ "expr ::= expr STAR|SLASH|REM expr", + /* 175 */ "expr ::= expr CONCAT expr", + /* 176 */ "likeop ::= NOT LIKE_KW|MATCH", + /* 177 */ "expr ::= expr likeop expr", + /* 178 */ "expr ::= expr likeop expr ESCAPE expr", + /* 179 */ "expr ::= expr ISNULL|NOTNULL", + /* 180 */ "expr ::= expr NOT NULL", + /* 181 */ "expr ::= expr IS expr", + /* 182 */ "expr ::= expr IS NOT expr", + /* 183 */ "expr ::= NOT expr", + /* 184 */ "expr ::= BITNOT expr", + /* 185 */ "expr ::= MINUS expr", + /* 186 */ "expr ::= PLUS expr", + /* 187 */ "between_op ::= BETWEEN", + /* 188 */ "between_op ::= NOT BETWEEN", + /* 189 */ "expr ::= expr between_op expr AND expr", + /* 190 */ "in_op ::= IN", + /* 191 */ "in_op ::= NOT IN", + /* 192 */ "expr ::= expr in_op LP exprlist RP", + /* 193 */ "expr ::= LP select RP", + /* 194 */ "expr ::= expr in_op LP select RP", + /* 195 */ "expr ::= expr in_op nm dbnm paren_exprlist", + /* 196 */ "expr ::= EXISTS LP select RP", + /* 197 */ "expr ::= CASE case_operand case_exprlist case_else END", + /* 198 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", + /* 199 */ "case_exprlist ::= WHEN expr THEN expr", + /* 200 */ "case_else ::= ELSE expr", + /* 201 */ "case_else ::=", + /* 202 */ "case_operand ::= expr", + /* 203 */ "case_operand ::=", + /* 204 */ "exprlist ::=", + /* 205 */ "nexprlist ::= nexprlist COMMA expr", + /* 206 */ "nexprlist ::= expr", + /* 207 */ "paren_exprlist ::=", + /* 208 */ "paren_exprlist ::= LP exprlist RP", + /* 209 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt", + /* 210 */ "uniqueflag ::= UNIQUE", + /* 211 */ "uniqueflag ::=", + /* 212 */ "eidlist_opt ::=", + /* 213 */ "eidlist_opt ::= LP eidlist RP", + /* 214 */ "eidlist ::= eidlist COMMA nm collate sortorder", + /* 215 */ "eidlist ::= nm collate sortorder", + /* 216 */ "collate ::=", + /* 217 */ "collate ::= COLLATE ID|STRING", + /* 218 */ "cmd ::= DROP INDEX ifexists fullname", + /* 219 */ "cmd ::= VACUUM", + /* 220 */ "cmd ::= VACUUM nm", + /* 221 */ "cmd ::= PRAGMA nm dbnm", + /* 222 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", + /* 223 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", + /* 224 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", + /* 225 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", + /* 226 */ "plus_num ::= PLUS INTEGER|FLOAT", + /* 227 */ "minus_num ::= MINUS INTEGER|FLOAT", + /* 228 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", + /* 229 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", + /* 230 */ "trigger_time ::= BEFORE|AFTER", + /* 231 */ "trigger_time ::= INSTEAD OF", + /* 232 */ "trigger_time ::=", + /* 233 */ "trigger_event ::= DELETE|INSERT", + /* 234 */ "trigger_event ::= UPDATE", + /* 235 */ "trigger_event ::= UPDATE OF idlist", + /* 236 */ "when_clause ::=", + /* 237 */ "when_clause ::= WHEN expr", + /* 238 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", + /* 239 */ "trigger_cmd_list ::= trigger_cmd SEMI", + /* 240 */ "trnm ::= nm DOT nm", + /* 241 */ "tridxby ::= INDEXED BY nm", + /* 242 */ "tridxby ::= NOT INDEXED", + /* 243 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt", + /* 244 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select scanpt", + /* 245 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt", + /* 246 */ "trigger_cmd ::= scanpt select scanpt", + /* 247 */ "expr ::= RAISE LP IGNORE RP", + /* 248 */ "expr ::= RAISE LP raisetype COMMA nm RP", + /* 249 */ "raisetype ::= ROLLBACK", + /* 250 */ "raisetype ::= ABORT", + /* 251 */ "raisetype ::= FAIL", + /* 252 */ "cmd ::= DROP TRIGGER ifexists fullname", + /* 253 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", + /* 254 */ "cmd ::= DETACH database_kw_opt expr", + /* 255 */ "key_opt ::=", + /* 256 */ "key_opt ::= KEY expr", + /* 257 */ "cmd ::= REINDEX", + /* 258 */ "cmd ::= REINDEX nm dbnm", + /* 259 */ "cmd ::= ANALYZE", + /* 260 */ "cmd ::= ANALYZE nm dbnm", + /* 261 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", + /* 262 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist", + /* 263 */ "add_column_fullname ::= fullname", + /* 264 */ "cmd ::= create_vtab", + /* 265 */ "cmd ::= create_vtab LP vtabarglist RP", + /* 266 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", + /* 267 */ "vtabarg ::=", + /* 268 */ "vtabargtoken ::= ANY", + /* 269 */ "vtabargtoken ::= lp anylist RP", + /* 270 */ "lp ::= LP", + /* 271 */ "with ::= WITH wqlist", + /* 272 */ "with ::= WITH RECURSIVE wqlist", + /* 273 */ "wqlist ::= nm eidlist_opt AS LP select RP", + /* 274 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP", + /* 275 */ "input ::= cmdlist", + /* 276 */ "cmdlist ::= cmdlist ecmd", + /* 277 */ "cmdlist ::= ecmd", + /* 278 */ "ecmd ::= SEMI", + /* 279 */ "ecmd ::= explain cmdx SEMI", + /* 280 */ "explain ::=", + /* 281 */ "trans_opt ::=", + /* 282 */ "trans_opt ::= TRANSACTION", + /* 283 */ "trans_opt ::= TRANSACTION nm", + /* 284 */ "savepoint_opt ::= SAVEPOINT", + /* 285 */ "savepoint_opt ::=", + /* 286 */ "cmd ::= create_table create_table_args", + /* 287 */ "columnlist ::= columnlist COMMA columnname carglist", + /* 288 */ "columnlist ::= columnname carglist", + /* 289 */ "nm ::= ID|INDEXED", + /* 290 */ "nm ::= STRING", + /* 291 */ "nm ::= JOIN_KW", + /* 292 */ "typetoken ::= typename", + /* 293 */ "typename ::= ID|STRING", + /* 294 */ "signed ::= plus_num", + /* 295 */ "signed ::= minus_num", + /* 296 */ "carglist ::= carglist ccons", + /* 297 */ "carglist ::=", + /* 298 */ "ccons ::= NULL onconf", + /* 299 */ "conslist_opt ::= COMMA conslist", + /* 300 */ "conslist ::= conslist tconscomma tcons", + /* 301 */ "conslist ::= tcons", + /* 302 */ "tconscomma ::=", + /* 303 */ "defer_subclause_opt ::= defer_subclause", + /* 304 */ "resolvetype ::= raisetype", + /* 305 */ "selectnowith ::= oneselect", + /* 306 */ "oneselect ::= values", + /* 307 */ "sclp ::= selcollist COMMA", + /* 308 */ "as ::= ID|STRING", + /* 309 */ "expr ::= term", + /* 310 */ "likeop ::= LIKE_KW|MATCH", + /* 311 */ "exprlist ::= nexprlist", + /* 312 */ "nmnum ::= plus_num", + /* 313 */ "nmnum ::= nm", + /* 314 */ "nmnum ::= ON", + /* 315 */ "nmnum ::= DELETE", + /* 316 */ "nmnum ::= DEFAULT", + /* 317 */ "plus_num ::= INTEGER|FLOAT", + /* 318 */ "foreach_clause ::=", + /* 319 */ "foreach_clause ::= FOR EACH ROW", + /* 320 */ "trnm ::= nm", + /* 321 */ "tridxby ::=", + /* 322 */ "database_kw_opt ::= DATABASE", + /* 323 */ "database_kw_opt ::=", + /* 324 */ "kwcolumn_opt ::=", + /* 325 */ "kwcolumn_opt ::= COLUMNKW", + /* 326 */ "vtabarglist ::= vtabarg", + /* 327 */ "vtabarglist ::= vtabarglist COMMA vtabarg", + /* 328 */ "vtabarg ::= vtabarg vtabargtoken", + /* 329 */ "anylist ::=", + /* 330 */ "anylist ::= anylist LP anylist RP", + /* 331 */ "anylist ::= anylist ANY", + /* 332 */ "with ::=", }; #endif /* NDEBUG */ @@ -139818,10 +141497,10 @@ sqlite3SelectDelete(pParse->db, (yypminor->yy387)); case 202: /* where_opt */ case 204: /* having_opt */ case 216: /* on_opt */ - case 226: /* case_operand */ - case 228: /* case_else */ - case 237: /* when_clause */ - case 242: /* key_opt */ + case 227: /* case_operand */ + case 229: /* case_else */ + case 238: /* when_clause */ + case 243: /* key_opt */ { sqlite3ExprDelete(pParse->db, (yypminor->yy314)); } @@ -139835,9 +141514,9 @@ sqlite3ExprDelete(pParse->db, (yypminor->yy314)); case 208: /* nexprlist */ case 209: /* exprlist */ case 210: /* sclp */ - case 219: /* setlist */ - case 225: /* paren_exprlist */ - case 227: /* case_exprlist */ + case 220: /* setlist */ + case 226: /* paren_exprlist */ + case 228: /* case_exprlist */ { sqlite3ExprListDelete(pParse->db, (yypminor->yy322)); } @@ -139850,26 +141529,25 @@ sqlite3ExprListDelete(pParse->db, (yypminor->yy322)); sqlite3SrcListDelete(pParse->db, (yypminor->yy259)); } break; - case 197: /* with */ - case 251: /* wqlist */ + case 197: /* wqlist */ { sqlite3WithDelete(pParse->db, (yypminor->yy451)); } break; case 217: /* using_opt */ case 218: /* idlist */ - case 221: /* idlist_opt */ + case 222: /* idlist_opt */ { sqlite3IdListDelete(pParse->db, (yypminor->yy384)); } break; - case 233: /* trigger_cmd_list */ - case 238: /* trigger_cmd */ + case 234: /* trigger_cmd_list */ + case 239: /* trigger_cmd */ { sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy203)); } break; - case 235: /* trigger_event */ + case 236: /* trigger_event */ { sqlite3IdListDelete(pParse->db, (yypminor->yy90).b); } @@ -139997,7 +141675,8 @@ static unsigned int yy_find_shift_action( #endif do{ i = yy_shift_ofst[stateno]; - assert( i>=0 && i+YYNTOKEN<=sizeof(yy_lookahead)/sizeof(yy_lookahead[0]) ); + assert( i>=0 ); + assert( i+YYNTOKEN<=(int)sizeof(yy_lookahead)/sizeof(yy_lookahead[0]) ); assert( iLookAhead!=YYNOCODE ); assert( iLookAhead < YYNTOKEN ); i += iLookAhead; @@ -140247,256 +141926,259 @@ static const struct { { 149, -9 }, /* (77) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */ { 149, -4 }, /* (78) cmd ::= DROP VIEW ifexists fullname */ { 149, -1 }, /* (79) cmd ::= select */ - { 163, -2 }, /* (80) select ::= with selectnowith */ - { 195, -3 }, /* (81) selectnowith ::= selectnowith multiselect_op oneselect */ - { 198, -1 }, /* (82) multiselect_op ::= UNION */ - { 198, -2 }, /* (83) multiselect_op ::= UNION ALL */ - { 198, -1 }, /* (84) multiselect_op ::= EXCEPT|INTERSECT */ - { 196, -9 }, /* (85) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ - { 207, -4 }, /* (86) values ::= VALUES LP nexprlist RP */ - { 207, -5 }, /* (87) values ::= values COMMA LP exprlist RP */ - { 199, -1 }, /* (88) distinct ::= DISTINCT */ - { 199, -1 }, /* (89) distinct ::= ALL */ - { 199, 0 }, /* (90) distinct ::= */ - { 210, 0 }, /* (91) sclp ::= */ - { 200, -5 }, /* (92) selcollist ::= sclp scanpt expr scanpt as */ - { 200, -3 }, /* (93) selcollist ::= sclp scanpt STAR */ - { 200, -5 }, /* (94) selcollist ::= sclp scanpt nm DOT STAR */ - { 211, -2 }, /* (95) as ::= AS nm */ - { 211, 0 }, /* (96) as ::= */ - { 201, 0 }, /* (97) from ::= */ - { 201, -2 }, /* (98) from ::= FROM seltablist */ - { 213, -2 }, /* (99) stl_prefix ::= seltablist joinop */ - { 213, 0 }, /* (100) stl_prefix ::= */ - { 212, -7 }, /* (101) seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */ - { 212, -9 }, /* (102) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */ - { 212, -7 }, /* (103) seltablist ::= stl_prefix LP select RP as on_opt using_opt */ - { 212, -7 }, /* (104) seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ - { 159, 0 }, /* (105) dbnm ::= */ - { 159, -2 }, /* (106) dbnm ::= DOT nm */ - { 194, -2 }, /* (107) fullname ::= nm dbnm */ - { 214, -1 }, /* (108) joinop ::= COMMA|JOIN */ - { 214, -2 }, /* (109) joinop ::= JOIN_KW JOIN */ - { 214, -3 }, /* (110) joinop ::= JOIN_KW nm JOIN */ - { 214, -4 }, /* (111) joinop ::= JOIN_KW nm nm JOIN */ - { 216, -2 }, /* (112) on_opt ::= ON expr */ - { 216, 0 }, /* (113) on_opt ::= */ - { 215, 0 }, /* (114) indexed_opt ::= */ - { 215, -3 }, /* (115) indexed_opt ::= INDEXED BY nm */ - { 215, -2 }, /* (116) indexed_opt ::= NOT INDEXED */ - { 217, -4 }, /* (117) using_opt ::= USING LP idlist RP */ - { 217, 0 }, /* (118) using_opt ::= */ - { 205, 0 }, /* (119) orderby_opt ::= */ - { 205, -3 }, /* (120) orderby_opt ::= ORDER BY sortlist */ - { 187, -4 }, /* (121) sortlist ::= sortlist COMMA expr sortorder */ - { 187, -2 }, /* (122) sortlist ::= expr sortorder */ - { 176, -1 }, /* (123) sortorder ::= ASC */ - { 176, -1 }, /* (124) sortorder ::= DESC */ - { 176, 0 }, /* (125) sortorder ::= */ - { 203, 0 }, /* (126) groupby_opt ::= */ - { 203, -3 }, /* (127) groupby_opt ::= GROUP BY nexprlist */ - { 204, 0 }, /* (128) having_opt ::= */ - { 204, -2 }, /* (129) having_opt ::= HAVING expr */ - { 206, 0 }, /* (130) limit_opt ::= */ - { 206, -2 }, /* (131) limit_opt ::= LIMIT expr */ - { 206, -4 }, /* (132) limit_opt ::= LIMIT expr OFFSET expr */ - { 206, -4 }, /* (133) limit_opt ::= LIMIT expr COMMA expr */ - { 149, -6 }, /* (134) cmd ::= with DELETE FROM fullname indexed_opt where_opt */ - { 202, 0 }, /* (135) where_opt ::= */ - { 202, -2 }, /* (136) where_opt ::= WHERE expr */ - { 149, -8 }, /* (137) cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt */ - { 219, -5 }, /* (138) setlist ::= setlist COMMA nm EQ expr */ - { 219, -7 }, /* (139) setlist ::= setlist COMMA LP idlist RP EQ expr */ - { 219, -3 }, /* (140) setlist ::= nm EQ expr */ - { 219, -5 }, /* (141) setlist ::= LP idlist RP EQ expr */ - { 149, -6 }, /* (142) cmd ::= with insert_cmd INTO fullname idlist_opt select */ - { 149, -7 }, /* (143) cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES */ - { 220, -2 }, /* (144) insert_cmd ::= INSERT orconf */ - { 220, -1 }, /* (145) insert_cmd ::= REPLACE */ - { 221, 0 }, /* (146) idlist_opt ::= */ - { 221, -3 }, /* (147) idlist_opt ::= LP idlist RP */ - { 218, -3 }, /* (148) idlist ::= idlist COMMA nm */ - { 218, -1 }, /* (149) idlist ::= nm */ - { 174, -3 }, /* (150) expr ::= LP expr RP */ - { 174, -1 }, /* (151) expr ::= ID|INDEXED */ - { 174, -1 }, /* (152) expr ::= JOIN_KW */ - { 174, -3 }, /* (153) expr ::= nm DOT nm */ - { 174, -5 }, /* (154) expr ::= nm DOT nm DOT nm */ - { 173, -1 }, /* (155) term ::= NULL|FLOAT|BLOB */ - { 173, -1 }, /* (156) term ::= STRING */ - { 173, -1 }, /* (157) term ::= INTEGER */ - { 174, -1 }, /* (158) expr ::= VARIABLE */ - { 174, -3 }, /* (159) expr ::= expr COLLATE ID|STRING */ - { 174, -6 }, /* (160) expr ::= CAST LP expr AS typetoken RP */ - { 174, -5 }, /* (161) expr ::= ID|INDEXED LP distinct exprlist RP */ - { 174, -4 }, /* (162) expr ::= ID|INDEXED LP STAR RP */ - { 173, -1 }, /* (163) term ::= CTIME_KW */ - { 174, -5 }, /* (164) expr ::= LP nexprlist COMMA expr RP */ - { 174, -3 }, /* (165) expr ::= expr AND expr */ - { 174, -3 }, /* (166) expr ::= expr OR expr */ - { 174, -3 }, /* (167) expr ::= expr LT|GT|GE|LE expr */ - { 174, -3 }, /* (168) expr ::= expr EQ|NE expr */ - { 174, -3 }, /* (169) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ - { 174, -3 }, /* (170) expr ::= expr PLUS|MINUS expr */ - { 174, -3 }, /* (171) expr ::= expr STAR|SLASH|REM expr */ - { 174, -3 }, /* (172) expr ::= expr CONCAT expr */ - { 222, -2 }, /* (173) likeop ::= NOT LIKE_KW|MATCH */ - { 174, -3 }, /* (174) expr ::= expr likeop expr */ - { 174, -5 }, /* (175) expr ::= expr likeop expr ESCAPE expr */ - { 174, -2 }, /* (176) expr ::= expr ISNULL|NOTNULL */ - { 174, -3 }, /* (177) expr ::= expr NOT NULL */ - { 174, -3 }, /* (178) expr ::= expr IS expr */ - { 174, -4 }, /* (179) expr ::= expr IS NOT expr */ - { 174, -2 }, /* (180) expr ::= NOT expr */ - { 174, -2 }, /* (181) expr ::= BITNOT expr */ - { 174, -2 }, /* (182) expr ::= MINUS expr */ - { 174, -2 }, /* (183) expr ::= PLUS expr */ - { 223, -1 }, /* (184) between_op ::= BETWEEN */ - { 223, -2 }, /* (185) between_op ::= NOT BETWEEN */ - { 174, -5 }, /* (186) expr ::= expr between_op expr AND expr */ - { 224, -1 }, /* (187) in_op ::= IN */ - { 224, -2 }, /* (188) in_op ::= NOT IN */ - { 174, -5 }, /* (189) expr ::= expr in_op LP exprlist RP */ - { 174, -3 }, /* (190) expr ::= LP select RP */ - { 174, -5 }, /* (191) expr ::= expr in_op LP select RP */ - { 174, -5 }, /* (192) expr ::= expr in_op nm dbnm paren_exprlist */ - { 174, -4 }, /* (193) expr ::= EXISTS LP select RP */ - { 174, -5 }, /* (194) expr ::= CASE case_operand case_exprlist case_else END */ - { 227, -5 }, /* (195) case_exprlist ::= case_exprlist WHEN expr THEN expr */ - { 227, -4 }, /* (196) case_exprlist ::= WHEN expr THEN expr */ - { 228, -2 }, /* (197) case_else ::= ELSE expr */ - { 228, 0 }, /* (198) case_else ::= */ - { 226, -1 }, /* (199) case_operand ::= expr */ - { 226, 0 }, /* (200) case_operand ::= */ - { 209, 0 }, /* (201) exprlist ::= */ - { 208, -3 }, /* (202) nexprlist ::= nexprlist COMMA expr */ - { 208, -1 }, /* (203) nexprlist ::= expr */ - { 225, 0 }, /* (204) paren_exprlist ::= */ - { 225, -3 }, /* (205) paren_exprlist ::= LP exprlist RP */ - { 149, -12 }, /* (206) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ - { 229, -1 }, /* (207) uniqueflag ::= UNIQUE */ - { 229, 0 }, /* (208) uniqueflag ::= */ - { 178, 0 }, /* (209) eidlist_opt ::= */ - { 178, -3 }, /* (210) eidlist_opt ::= LP eidlist RP */ - { 188, -5 }, /* (211) eidlist ::= eidlist COMMA nm collate sortorder */ - { 188, -3 }, /* (212) eidlist ::= nm collate sortorder */ - { 230, 0 }, /* (213) collate ::= */ - { 230, -2 }, /* (214) collate ::= COLLATE ID|STRING */ - { 149, -4 }, /* (215) cmd ::= DROP INDEX ifexists fullname */ - { 149, -1 }, /* (216) cmd ::= VACUUM */ - { 149, -2 }, /* (217) cmd ::= VACUUM nm */ - { 149, -3 }, /* (218) cmd ::= PRAGMA nm dbnm */ - { 149, -5 }, /* (219) cmd ::= PRAGMA nm dbnm EQ nmnum */ - { 149, -6 }, /* (220) cmd ::= PRAGMA nm dbnm LP nmnum RP */ - { 149, -5 }, /* (221) cmd ::= PRAGMA nm dbnm EQ minus_num */ - { 149, -6 }, /* (222) cmd ::= PRAGMA nm dbnm LP minus_num RP */ - { 169, -2 }, /* (223) plus_num ::= PLUS INTEGER|FLOAT */ - { 170, -2 }, /* (224) minus_num ::= MINUS INTEGER|FLOAT */ - { 149, -5 }, /* (225) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ - { 232, -11 }, /* (226) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ - { 234, -1 }, /* (227) trigger_time ::= BEFORE|AFTER */ - { 234, -2 }, /* (228) trigger_time ::= INSTEAD OF */ - { 234, 0 }, /* (229) trigger_time ::= */ - { 235, -1 }, /* (230) trigger_event ::= DELETE|INSERT */ - { 235, -1 }, /* (231) trigger_event ::= UPDATE */ - { 235, -3 }, /* (232) trigger_event ::= UPDATE OF idlist */ - { 237, 0 }, /* (233) when_clause ::= */ - { 237, -2 }, /* (234) when_clause ::= WHEN expr */ - { 233, -3 }, /* (235) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ - { 233, -2 }, /* (236) trigger_cmd_list ::= trigger_cmd SEMI */ - { 239, -3 }, /* (237) trnm ::= nm DOT nm */ - { 240, -3 }, /* (238) tridxby ::= INDEXED BY nm */ - { 240, -2 }, /* (239) tridxby ::= NOT INDEXED */ - { 238, -8 }, /* (240) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */ - { 238, -7 }, /* (241) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select scanpt */ - { 238, -6 }, /* (242) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ - { 238, -3 }, /* (243) trigger_cmd ::= scanpt select scanpt */ - { 174, -4 }, /* (244) expr ::= RAISE LP IGNORE RP */ - { 174, -6 }, /* (245) expr ::= RAISE LP raisetype COMMA nm RP */ - { 192, -1 }, /* (246) raisetype ::= ROLLBACK */ - { 192, -1 }, /* (247) raisetype ::= ABORT */ - { 192, -1 }, /* (248) raisetype ::= FAIL */ - { 149, -4 }, /* (249) cmd ::= DROP TRIGGER ifexists fullname */ - { 149, -6 }, /* (250) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ - { 149, -3 }, /* (251) cmd ::= DETACH database_kw_opt expr */ - { 242, 0 }, /* (252) key_opt ::= */ - { 242, -2 }, /* (253) key_opt ::= KEY expr */ - { 149, -1 }, /* (254) cmd ::= REINDEX */ - { 149, -3 }, /* (255) cmd ::= REINDEX nm dbnm */ - { 149, -1 }, /* (256) cmd ::= ANALYZE */ - { 149, -3 }, /* (257) cmd ::= ANALYZE nm dbnm */ - { 149, -6 }, /* (258) cmd ::= ALTER TABLE fullname RENAME TO nm */ - { 149, -7 }, /* (259) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ - { 243, -1 }, /* (260) add_column_fullname ::= fullname */ - { 149, -1 }, /* (261) cmd ::= create_vtab */ - { 149, -4 }, /* (262) cmd ::= create_vtab LP vtabarglist RP */ - { 245, -8 }, /* (263) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ - { 247, 0 }, /* (264) vtabarg ::= */ - { 248, -1 }, /* (265) vtabargtoken ::= ANY */ - { 248, -3 }, /* (266) vtabargtoken ::= lp anylist RP */ - { 249, -1 }, /* (267) lp ::= LP */ - { 197, 0 }, /* (268) with ::= */ - { 197, -2 }, /* (269) with ::= WITH wqlist */ - { 197, -3 }, /* (270) with ::= WITH RECURSIVE wqlist */ - { 251, -6 }, /* (271) wqlist ::= nm eidlist_opt AS LP select RP */ - { 251, -8 }, /* (272) wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ - { 144, -1 }, /* (273) input ::= cmdlist */ - { 145, -2 }, /* (274) cmdlist ::= cmdlist ecmd */ - { 145, -1 }, /* (275) cmdlist ::= ecmd */ - { 146, -1 }, /* (276) ecmd ::= SEMI */ - { 146, -3 }, /* (277) ecmd ::= explain cmdx SEMI */ - { 147, 0 }, /* (278) explain ::= */ - { 151, 0 }, /* (279) trans_opt ::= */ - { 151, -1 }, /* (280) trans_opt ::= TRANSACTION */ - { 151, -2 }, /* (281) trans_opt ::= TRANSACTION nm */ - { 153, -1 }, /* (282) savepoint_opt ::= SAVEPOINT */ - { 153, 0 }, /* (283) savepoint_opt ::= */ - { 149, -2 }, /* (284) cmd ::= create_table create_table_args */ - { 160, -4 }, /* (285) columnlist ::= columnlist COMMA columnname carglist */ - { 160, -2 }, /* (286) columnlist ::= columnname carglist */ - { 152, -1 }, /* (287) nm ::= ID|INDEXED */ - { 152, -1 }, /* (288) nm ::= STRING */ - { 152, -1 }, /* (289) nm ::= JOIN_KW */ - { 166, -1 }, /* (290) typetoken ::= typename */ - { 167, -1 }, /* (291) typename ::= ID|STRING */ - { 168, -1 }, /* (292) signed ::= plus_num */ - { 168, -1 }, /* (293) signed ::= minus_num */ - { 165, -2 }, /* (294) carglist ::= carglist ccons */ - { 165, 0 }, /* (295) carglist ::= */ - { 172, -2 }, /* (296) ccons ::= NULL onconf */ - { 161, -2 }, /* (297) conslist_opt ::= COMMA conslist */ - { 184, -3 }, /* (298) conslist ::= conslist tconscomma tcons */ - { 184, -1 }, /* (299) conslist ::= tcons */ - { 185, 0 }, /* (300) tconscomma ::= */ - { 189, -1 }, /* (301) defer_subclause_opt ::= defer_subclause */ - { 191, -1 }, /* (302) resolvetype ::= raisetype */ - { 195, -1 }, /* (303) selectnowith ::= oneselect */ - { 196, -1 }, /* (304) oneselect ::= values */ - { 210, -2 }, /* (305) sclp ::= selcollist COMMA */ - { 211, -1 }, /* (306) as ::= ID|STRING */ - { 174, -1 }, /* (307) expr ::= term */ - { 222, -1 }, /* (308) likeop ::= LIKE_KW|MATCH */ - { 209, -1 }, /* (309) exprlist ::= nexprlist */ - { 231, -1 }, /* (310) nmnum ::= plus_num */ - { 231, -1 }, /* (311) nmnum ::= nm */ - { 231, -1 }, /* (312) nmnum ::= ON */ - { 231, -1 }, /* (313) nmnum ::= DELETE */ - { 231, -1 }, /* (314) nmnum ::= DEFAULT */ - { 169, -1 }, /* (315) plus_num ::= INTEGER|FLOAT */ - { 236, 0 }, /* (316) foreach_clause ::= */ - { 236, -3 }, /* (317) foreach_clause ::= FOR EACH ROW */ - { 239, -1 }, /* (318) trnm ::= nm */ - { 240, 0 }, /* (319) tridxby ::= */ - { 241, -1 }, /* (320) database_kw_opt ::= DATABASE */ - { 241, 0 }, /* (321) database_kw_opt ::= */ - { 244, 0 }, /* (322) kwcolumn_opt ::= */ - { 244, -1 }, /* (323) kwcolumn_opt ::= COLUMNKW */ - { 246, -1 }, /* (324) vtabarglist ::= vtabarg */ - { 246, -3 }, /* (325) vtabarglist ::= vtabarglist COMMA vtabarg */ - { 247, -2 }, /* (326) vtabarg ::= vtabarg vtabargtoken */ - { 250, 0 }, /* (327) anylist ::= */ - { 250, -4 }, /* (328) anylist ::= anylist LP anylist RP */ - { 250, -2 }, /* (329) anylist ::= anylist ANY */ + { 163, -3 }, /* (80) select ::= WITH wqlist selectnowith */ + { 163, -4 }, /* (81) select ::= WITH RECURSIVE wqlist selectnowith */ + { 163, -1 }, /* (82) select ::= selectnowith */ + { 195, -3 }, /* (83) selectnowith ::= selectnowith multiselect_op oneselect */ + { 198, -1 }, /* (84) multiselect_op ::= UNION */ + { 198, -2 }, /* (85) multiselect_op ::= UNION ALL */ + { 198, -1 }, /* (86) multiselect_op ::= EXCEPT|INTERSECT */ + { 196, -9 }, /* (87) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ + { 207, -4 }, /* (88) values ::= VALUES LP nexprlist RP */ + { 207, -5 }, /* (89) values ::= values COMMA LP exprlist RP */ + { 199, -1 }, /* (90) distinct ::= DISTINCT */ + { 199, -1 }, /* (91) distinct ::= ALL */ + { 199, 0 }, /* (92) distinct ::= */ + { 210, 0 }, /* (93) sclp ::= */ + { 200, -5 }, /* (94) selcollist ::= sclp scanpt expr scanpt as */ + { 200, -3 }, /* (95) selcollist ::= sclp scanpt STAR */ + { 200, -5 }, /* (96) selcollist ::= sclp scanpt nm DOT STAR */ + { 211, -2 }, /* (97) as ::= AS nm */ + { 211, 0 }, /* (98) as ::= */ + { 201, 0 }, /* (99) from ::= */ + { 201, -2 }, /* (100) from ::= FROM seltablist */ + { 213, -2 }, /* (101) stl_prefix ::= seltablist joinop */ + { 213, 0 }, /* (102) stl_prefix ::= */ + { 212, -7 }, /* (103) seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */ + { 212, -9 }, /* (104) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */ + { 212, -7 }, /* (105) seltablist ::= stl_prefix LP select RP as on_opt using_opt */ + { 212, -7 }, /* (106) seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ + { 159, 0 }, /* (107) dbnm ::= */ + { 159, -2 }, /* (108) dbnm ::= DOT nm */ + { 194, -1 }, /* (109) fullname ::= nm */ + { 194, -3 }, /* (110) fullname ::= nm DOT nm */ + { 214, -1 }, /* (111) joinop ::= COMMA|JOIN */ + { 214, -2 }, /* (112) joinop ::= JOIN_KW JOIN */ + { 214, -3 }, /* (113) joinop ::= JOIN_KW nm JOIN */ + { 214, -4 }, /* (114) joinop ::= JOIN_KW nm nm JOIN */ + { 216, -2 }, /* (115) on_opt ::= ON expr */ + { 216, 0 }, /* (116) on_opt ::= */ + { 215, 0 }, /* (117) indexed_opt ::= */ + { 215, -3 }, /* (118) indexed_opt ::= INDEXED BY nm */ + { 215, -2 }, /* (119) indexed_opt ::= NOT INDEXED */ + { 217, -4 }, /* (120) using_opt ::= USING LP idlist RP */ + { 217, 0 }, /* (121) using_opt ::= */ + { 205, 0 }, /* (122) orderby_opt ::= */ + { 205, -3 }, /* (123) orderby_opt ::= ORDER BY sortlist */ + { 187, -4 }, /* (124) sortlist ::= sortlist COMMA expr sortorder */ + { 187, -2 }, /* (125) sortlist ::= expr sortorder */ + { 176, -1 }, /* (126) sortorder ::= ASC */ + { 176, -1 }, /* (127) sortorder ::= DESC */ + { 176, 0 }, /* (128) sortorder ::= */ + { 203, 0 }, /* (129) groupby_opt ::= */ + { 203, -3 }, /* (130) groupby_opt ::= GROUP BY nexprlist */ + { 204, 0 }, /* (131) having_opt ::= */ + { 204, -2 }, /* (132) having_opt ::= HAVING expr */ + { 206, 0 }, /* (133) limit_opt ::= */ + { 206, -2 }, /* (134) limit_opt ::= LIMIT expr */ + { 206, -4 }, /* (135) limit_opt ::= LIMIT expr OFFSET expr */ + { 206, -4 }, /* (136) limit_opt ::= LIMIT expr COMMA expr */ + { 149, -6 }, /* (137) cmd ::= with DELETE FROM fullname indexed_opt where_opt */ + { 202, 0 }, /* (138) where_opt ::= */ + { 202, -2 }, /* (139) where_opt ::= WHERE expr */ + { 149, -8 }, /* (140) cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt */ + { 220, -5 }, /* (141) setlist ::= setlist COMMA nm EQ expr */ + { 220, -7 }, /* (142) setlist ::= setlist COMMA LP idlist RP EQ expr */ + { 220, -3 }, /* (143) setlist ::= nm EQ expr */ + { 220, -5 }, /* (144) setlist ::= LP idlist RP EQ expr */ + { 149, -6 }, /* (145) cmd ::= with insert_cmd INTO fullname idlist_opt select */ + { 149, -7 }, /* (146) cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES */ + { 221, -2 }, /* (147) insert_cmd ::= INSERT orconf */ + { 221, -1 }, /* (148) insert_cmd ::= REPLACE */ + { 222, 0 }, /* (149) idlist_opt ::= */ + { 222, -3 }, /* (150) idlist_opt ::= LP idlist RP */ + { 218, -3 }, /* (151) idlist ::= idlist COMMA nm */ + { 218, -1 }, /* (152) idlist ::= nm */ + { 174, -3 }, /* (153) expr ::= LP expr RP */ + { 174, -1 }, /* (154) expr ::= ID|INDEXED */ + { 174, -1 }, /* (155) expr ::= JOIN_KW */ + { 174, -3 }, /* (156) expr ::= nm DOT nm */ + { 174, -5 }, /* (157) expr ::= nm DOT nm DOT nm */ + { 173, -1 }, /* (158) term ::= NULL|FLOAT|BLOB */ + { 173, -1 }, /* (159) term ::= STRING */ + { 173, -1 }, /* (160) term ::= INTEGER */ + { 174, -1 }, /* (161) expr ::= VARIABLE */ + { 174, -3 }, /* (162) expr ::= expr COLLATE ID|STRING */ + { 174, -6 }, /* (163) expr ::= CAST LP expr AS typetoken RP */ + { 174, -5 }, /* (164) expr ::= ID|INDEXED LP distinct exprlist RP */ + { 174, -4 }, /* (165) expr ::= ID|INDEXED LP STAR RP */ + { 173, -1 }, /* (166) term ::= CTIME_KW */ + { 174, -5 }, /* (167) expr ::= LP nexprlist COMMA expr RP */ + { 174, -3 }, /* (168) expr ::= expr AND expr */ + { 174, -3 }, /* (169) expr ::= expr OR expr */ + { 174, -3 }, /* (170) expr ::= expr LT|GT|GE|LE expr */ + { 174, -3 }, /* (171) expr ::= expr EQ|NE expr */ + { 174, -3 }, /* (172) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ + { 174, -3 }, /* (173) expr ::= expr PLUS|MINUS expr */ + { 174, -3 }, /* (174) expr ::= expr STAR|SLASH|REM expr */ + { 174, -3 }, /* (175) expr ::= expr CONCAT expr */ + { 223, -2 }, /* (176) likeop ::= NOT LIKE_KW|MATCH */ + { 174, -3 }, /* (177) expr ::= expr likeop expr */ + { 174, -5 }, /* (178) expr ::= expr likeop expr ESCAPE expr */ + { 174, -2 }, /* (179) expr ::= expr ISNULL|NOTNULL */ + { 174, -3 }, /* (180) expr ::= expr NOT NULL */ + { 174, -3 }, /* (181) expr ::= expr IS expr */ + { 174, -4 }, /* (182) expr ::= expr IS NOT expr */ + { 174, -2 }, /* (183) expr ::= NOT expr */ + { 174, -2 }, /* (184) expr ::= BITNOT expr */ + { 174, -2 }, /* (185) expr ::= MINUS expr */ + { 174, -2 }, /* (186) expr ::= PLUS expr */ + { 224, -1 }, /* (187) between_op ::= BETWEEN */ + { 224, -2 }, /* (188) between_op ::= NOT BETWEEN */ + { 174, -5 }, /* (189) expr ::= expr between_op expr AND expr */ + { 225, -1 }, /* (190) in_op ::= IN */ + { 225, -2 }, /* (191) in_op ::= NOT IN */ + { 174, -5 }, /* (192) expr ::= expr in_op LP exprlist RP */ + { 174, -3 }, /* (193) expr ::= LP select RP */ + { 174, -5 }, /* (194) expr ::= expr in_op LP select RP */ + { 174, -5 }, /* (195) expr ::= expr in_op nm dbnm paren_exprlist */ + { 174, -4 }, /* (196) expr ::= EXISTS LP select RP */ + { 174, -5 }, /* (197) expr ::= CASE case_operand case_exprlist case_else END */ + { 228, -5 }, /* (198) case_exprlist ::= case_exprlist WHEN expr THEN expr */ + { 228, -4 }, /* (199) case_exprlist ::= WHEN expr THEN expr */ + { 229, -2 }, /* (200) case_else ::= ELSE expr */ + { 229, 0 }, /* (201) case_else ::= */ + { 227, -1 }, /* (202) case_operand ::= expr */ + { 227, 0 }, /* (203) case_operand ::= */ + { 209, 0 }, /* (204) exprlist ::= */ + { 208, -3 }, /* (205) nexprlist ::= nexprlist COMMA expr */ + { 208, -1 }, /* (206) nexprlist ::= expr */ + { 226, 0 }, /* (207) paren_exprlist ::= */ + { 226, -3 }, /* (208) paren_exprlist ::= LP exprlist RP */ + { 149, -12 }, /* (209) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ + { 230, -1 }, /* (210) uniqueflag ::= UNIQUE */ + { 230, 0 }, /* (211) uniqueflag ::= */ + { 178, 0 }, /* (212) eidlist_opt ::= */ + { 178, -3 }, /* (213) eidlist_opt ::= LP eidlist RP */ + { 188, -5 }, /* (214) eidlist ::= eidlist COMMA nm collate sortorder */ + { 188, -3 }, /* (215) eidlist ::= nm collate sortorder */ + { 231, 0 }, /* (216) collate ::= */ + { 231, -2 }, /* (217) collate ::= COLLATE ID|STRING */ + { 149, -4 }, /* (218) cmd ::= DROP INDEX ifexists fullname */ + { 149, -1 }, /* (219) cmd ::= VACUUM */ + { 149, -2 }, /* (220) cmd ::= VACUUM nm */ + { 149, -3 }, /* (221) cmd ::= PRAGMA nm dbnm */ + { 149, -5 }, /* (222) cmd ::= PRAGMA nm dbnm EQ nmnum */ + { 149, -6 }, /* (223) cmd ::= PRAGMA nm dbnm LP nmnum RP */ + { 149, -5 }, /* (224) cmd ::= PRAGMA nm dbnm EQ minus_num */ + { 149, -6 }, /* (225) cmd ::= PRAGMA nm dbnm LP minus_num RP */ + { 169, -2 }, /* (226) plus_num ::= PLUS INTEGER|FLOAT */ + { 170, -2 }, /* (227) minus_num ::= MINUS INTEGER|FLOAT */ + { 149, -5 }, /* (228) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ + { 233, -11 }, /* (229) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ + { 235, -1 }, /* (230) trigger_time ::= BEFORE|AFTER */ + { 235, -2 }, /* (231) trigger_time ::= INSTEAD OF */ + { 235, 0 }, /* (232) trigger_time ::= */ + { 236, -1 }, /* (233) trigger_event ::= DELETE|INSERT */ + { 236, -1 }, /* (234) trigger_event ::= UPDATE */ + { 236, -3 }, /* (235) trigger_event ::= UPDATE OF idlist */ + { 238, 0 }, /* (236) when_clause ::= */ + { 238, -2 }, /* (237) when_clause ::= WHEN expr */ + { 234, -3 }, /* (238) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ + { 234, -2 }, /* (239) trigger_cmd_list ::= trigger_cmd SEMI */ + { 240, -3 }, /* (240) trnm ::= nm DOT nm */ + { 241, -3 }, /* (241) tridxby ::= INDEXED BY nm */ + { 241, -2 }, /* (242) tridxby ::= NOT INDEXED */ + { 239, -8 }, /* (243) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */ + { 239, -7 }, /* (244) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select scanpt */ + { 239, -6 }, /* (245) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ + { 239, -3 }, /* (246) trigger_cmd ::= scanpt select scanpt */ + { 174, -4 }, /* (247) expr ::= RAISE LP IGNORE RP */ + { 174, -6 }, /* (248) expr ::= RAISE LP raisetype COMMA nm RP */ + { 192, -1 }, /* (249) raisetype ::= ROLLBACK */ + { 192, -1 }, /* (250) raisetype ::= ABORT */ + { 192, -1 }, /* (251) raisetype ::= FAIL */ + { 149, -4 }, /* (252) cmd ::= DROP TRIGGER ifexists fullname */ + { 149, -6 }, /* (253) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ + { 149, -3 }, /* (254) cmd ::= DETACH database_kw_opt expr */ + { 243, 0 }, /* (255) key_opt ::= */ + { 243, -2 }, /* (256) key_opt ::= KEY expr */ + { 149, -1 }, /* (257) cmd ::= REINDEX */ + { 149, -3 }, /* (258) cmd ::= REINDEX nm dbnm */ + { 149, -1 }, /* (259) cmd ::= ANALYZE */ + { 149, -3 }, /* (260) cmd ::= ANALYZE nm dbnm */ + { 149, -6 }, /* (261) cmd ::= ALTER TABLE fullname RENAME TO nm */ + { 149, -7 }, /* (262) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ + { 244, -1 }, /* (263) add_column_fullname ::= fullname */ + { 149, -1 }, /* (264) cmd ::= create_vtab */ + { 149, -4 }, /* (265) cmd ::= create_vtab LP vtabarglist RP */ + { 246, -8 }, /* (266) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ + { 248, 0 }, /* (267) vtabarg ::= */ + { 249, -1 }, /* (268) vtabargtoken ::= ANY */ + { 249, -3 }, /* (269) vtabargtoken ::= lp anylist RP */ + { 250, -1 }, /* (270) lp ::= LP */ + { 219, -2 }, /* (271) with ::= WITH wqlist */ + { 219, -3 }, /* (272) with ::= WITH RECURSIVE wqlist */ + { 197, -6 }, /* (273) wqlist ::= nm eidlist_opt AS LP select RP */ + { 197, -8 }, /* (274) wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ + { 144, -1 }, /* (275) input ::= cmdlist */ + { 145, -2 }, /* (276) cmdlist ::= cmdlist ecmd */ + { 145, -1 }, /* (277) cmdlist ::= ecmd */ + { 146, -1 }, /* (278) ecmd ::= SEMI */ + { 146, -3 }, /* (279) ecmd ::= explain cmdx SEMI */ + { 147, 0 }, /* (280) explain ::= */ + { 151, 0 }, /* (281) trans_opt ::= */ + { 151, -1 }, /* (282) trans_opt ::= TRANSACTION */ + { 151, -2 }, /* (283) trans_opt ::= TRANSACTION nm */ + { 153, -1 }, /* (284) savepoint_opt ::= SAVEPOINT */ + { 153, 0 }, /* (285) savepoint_opt ::= */ + { 149, -2 }, /* (286) cmd ::= create_table create_table_args */ + { 160, -4 }, /* (287) columnlist ::= columnlist COMMA columnname carglist */ + { 160, -2 }, /* (288) columnlist ::= columnname carglist */ + { 152, -1 }, /* (289) nm ::= ID|INDEXED */ + { 152, -1 }, /* (290) nm ::= STRING */ + { 152, -1 }, /* (291) nm ::= JOIN_KW */ + { 166, -1 }, /* (292) typetoken ::= typename */ + { 167, -1 }, /* (293) typename ::= ID|STRING */ + { 168, -1 }, /* (294) signed ::= plus_num */ + { 168, -1 }, /* (295) signed ::= minus_num */ + { 165, -2 }, /* (296) carglist ::= carglist ccons */ + { 165, 0 }, /* (297) carglist ::= */ + { 172, -2 }, /* (298) ccons ::= NULL onconf */ + { 161, -2 }, /* (299) conslist_opt ::= COMMA conslist */ + { 184, -3 }, /* (300) conslist ::= conslist tconscomma tcons */ + { 184, -1 }, /* (301) conslist ::= tcons */ + { 185, 0 }, /* (302) tconscomma ::= */ + { 189, -1 }, /* (303) defer_subclause_opt ::= defer_subclause */ + { 191, -1 }, /* (304) resolvetype ::= raisetype */ + { 195, -1 }, /* (305) selectnowith ::= oneselect */ + { 196, -1 }, /* (306) oneselect ::= values */ + { 210, -2 }, /* (307) sclp ::= selcollist COMMA */ + { 211, -1 }, /* (308) as ::= ID|STRING */ + { 174, -1 }, /* (309) expr ::= term */ + { 223, -1 }, /* (310) likeop ::= LIKE_KW|MATCH */ + { 209, -1 }, /* (311) exprlist ::= nexprlist */ + { 232, -1 }, /* (312) nmnum ::= plus_num */ + { 232, -1 }, /* (313) nmnum ::= nm */ + { 232, -1 }, /* (314) nmnum ::= ON */ + { 232, -1 }, /* (315) nmnum ::= DELETE */ + { 232, -1 }, /* (316) nmnum ::= DEFAULT */ + { 169, -1 }, /* (317) plus_num ::= INTEGER|FLOAT */ + { 237, 0 }, /* (318) foreach_clause ::= */ + { 237, -3 }, /* (319) foreach_clause ::= FOR EACH ROW */ + { 240, -1 }, /* (320) trnm ::= nm */ + { 241, 0 }, /* (321) tridxby ::= */ + { 242, -1 }, /* (322) database_kw_opt ::= DATABASE */ + { 242, 0 }, /* (323) database_kw_opt ::= */ + { 245, 0 }, /* (324) kwcolumn_opt ::= */ + { 245, -1 }, /* (325) kwcolumn_opt ::= COLUMNKW */ + { 247, -1 }, /* (326) vtabarglist ::= vtabarg */ + { 247, -3 }, /* (327) vtabarglist ::= vtabarglist COMMA vtabarg */ + { 248, -2 }, /* (328) vtabarg ::= vtabarg vtabargtoken */ + { 251, 0 }, /* (329) anylist ::= */ + { 251, -4 }, /* (330) anylist ::= anylist LP anylist RP */ + { 251, -2 }, /* (331) anylist ::= anylist ANY */ + { 219, 0 }, /* (332) with ::= */ }; static void yy_accept(yyParser*); /* Forward Declaration */ @@ -140630,8 +142312,8 @@ static void yy_reduce( case 57: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==57); case 67: /* defer_subclause_opt ::= */ yytestcase(yyruleno==67); case 76: /* ifexists ::= */ yytestcase(yyruleno==76); - case 90: /* distinct ::= */ yytestcase(yyruleno==90); - case 213: /* collate ::= */ yytestcase(yyruleno==213); + case 92: /* distinct ::= */ yytestcase(yyruleno==92); + case 216: /* collate ::= */ yytestcase(yyruleno==216); {yymsp[1].minor.yy4 = 0;} break; case 16: /* ifnotexists ::= IF NOT EXISTS */ @@ -140667,7 +142349,7 @@ static void yy_reduce( break; case 24: /* typetoken ::= */ case 60: /* conslist_opt ::= */ yytestcase(yyruleno==60); - case 96: /* as ::= */ yytestcase(yyruleno==96); + case 98: /* as ::= */ yytestcase(yyruleno==98); {yymsp[1].minor.yy0.n = 0; yymsp[1].minor.yy0.z = 0;} break; case 25: /* typetoken ::= typename LP signed RP */ @@ -140711,6 +142393,10 @@ static void yy_reduce( case 34: /* ccons ::= DEFAULT scanpt ID|INDEXED */ { Expr *p = tokenExpr(pParse, TK_STRING, yymsp[0].minor.yy0); + if( p ){ + sqlite3ExprIdToTrueFalse(p); + testcase( p->op==TK_TRUEFALSE && sqlite3ExprTruthValue(p) ); + } sqlite3AddDefaultValue(pParse,p,yymsp[0].minor.yy0.z,yymsp[0].minor.yy0.z+yymsp[0].minor.yy0.n); } break; @@ -140774,14 +142460,14 @@ static void yy_reduce( break; case 56: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ case 71: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==71); - case 144: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==144); + case 147: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==147); {yymsp[-1].minor.yy4 = yymsp[0].minor.yy4;} break; case 58: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ case 75: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==75); - case 185: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==185); - case 188: /* in_op ::= NOT IN */ yytestcase(yyruleno==188); - case 214: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==214); + case 188: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==188); + case 191: /* in_op ::= NOT IN */ yytestcase(yyruleno==191); + case 217: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==217); {yymsp[-1].minor.yy4 = 1;} break; case 59: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ @@ -140817,7 +142503,7 @@ static void yy_reduce( {yymsp[0].minor.yy4 = OE_Ignore;} break; case 73: /* resolvetype ::= REPLACE */ - case 145: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==145); + case 148: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==148); {yymsp[0].minor.yy4 = OE_Replace;} break; case 74: /* cmd ::= DROP TABLE ifexists fullname */ @@ -140842,7 +142528,7 @@ static void yy_reduce( sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy387); } break; - case 80: /* select ::= with selectnowith */ + case 80: /* select ::= WITH wqlist selectnowith */ { Select *p = yymsp[0].minor.yy387; if( p ){ @@ -140851,10 +142537,31 @@ static void yy_reduce( }else{ sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy451); } - yymsp[-1].minor.yy387 = p; /*A-overwrites-W*/ + yymsp[-2].minor.yy387 = p; } break; - case 81: /* selectnowith ::= selectnowith multiselect_op oneselect */ + case 81: /* select ::= WITH RECURSIVE wqlist selectnowith */ +{ + Select *p = yymsp[0].minor.yy387; + if( p ){ + p->pWith = yymsp[-1].minor.yy451; + parserDoubleLinkSelect(pParse, p); + }else{ + sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy451); + } + yymsp[-3].minor.yy387 = p; +} + break; + case 82: /* select ::= selectnowith */ +{ + Select *p = yymsp[0].minor.yy387; + if( p ){ + parserDoubleLinkSelect(pParse, p); + } + yymsp[0].minor.yy387 = p; /*A-overwrites-X*/ +} + break; + case 83: /* selectnowith ::= selectnowith multiselect_op oneselect */ { Select *pRhs = yymsp[0].minor.yy387; Select *pLhs = yymsp[-2].minor.yy387; @@ -140878,14 +142585,14 @@ static void yy_reduce( yymsp[-2].minor.yy387 = pRhs; } break; - case 82: /* multiselect_op ::= UNION */ - case 84: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==84); + case 84: /* multiselect_op ::= UNION */ + case 86: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==86); {yymsp[0].minor.yy4 = yymsp[0].major; /*A-overwrites-OP*/} break; - case 83: /* multiselect_op ::= UNION ALL */ + case 85: /* multiselect_op ::= UNION ALL */ {yymsp[-1].minor.yy4 = TK_ALL;} break; - case 85: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ + case 87: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ { #if SELECTTRACE_ENABLED Token s = yymsp[-8].minor.yy0; /*A-overwrites-S*/ @@ -140904,8 +142611,7 @@ static void yy_reduce( if( yymsp[-8].minor.yy387!=0 ){ const char *z = s.z+6; int i; - sqlite3_snprintf(sizeof(yymsp[-8].minor.yy387->zSelName), yymsp[-8].minor.yy387->zSelName, "#%d", - ++pParse->nSelect); + sqlite3_snprintf(sizeof(yymsp[-8].minor.yy387->zSelName), yymsp[-8].minor.yy387->zSelName,"#%d",++pParse->nSelect); while( z[0]==' ' ) z++; if( z[0]=='/' && z[1]=='*' ){ z += 2; @@ -140917,12 +142623,12 @@ static void yy_reduce( #endif /* SELECTRACE_ENABLED */ } break; - case 86: /* values ::= VALUES LP nexprlist RP */ + case 88: /* values ::= VALUES LP nexprlist RP */ { yymsp[-3].minor.yy387 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy322,0,0,0,0,0,SF_Values,0); } break; - case 87: /* values ::= values COMMA LP exprlist RP */ + case 89: /* values ::= values COMMA LP exprlist RP */ { Select *pRight, *pLeft = yymsp[-4].minor.yy387; pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy322,0,0,0,0,0,SF_Values|SF_MultiValue,0); @@ -140936,34 +142642,34 @@ static void yy_reduce( } } break; - case 88: /* distinct ::= DISTINCT */ + case 90: /* distinct ::= DISTINCT */ {yymsp[0].minor.yy4 = SF_Distinct;} break; - case 89: /* distinct ::= ALL */ + case 91: /* distinct ::= ALL */ {yymsp[0].minor.yy4 = SF_All;} break; - case 91: /* sclp ::= */ - case 119: /* orderby_opt ::= */ yytestcase(yyruleno==119); - case 126: /* groupby_opt ::= */ yytestcase(yyruleno==126); - case 201: /* exprlist ::= */ yytestcase(yyruleno==201); - case 204: /* paren_exprlist ::= */ yytestcase(yyruleno==204); - case 209: /* eidlist_opt ::= */ yytestcase(yyruleno==209); + case 93: /* sclp ::= */ + case 122: /* orderby_opt ::= */ yytestcase(yyruleno==122); + case 129: /* groupby_opt ::= */ yytestcase(yyruleno==129); + case 204: /* exprlist ::= */ yytestcase(yyruleno==204); + case 207: /* paren_exprlist ::= */ yytestcase(yyruleno==207); + case 212: /* eidlist_opt ::= */ yytestcase(yyruleno==212); {yymsp[1].minor.yy322 = 0;} break; - case 92: /* selcollist ::= sclp scanpt expr scanpt as */ + case 94: /* selcollist ::= sclp scanpt expr scanpt as */ { yymsp[-4].minor.yy322 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy322, yymsp[-2].minor.yy314); if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy322, &yymsp[0].minor.yy0, 1); sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy322,yymsp[-3].minor.yy336,yymsp[-1].minor.yy336); } break; - case 93: /* selcollist ::= sclp scanpt STAR */ + case 95: /* selcollist ::= sclp scanpt STAR */ { Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0); yymsp[-2].minor.yy322 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy322, p); } break; - case 94: /* selcollist ::= sclp scanpt nm DOT STAR */ + case 96: /* selcollist ::= sclp scanpt nm DOT STAR */ { Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0); Expr *pLeft = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1); @@ -140971,47 +142677,47 @@ static void yy_reduce( yymsp[-4].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322, pDot); } break; - case 95: /* as ::= AS nm */ - case 106: /* dbnm ::= DOT nm */ yytestcase(yyruleno==106); - case 223: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==223); - case 224: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==224); + case 97: /* as ::= AS nm */ + case 108: /* dbnm ::= DOT nm */ yytestcase(yyruleno==108); + case 226: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==226); + case 227: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==227); {yymsp[-1].minor.yy0 = yymsp[0].minor.yy0;} break; - case 97: /* from ::= */ + case 99: /* from ::= */ {yymsp[1].minor.yy259 = sqlite3DbMallocZero(pParse->db, sizeof(*yymsp[1].minor.yy259));} break; - case 98: /* from ::= FROM seltablist */ + case 100: /* from ::= FROM seltablist */ { yymsp[-1].minor.yy259 = yymsp[0].minor.yy259; sqlite3SrcListShiftJoinType(yymsp[-1].minor.yy259); } break; - case 99: /* stl_prefix ::= seltablist joinop */ + case 101: /* stl_prefix ::= seltablist joinop */ { if( ALWAYS(yymsp[-1].minor.yy259 && yymsp[-1].minor.yy259->nSrc>0) ) yymsp[-1].minor.yy259->a[yymsp[-1].minor.yy259->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy4; } break; - case 100: /* stl_prefix ::= */ + case 102: /* stl_prefix ::= */ {yymsp[1].minor.yy259 = 0;} break; - case 101: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */ + case 103: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */ { yymsp[-6].minor.yy259 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy259,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy314,yymsp[0].minor.yy384); sqlite3SrcListIndexedBy(pParse, yymsp[-6].minor.yy259, &yymsp[-2].minor.yy0); } break; - case 102: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */ + case 104: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */ { yymsp[-8].minor.yy259 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-8].minor.yy259,&yymsp[-7].minor.yy0,&yymsp[-6].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy314,yymsp[0].minor.yy384); sqlite3SrcListFuncArgs(pParse, yymsp[-8].minor.yy259, yymsp[-4].minor.yy322); } break; - case 103: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */ + case 105: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */ { yymsp[-6].minor.yy259 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy259,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy387,yymsp[-1].minor.yy314,yymsp[0].minor.yy384); } break; - case 104: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ + case 106: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ { if( yymsp[-6].minor.yy259==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy314==0 && yymsp[0].minor.yy384==0 ){ yymsp[-6].minor.yy259 = yymsp[-4].minor.yy259; @@ -141035,153 +142741,152 @@ static void yy_reduce( } } break; - case 105: /* dbnm ::= */ - case 114: /* indexed_opt ::= */ yytestcase(yyruleno==114); + case 107: /* dbnm ::= */ + case 117: /* indexed_opt ::= */ yytestcase(yyruleno==117); {yymsp[1].minor.yy0.z=0; yymsp[1].minor.yy0.n=0;} break; - case 107: /* fullname ::= nm dbnm */ -{yymsp[-1].minor.yy259 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/} + case 109: /* fullname ::= nm */ +{yymsp[0].minor.yy259 = sqlite3SrcListAppend(pParse->db,0,&yymsp[0].minor.yy0,0); /*A-overwrites-X*/} break; - case 108: /* joinop ::= COMMA|JOIN */ + case 110: /* fullname ::= nm DOT nm */ +{yymsp[-2].minor.yy259 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/} + break; + case 111: /* joinop ::= COMMA|JOIN */ { yymsp[0].minor.yy4 = JT_INNER; } break; - case 109: /* joinop ::= JOIN_KW JOIN */ + case 112: /* joinop ::= JOIN_KW JOIN */ {yymsp[-1].minor.yy4 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/} break; - case 110: /* joinop ::= JOIN_KW nm JOIN */ + case 113: /* joinop ::= JOIN_KW nm JOIN */ {yymsp[-2].minor.yy4 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/} break; - case 111: /* joinop ::= JOIN_KW nm nm JOIN */ + case 114: /* joinop ::= JOIN_KW nm nm JOIN */ {yymsp[-3].minor.yy4 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/} break; - case 112: /* on_opt ::= ON expr */ - case 129: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==129); - case 136: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==136); - case 197: /* case_else ::= ELSE expr */ yytestcase(yyruleno==197); + case 115: /* on_opt ::= ON expr */ + case 132: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==132); + case 139: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==139); + case 200: /* case_else ::= ELSE expr */ yytestcase(yyruleno==200); {yymsp[-1].minor.yy314 = yymsp[0].minor.yy314;} break; - case 113: /* on_opt ::= */ - case 128: /* having_opt ::= */ yytestcase(yyruleno==128); - case 130: /* limit_opt ::= */ yytestcase(yyruleno==130); - case 135: /* where_opt ::= */ yytestcase(yyruleno==135); - case 198: /* case_else ::= */ yytestcase(yyruleno==198); - case 200: /* case_operand ::= */ yytestcase(yyruleno==200); + case 116: /* on_opt ::= */ + case 131: /* having_opt ::= */ yytestcase(yyruleno==131); + case 133: /* limit_opt ::= */ yytestcase(yyruleno==133); + case 138: /* where_opt ::= */ yytestcase(yyruleno==138); + case 201: /* case_else ::= */ yytestcase(yyruleno==201); + case 203: /* case_operand ::= */ yytestcase(yyruleno==203); {yymsp[1].minor.yy314 = 0;} break; - case 115: /* indexed_opt ::= INDEXED BY nm */ + case 118: /* indexed_opt ::= INDEXED BY nm */ {yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;} break; - case 116: /* indexed_opt ::= NOT INDEXED */ + case 119: /* indexed_opt ::= NOT INDEXED */ {yymsp[-1].minor.yy0.z=0; yymsp[-1].minor.yy0.n=1;} break; - case 117: /* using_opt ::= USING LP idlist RP */ + case 120: /* using_opt ::= USING LP idlist RP */ {yymsp[-3].minor.yy384 = yymsp[-1].minor.yy384;} break; - case 118: /* using_opt ::= */ - case 146: /* idlist_opt ::= */ yytestcase(yyruleno==146); + case 121: /* using_opt ::= */ + case 149: /* idlist_opt ::= */ yytestcase(yyruleno==149); {yymsp[1].minor.yy384 = 0;} break; - case 120: /* orderby_opt ::= ORDER BY sortlist */ - case 127: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==127); + case 123: /* orderby_opt ::= ORDER BY sortlist */ + case 130: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==130); {yymsp[-2].minor.yy322 = yymsp[0].minor.yy322;} break; - case 121: /* sortlist ::= sortlist COMMA expr sortorder */ + case 124: /* sortlist ::= sortlist COMMA expr sortorder */ { yymsp[-3].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy322,yymsp[-1].minor.yy314); sqlite3ExprListSetSortOrder(yymsp[-3].minor.yy322,yymsp[0].minor.yy4); } break; - case 122: /* sortlist ::= expr sortorder */ + case 125: /* sortlist ::= expr sortorder */ { yymsp[-1].minor.yy322 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy314); /*A-overwrites-Y*/ sqlite3ExprListSetSortOrder(yymsp[-1].minor.yy322,yymsp[0].minor.yy4); } break; - case 123: /* sortorder ::= ASC */ + case 126: /* sortorder ::= ASC */ {yymsp[0].minor.yy4 = SQLITE_SO_ASC;} break; - case 124: /* sortorder ::= DESC */ + case 127: /* sortorder ::= DESC */ {yymsp[0].minor.yy4 = SQLITE_SO_DESC;} break; - case 125: /* sortorder ::= */ + case 128: /* sortorder ::= */ {yymsp[1].minor.yy4 = SQLITE_SO_UNDEFINED;} break; - case 131: /* limit_opt ::= LIMIT expr */ + case 134: /* limit_opt ::= LIMIT expr */ {yymsp[-1].minor.yy314 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy314,0);} break; - case 132: /* limit_opt ::= LIMIT expr OFFSET expr */ + case 135: /* limit_opt ::= LIMIT expr OFFSET expr */ {yymsp[-3].minor.yy314 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy314,yymsp[0].minor.yy314);} break; - case 133: /* limit_opt ::= LIMIT expr COMMA expr */ + case 136: /* limit_opt ::= LIMIT expr COMMA expr */ {yymsp[-3].minor.yy314 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy314,yymsp[-2].minor.yy314);} break; - case 134: /* cmd ::= with DELETE FROM fullname indexed_opt where_opt */ + case 137: /* cmd ::= with DELETE FROM fullname indexed_opt where_opt */ { - sqlite3WithPush(pParse, yymsp[-5].minor.yy451, 1); sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy259, &yymsp[-1].minor.yy0); sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy259,yymsp[0].minor.yy314,0,0); } break; - case 137: /* cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt */ + case 140: /* cmd ::= with UPDATE orconf fullname indexed_opt SET setlist where_opt */ { - sqlite3WithPush(pParse, yymsp[-7].minor.yy451, 1); sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy259, &yymsp[-3].minor.yy0); sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy322,"set list"); sqlite3Update(pParse,yymsp[-4].minor.yy259,yymsp[-1].minor.yy322,yymsp[0].minor.yy314,yymsp[-5].minor.yy4,0,0); } break; - case 138: /* setlist ::= setlist COMMA nm EQ expr */ + case 141: /* setlist ::= setlist COMMA nm EQ expr */ { yymsp[-4].minor.yy322 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy322, yymsp[0].minor.yy314); sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy322, &yymsp[-2].minor.yy0, 1); } break; - case 139: /* setlist ::= setlist COMMA LP idlist RP EQ expr */ + case 142: /* setlist ::= setlist COMMA LP idlist RP EQ expr */ { yymsp[-6].minor.yy322 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy322, yymsp[-3].minor.yy384, yymsp[0].minor.yy314); } break; - case 140: /* setlist ::= nm EQ expr */ + case 143: /* setlist ::= nm EQ expr */ { yylhsminor.yy322 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy314); sqlite3ExprListSetName(pParse, yylhsminor.yy322, &yymsp[-2].minor.yy0, 1); } yymsp[-2].minor.yy322 = yylhsminor.yy322; break; - case 141: /* setlist ::= LP idlist RP EQ expr */ + case 144: /* setlist ::= LP idlist RP EQ expr */ { yymsp[-4].minor.yy322 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy384, yymsp[0].minor.yy314); } break; - case 142: /* cmd ::= with insert_cmd INTO fullname idlist_opt select */ + case 145: /* cmd ::= with insert_cmd INTO fullname idlist_opt select */ { - sqlite3WithPush(pParse, yymsp[-5].minor.yy451, 1); sqlite3Insert(pParse, yymsp[-2].minor.yy259, yymsp[0].minor.yy387, yymsp[-1].minor.yy384, yymsp[-4].minor.yy4); } break; - case 143: /* cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES */ + case 146: /* cmd ::= with insert_cmd INTO fullname idlist_opt DEFAULT VALUES */ { - sqlite3WithPush(pParse, yymsp[-6].minor.yy451, 1); sqlite3Insert(pParse, yymsp[-3].minor.yy259, 0, yymsp[-2].minor.yy384, yymsp[-5].minor.yy4); } break; - case 147: /* idlist_opt ::= LP idlist RP */ + case 150: /* idlist_opt ::= LP idlist RP */ {yymsp[-2].minor.yy384 = yymsp[-1].minor.yy384;} break; - case 148: /* idlist ::= idlist COMMA nm */ + case 151: /* idlist ::= idlist COMMA nm */ {yymsp[-2].minor.yy384 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy384,&yymsp[0].minor.yy0);} break; - case 149: /* idlist ::= nm */ + case 152: /* idlist ::= nm */ {yymsp[0].minor.yy384 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/} break; - case 150: /* expr ::= LP expr RP */ + case 153: /* expr ::= LP expr RP */ {yymsp[-2].minor.yy314 = yymsp[-1].minor.yy314;} break; - case 151: /* expr ::= ID|INDEXED */ - case 152: /* expr ::= JOIN_KW */ yytestcase(yyruleno==152); + case 154: /* expr ::= ID|INDEXED */ + case 155: /* expr ::= JOIN_KW */ yytestcase(yyruleno==155); {yymsp[0].minor.yy314=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/} break; - case 153: /* expr ::= nm DOT nm */ + case 156: /* expr ::= nm DOT nm */ { Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1); Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[0].minor.yy0, 1); @@ -141189,7 +142894,7 @@ static void yy_reduce( } yymsp[-2].minor.yy314 = yylhsminor.yy314; break; - case 154: /* expr ::= nm DOT nm DOT nm */ + case 157: /* expr ::= nm DOT nm DOT nm */ { Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-4].minor.yy0, 1); Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1); @@ -141199,17 +142904,17 @@ static void yy_reduce( } yymsp[-4].minor.yy314 = yylhsminor.yy314; break; - case 155: /* term ::= NULL|FLOAT|BLOB */ - case 156: /* term ::= STRING */ yytestcase(yyruleno==156); + case 158: /* term ::= NULL|FLOAT|BLOB */ + case 159: /* term ::= STRING */ yytestcase(yyruleno==159); {yymsp[0].minor.yy314=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/} break; - case 157: /* term ::= INTEGER */ + case 160: /* term ::= INTEGER */ { yylhsminor.yy314 = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1); } yymsp[0].minor.yy314 = yylhsminor.yy314; break; - case 158: /* expr ::= VARIABLE */ + case 161: /* expr ::= VARIABLE */ { if( !(yymsp[0].minor.yy0.z[0]=='#' && sqlite3Isdigit(yymsp[0].minor.yy0.z[1])) ){ u32 n = yymsp[0].minor.yy0.n; @@ -141231,18 +142936,18 @@ static void yy_reduce( } } break; - case 159: /* expr ::= expr COLLATE ID|STRING */ + case 162: /* expr ::= expr COLLATE ID|STRING */ { yymsp[-2].minor.yy314 = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy314, &yymsp[0].minor.yy0, 1); } break; - case 160: /* expr ::= CAST LP expr AS typetoken RP */ + case 163: /* expr ::= CAST LP expr AS typetoken RP */ { yymsp[-5].minor.yy314 = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1); sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy314, yymsp[-3].minor.yy314, 0); } break; - case 161: /* expr ::= ID|INDEXED LP distinct exprlist RP */ + case 164: /* expr ::= ID|INDEXED LP distinct exprlist RP */ { if( yymsp[-1].minor.yy322 && yymsp[-1].minor.yy322->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0); @@ -141254,19 +142959,19 @@ static void yy_reduce( } yymsp[-4].minor.yy314 = yylhsminor.yy314; break; - case 162: /* expr ::= ID|INDEXED LP STAR RP */ + case 165: /* expr ::= ID|INDEXED LP STAR RP */ { yylhsminor.yy314 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0); } yymsp[-3].minor.yy314 = yylhsminor.yy314; break; - case 163: /* term ::= CTIME_KW */ + case 166: /* term ::= CTIME_KW */ { yylhsminor.yy314 = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0); } yymsp[0].minor.yy314 = yylhsminor.yy314; break; - case 164: /* expr ::= LP nexprlist COMMA expr RP */ + case 167: /* expr ::= LP nexprlist COMMA expr RP */ { ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy322, yymsp[-1].minor.yy314); yymsp[-4].minor.yy314 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0); @@ -141277,20 +142982,20 @@ static void yy_reduce( } } break; - case 165: /* expr ::= expr AND expr */ - case 166: /* expr ::= expr OR expr */ yytestcase(yyruleno==166); - case 167: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==167); - case 168: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==168); - case 169: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==169); - case 170: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==170); - case 171: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==171); - case 172: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==172); + case 168: /* expr ::= expr AND expr */ + case 169: /* expr ::= expr OR expr */ yytestcase(yyruleno==169); + case 170: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==170); + case 171: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==171); + case 172: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==172); + case 173: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==173); + case 174: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==174); + case 175: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==175); {yymsp[-2].minor.yy314=sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy314,yymsp[0].minor.yy314);} break; - case 173: /* likeop ::= NOT LIKE_KW|MATCH */ + case 176: /* likeop ::= NOT LIKE_KW|MATCH */ {yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.n|=0x80000000; /*yymsp[-1].minor.yy0-overwrite-yymsp[0].minor.yy0*/} break; - case 174: /* expr ::= expr likeop expr */ + case 177: /* expr ::= expr likeop expr */ { ExprList *pList; int bNot = yymsp[-1].minor.yy0.n & 0x80000000; @@ -141302,7 +143007,7 @@ static void yy_reduce( if( yymsp[-2].minor.yy314 ) yymsp[-2].minor.yy314->flags |= EP_InfixFunc; } break; - case 175: /* expr ::= expr likeop expr ESCAPE expr */ + case 178: /* expr ::= expr likeop expr ESCAPE expr */ { ExprList *pList; int bNot = yymsp[-3].minor.yy0.n & 0x80000000; @@ -141315,39 +143020,39 @@ static void yy_reduce( if( yymsp[-4].minor.yy314 ) yymsp[-4].minor.yy314->flags |= EP_InfixFunc; } break; - case 176: /* expr ::= expr ISNULL|NOTNULL */ + case 179: /* expr ::= expr ISNULL|NOTNULL */ {yymsp[-1].minor.yy314 = sqlite3PExpr(pParse,yymsp[0].major,yymsp[-1].minor.yy314,0);} break; - case 177: /* expr ::= expr NOT NULL */ + case 180: /* expr ::= expr NOT NULL */ {yymsp[-2].minor.yy314 = sqlite3PExpr(pParse,TK_NOTNULL,yymsp[-2].minor.yy314,0);} break; - case 178: /* expr ::= expr IS expr */ + case 181: /* expr ::= expr IS expr */ { yymsp[-2].minor.yy314 = sqlite3PExpr(pParse,TK_IS,yymsp[-2].minor.yy314,yymsp[0].minor.yy314); binaryToUnaryIfNull(pParse, yymsp[0].minor.yy314, yymsp[-2].minor.yy314, TK_ISNULL); } break; - case 179: /* expr ::= expr IS NOT expr */ + case 182: /* expr ::= expr IS NOT expr */ { yymsp[-3].minor.yy314 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy314,yymsp[0].minor.yy314); binaryToUnaryIfNull(pParse, yymsp[0].minor.yy314, yymsp[-3].minor.yy314, TK_NOTNULL); } break; - case 180: /* expr ::= NOT expr */ - case 181: /* expr ::= BITNOT expr */ yytestcase(yyruleno==181); + case 183: /* expr ::= NOT expr */ + case 184: /* expr ::= BITNOT expr */ yytestcase(yyruleno==184); {yymsp[-1].minor.yy314 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy314, 0);/*A-overwrites-B*/} break; - case 182: /* expr ::= MINUS expr */ + case 185: /* expr ::= MINUS expr */ {yymsp[-1].minor.yy314 = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy314, 0);} break; - case 183: /* expr ::= PLUS expr */ + case 186: /* expr ::= PLUS expr */ {yymsp[-1].minor.yy314 = sqlite3PExpr(pParse, TK_UPLUS, yymsp[0].minor.yy314, 0);} break; - case 184: /* between_op ::= BETWEEN */ - case 187: /* in_op ::= IN */ yytestcase(yyruleno==187); + case 187: /* between_op ::= BETWEEN */ + case 190: /* in_op ::= IN */ yytestcase(yyruleno==190); {yymsp[0].minor.yy4 = 0;} break; - case 186: /* expr ::= expr between_op expr AND expr */ + case 189: /* expr ::= expr between_op expr AND expr */ { ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy314); pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy314); @@ -141360,7 +143065,7 @@ static void yy_reduce( if( yymsp[-3].minor.yy4 ) yymsp[-4].minor.yy314 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy314, 0); } break; - case 189: /* expr ::= expr in_op LP exprlist RP */ + case 192: /* expr ::= expr in_op LP exprlist RP */ { if( yymsp[-1].minor.yy322==0 ){ /* Expressions of the form @@ -141412,20 +143117,20 @@ static void yy_reduce( } } break; - case 190: /* expr ::= LP select RP */ + case 193: /* expr ::= LP select RP */ { yymsp[-2].minor.yy314 = sqlite3PExpr(pParse, TK_SELECT, 0, 0); sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy314, yymsp[-1].minor.yy387); } break; - case 191: /* expr ::= expr in_op LP select RP */ + case 194: /* expr ::= expr in_op LP select RP */ { yymsp[-4].minor.yy314 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy314, 0); sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy314, yymsp[-1].minor.yy387); if( yymsp[-3].minor.yy4 ) yymsp[-4].minor.yy314 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy314, 0); } break; - case 192: /* expr ::= expr in_op nm dbnm paren_exprlist */ + case 195: /* expr ::= expr in_op nm dbnm paren_exprlist */ { SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0); @@ -141435,14 +143140,14 @@ static void yy_reduce( if( yymsp[-3].minor.yy4 ) yymsp[-4].minor.yy314 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy314, 0); } break; - case 193: /* expr ::= EXISTS LP select RP */ + case 196: /* expr ::= EXISTS LP select RP */ { Expr *p; p = yymsp[-3].minor.yy314 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0); sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy387); } break; - case 194: /* expr ::= CASE case_operand case_exprlist case_else END */ + case 197: /* expr ::= CASE case_operand case_exprlist case_else END */ { yymsp[-4].minor.yy314 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy314, 0); if( yymsp[-4].minor.yy314 ){ @@ -141454,80 +143159,80 @@ static void yy_reduce( } } break; - case 195: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ + case 198: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ { yymsp[-4].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322, yymsp[-2].minor.yy314); yymsp[-4].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322, yymsp[0].minor.yy314); } break; - case 196: /* case_exprlist ::= WHEN expr THEN expr */ + case 199: /* case_exprlist ::= WHEN expr THEN expr */ { yymsp[-3].minor.yy322 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy314); yymsp[-3].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy322, yymsp[0].minor.yy314); } break; - case 199: /* case_operand ::= expr */ + case 202: /* case_operand ::= expr */ {yymsp[0].minor.yy314 = yymsp[0].minor.yy314; /*A-overwrites-X*/} break; - case 202: /* nexprlist ::= nexprlist COMMA expr */ + case 205: /* nexprlist ::= nexprlist COMMA expr */ {yymsp[-2].minor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy322,yymsp[0].minor.yy314);} break; - case 203: /* nexprlist ::= expr */ + case 206: /* nexprlist ::= expr */ {yymsp[0].minor.yy322 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy314); /*A-overwrites-Y*/} break; - case 205: /* paren_exprlist ::= LP exprlist RP */ - case 210: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==210); + case 208: /* paren_exprlist ::= LP exprlist RP */ + case 213: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==213); {yymsp[-2].minor.yy322 = yymsp[-1].minor.yy322;} break; - case 206: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ + case 209: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */ { sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy322, yymsp[-10].minor.yy4, &yymsp[-11].minor.yy0, yymsp[0].minor.yy314, SQLITE_SO_ASC, yymsp[-8].minor.yy4, SQLITE_IDXTYPE_APPDEF); } break; - case 207: /* uniqueflag ::= UNIQUE */ - case 247: /* raisetype ::= ABORT */ yytestcase(yyruleno==247); + case 210: /* uniqueflag ::= UNIQUE */ + case 250: /* raisetype ::= ABORT */ yytestcase(yyruleno==250); {yymsp[0].minor.yy4 = OE_Abort;} break; - case 208: /* uniqueflag ::= */ + case 211: /* uniqueflag ::= */ {yymsp[1].minor.yy4 = OE_None;} break; - case 211: /* eidlist ::= eidlist COMMA nm collate sortorder */ + case 214: /* eidlist ::= eidlist COMMA nm collate sortorder */ { yymsp[-4].minor.yy322 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy322, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy4, yymsp[0].minor.yy4); } break; - case 212: /* eidlist ::= nm collate sortorder */ + case 215: /* eidlist ::= nm collate sortorder */ { yymsp[-2].minor.yy322 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy4, yymsp[0].minor.yy4); /*A-overwrites-Y*/ } break; - case 215: /* cmd ::= DROP INDEX ifexists fullname */ + case 218: /* cmd ::= DROP INDEX ifexists fullname */ {sqlite3DropIndex(pParse, yymsp[0].minor.yy259, yymsp[-1].minor.yy4);} break; - case 216: /* cmd ::= VACUUM */ + case 219: /* cmd ::= VACUUM */ {sqlite3Vacuum(pParse,0);} break; - case 217: /* cmd ::= VACUUM nm */ + case 220: /* cmd ::= VACUUM nm */ {sqlite3Vacuum(pParse,&yymsp[0].minor.yy0);} break; - case 218: /* cmd ::= PRAGMA nm dbnm */ + case 221: /* cmd ::= PRAGMA nm dbnm */ {sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);} break; - case 219: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ + case 222: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);} break; - case 220: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ + case 223: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);} break; - case 221: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ + case 224: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);} break; - case 222: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ + case 225: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);} break; - case 225: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ + case 228: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ { Token all; all.z = yymsp[-3].minor.yy0.z; @@ -141535,50 +143240,50 @@ static void yy_reduce( sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy203, &all); } break; - case 226: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ + case 229: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ { sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy4, yymsp[-4].minor.yy90.a, yymsp[-4].minor.yy90.b, yymsp[-2].minor.yy259, yymsp[0].minor.yy314, yymsp[-10].minor.yy4, yymsp[-8].minor.yy4); yymsp[-10].minor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); /*A-overwrites-T*/ } break; - case 227: /* trigger_time ::= BEFORE|AFTER */ + case 230: /* trigger_time ::= BEFORE|AFTER */ { yymsp[0].minor.yy4 = yymsp[0].major; /*A-overwrites-X*/ } break; - case 228: /* trigger_time ::= INSTEAD OF */ + case 231: /* trigger_time ::= INSTEAD OF */ { yymsp[-1].minor.yy4 = TK_INSTEAD;} break; - case 229: /* trigger_time ::= */ + case 232: /* trigger_time ::= */ { yymsp[1].minor.yy4 = TK_BEFORE; } break; - case 230: /* trigger_event ::= DELETE|INSERT */ - case 231: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==231); + case 233: /* trigger_event ::= DELETE|INSERT */ + case 234: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==234); {yymsp[0].minor.yy90.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy90.b = 0;} break; - case 232: /* trigger_event ::= UPDATE OF idlist */ + case 235: /* trigger_event ::= UPDATE OF idlist */ {yymsp[-2].minor.yy90.a = TK_UPDATE; yymsp[-2].minor.yy90.b = yymsp[0].minor.yy384;} break; - case 233: /* when_clause ::= */ - case 252: /* key_opt ::= */ yytestcase(yyruleno==252); + case 236: /* when_clause ::= */ + case 255: /* key_opt ::= */ yytestcase(yyruleno==255); { yymsp[1].minor.yy314 = 0; } break; - case 234: /* when_clause ::= WHEN expr */ - case 253: /* key_opt ::= KEY expr */ yytestcase(yyruleno==253); + case 237: /* when_clause ::= WHEN expr */ + case 256: /* key_opt ::= KEY expr */ yytestcase(yyruleno==256); { yymsp[-1].minor.yy314 = yymsp[0].minor.yy314; } break; - case 235: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ + case 238: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ { assert( yymsp[-2].minor.yy203!=0 ); yymsp[-2].minor.yy203->pLast->pNext = yymsp[-1].minor.yy203; yymsp[-2].minor.yy203->pLast = yymsp[-1].minor.yy203; } break; - case 236: /* trigger_cmd_list ::= trigger_cmd SEMI */ + case 239: /* trigger_cmd_list ::= trigger_cmd SEMI */ { assert( yymsp[-1].minor.yy203!=0 ); yymsp[-1].minor.yy203->pLast = yymsp[-1].minor.yy203; } break; - case 237: /* trnm ::= nm DOT nm */ + case 240: /* trnm ::= nm DOT nm */ { yymsp[-2].minor.yy0 = yymsp[0].minor.yy0; sqlite3ErrorMsg(pParse, @@ -141586,37 +143291,37 @@ static void yy_reduce( "statements within triggers"); } break; - case 238: /* tridxby ::= INDEXED BY nm */ + case 241: /* tridxby ::= INDEXED BY nm */ { sqlite3ErrorMsg(pParse, "the INDEXED BY clause is not allowed on UPDATE or DELETE statements " "within triggers"); } break; - case 239: /* tridxby ::= NOT INDEXED */ + case 242: /* tridxby ::= NOT INDEXED */ { sqlite3ErrorMsg(pParse, "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements " "within triggers"); } break; - case 240: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */ + case 243: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */ {yylhsminor.yy203 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-5].minor.yy0, yymsp[-2].minor.yy322, yymsp[-1].minor.yy314, yymsp[-6].minor.yy4, yymsp[-7].minor.yy0.z, yymsp[0].minor.yy336);} yymsp[-7].minor.yy203 = yylhsminor.yy203; break; - case 241: /* trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select scanpt */ + case 244: /* trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select scanpt */ {yylhsminor.yy203 = sqlite3TriggerInsertStep(pParse->db,&yymsp[-3].minor.yy0,yymsp[-2].minor.yy384,yymsp[-1].minor.yy387,yymsp[-5].minor.yy4,yymsp[-6].minor.yy336,yymsp[0].minor.yy336);/*yylhsminor.yy203-overwrites-yymsp[-5].minor.yy4*/} yymsp[-6].minor.yy203 = yylhsminor.yy203; break; - case 242: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ + case 245: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */ {yylhsminor.yy203 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy314, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy336);} yymsp[-5].minor.yy203 = yylhsminor.yy203; break; - case 243: /* trigger_cmd ::= scanpt select scanpt */ + case 246: /* trigger_cmd ::= scanpt select scanpt */ {yylhsminor.yy203 = sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy387, yymsp[-2].minor.yy336, yymsp[0].minor.yy336); /*yylhsminor.yy203-overwrites-yymsp[-1].minor.yy387*/} yymsp[-2].minor.yy203 = yylhsminor.yy203; break; - case 244: /* expr ::= RAISE LP IGNORE RP */ + case 247: /* expr ::= RAISE LP IGNORE RP */ { yymsp[-3].minor.yy314 = sqlite3PExpr(pParse, TK_RAISE, 0, 0); if( yymsp[-3].minor.yy314 ){ @@ -141624,7 +143329,7 @@ static void yy_reduce( } } break; - case 245: /* expr ::= RAISE LP raisetype COMMA nm RP */ + case 248: /* expr ::= RAISE LP raisetype COMMA nm RP */ { yymsp[-5].minor.yy314 = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1); if( yymsp[-5].minor.yy314 ) { @@ -141632,152 +143337,148 @@ static void yy_reduce( } } break; - case 246: /* raisetype ::= ROLLBACK */ + case 249: /* raisetype ::= ROLLBACK */ {yymsp[0].minor.yy4 = OE_Rollback;} break; - case 248: /* raisetype ::= FAIL */ + case 251: /* raisetype ::= FAIL */ {yymsp[0].minor.yy4 = OE_Fail;} break; - case 249: /* cmd ::= DROP TRIGGER ifexists fullname */ + case 252: /* cmd ::= DROP TRIGGER ifexists fullname */ { sqlite3DropTrigger(pParse,yymsp[0].minor.yy259,yymsp[-1].minor.yy4); } break; - case 250: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ + case 253: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ { sqlite3Attach(pParse, yymsp[-3].minor.yy314, yymsp[-1].minor.yy314, yymsp[0].minor.yy314); } break; - case 251: /* cmd ::= DETACH database_kw_opt expr */ + case 254: /* cmd ::= DETACH database_kw_opt expr */ { sqlite3Detach(pParse, yymsp[0].minor.yy314); } break; - case 254: /* cmd ::= REINDEX */ + case 257: /* cmd ::= REINDEX */ {sqlite3Reindex(pParse, 0, 0);} break; - case 255: /* cmd ::= REINDEX nm dbnm */ + case 258: /* cmd ::= REINDEX nm dbnm */ {sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} break; - case 256: /* cmd ::= ANALYZE */ + case 259: /* cmd ::= ANALYZE */ {sqlite3Analyze(pParse, 0, 0);} break; - case 257: /* cmd ::= ANALYZE nm dbnm */ + case 260: /* cmd ::= ANALYZE nm dbnm */ {sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} break; - case 258: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ + case 261: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ { sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy259,&yymsp[0].minor.yy0); } break; - case 259: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ + case 262: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */ { yymsp[-1].minor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-1].minor.yy0.z) + pParse->sLastToken.n; sqlite3AlterFinishAddColumn(pParse, &yymsp[-1].minor.yy0); } break; - case 260: /* add_column_fullname ::= fullname */ + case 263: /* add_column_fullname ::= fullname */ { disableLookaside(pParse); sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy259); } break; - case 261: /* cmd ::= create_vtab */ + case 264: /* cmd ::= create_vtab */ {sqlite3VtabFinishParse(pParse,0);} break; - case 262: /* cmd ::= create_vtab LP vtabarglist RP */ + case 265: /* cmd ::= create_vtab LP vtabarglist RP */ {sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);} break; - case 263: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ + case 266: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ { sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy4); } break; - case 264: /* vtabarg ::= */ + case 267: /* vtabarg ::= */ {sqlite3VtabArgInit(pParse);} break; - case 265: /* vtabargtoken ::= ANY */ - case 266: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==266); - case 267: /* lp ::= LP */ yytestcase(yyruleno==267); + case 268: /* vtabargtoken ::= ANY */ + case 269: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==269); + case 270: /* lp ::= LP */ yytestcase(yyruleno==270); {sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);} break; - case 268: /* with ::= */ -{yymsp[1].minor.yy451 = 0;} + case 271: /* with ::= WITH wqlist */ + case 272: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==272); +{ sqlite3WithPush(pParse, yymsp[0].minor.yy451, 1); } break; - case 269: /* with ::= WITH wqlist */ -{ yymsp[-1].minor.yy451 = yymsp[0].minor.yy451; } - break; - case 270: /* with ::= WITH RECURSIVE wqlist */ -{ yymsp[-2].minor.yy451 = yymsp[0].minor.yy451; } - break; - case 271: /* wqlist ::= nm eidlist_opt AS LP select RP */ + case 273: /* wqlist ::= nm eidlist_opt AS LP select RP */ { yymsp[-5].minor.yy451 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy322, yymsp[-1].minor.yy387); /*A-overwrites-X*/ } break; - case 272: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ + case 274: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */ { yymsp[-7].minor.yy451 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy451, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy322, yymsp[-1].minor.yy387); } break; default: - /* (273) input ::= cmdlist */ yytestcase(yyruleno==273); - /* (274) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==274); - /* (275) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=275); - /* (276) ecmd ::= SEMI */ yytestcase(yyruleno==276); - /* (277) ecmd ::= explain cmdx SEMI */ yytestcase(yyruleno==277); - /* (278) explain ::= */ yytestcase(yyruleno==278); - /* (279) trans_opt ::= */ yytestcase(yyruleno==279); - /* (280) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==280); - /* (281) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==281); - /* (282) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==282); - /* (283) savepoint_opt ::= */ yytestcase(yyruleno==283); - /* (284) cmd ::= create_table create_table_args */ yytestcase(yyruleno==284); - /* (285) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==285); - /* (286) columnlist ::= columnname carglist */ yytestcase(yyruleno==286); - /* (287) nm ::= ID|INDEXED */ yytestcase(yyruleno==287); - /* (288) nm ::= STRING */ yytestcase(yyruleno==288); - /* (289) nm ::= JOIN_KW */ yytestcase(yyruleno==289); - /* (290) typetoken ::= typename */ yytestcase(yyruleno==290); - /* (291) typename ::= ID|STRING */ yytestcase(yyruleno==291); - /* (292) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=292); - /* (293) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=293); - /* (294) carglist ::= carglist ccons */ yytestcase(yyruleno==294); - /* (295) carglist ::= */ yytestcase(yyruleno==295); - /* (296) ccons ::= NULL onconf */ yytestcase(yyruleno==296); - /* (297) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==297); - /* (298) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==298); - /* (299) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=299); - /* (300) tconscomma ::= */ yytestcase(yyruleno==300); - /* (301) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=301); - /* (302) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=302); - /* (303) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=303); - /* (304) oneselect ::= values */ yytestcase(yyruleno==304); - /* (305) sclp ::= selcollist COMMA */ yytestcase(yyruleno==305); - /* (306) as ::= ID|STRING */ yytestcase(yyruleno==306); - /* (307) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=307); - /* (308) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==308); - /* (309) exprlist ::= nexprlist */ yytestcase(yyruleno==309); - /* (310) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=310); - /* (311) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=311); - /* (312) nmnum ::= ON */ yytestcase(yyruleno==312); - /* (313) nmnum ::= DELETE */ yytestcase(yyruleno==313); - /* (314) nmnum ::= DEFAULT */ yytestcase(yyruleno==314); - /* (315) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==315); - /* (316) foreach_clause ::= */ yytestcase(yyruleno==316); - /* (317) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==317); - /* (318) trnm ::= nm */ yytestcase(yyruleno==318); - /* (319) tridxby ::= */ yytestcase(yyruleno==319); - /* (320) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==320); - /* (321) database_kw_opt ::= */ yytestcase(yyruleno==321); - /* (322) kwcolumn_opt ::= */ yytestcase(yyruleno==322); - /* (323) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==323); - /* (324) vtabarglist ::= vtabarg */ yytestcase(yyruleno==324); - /* (325) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==325); - /* (326) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==326); - /* (327) anylist ::= */ yytestcase(yyruleno==327); - /* (328) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==328); - /* (329) anylist ::= anylist ANY */ yytestcase(yyruleno==329); + /* (275) input ::= cmdlist */ yytestcase(yyruleno==275); + /* (276) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==276); + /* (277) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=277); + /* (278) ecmd ::= SEMI */ yytestcase(yyruleno==278); + /* (279) ecmd ::= explain cmdx SEMI */ yytestcase(yyruleno==279); + /* (280) explain ::= */ yytestcase(yyruleno==280); + /* (281) trans_opt ::= */ yytestcase(yyruleno==281); + /* (282) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==282); + /* (283) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==283); + /* (284) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==284); + /* (285) savepoint_opt ::= */ yytestcase(yyruleno==285); + /* (286) cmd ::= create_table create_table_args */ yytestcase(yyruleno==286); + /* (287) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==287); + /* (288) columnlist ::= columnname carglist */ yytestcase(yyruleno==288); + /* (289) nm ::= ID|INDEXED */ yytestcase(yyruleno==289); + /* (290) nm ::= STRING */ yytestcase(yyruleno==290); + /* (291) nm ::= JOIN_KW */ yytestcase(yyruleno==291); + /* (292) typetoken ::= typename */ yytestcase(yyruleno==292); + /* (293) typename ::= ID|STRING */ yytestcase(yyruleno==293); + /* (294) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=294); + /* (295) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=295); + /* (296) carglist ::= carglist ccons */ yytestcase(yyruleno==296); + /* (297) carglist ::= */ yytestcase(yyruleno==297); + /* (298) ccons ::= NULL onconf */ yytestcase(yyruleno==298); + /* (299) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==299); + /* (300) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==300); + /* (301) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=301); + /* (302) tconscomma ::= */ yytestcase(yyruleno==302); + /* (303) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=303); + /* (304) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=304); + /* (305) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=305); + /* (306) oneselect ::= values */ yytestcase(yyruleno==306); + /* (307) sclp ::= selcollist COMMA */ yytestcase(yyruleno==307); + /* (308) as ::= ID|STRING */ yytestcase(yyruleno==308); + /* (309) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=309); + /* (310) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==310); + /* (311) exprlist ::= nexprlist */ yytestcase(yyruleno==311); + /* (312) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=312); + /* (313) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=313); + /* (314) nmnum ::= ON */ yytestcase(yyruleno==314); + /* (315) nmnum ::= DELETE */ yytestcase(yyruleno==315); + /* (316) nmnum ::= DEFAULT */ yytestcase(yyruleno==316); + /* (317) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==317); + /* (318) foreach_clause ::= */ yytestcase(yyruleno==318); + /* (319) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==319); + /* (320) trnm ::= nm */ yytestcase(yyruleno==320); + /* (321) tridxby ::= */ yytestcase(yyruleno==321); + /* (322) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==322); + /* (323) database_kw_opt ::= */ yytestcase(yyruleno==323); + /* (324) kwcolumn_opt ::= */ yytestcase(yyruleno==324); + /* (325) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==325); + /* (326) vtabarglist ::= vtabarg */ yytestcase(yyruleno==326); + /* (327) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==327); + /* (328) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==328); + /* (329) anylist ::= */ yytestcase(yyruleno==329); + /* (330) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==330); + /* (331) anylist ::= anylist ANY */ yytestcase(yyruleno==331); + /* (332) with ::= */ yytestcase(yyruleno==332); break; /********** End reduce actions ************************************************/ }; @@ -143604,6 +145305,11 @@ SQLITE_API int sqlite3_initialize(void){ sqlite3GlobalConfig.isPCacheInit = 1; rc = sqlite3OsInit(); } +#ifdef SQLITE_ENABLE_DESERIALIZE + if( rc==SQLITE_OK ){ + rc = sqlite3MemdbInit(); + } +#endif if( rc==SQLITE_OK ){ sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage, sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage); @@ -143636,7 +145342,7 @@ SQLITE_API int sqlite3_initialize(void){ #ifndef NDEBUG #ifndef SQLITE_OMIT_FLOATING_POINT /* This section of code's only "output" is via assert() statements. */ - if ( rc==SQLITE_OK ){ + if( rc==SQLITE_OK ){ u64 x = (((u64)1)<<63)-1; double y; assert(sizeof(x)==8); @@ -144803,6 +146509,8 @@ SQLITE_PRIVATE const char *sqlite3ErrStr(int rc){ /* SQLITE_FORMAT */ 0, /* SQLITE_RANGE */ "column index out of range", /* SQLITE_NOTADB */ "file is not a database", + /* SQLITE_NOTICE */ "notification message", + /* SQLITE_WARNING */ "warning message", }; const char *zErr = "unknown error"; switch( rc ){ @@ -144810,6 +146518,14 @@ SQLITE_PRIVATE const char *sqlite3ErrStr(int rc){ zErr = "abort due to ROLLBACK"; break; } + case SQLITE_ROW: { + zErr = "another row available"; + break; + } + case SQLITE_DONE: { + zErr = "no more rows available"; + break; + } default: { rc &= 0xff; if( ALWAYS(rc>=0) && rcbusyTimeout; + int tmout = db->busyTimeout; int delay, prior; +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT + if( sqlite3OsFileControl(pFile,SQLITE_FCNTL_LOCK_TIMEOUT,&tmout)==SQLITE_OK ){ + if( count ){ + tmout = 0; + sqlite3OsFileControl(pFile, SQLITE_FCNTL_LOCK_TIMEOUT, &tmout); + return 0; + }else{ + return 1; + } + } +#else + UNUSED_PARAMETER(pFile); +#endif assert( count>=0 ); if( count < NDELAY ){ delay = delays[count]; @@ -144849,16 +146584,19 @@ static int sqliteDefaultBusyCallback( delay = delays[NDELAY-1]; prior = totals[NDELAY-1] + delay*(count-(NDELAY-1)); } - if( prior + delay > timeout ){ - delay = timeout - prior; + if( prior + delay > tmout ){ + delay = tmout - prior; if( delay<=0 ) return 0; } sqlite3OsSleep(db->pVfs, delay*1000); return 1; #else + /* This case for unix systems that lack usleep() support. Sleeping + ** must be done in increments of whole seconds */ sqlite3 *db = (sqlite3 *)ptr; - int timeout = ((sqlite3 *)ptr)->busyTimeout; - if( (count+1)*1000 > timeout ){ + int tmout = ((sqlite3 *)ptr)->busyTimeout; + UNUSED_PARAMETER(pFile); + if( (count+1)*1000 > tmout ){ return 0; } sqlite3OsSleep(db->pVfs, 1000000); @@ -144869,14 +146607,25 @@ static int sqliteDefaultBusyCallback( /* ** Invoke the given busy handler. ** -** This routine is called when an operation failed with a lock. +** This routine is called when an operation failed to acquire a +** lock on VFS file pFile. +** ** If this routine returns non-zero, the lock is retried. If it ** returns 0, the operation aborts with an SQLITE_BUSY error. */ -SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler *p){ +SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler *p, sqlite3_file *pFile){ int rc; - if( NEVER(p==0) || p->xFunc==0 || p->nBusy<0 ) return 0; - rc = p->xFunc(p->pArg, p->nBusy); + if( p->xBusyHandler==0 || p->nBusy<0 ) return 0; + if( p->bExtraFileArg ){ + /* Add an extra parameter with the pFile pointer to the end of the + ** callback argument list */ + int (*xTra)(void*,int,sqlite3_file*); + xTra = (int(*)(void*,int,sqlite3_file*))p->xBusyHandler; + rc = xTra(p->pBusyArg, p->nBusy, pFile); + }else{ + /* Legacy style busy handler callback */ + rc = p->xBusyHandler(p->pBusyArg, p->nBusy); + } if( rc==0 ){ p->nBusy = -1; }else{ @@ -144898,9 +146647,10 @@ SQLITE_API int sqlite3_busy_handler( if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; #endif sqlite3_mutex_enter(db->mutex); - db->busyHandler.xFunc = xBusy; - db->busyHandler.pArg = pArg; + db->busyHandler.xBusyHandler = xBusy; + db->busyHandler.pBusyArg = pArg; db->busyHandler.nBusy = 0; + db->busyHandler.bExtraFileArg = 0; db->busyTimeout = 0; sqlite3_mutex_leave(db->mutex); return SQLITE_OK; @@ -144948,8 +146698,10 @@ SQLITE_API int sqlite3_busy_timeout(sqlite3 *db, int ms){ if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; #endif if( ms>0 ){ - sqlite3_busy_handler(db, sqliteDefaultBusyCallback, (void*)db); + sqlite3_busy_handler(db, (int(*)(void*,int))sqliteDefaultBusyCallback, + (void*)db); db->busyTimeout = ms; + db->busyHandler.bExtraFileArg = 1; }else{ sqlite3_busy_handler(db, 0, 0); } @@ -146942,10 +148694,8 @@ SQLITE_API int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, vo }else if( op==SQLITE_FCNTL_JOURNAL_POINTER ){ *(sqlite3_file**)pArg = sqlite3PagerJrnlFile(pPager); rc = SQLITE_OK; - }else if( fd->pMethods ){ - rc = sqlite3OsFileControl(fd, op, pArg); }else{ - rc = SQLITE_NOTFOUND; + rc = sqlite3OsFileControl(fd, op, pArg); } sqlite3BtreeLeave(pBtree); } @@ -160796,6 +162546,7 @@ static int fts3WriteSegment( sqlite3_bind_blob(pStmt, 2, z, n, SQLITE_STATIC); sqlite3_step(pStmt); rc = sqlite3_reset(pStmt); + sqlite3_bind_null(pStmt, 2); } return rc; } @@ -160852,6 +162603,7 @@ static int fts3WriteSegdir( sqlite3_bind_blob(pStmt, 6, zRoot, nRoot, SQLITE_STATIC); sqlite3_step(pStmt); rc = sqlite3_reset(pStmt); + sqlite3_bind_null(pStmt, 6); } return rc; } @@ -162331,6 +164083,7 @@ static void fts3UpdateDocTotals( sqlite3_bind_blob(pStmt, 2, pBlob, nBlob, SQLITE_STATIC); sqlite3_step(pStmt); *pRC = sqlite3_reset(pStmt); + sqlite3_bind_null(pStmt, 2); sqlite3_free(a); } @@ -163519,6 +165272,7 @@ static int fts3TruncateSegment( sqlite3_bind_int(pChomp, 4, iIdx); sqlite3_step(pChomp); rc = sqlite3_reset(pChomp); + sqlite3_bind_null(pChomp, 2); } } @@ -163598,6 +165352,7 @@ static int fts3IncrmergeHintStore(Fts3Table *p, Blob *pHint){ sqlite3_bind_blob(pReplace, 2, pHint->a, pHint->n, SQLITE_STATIC); sqlite3_step(pReplace); rc = sqlite3_reset(pReplace); + sqlite3_bind_null(pReplace, 2); } return rc; @@ -164412,7 +166167,6 @@ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod( ){ Fts3Table *p = (Fts3Table *)pVtab; int rc = SQLITE_OK; /* Return Code */ - int isRemove = 0; /* True for an UPDATE or DELETE */ u32 *aSzIns = 0; /* Sizes of inserted documents */ u32 *aSzDel = 0; /* Sizes of deleted documents */ int nChng = 0; /* Net change in number of documents */ @@ -164510,7 +166264,6 @@ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod( if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){ assert( sqlite3_value_type(apVal[0])==SQLITE_INTEGER ); rc = fts3DeleteByRowid(p, apVal[0], &nChng, aSzDel); - isRemove = 1; } /* If this is an INSERT or UPDATE operation, insert the new record. */ @@ -164522,7 +166275,7 @@ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod( rc = FTS_CORRUPT_VTAB; } } - if( rc==SQLITE_OK && (!isRemove || *pRowid!=p->iPrevDocid ) ){ + if( rc==SQLITE_OK ){ rc = fts3PendingTermsDocid(p, 0, iLangid, *pRowid); } if( rc==SQLITE_OK ){ @@ -167830,6 +169583,7 @@ static int nodeWrite(Rtree *pRtree, RtreeNode *pNode){ sqlite3_step(p); pNode->isDirty = 0; rc = sqlite3_reset(p); + sqlite3_bind_null(p, 2); if( pNode->iNode==0 && rc==SQLITE_OK ){ pNode->iNode = sqlite3_last_insert_rowid(pRtree->db); nodeHashInsert(pRtree, pNode); @@ -174517,7 +176271,7 @@ static void rbuCreateImposterTable2(sqlite3rbu *p, RbuObjIter *pIter){ int iCid = sqlite3_column_int(pXInfo, 1); int bDesc = sqlite3_column_int(pXInfo, 3); const char *zCollate = (const char*)sqlite3_column_text(pXInfo, 4); - zCols = rbuMPrintf(p, "%z%sc%d %s COLLATE %s", zCols, zComma, + zCols = rbuMPrintf(p, "%z%sc%d %s COLLATE %Q", zCols, zComma, iCid, pIter->azTblType[iCid], zCollate ); zPk = rbuMPrintf(p, "%z%sc%d%s", zPk, zComma, iCid, bDesc?" DESC":""); @@ -174578,7 +176332,7 @@ static void rbuCreateImposterTable(sqlite3rbu *p, RbuObjIter *pIter){ ** "PRIMARY KEY" to the imposter table column declaration. */ zPk = "PRIMARY KEY "; } - zSql = rbuMPrintf(p, "%z%s\"%w\" %s %sCOLLATE %s%s", + zSql = rbuMPrintf(p, "%z%s\"%w\" %s %sCOLLATE %Q%s", zSql, zComma, zCol, pIter->azTblType[iCol], zPk, zColl, (pIter->abNotNull[iCol] ? " NOT NULL" : "") ); @@ -178012,7 +179766,7 @@ static void statSizeAndOffset(StatCursor *pCsr){ */ fd = sqlite3PagerFile(pPager); x[0] = pCsr->iPageno; - if( fd->pMethods!=0 && sqlite3OsFileControl(fd, 230440, &x)==SQLITE_OK ){ + if( sqlite3OsFileControl(fd, 230440, &x)==SQLITE_OK ){ pCsr->iOffset = x[0]; pCsr->szPage = (int)x[1]; } @@ -178778,7 +180532,7 @@ struct SessionBuffer { ** sqlite3changeset_start_strm()). */ struct SessionInput { - int bNoDiscard; /* If true, discard no data */ + int bNoDiscard; /* If true, do not discard in InputBuffer() */ int iCurrent; /* Offset in aData[] of current change */ int iNext; /* Offset in aData[] of next change */ u8 *aData; /* Pointer to buffer containing changeset */ @@ -178942,8 +180696,8 @@ struct SessionTable { ** statement. ** ** For a DELETE change, all fields within the record except those associated -** with PRIMARY KEY columns are set to "undefined". The PRIMARY KEY fields -** contain the values identifying the row to delete. +** with PRIMARY KEY columns are omitted. The PRIMARY KEY fields contain the +** values identifying the row to delete. ** ** For an UPDATE change, all fields except those associated with PRIMARY KEY ** columns and columns that are modified by the UPDATE are set to "undefined". @@ -179226,7 +180980,7 @@ static int sessionPreupdateHash( static int sessionSerialLen(u8 *a){ int e = *a; int n; - if( e==0 ) return 1; + if( e==0 || e==0xFF ) return 1; if( e==SQLITE_NULL ) return 1; if( e==SQLITE_INTEGER || e==SQLITE_FLOAT ) return 9; return sessionVarintGet(&a[1], &n) + 1 + n; @@ -179306,7 +181060,7 @@ static int sessionChangeEqual( int n1 = sessionSerialLen(a1); int n2 = sessionSerialLen(a2); - if( pTab->abPK[iCol] && (n1!=n2 || memcmp(a1, a2, n1)) ){ + if( n1!=n2 || memcmp(a1, a2, n1) ){ return 0; } a1 += n1; @@ -179549,7 +181303,7 @@ static int sessionPreupdateEqual( }else{ z = sqlite3_value_blob(pVal); } - if( memcmp(a, z, n) ) return 0; + if( n>0 && memcmp(a, z, n) ) return 0; a += n; } } @@ -179825,7 +181579,7 @@ static void sessionPreupdateOneChange( int iHash; int bNull = 0; int rc = SQLITE_OK; - SessionStat1Ctx stat1; + SessionStat1Ctx stat1 = {0}; if( pSession->rc ) return; @@ -180893,6 +182647,7 @@ static int sessionSelectStmt( "SELECT tbl, ?2, stat FROM %Q.sqlite_stat1 WHERE tbl IS ?1 AND " "idx IS (CASE WHEN ?2=X'' THEN NULL ELSE ?2 END)", zDb ); + if( zSql==0 ) rc = SQLITE_NOMEM; }else{ int i; const char *zSep = ""; @@ -181302,7 +183057,7 @@ SQLITE_API int sqlite3changeset_start_strm( ** object and the buffer is full, discard some data to free up space. */ static void sessionDiscardData(SessionInput *pIn){ - if( pIn->bEof && pIn->xInput && pIn->iNext>=SESSIONS_STRM_CHUNK_SIZE ){ + if( pIn->xInput && pIn->iNext>=SESSIONS_STRM_CHUNK_SIZE ){ int nMove = pIn->buf.nBuf - pIn->iNext; assert( nMove>=0 ); if( nMove>0 ){ @@ -181430,13 +183185,16 @@ static int sessionReadRecord( if( abPK && abPK[i]==0 ) continue; rc = sessionInputBuffer(pIn, 9); if( rc==SQLITE_OK ){ - eType = pIn->aData[pIn->iNext++]; - } - - assert( apOut[i]==0 ); - if( eType ){ - apOut[i] = sqlite3ValueNew(0); - if( !apOut[i] ) rc = SQLITE_NOMEM; + if( pIn->iNext>=pIn->nData ){ + rc = SQLITE_CORRUPT_BKPT; + }else{ + eType = pIn->aData[pIn->iNext++]; + assert( apOut[i]==0 ); + if( eType ){ + apOut[i] = sqlite3ValueNew(0); + if( !apOut[i] ) rc = SQLITE_NOMEM; + } + } } if( rc==SQLITE_OK ){ @@ -181446,10 +183204,14 @@ static int sessionReadRecord( pIn->iNext += sessionVarintGet(aVal, &nByte); rc = sessionInputBuffer(pIn, nByte); if( rc==SQLITE_OK ){ - u8 enc = (eType==SQLITE_TEXT ? SQLITE_UTF8 : 0); - rc = sessionValueSetStr(apOut[i],&pIn->aData[pIn->iNext],nByte,enc); + if( nByte<0 || nByte>pIn->nData-pIn->iNext ){ + rc = SQLITE_CORRUPT_BKPT; + }else{ + u8 enc = (eType==SQLITE_TEXT ? SQLITE_UTF8 : 0); + rc = sessionValueSetStr(apOut[i],&pIn->aData[pIn->iNext],nByte,enc); + pIn->iNext += nByte; + } } - pIn->iNext += nByte; } if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ sqlite3_int64 v = sessionGetI64(aVal); @@ -181489,8 +183251,19 @@ static int sessionChangesetBufferTblhdr(SessionInput *pIn, int *pnByte){ rc = sessionInputBuffer(pIn, 9); if( rc==SQLITE_OK ){ nRead += sessionVarintGet(&pIn->aData[pIn->iNext + nRead], &nCol); - rc = sessionInputBuffer(pIn, nRead+nCol+100); - nRead += nCol; + /* The hard upper limit for the number of columns in an SQLite + ** database table is, according to sqliteLimit.h, 32676. So + ** consider any table-header that purports to have more than 65536 + ** columns to be corrupt. This is convenient because otherwise, + ** if the (nCol>65536) condition below were omitted, a sufficiently + ** large value for nCol may cause nRead to wrap around and become + ** negative. Leading to a crash. */ + if( nCol<0 || nCol>65536 ){ + rc = SQLITE_CORRUPT_BKPT; + }else{ + rc = sessionInputBuffer(pIn, nRead+nCol+100); + nRead += nCol; + } } while( rc==SQLITE_OK ){ @@ -181567,11 +183340,15 @@ static int sessionChangesetReadTblhdr(sqlite3_changeset_iter *p){ int nByte; int nVarint; nVarint = sessionVarintGet(&p->in.aData[p->in.iNext], &p->nCol); - nCopy -= nVarint; - p->in.iNext += nVarint; - nByte = p->nCol * sizeof(sqlite3_value*) * 2 + nCopy; - p->tblhdr.nBuf = 0; - sessionBufferGrow(&p->tblhdr, nByte, &rc); + if( p->nCol>0 ){ + nCopy -= nVarint; + p->in.iNext += nVarint; + nByte = p->nCol * sizeof(sqlite3_value*) * 2 + nCopy; + p->tblhdr.nBuf = 0; + sessionBufferGrow(&p->tblhdr, nByte, &rc); + }else{ + rc = SQLITE_CORRUPT_BKPT; + } } if( rc==SQLITE_OK ){ @@ -181606,7 +183383,8 @@ static int sessionChangesetReadTblhdr(sqlite3_changeset_iter *p){ static int sessionChangesetNext( sqlite3_changeset_iter *p, /* Changeset iterator */ u8 **paRec, /* If non-NULL, store record pointer here */ - int *pnRec /* If non-NULL, store size of record here */ + int *pnRec, /* If non-NULL, store size of record here */ + int *pbNew /* If non-NULL, true if new table */ ){ int i; u8 op; @@ -181641,6 +183419,7 @@ static int sessionChangesetNext( op = p->in.aData[p->in.iNext++]; while( op=='T' || op=='P' ){ + if( pbNew ) *pbNew = 1; p->bPatchset = (op=='P'); if( sessionChangesetReadTblhdr(p) ) return p->rc; if( (p->rc = sessionInputBuffer(&p->in, 2)) ) return p->rc; @@ -181649,6 +183428,13 @@ static int sessionChangesetNext( op = p->in.aData[p->in.iNext++]; } + if( p->zTab==0 ){ + /* The first record in the changeset is not a table header. Must be a + ** corrupt changeset. */ + assert( p->in.iNext==1 ); + return (p->rc = SQLITE_CORRUPT_BKPT); + } + p->op = op; p->bIndirect = p->in.aData[p->in.iNext++]; if( p->op!=SQLITE_UPDATE && p->op!=SQLITE_DELETE && p->op!=SQLITE_INSERT ){ @@ -181691,9 +183477,9 @@ static int sessionChangesetNext( ** new.* to old.*, to accommodate the code that reads these arrays. */ for(i=0; inCol; i++){ assert( p->apValue[i]==0 ); - assert( p->abPK[i]==0 || p->apValue[i+p->nCol] ); if( p->abPK[i] ){ p->apValue[i] = p->apValue[i+p->nCol]; + if( p->apValue[i]==0 ) return (p->rc = SQLITE_CORRUPT_BKPT); p->apValue[i+p->nCol] = 0; } } @@ -181712,7 +183498,7 @@ static int sessionChangesetNext( ** callback by changeset_apply(). */ SQLITE_API int sqlite3changeset_next(sqlite3_changeset_iter *p){ - return sessionChangesetNext(p, 0, 0); + return sessionChangesetNext(p, 0, 0, 0); } /* @@ -182091,6 +183877,8 @@ struct SessionApplyCtx { int bStat1; /* True if table is sqlite_stat1 */ int bDeferConstraints; /* True to defer constraints */ SessionBuffer constraints; /* Deferred constraints are stored here */ + SessionBuffer rebase; /* Rebase information (if any) here */ + int bRebaseStarted; /* If table header is already in rebase */ }; /* @@ -182357,7 +184145,6 @@ static int sessionStat1Sql(sqlite3 *db, SessionApplyCtx *p){ "AND (?4 OR stat IS ?3)" ); } - assert( rc==SQLITE_OK ); return rc; } @@ -182418,7 +184205,13 @@ static int sessionBindRow( if( !abPK || abPK[i] ){ sqlite3_value *pVal; (void)xValue(pIter, i, &pVal); - rc = sessionBindValue(pStmt, i+1, pVal); + if( pVal==0 ){ + /* The value in the changeset was "undefined". This indicates a + ** corrupt changeset blob. */ + rc = SQLITE_CORRUPT_BKPT; + }else{ + rc = sessionBindValue(pStmt, i+1, pVal); + } } } return rc; @@ -182466,6 +184259,54 @@ static int sessionSeekToRow( return rc; } +/* +** This function is called from within sqlite3changset_apply_v2() when +** a conflict is encountered and resolved using conflict resolution +** mode eType (either SQLITE_CHANGESET_OMIT or SQLITE_CHANGESET_REPLACE).. +** It adds a conflict resolution record to the buffer in +** SessionApplyCtx.rebase, which will eventually be returned to the caller +** of apply_v2() as the "rebase" buffer. +** +** Return SQLITE_OK if successful, or an SQLite error code otherwise. +*/ +static int sessionRebaseAdd( + SessionApplyCtx *p, /* Apply context */ + int eType, /* Conflict resolution (OMIT or REPLACE) */ + sqlite3_changeset_iter *pIter /* Iterator pointing at current change */ +){ + int rc = SQLITE_OK; + int i; + int eOp = pIter->op; + if( p->bRebaseStarted==0 ){ + /* Append a table-header to the rebase buffer */ + const char *zTab = pIter->zTab; + sessionAppendByte(&p->rebase, 'T', &rc); + sessionAppendVarint(&p->rebase, p->nCol, &rc); + sessionAppendBlob(&p->rebase, p->abPK, p->nCol, &rc); + sessionAppendBlob(&p->rebase, (u8*)zTab, (int)strlen(zTab)+1, &rc); + p->bRebaseStarted = 1; + } + + assert( eType==SQLITE_CHANGESET_REPLACE||eType==SQLITE_CHANGESET_OMIT ); + assert( eOp==SQLITE_DELETE || eOp==SQLITE_INSERT || eOp==SQLITE_UPDATE ); + + sessionAppendByte(&p->rebase, + (eOp==SQLITE_DELETE ? SQLITE_DELETE : SQLITE_INSERT), &rc + ); + sessionAppendByte(&p->rebase, (eType==SQLITE_CHANGESET_REPLACE), &rc); + for(i=0; inCol; i++){ + sqlite3_value *pVal = 0; + if( eOp==SQLITE_DELETE || (eOp==SQLITE_UPDATE && p->abPK[i]) ){ + sqlite3changeset_old(pIter, i, &pVal); + }else{ + sqlite3changeset_new(pIter, i, &pVal); + } + sessionAppendValue(&p->rebase, pVal, &rc); + } + + return rc; +} + /* ** Invoke the conflict handler for the change that the changeset iterator ** currently points to. @@ -182541,7 +184382,7 @@ static int sessionConflictHandler( u8 *aBlob = &pIter->in.aData[pIter->in.iCurrent]; int nBlob = pIter->in.iNext - pIter->in.iCurrent; sessionAppendBlob(&p->constraints, aBlob, nBlob, &rc); - res = SQLITE_CHANGESET_OMIT; + return SQLITE_OK; }else{ /* No other row with the new.* primary key. */ res = xConflict(pCtx, eType+1, pIter); @@ -182567,6 +184408,9 @@ static int sessionConflictHandler( rc = SQLITE_MISUSE; break; } + if( rc==SQLITE_OK ){ + rc = sessionRebaseAdd(p, res, pIter); + } } return rc; @@ -182742,42 +184586,42 @@ static int sessionApplyOneWithRetry( int rc; rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, &bReplace, &bRetry); - assert( rc==SQLITE_OK || (bRetry==0 && bReplace==0) ); - - /* If the bRetry flag is set, the change has not been applied due to an - ** SQLITE_CHANGESET_DATA problem (i.e. this is an UPDATE or DELETE and - ** a row with the correct PK is present in the db, but one or more other - ** fields do not contain the expected values) and the conflict handler - ** returned SQLITE_CHANGESET_REPLACE. In this case retry the operation, - ** but pass NULL as the final argument so that sessionApplyOneOp() ignores - ** the SQLITE_CHANGESET_DATA problem. */ - if( bRetry ){ - assert( pIter->op==SQLITE_UPDATE || pIter->op==SQLITE_DELETE ); - rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, 0, 0); - } - - /* If the bReplace flag is set, the change is an INSERT that has not - ** been performed because the database already contains a row with the - ** specified primary key and the conflict handler returned - ** SQLITE_CHANGESET_REPLACE. In this case remove the conflicting row - ** before reattempting the INSERT. */ - else if( bReplace ){ - assert( pIter->op==SQLITE_INSERT ); - rc = sqlite3_exec(db, "SAVEPOINT replace_op", 0, 0, 0); - if( rc==SQLITE_OK ){ - rc = sessionBindRow(pIter, - sqlite3changeset_new, pApply->nCol, pApply->abPK, pApply->pDelete); - sqlite3_bind_int(pApply->pDelete, pApply->nCol+1, 1); - } - if( rc==SQLITE_OK ){ - sqlite3_step(pApply->pDelete); - rc = sqlite3_reset(pApply->pDelete); - } - if( rc==SQLITE_OK ){ + if( rc==SQLITE_OK ){ + /* If the bRetry flag is set, the change has not been applied due to an + ** SQLITE_CHANGESET_DATA problem (i.e. this is an UPDATE or DELETE and + ** a row with the correct PK is present in the db, but one or more other + ** fields do not contain the expected values) and the conflict handler + ** returned SQLITE_CHANGESET_REPLACE. In this case retry the operation, + ** but pass NULL as the final argument so that sessionApplyOneOp() ignores + ** the SQLITE_CHANGESET_DATA problem. */ + if( bRetry ){ + assert( pIter->op==SQLITE_UPDATE || pIter->op==SQLITE_DELETE ); rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, 0, 0); } - if( rc==SQLITE_OK ){ - rc = sqlite3_exec(db, "RELEASE replace_op", 0, 0, 0); + + /* If the bReplace flag is set, the change is an INSERT that has not + ** been performed because the database already contains a row with the + ** specified primary key and the conflict handler returned + ** SQLITE_CHANGESET_REPLACE. In this case remove the conflicting row + ** before reattempting the INSERT. */ + else if( bReplace ){ + assert( pIter->op==SQLITE_INSERT ); + rc = sqlite3_exec(db, "SAVEPOINT replace_op", 0, 0, 0); + if( rc==SQLITE_OK ){ + rc = sessionBindRow(pIter, + sqlite3changeset_new, pApply->nCol, pApply->abPK, pApply->pDelete); + sqlite3_bind_int(pApply->pDelete, pApply->nCol+1, 1); + } + if( rc==SQLITE_OK ){ + sqlite3_step(pApply->pDelete); + rc = sqlite3_reset(pApply->pDelete); + } + if( rc==SQLITE_OK ){ + rc = sessionApplyOneOp(pIter, pApply, xConflict, pCtx, 0, 0); + } + if( rc==SQLITE_OK ){ + rc = sqlite3_exec(db, "RELEASE replace_op", 0, 0, 0); + } } } @@ -182853,10 +184697,12 @@ static int sessionChangesetApply( int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ sqlite3_changeset_iter *p /* Handle describing change and conflict */ ), - void *pCtx /* First argument passed to xConflict */ + void *pCtx, /* First argument passed to xConflict */ + void **ppRebase, int *pnRebase, /* OUT: Rebase information */ + int flags /* SESSION_APPLY_XXX flags */ ){ int schemaMismatch = 0; - int rc; /* Return code */ + int rc = SQLITE_OK; /* Return code */ const char *zTab = 0; /* Name of current table */ int nTab = 0; /* Result of sqlite3Strlen30(zTab) */ SessionApplyCtx sApply; /* changeset_apply() context object */ @@ -182867,7 +184713,9 @@ static int sessionChangesetApply( pIter->in.bNoDiscard = 1; memset(&sApply, 0, sizeof(sApply)); sqlite3_mutex_enter(sqlite3_db_mutex(db)); - rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0); + if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){ + rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0); + } if( rc==SQLITE_OK ){ rc = sqlite3_exec(db, "PRAGMA defer_foreign_keys = 1", 0, 0, 0); } @@ -182891,9 +184739,18 @@ static int sessionChangesetApply( sqlite3_finalize(sApply.pUpdate); sqlite3_finalize(sApply.pInsert); sqlite3_finalize(sApply.pSelect); - memset(&sApply, 0, sizeof(sApply)); sApply.db = db; + sApply.pDelete = 0; + sApply.pUpdate = 0; + sApply.pInsert = 0; + sApply.pSelect = 0; + sApply.nCol = 0; + sApply.azCol = 0; + sApply.abPK = 0; + sApply.bStat1 = 0; sApply.bDeferConstraints = 1; + sApply.bRebaseStarted = 0; + memset(&sApply.constraints, 0, sizeof(SessionBuffer)); /* If an xFilter() callback was specified, invoke it now. If the ** xFilter callback returns zero, skip this table. If it returns @@ -182996,23 +184853,62 @@ static int sessionChangesetApply( } sqlite3_exec(db, "PRAGMA defer_foreign_keys = 0", 0, 0, 0); - if( rc==SQLITE_OK ){ - rc = sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0); - }else{ - sqlite3_exec(db, "ROLLBACK TO changeset_apply", 0, 0, 0); - sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0); + if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){ + if( rc==SQLITE_OK ){ + rc = sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0); + }else{ + sqlite3_exec(db, "ROLLBACK TO changeset_apply", 0, 0, 0); + sqlite3_exec(db, "RELEASE changeset_apply", 0, 0, 0); + } } + if( rc==SQLITE_OK && bPatchset==0 && ppRebase && pnRebase ){ + *ppRebase = (void*)sApply.rebase.aBuf; + *pnRebase = sApply.rebase.nBuf; + sApply.rebase.aBuf = 0; + } sqlite3_finalize(sApply.pInsert); sqlite3_finalize(sApply.pDelete); sqlite3_finalize(sApply.pUpdate); sqlite3_finalize(sApply.pSelect); sqlite3_free((char*)sApply.azCol); /* cast works around VC++ bug */ sqlite3_free((char*)sApply.constraints.aBuf); + sqlite3_free((char*)sApply.rebase.aBuf); sqlite3_mutex_leave(sqlite3_db_mutex(db)); return rc; } +/* +** Apply the changeset passed via pChangeset/nChangeset to the main +** database attached to handle "db". +*/ +SQLITE_API int sqlite3changeset_apply_v2( + sqlite3 *db, /* Apply change to "main" db of this handle */ + int nChangeset, /* Size of changeset in bytes */ + void *pChangeset, /* Changeset blob */ + int(*xFilter)( + void *pCtx, /* Copy of sixth arg to _apply() */ + const char *zTab /* Table name */ + ), + int(*xConflict)( + void *pCtx, /* Copy of sixth arg to _apply() */ + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ + sqlite3_changeset_iter *p /* Handle describing change and conflict */ + ), + void *pCtx, /* First argument passed to xConflict */ + void **ppRebase, int *pnRebase, + int flags +){ + sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ + int rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset); + if( rc==SQLITE_OK ){ + rc = sessionChangesetApply( + db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags + ); + } + return rc; +} + /* ** Apply the changeset passed via pChangeset/nChangeset to the main database ** attached to handle "db". Invoke the supplied conflict handler callback @@ -183033,12 +184929,9 @@ SQLITE_API int sqlite3changeset_apply( ), void *pCtx /* First argument passed to xConflict */ ){ - sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ - int rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset); - if( rc==SQLITE_OK ){ - rc = sessionChangesetApply(db, pIter, xFilter, xConflict, pCtx); - } - return rc; + return sqlite3changeset_apply_v2( + db, nChangeset, pChangeset, xFilter, xConflict, pCtx, 0, 0, 0 + ); } /* @@ -183046,6 +184939,32 @@ SQLITE_API int sqlite3changeset_apply( ** attached to handle "db". Invoke the supplied conflict handler callback ** to resolve any conflicts encountered while applying the change. */ +SQLITE_API int sqlite3changeset_apply_v2_strm( + sqlite3 *db, /* Apply change to "main" db of this handle */ + int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ + void *pIn, /* First arg for xInput */ + int(*xFilter)( + void *pCtx, /* Copy of sixth arg to _apply() */ + const char *zTab /* Table name */ + ), + int(*xConflict)( + void *pCtx, /* Copy of sixth arg to _apply() */ + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ + sqlite3_changeset_iter *p /* Handle describing change and conflict */ + ), + void *pCtx, /* First argument passed to xConflict */ + void **ppRebase, int *pnRebase, + int flags +){ + sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ + int rc = sqlite3changeset_start_strm(&pIter, xInput, pIn); + if( rc==SQLITE_OK ){ + rc = sessionChangesetApply( + db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags + ); + } + return rc; +} SQLITE_API int sqlite3changeset_apply_strm( sqlite3 *db, /* Apply change to "main" db of this handle */ int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ @@ -183061,12 +184980,9 @@ SQLITE_API int sqlite3changeset_apply_strm( ), void *pCtx /* First argument passed to xConflict */ ){ - sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */ - int rc = sqlite3changeset_start_strm(&pIter, xInput, pIn); - if( rc==SQLITE_OK ){ - rc = sessionChangesetApply(db, pIter, xFilter, xConflict, pCtx); - } - return rc; + return sqlite3changeset_apply_v2_strm( + db, xInput, pIn, xFilter, xConflict, pCtx, 0, 0, 0 + ); } /* @@ -183085,6 +185001,7 @@ struct sqlite3_changegroup { */ static int sessionChangeMerge( SessionTable *pTab, /* Table structure */ + int bRebase, /* True for a rebase hash-table */ int bPatchset, /* True for patchsets */ SessionChange *pExist, /* Existing change */ int op2, /* Second change operation */ @@ -183094,6 +185011,7 @@ static int sessionChangeMerge( SessionChange **ppNew /* OUT: Merged change */ ){ SessionChange *pNew = 0; + int rc = SQLITE_OK; if( !pExist ){ pNew = (SessionChange *)sqlite3_malloc(sizeof(SessionChange) + nRec); @@ -183103,9 +185021,66 @@ static int sessionChangeMerge( memset(pNew, 0, sizeof(SessionChange)); pNew->op = op2; pNew->bIndirect = bIndirect; - pNew->nRecord = nRec; pNew->aRecord = (u8*)&pNew[1]; - memcpy(pNew->aRecord, aRec, nRec); + if( bIndirect==0 || bRebase==0 ){ + pNew->nRecord = nRec; + memcpy(pNew->aRecord, aRec, nRec); + }else{ + int i; + u8 *pIn = aRec; + u8 *pOut = pNew->aRecord; + for(i=0; inCol; i++){ + int nIn = sessionSerialLen(pIn); + if( *pIn==0 ){ + *pOut++ = 0; + }else if( pTab->abPK[i]==0 ){ + *pOut++ = 0xFF; + }else{ + memcpy(pOut, pIn, nIn); + pOut += nIn; + } + pIn += nIn; + } + pNew->nRecord = pOut - pNew->aRecord; + } + }else if( bRebase ){ + if( pExist->op==SQLITE_DELETE && pExist->bIndirect ){ + *ppNew = pExist; + }else{ + int nByte = nRec + pExist->nRecord + sizeof(SessionChange); + pNew = (SessionChange*)sqlite3_malloc(nByte); + if( pNew==0 ){ + rc = SQLITE_NOMEM; + }else{ + int i; + u8 *a1 = pExist->aRecord; + u8 *a2 = aRec; + u8 *pOut; + + memset(pNew, 0, nByte); + pNew->bIndirect = bIndirect || pExist->bIndirect; + pNew->op = op2; + pOut = pNew->aRecord = (u8*)&pNew[1]; + + for(i=0; inCol; i++){ + int n1 = sessionSerialLen(a1); + int n2 = sessionSerialLen(a2); + if( *a1==0xFF || (pTab->abPK[i]==0 && bIndirect) ){ + *pOut++ = 0xFF; + }else if( *a2==0 ){ + memcpy(pOut, a1, n1); + pOut += n1; + }else{ + memcpy(pOut, a2, n2); + pOut += n2; + } + a1 += n1; + a2 += n2; + } + pNew->nRecord = pOut - pNew->aRecord; + } + sqlite3_free(pExist); + } }else{ int op1 = pExist->op; @@ -183199,7 +185174,7 @@ static int sessionChangeMerge( } *ppNew = pNew; - return SQLITE_OK; + return rc; } /* @@ -183208,15 +185183,15 @@ static int sessionChangeMerge( */ static int sessionChangesetToHash( sqlite3_changeset_iter *pIter, /* Iterator to read from */ - sqlite3_changegroup *pGrp /* Changegroup object to add changeset to */ + sqlite3_changegroup *pGrp, /* Changegroup object to add changeset to */ + int bRebase /* True if hash table is for rebasing */ ){ u8 *aRec; int nRec; int rc = SQLITE_OK; SessionTable *pTab = 0; - - while( SQLITE_ROW==sessionChangesetNext(pIter, &aRec, &nRec) ){ + while( SQLITE_ROW==sessionChangesetNext(pIter, &aRec, &nRec, 0) ){ const char *zNew; int nCol; int op; @@ -183296,7 +185271,7 @@ static int sessionChangesetToHash( } } - rc = sessionChangeMerge(pTab, + rc = sessionChangeMerge(pTab, bRebase, pIter->bPatchset, pExist, op, bIndirect, aRec, nRec, &pChange ); if( rc ) break; @@ -183404,7 +185379,7 @@ SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup *pGrp, int nData, void rc = sqlite3changeset_start(&pIter, nData, pData); if( rc==SQLITE_OK ){ - rc = sessionChangesetToHash(pIter, pGrp); + rc = sessionChangesetToHash(pIter, pGrp, 0); } sqlite3changeset_finalize(pIter); return rc; @@ -183435,7 +185410,7 @@ SQLITE_API int sqlite3changegroup_add_strm( rc = sqlite3changeset_start_strm(&pIter, xInput, pIn); if( rc==SQLITE_OK ){ - rc = sessionChangesetToHash(pIter, pGrp); + rc = sessionChangesetToHash(pIter, pGrp, 0); } sqlite3changeset_finalize(pIter); return rc; @@ -183520,6 +185495,349 @@ SQLITE_API int sqlite3changeset_concat_strm( return rc; } +/* +** Changeset rebaser handle. +*/ +struct sqlite3_rebaser { + sqlite3_changegroup grp; /* Hash table */ +}; + +/* +** Buffers a1 and a2 must both contain a sessions module record nCol +** fields in size. This function appends an nCol sessions module +** record to buffer pBuf that is a copy of a1, except that for +** each field that is undefined in a1[], swap in the field from a2[]. +*/ +static void sessionAppendRecordMerge( + SessionBuffer *pBuf, /* Buffer to append to */ + int nCol, /* Number of columns in each record */ + u8 *a1, int n1, /* Record 1 */ + u8 *a2, int n2, /* Record 2 */ + int *pRc /* IN/OUT: error code */ +){ + sessionBufferGrow(pBuf, n1+n2, pRc); + if( *pRc==SQLITE_OK ){ + int i; + u8 *pOut = &pBuf->aBuf[pBuf->nBuf]; + for(i=0; inBuf = pOut-pBuf->aBuf; + assert( pBuf->nBuf<=pBuf->nAlloc ); + } +} + +/* +** This function is called when rebasing a local UPDATE change against one +** or more remote UPDATE changes. The aRec/nRec buffer contains the current +** old.* and new.* records for the change. The rebase buffer (a single +** record) is in aChange/nChange. The rebased change is appended to buffer +** pBuf. +** +** Rebasing the UPDATE involves: +** +** * Removing any changes to fields for which the corresponding field +** in the rebase buffer is set to "replaced" (type 0xFF). If this +** means the UPDATE change updates no fields, nothing is appended +** to the output buffer. +** +** * For each field modified by the local change for which the +** corresponding field in the rebase buffer is not "undefined" (0x00) +** or "replaced" (0xFF), the old.* value is replaced by the value +** in the rebase buffer. +*/ +static void sessionAppendPartialUpdate( + SessionBuffer *pBuf, /* Append record here */ + sqlite3_changeset_iter *pIter, /* Iterator pointed at local change */ + u8 *aRec, int nRec, /* Local change */ + u8 *aChange, int nChange, /* Record to rebase against */ + int *pRc /* IN/OUT: Return Code */ +){ + sessionBufferGrow(pBuf, 2+nRec+nChange, pRc); + if( *pRc==SQLITE_OK ){ + int bData = 0; + u8 *pOut = &pBuf->aBuf[pBuf->nBuf]; + int i; + u8 *a1 = aRec; + u8 *a2 = aChange; + + *pOut++ = SQLITE_UPDATE; + *pOut++ = pIter->bIndirect; + for(i=0; inCol; i++){ + int n1 = sessionSerialLen(a1); + int n2 = sessionSerialLen(a2); + if( pIter->abPK[i] || a2[0]==0 ){ + if( !pIter->abPK[i] ) bData = 1; + memcpy(pOut, a1, n1); + pOut += n1; + }else if( a2[0]!=0xFF ){ + bData = 1; + memcpy(pOut, a2, n2); + pOut += n2; + }else{ + *pOut++ = '\0'; + } + a1 += n1; + a2 += n2; + } + if( bData ){ + a2 = aChange; + for(i=0; inCol; i++){ + int n1 = sessionSerialLen(a1); + int n2 = sessionSerialLen(a2); + if( pIter->abPK[i] || a2[0]!=0xFF ){ + memcpy(pOut, a1, n1); + pOut += n1; + }else{ + *pOut++ = '\0'; + } + a1 += n1; + a2 += n2; + } + pBuf->nBuf = (pOut - pBuf->aBuf); + } + } +} + +/* +** pIter is configured to iterate through a changeset. This function rebases +** that changeset according to the current configuration of the rebaser +** object passed as the first argument. If no error occurs and argument xOutput +** is not NULL, then the changeset is returned to the caller by invoking +** xOutput zero or more times and SQLITE_OK returned. Or, if xOutput is NULL, +** then (*ppOut) is set to point to a buffer containing the rebased changeset +** before this function returns. In this case (*pnOut) is set to the size of +** the buffer in bytes. It is the responsibility of the caller to eventually +** free the (*ppOut) buffer using sqlite3_free(). +** +** If an error occurs, an SQLite error code is returned. If ppOut and +** pnOut are not NULL, then the two output parameters are set to 0 before +** returning. +*/ +static int sessionRebase( + sqlite3_rebaser *p, /* Rebaser hash table */ + sqlite3_changeset_iter *pIter, /* Input data */ + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut, /* Context for xOutput callback */ + int *pnOut, /* OUT: Number of bytes in output changeset */ + void **ppOut /* OUT: Inverse of pChangeset */ +){ + int rc = SQLITE_OK; + u8 *aRec = 0; + int nRec = 0; + int bNew = 0; + SessionTable *pTab = 0; + SessionBuffer sOut = {0,0,0}; + + while( SQLITE_ROW==sessionChangesetNext(pIter, &aRec, &nRec, &bNew) ){ + SessionChange *pChange = 0; + int bDone = 0; + + if( bNew ){ + const char *zTab = pIter->zTab; + for(pTab=p->grp.pList; pTab; pTab=pTab->pNext){ + if( 0==sqlite3_stricmp(pTab->zName, zTab) ) break; + } + bNew = 0; + + /* A patchset may not be rebased */ + if( pIter->bPatchset ){ + rc = SQLITE_ERROR; + } + + /* Append a table header to the output for this new table */ + sessionAppendByte(&sOut, pIter->bPatchset ? 'P' : 'T', &rc); + sessionAppendVarint(&sOut, pIter->nCol, &rc); + sessionAppendBlob(&sOut, pIter->abPK, pIter->nCol, &rc); + sessionAppendBlob(&sOut,(u8*)pIter->zTab,(int)strlen(pIter->zTab)+1,&rc); + } + + if( pTab && rc==SQLITE_OK ){ + int iHash = sessionChangeHash(pTab, 0, aRec, pTab->nChange); + + for(pChange=pTab->apChange[iHash]; pChange; pChange=pChange->pNext){ + if( sessionChangeEqual(pTab, 0, aRec, 0, pChange->aRecord) ){ + break; + } + } + } + + if( pChange ){ + assert( pChange->op==SQLITE_DELETE || pChange->op==SQLITE_INSERT ); + switch( pIter->op ){ + case SQLITE_INSERT: + if( pChange->op==SQLITE_INSERT ){ + bDone = 1; + if( pChange->bIndirect==0 ){ + sessionAppendByte(&sOut, SQLITE_UPDATE, &rc); + sessionAppendByte(&sOut, pIter->bIndirect, &rc); + sessionAppendBlob(&sOut, pChange->aRecord, pChange->nRecord, &rc); + sessionAppendBlob(&sOut, aRec, nRec, &rc); + } + } + break; + + case SQLITE_UPDATE: + bDone = 1; + if( pChange->op==SQLITE_DELETE ){ + if( pChange->bIndirect==0 ){ + u8 *pCsr = aRec; + sessionSkipRecord(&pCsr, pIter->nCol); + sessionAppendByte(&sOut, SQLITE_INSERT, &rc); + sessionAppendByte(&sOut, pIter->bIndirect, &rc); + sessionAppendRecordMerge(&sOut, pIter->nCol, + pCsr, nRec-(pCsr-aRec), + pChange->aRecord, pChange->nRecord, &rc + ); + } + }else{ + sessionAppendPartialUpdate(&sOut, pIter, + aRec, nRec, pChange->aRecord, pChange->nRecord, &rc + ); + } + break; + + default: + assert( pIter->op==SQLITE_DELETE ); + bDone = 1; + if( pChange->op==SQLITE_INSERT ){ + sessionAppendByte(&sOut, SQLITE_DELETE, &rc); + sessionAppendByte(&sOut, pIter->bIndirect, &rc); + sessionAppendRecordMerge(&sOut, pIter->nCol, + pChange->aRecord, pChange->nRecord, aRec, nRec, &rc + ); + } + break; + } + } + + if( bDone==0 ){ + sessionAppendByte(&sOut, pIter->op, &rc); + sessionAppendByte(&sOut, pIter->bIndirect, &rc); + sessionAppendBlob(&sOut, aRec, nRec, &rc); + } + if( rc==SQLITE_OK && xOutput && sOut.nBuf>SESSIONS_STRM_CHUNK_SIZE ){ + rc = xOutput(pOut, sOut.aBuf, sOut.nBuf); + sOut.nBuf = 0; + } + if( rc ) break; + } + + if( rc!=SQLITE_OK ){ + sqlite3_free(sOut.aBuf); + memset(&sOut, 0, sizeof(sOut)); + } + + if( rc==SQLITE_OK ){ + if( xOutput ){ + if( sOut.nBuf>0 ){ + rc = xOutput(pOut, sOut.aBuf, sOut.nBuf); + } + }else{ + *ppOut = (void*)sOut.aBuf; + *pnOut = sOut.nBuf; + sOut.aBuf = 0; + } + } + sqlite3_free(sOut.aBuf); + return rc; +} + +/* +** Create a new rebaser object. +*/ +SQLITE_API int sqlite3rebaser_create(sqlite3_rebaser **ppNew){ + int rc = SQLITE_OK; + sqlite3_rebaser *pNew; + + pNew = sqlite3_malloc(sizeof(sqlite3_rebaser)); + if( pNew==0 ){ + rc = SQLITE_NOMEM; + }else{ + memset(pNew, 0, sizeof(sqlite3_rebaser)); + } + *ppNew = pNew; + return rc; +} + +/* +** Call this one or more times to configure a rebaser. +*/ +SQLITE_API int sqlite3rebaser_configure( + sqlite3_rebaser *p, + int nRebase, const void *pRebase +){ + sqlite3_changeset_iter *pIter = 0; /* Iterator opened on pData/nData */ + int rc; /* Return code */ + rc = sqlite3changeset_start(&pIter, nRebase, (void*)pRebase); + if( rc==SQLITE_OK ){ + rc = sessionChangesetToHash(pIter, &p->grp, 1); + } + sqlite3changeset_finalize(pIter); + return rc; +} + +/* +** Rebase a changeset according to current rebaser configuration +*/ +SQLITE_API int sqlite3rebaser_rebase( + sqlite3_rebaser *p, + int nIn, const void *pIn, + int *pnOut, void **ppOut +){ + sqlite3_changeset_iter *pIter = 0; /* Iterator to skip through input */ + int rc = sqlite3changeset_start(&pIter, nIn, (void*)pIn); + + if( rc==SQLITE_OK ){ + rc = sessionRebase(p, pIter, 0, 0, pnOut, ppOut); + sqlite3changeset_finalize(pIter); + } + + return rc; +} + +/* +** Rebase a changeset according to current rebaser configuration +*/ +SQLITE_API int sqlite3rebaser_rebase_strm( + sqlite3_rebaser *p, + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +){ + sqlite3_changeset_iter *pIter = 0; /* Iterator to skip through input */ + int rc = sqlite3changeset_start_strm(&pIter, xInput, pIn); + + if( rc==SQLITE_OK ){ + rc = sessionRebase(p, pIter, xOutput, pOut, 0, 0); + sqlite3changeset_finalize(pIter); + } + + return rc; +} + +/* +** Destroy a rebaser object +*/ +SQLITE_API void sqlite3rebaser_delete(sqlite3_rebaser *p){ + if( p ){ + sessionDeleteTable(p->grp.pList); + sqlite3_free(p); + } +} + #endif /* SQLITE_ENABLE_SESSION && SQLITE_ENABLE_PREUPDATE_HOOK */ /************** End of sqlite3session.c **************************************/ @@ -188055,7 +190373,8 @@ static unsigned int fts5yy_find_shift_action( #endif do{ i = fts5yy_shift_ofst[stateno]; - assert( i>=0 && i+fts5YYNFTS5TOKEN<=sizeof(fts5yy_lookahead)/sizeof(fts5yy_lookahead[0]) ); + assert( i>=0 ); + assert( i+fts5YYNFTS5TOKEN<=(int)sizeof(fts5yy_lookahead)/sizeof(fts5yy_lookahead[0]) ); assert( iLookAhead!=fts5YYNOCODE ); assert( iLookAhead < fts5YYNFTS5TOKEN ); i += iLookAhead; @@ -192497,7 +194816,7 @@ static Fts5ExprPhrase *sqlite3Fts5ParseTerm( ** no token characters at all. (e.g ... MATCH '""'). */ sCtx.pPhrase = sqlite3Fts5MallocZero(&pParse->rc, sizeof(Fts5ExprPhrase)); }else if( sCtx.pPhrase->nTerm ){ - sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = bPrefix; + sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = (u8)bPrefix; } pParse->apPhrase[pParse->nPhrase-1] = sCtx.pPhrase; } @@ -194960,6 +197279,7 @@ static void fts5DataWrite(Fts5Index *p, i64 iRowid, const u8 *pData, int nData){ sqlite3_bind_blob(p->pWriter, 2, pData, nData, SQLITE_STATIC); sqlite3_step(p->pWriter); p->rc = sqlite3_reset(p->pWriter); + sqlite3_bind_null(p->pWriter, 2); } /* @@ -196588,6 +198908,7 @@ static void fts5SegIterSeekInit( bDlidx = (val & 0x0001); } p->rc = sqlite3_reset(pIdxSelect); + sqlite3_bind_null(pIdxSelect, 2); if( iPgpgnoFirst ){ iPg = pSeg->pgnoFirst; @@ -197800,6 +200121,7 @@ static int fts5AllocateSegid(Fts5Index *p, Fts5Structure *pStruct){ sqlite3_bind_blob(pIdxSelect, 2, aBlob, 2, SQLITE_STATIC); assert( sqlite3_step(pIdxSelect)!=SQLITE_ROW ); p->rc = sqlite3_reset(pIdxSelect); + sqlite3_bind_null(pIdxSelect, 2); } } #endif @@ -197926,6 +200248,7 @@ static void fts5WriteFlushBtree(Fts5Index *p, Fts5SegWriter *pWriter){ sqlite3_bind_int64(p->pIdxWriter, 3, bFlag + ((i64)pWriter->iBtPage<<1)); sqlite3_step(p->pIdxWriter); p->rc = sqlite3_reset(p->pIdxWriter); + sqlite3_bind_null(p->pIdxWriter, 2); } pWriter->iBtPage = 0; } @@ -201239,6 +203562,12 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ aColMap[1] = nCol; aColMap[2] = nCol+1; + assert( SQLITE_INDEX_CONSTRAINT_EQnConstraint; i++){ struct sqlite3_index_constraint *p = &pInfo->aConstraint[i]; @@ -201257,11 +203586,11 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ pInfo->estimatedCost = 1e50; return SQLITE_OK; } - }else{ + }else if( p->op<=SQLITE_INDEX_CONSTRAINT_MATCH ){ int j; for(j=1; jiCol] && p->op & pC->op && p->usable ){ + if( iCol==aColMap[pC->iCol] && (p->op & pC->op) && p->usable ){ pC->iConsIndex = i; idxFlags |= pC->fts5op; } @@ -203333,7 +205662,7 @@ static void fts5SourceIdFunc( ){ assert( nArg==0 ); UNUSED_PARAM2(nArg, apUnused); - sqlite3_result_text(pCtx, "fts5: 2018-01-22 18:45:57 0c55d179733b46d8d0ba4d88e01a25e10677046ee3da1d5b1581e86726f2171d", -1, SQLITE_TRANSIENT); + sqlite3_result_text(pCtx, "fts5: 2018-04-10 17:39:29 4bb2294022060e61de7da5c227a69ccd846ba330e31626ebcd59a94efd148b3b", -1, SQLITE_TRANSIENT); } static int fts5Init(sqlite3 *db){ @@ -203909,6 +206238,7 @@ static int fts5StorageInsertDocsize( sqlite3_bind_blob(pReplace, 2, pBuf->p, pBuf->n, SQLITE_STATIC); sqlite3_step(pReplace); rc = sqlite3_reset(pReplace); + sqlite3_bind_null(pReplace, 2); } } return rc; @@ -204569,6 +206899,7 @@ static int sqlite3Fts5StorageConfigValue( } sqlite3_step(pReplace); rc = sqlite3_reset(pReplace); + sqlite3_bind_null(pReplace, 1); } if( rc==SQLITE_OK && pVal ){ int iNew = p->pConfig->iCookie + 1; @@ -207601,9 +209932,9 @@ SQLITE_API int sqlite3_stmt_init( #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */ /************** End of stmt.c ************************************************/ -#if __LINE__!=207604 +#if __LINE__!=209935 #undef SQLITE_SOURCE_ID -#define SQLITE_SOURCE_ID "2018-01-22 18:45:57 0c55d179733b46d8d0ba4d88e01a25e10677046ee3da1d5b1581e86726f2alt2" +#define SQLITE_SOURCE_ID "2018-04-10 17:39:29 4bb2294022060e61de7da5c227a69ccd846ba330e31626ebcd59a94efd14alt2" #endif /* Return the source-id for this library */ SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; } diff --git a/src/3rdparty/sqlite/sqlite3.h b/src/3rdparty/sqlite/sqlite3.h index d8138b709a..0ba2852d78 100644 --- a/src/3rdparty/sqlite/sqlite3.h +++ b/src/3rdparty/sqlite/sqlite3.h @@ -123,9 +123,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.22.0" -#define SQLITE_VERSION_NUMBER 3022000 -#define SQLITE_SOURCE_ID "2018-01-22 18:45:57 0c55d179733b46d8d0ba4d88e01a25e10677046ee3da1d5b1581e86726f2171d" +#define SQLITE_VERSION "3.23.1" +#define SQLITE_VERSION_NUMBER 3023001 +#define SQLITE_SOURCE_ID "2018-04-10 17:39:29 4bb2294022060e61de7da5c227a69ccd846ba330e31626ebcd59a94efd148b3b" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -1064,6 +1064,12 @@ struct sqlite3_io_methods { ** so that all subsequent write operations are independent. ** ^SQLite will never invoke SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE without ** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE]. +** +**
  • [[SQLITE_FCNTL_LOCK_TIMEOUT]] +** The [SQLITE_FCNTL_LOCK_TIMEOUT] opcode causes attempts to obtain +** a file lock using the xLock or xShmLock methods of the VFS to wait +** for up to M milliseconds before failing, where M is the single +** unsigned integer parameter. ** */ #define SQLITE_FCNTL_LOCKSTATE 1 @@ -1098,6 +1104,7 @@ struct sqlite3_io_methods { #define SQLITE_FCNTL_BEGIN_ATOMIC_WRITE 31 #define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE 32 #define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33 +#define SQLITE_FCNTL_LOCK_TIMEOUT 34 /* deprecated names */ #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE @@ -2054,11 +2061,13 @@ struct sqlite3_mem_methods { ** connections at all to the database. If so, it performs a checkpoint ** operation before closing the connection. This option may be used to ** override this behaviour. The first parameter passed to this operation -** is an integer - non-zero to disable checkpoints-on-close, or zero (the -** default) to enable them. The second parameter is a pointer to an integer +** is an integer - positive to disable checkpoints-on-close, or zero (the +** default) to enable them, and negative to leave the setting unchanged. +** The second parameter is a pointer to an integer ** into which is written 0 or 1 to indicate whether checkpoints-on-close ** have been disabled - 0 if they are not disabled, 1 if they are. ** +** **
    SQLITE_DBCONFIG_ENABLE_QPSG
    **
    ^(The SQLITE_DBCONFIG_ENABLE_QPSG option activates or deactivates ** the [query planner stability guarantee] (QPSG). When the QPSG is active, @@ -2068,13 +2077,20 @@ struct sqlite3_mem_methods { ** slower. But the QPSG has the advantage of more predictable behavior. With ** the QPSG active, SQLite will always use the same query plan in the field as ** was used during testing in the lab. +** The first argument to this setting is an integer which is 0 to disable +** the QPSG, positive to enable QPSG, or negative to leave the setting +** unchanged. The second parameter is a pointer to an integer into which +** is written 0 or 1 to indicate whether the QPSG is disabled or enabled +** following this call. **
    +** **
    SQLITE_DBCONFIG_TRIGGER_EQP
    **
    By default, the output of EXPLAIN QUERY PLAN commands does not ** include output for any operations performed by trigger programs. This ** option is used to set or clear (the default) a flag that governs this ** behavior. The first parameter passed to this operation is an integer - -** non-zero to enable output for trigger programs, or zero to disable it. +** positive to enable output for trigger programs, or zero to disable it, +** or negative to leave the setting unchanged. ** The second parameter is a pointer to an integer into which is written ** 0 or 1 to indicate whether output-for-triggers has been disabled - 0 if ** it is not disabled, 1 if it is. @@ -2496,16 +2512,16 @@ SQLITE_API void sqlite3_free_table(char **result); ** ** These routines are work-alikes of the "printf()" family of functions ** from the standard C library. -** These routines understand most of the common K&R formatting options, -** plus some additional non-standard formats, detailed below. -** Note that some of the more obscure formatting options from recent -** C-library standards are omitted from this implementation. +** These routines understand most of the common formatting options from +** the standard library printf() +** plus some additional non-standard formats ([%q], [%Q], [%w], and [%z]). +** See the [built-in printf()] documentation for details. ** ** ^The sqlite3_mprintf() and sqlite3_vmprintf() routines write their -** results into memory obtained from [sqlite3_malloc()]. +** results into memory obtained from [sqlite3_malloc64()]. ** The strings returned by these two routines should be ** released by [sqlite3_free()]. ^Both routines return a -** NULL pointer if [sqlite3_malloc()] is unable to allocate enough +** NULL pointer if [sqlite3_malloc64()] is unable to allocate enough ** memory to hold the resulting string. ** ** ^(The sqlite3_snprintf() routine is similar to "snprintf()" from @@ -2529,71 +2545,7 @@ SQLITE_API void sqlite3_free_table(char **result); ** ** ^The sqlite3_vsnprintf() routine is a varargs version of sqlite3_snprintf(). ** -** These routines all implement some additional formatting -** options that are useful for constructing SQL statements. -** All of the usual printf() formatting options apply. In addition, there -** is are "%q", "%Q", "%w" and "%z" options. -** -** ^(The %q option works like %s in that it substitutes a nul-terminated -** string from the argument list. But %q also doubles every '\'' character. -** %q is designed for use inside a string literal.)^ By doubling each '\'' -** character it escapes that character and allows it to be inserted into -** the string. -** -** For example, assume the string variable zText contains text as follows: -** -**
    -**  char *zText = "It's a happy day!";
    -** 
    -** -** One can use this text in an SQL statement as follows: -** -**
    -**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES('%q')", zText);
    -**  sqlite3_exec(db, zSQL, 0, 0, 0);
    -**  sqlite3_free(zSQL);
    -** 
    -** -** Because the %q format string is used, the '\'' character in zText -** is escaped and the SQL generated is as follows: -** -**
    -**  INSERT INTO table1 VALUES('It''s a happy day!')
    -** 
    -** -** This is correct. Had we used %s instead of %q, the generated SQL -** would have looked like this: -** -**
    -**  INSERT INTO table1 VALUES('It's a happy day!');
    -** 
    -** -** This second example is an SQL syntax error. As a general rule you should -** always use %q instead of %s when inserting text into a string literal. -** -** ^(The %Q option works like %q except it also adds single quotes around -** the outside of the total string. Additionally, if the parameter in the -** argument list is a NULL pointer, %Q substitutes the text "NULL" (without -** single quotes).)^ So, for example, one could say: -** -**
    -**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES(%Q)", zText);
    -**  sqlite3_exec(db, zSQL, 0, 0, 0);
    -**  sqlite3_free(zSQL);
    -** 
    -** -** The code above will render a correct SQL statement in the zSQL -** variable even if the zText variable is a NULL pointer. -** -** ^(The "%w" formatting option is like "%q" except that it expects to -** be contained within double-quotes instead of single quotes, and it -** escapes the double-quote character instead of the single-quote -** character.)^ The "%w" formatting option is intended for safely inserting -** table and column names into a constructed SQL statement. -** -** ^(The "%z" formatting option works like "%s" but with the -** addition that after the string has been read and copied into -** the result, [sqlite3_free()] is called on the input string.)^ +** See also: [built-in printf()], [printf() SQL function] */ SQLITE_API char *sqlite3_mprintf(const char*,...); SQLITE_API char *sqlite3_vmprintf(const char*, va_list); @@ -3659,13 +3611,13 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); ** or [GLOB] operator or if the parameter is compared to an indexed column ** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled. **
  • +** ** **

    ^sqlite3_prepare_v3() differs from sqlite3_prepare_v2() only in having ** the extra prepFlags parameter, which is a bit array consisting of zero or ** more of the [SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_*] flags. ^The ** sqlite3_prepare_v2() interface works exactly the same as ** sqlite3_prepare_v3() with a zero prepFlags parameter. -** */ SQLITE_API int sqlite3_prepare( sqlite3 *db, /* Database handle */ @@ -7294,6 +7246,15 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r ** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0. ** ** +** [[SQLITE_DBSTATUS_CACHE_SPILL]] ^(

    SQLITE_DBSTATUS_CACHE_SPILL
    +**
    This parameter returns the number of dirty cache entries that have +** been written to disk in the middle of a transaction due to the page +** cache overflowing. Transactions are more efficient if they are written +** to disk all at once. When pages spill mid-transaction, that introduces +** additional overhead. This parameter can be used help identify +** inefficiencies that can be resolve by increasing the cache size. +**
    +** ** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(
    SQLITE_DBSTATUS_DEFERRED_FKS
    **
    This parameter returns zero for the current value if and only if ** all foreign key constraints (deferred or immediate) have been @@ -7313,7 +7274,8 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r #define SQLITE_DBSTATUS_CACHE_WRITE 9 #define SQLITE_DBSTATUS_DEFERRED_FKS 10 #define SQLITE_DBSTATUS_CACHE_USED_SHARED 11 -#define SQLITE_DBSTATUS_MAX 11 /* Largest defined DBSTATUS */ +#define SQLITE_DBSTATUS_CACHE_SPILL 12 +#define SQLITE_DBSTATUS_MAX 12 /* Largest defined DBSTATUS */ /* @@ -8793,6 +8755,128 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp( */ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb); +/* +** CAPI3REF: Serialize a database +** +** The sqlite3_serialize(D,S,P,F) interface returns a pointer to memory +** that is a serialization of the S database on [database connection] D. +** If P is not a NULL pointer, then the size of the database in bytes +** is written into *P. +** +** For an ordinary on-disk database file, the serialization is just a +** copy of the disk file. For an in-memory database or a "TEMP" database, +** the serialization is the same sequence of bytes which would be written +** to disk if that database where backed up to disk. +** +** The usual case is that sqlite3_serialize() copies the serialization of +** the database into memory obtained from [sqlite3_malloc64()] and returns +** a pointer to that memory. The caller is responsible for freeing the +** returned value to avoid a memory leak. However, if the F argument +** contains the SQLITE_SERIALIZE_NOCOPY bit, then no memory allocations +** are made, and the sqlite3_serialize() function will return a pointer +** to the contiguous memory representation of the database that SQLite +** is currently using for that database, or NULL if the no such contiguous +** memory representation of the database exists. A contiguous memory +** representation of the database will usually only exist if there has +** been a prior call to [sqlite3_deserialize(D,S,...)] with the same +** values of D and S. +** The size of the database is written into *P even if the +** SQLITE_SERIALIZE_NOCOPY bit is set but no contigious copy +** of the database exists. +** +** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the +** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory +** allocation error occurs. +** +** This interface is only available if SQLite is compiled with the +** [SQLITE_ENABLE_DESERIALIZE] option. +*/ +SQLITE_API unsigned char *sqlite3_serialize( + sqlite3 *db, /* The database connection */ + const char *zSchema, /* Which DB to serialize. ex: "main", "temp", ... */ + sqlite3_int64 *piSize, /* Write size of the DB here, if not NULL */ + unsigned int mFlags /* Zero or more SQLITE_SERIALIZE_* flags */ +); + +/* +** CAPI3REF: Flags for sqlite3_serialize +** +** Zero or more of the following constants can be OR-ed together for +** the F argument to [sqlite3_serialize(D,S,P,F)]. +** +** SQLITE_SERIALIZE_NOCOPY means that [sqlite3_serialize()] will return +** a pointer to contiguous in-memory database that it is currently using, +** without making a copy of the database. If SQLite is not currently using +** a contiguous in-memory database, then this option causes +** [sqlite3_serialize()] to return a NULL pointer. SQLite will only be +** using a contiguous in-memory database if it has been initialized by a +** prior call to [sqlite3_deserialize()]. +*/ +#define SQLITE_SERIALIZE_NOCOPY 0x001 /* Do no memory allocations */ + +/* +** CAPI3REF: Deserialize a database +** +** The sqlite3_deserialize(D,S,P,N,M,F) interface causes the +** [database connection] D to disconnect from database S and then +** reopen S as an in-memory database based on the serialization contained +** in P. The serialized database P is N bytes in size. M is the size of +** the buffer P, which might be larger than N. If M is larger than N, and +** the SQLITE_DESERIALIZE_READONLY bit is not set in F, then SQLite is +** permitted to add content to the in-memory database as long as the total +** size does not exceed M bytes. +** +** If the SQLITE_DESERIALIZE_FREEONCLOSE bit is set in F, then SQLite will +** invoke sqlite3_free() on the serialization buffer when the database +** connection closes. If the SQLITE_DESERIALIZE_RESIZEABLE bit is set, then +** SQLite will try to increase the buffer size using sqlite3_realloc64() +** if writes on the database cause it to grow larger than M bytes. +** +** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the +** database is currently in a read transaction or is involved in a backup +** operation. +** +** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the +** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then +** [sqlite3_free()] is invoked on argument P prior to returning. +** +** This interface is only available if SQLite is compiled with the +** [SQLITE_ENABLE_DESERIALIZE] option. +*/ +SQLITE_API int sqlite3_deserialize( + sqlite3 *db, /* The database connection */ + const char *zSchema, /* Which DB to reopen with the deserialization */ + unsigned char *pData, /* The serialized database content */ + sqlite3_int64 szDb, /* Number bytes in the deserialization */ + sqlite3_int64 szBuf, /* Total size of buffer pData[] */ + unsigned mFlags /* Zero or more SQLITE_DESERIALIZE_* flags */ +); + +/* +** CAPI3REF: Flags for sqlite3_deserialize() +** +** The following are allowed values for 6th argument (the F argument) to +** the [sqlite3_deserialize(D,S,P,N,M,F)] interface. +** +** The SQLITE_DESERIALIZE_FREEONCLOSE means that the database serialization +** in the P argument is held in memory obtained from [sqlite3_malloc64()] +** and that SQLite should take ownership of this memory and automatically +** free it when it has finished using it. Without this flag, the caller +** is resposible for freeing any dynamically allocated memory. +** +** The SQLITE_DESERIALIZE_RESIZEABLE flag means that SQLite is allowed to +** grow the size of the database using calls to [sqlite3_realloc64()]. This +** flag should only be used if SQLITE_DESERIALIZE_FREEONCLOSE is also used. +** Without this flag, the deserialized database cannot increase in size beyond +** the number of bytes specified by the M parameter. +** +** The SQLITE_DESERIALIZE_READONLY flag means that the deserialized database +** should be treated as read-only. +*/ +#define SQLITE_DESERIALIZE_FREEONCLOSE 1 /* Call sqlite3_free() on close */ +#define SQLITE_DESERIALIZE_RESIZEABLE 2 /* Resize using sqlite3_realloc64() */ +#define SQLITE_DESERIALIZE_READONLY 4 /* Database is read-only */ + /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. @@ -8940,16 +9024,23 @@ extern "C" { /* ** CAPI3REF: Session Object Handle +** +** An instance of this object is a [session] that can be used to +** record changes to a database. */ typedef struct sqlite3_session sqlite3_session; /* ** CAPI3REF: Changeset Iterator Handle +** +** An instance of this object acts as a cursor for iterating +** over the elements of a [changeset] or [patchset]. */ typedef struct sqlite3_changeset_iter sqlite3_changeset_iter; /* ** CAPI3REF: Create A New Session Object +** CONSTRUCTOR: sqlite3_session ** ** Create a new session object attached to database handle db. If successful, ** a pointer to the new object is written to *ppSession and SQLITE_OK is @@ -8986,6 +9077,7 @@ SQLITE_API int sqlite3session_create( /* ** CAPI3REF: Delete A Session Object +** DESTRUCTOR: sqlite3_session ** ** Delete a session object previously allocated using ** [sqlite3session_create()]. Once a session object has been deleted, the @@ -9001,6 +9093,7 @@ SQLITE_API void sqlite3session_delete(sqlite3_session *pSession); /* ** CAPI3REF: Enable Or Disable A Session Object +** METHOD: sqlite3_session ** ** Enable or disable the recording of changes by a session object. When ** enabled, a session object records changes made to the database. When @@ -9020,6 +9113,7 @@ SQLITE_API int sqlite3session_enable(sqlite3_session *pSession, int bEnable); /* ** CAPI3REF: Set Or Clear the Indirect Change Flag +** METHOD: sqlite3_session ** ** Each change recorded by a session object is marked as either direct or ** indirect. A change is marked as indirect if either: @@ -9049,6 +9143,7 @@ SQLITE_API int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect) /* ** CAPI3REF: Attach A Table To A Session Object +** METHOD: sqlite3_session ** ** If argument zTab is not NULL, then it is the name of a table to attach ** to the session object passed as the first argument. All subsequent changes @@ -9111,6 +9206,7 @@ SQLITE_API int sqlite3session_attach( /* ** CAPI3REF: Set a table filter on a Session Object. +** METHOD: sqlite3_session ** ** The second argument (xFilter) is the "filter callback". For changes to rows ** in tables that are not attached to the Session object, the filter is called @@ -9129,6 +9225,7 @@ SQLITE_API void sqlite3session_table_filter( /* ** CAPI3REF: Generate A Changeset From A Session Object +** METHOD: sqlite3_session ** ** Obtain a changeset containing changes to the tables attached to the ** session object passed as the first argument. If successful, @@ -9238,7 +9335,8 @@ SQLITE_API int sqlite3session_changeset( ); /* -** CAPI3REF: Load The Difference Between Tables Into A Session +** CAPI3REF: Load The Difference Between Tables Into A Session +** METHOD: sqlite3_session ** ** If it is not already attached to the session object passed as the first ** argument, this function attaches table zTbl in the same manner as the @@ -9303,6 +9401,7 @@ SQLITE_API int sqlite3session_diff( /* ** CAPI3REF: Generate A Patchset From A Session Object +** METHOD: sqlite3_session ** ** The differences between a patchset and a changeset are that: ** @@ -9354,6 +9453,7 @@ SQLITE_API int sqlite3session_isempty(sqlite3_session *pSession); /* ** CAPI3REF: Create An Iterator To Traverse A Changeset +** CONSTRUCTOR: sqlite3_changeset_iter ** ** Create an iterator used to iterate through the contents of a changeset. ** If successful, *pp is set to point to the iterator handle and SQLITE_OK @@ -9394,6 +9494,7 @@ SQLITE_API int sqlite3changeset_start( /* ** CAPI3REF: Advance A Changeset Iterator +** METHOD: sqlite3_changeset_iter ** ** This function may only be used with iterators created by function ** [sqlite3changeset_start()]. If it is called on an iterator passed to @@ -9418,6 +9519,7 @@ SQLITE_API int sqlite3changeset_next(sqlite3_changeset_iter *pIter); /* ** CAPI3REF: Obtain The Current Operation From A Changeset Iterator +** METHOD: sqlite3_changeset_iter ** ** The pIter argument passed to this function may either be an iterator ** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator @@ -9452,6 +9554,7 @@ SQLITE_API int sqlite3changeset_op( /* ** CAPI3REF: Obtain The Primary Key Definition Of A Table +** METHOD: sqlite3_changeset_iter ** ** For each modified table, a changeset includes the following: ** @@ -9483,6 +9586,7 @@ SQLITE_API int sqlite3changeset_pk( /* ** CAPI3REF: Obtain old.* Values From A Changeset Iterator +** METHOD: sqlite3_changeset_iter ** ** The pIter argument passed to this function may either be an iterator ** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator @@ -9513,6 +9617,7 @@ SQLITE_API int sqlite3changeset_old( /* ** CAPI3REF: Obtain new.* Values From A Changeset Iterator +** METHOD: sqlite3_changeset_iter ** ** The pIter argument passed to this function may either be an iterator ** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator @@ -9546,6 +9651,7 @@ SQLITE_API int sqlite3changeset_new( /* ** CAPI3REF: Obtain Conflicting Row Values From A Changeset Iterator +** METHOD: sqlite3_changeset_iter ** ** This function should only be used with iterator objects passed to a ** conflict-handler callback by [sqlite3changeset_apply()] with either @@ -9573,6 +9679,7 @@ SQLITE_API int sqlite3changeset_conflict( /* ** CAPI3REF: Determine The Number Of Foreign Key Constraint Violations +** METHOD: sqlite3_changeset_iter ** ** This function may only be called with an iterator passed to an ** SQLITE_CHANGESET_FOREIGN_KEY conflict handler callback. In this case @@ -9589,6 +9696,7 @@ SQLITE_API int sqlite3changeset_fk_conflicts( /* ** CAPI3REF: Finalize A Changeset Iterator +** METHOD: sqlite3_changeset_iter ** ** This function is used to finalize an iterator allocated with ** [sqlite3changeset_start()]. @@ -9605,6 +9713,7 @@ SQLITE_API int sqlite3changeset_fk_conflicts( ** to that error is returned by this function. Otherwise, SQLITE_OK is ** returned. This is to allow the following pattern (pseudo-code): ** +**
     **   sqlite3changeset_start();
     **   while( SQLITE_ROW==sqlite3changeset_next() ){
     **     // Do something with change.
    @@ -9613,6 +9722,7 @@ SQLITE_API int sqlite3changeset_fk_conflicts(
     **   if( rc!=SQLITE_OK ){
     **     // An error has occurred 
     **   }
    +** 
    */ SQLITE_API int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter); @@ -9660,6 +9770,7 @@ SQLITE_API int sqlite3changeset_invert( ** sqlite3_changegroup object. Calling it produces similar results as the ** following code fragment: ** +**
     **   sqlite3_changegroup *pGrp;
     **   rc = sqlite3_changegroup_new(&pGrp);
     **   if( rc==SQLITE_OK ) rc = sqlite3changegroup_add(pGrp, nA, pA);
    @@ -9670,6 +9781,7 @@ SQLITE_API int sqlite3changeset_invert(
     **     *ppOut = 0;
     **     *pnOut = 0;
     **   }
    +** 
    ** ** Refer to the sqlite3_changegroup documentation below for details. */ @@ -9685,11 +9797,15 @@ SQLITE_API int sqlite3changeset_concat( /* ** CAPI3REF: Changegroup Handle +** +** A changegroup is an object used to combine two or more +** [changesets] or [patchsets] */ typedef struct sqlite3_changegroup sqlite3_changegroup; /* ** CAPI3REF: Create A New Changegroup Object +** CONSTRUCTOR: sqlite3_changegroup ** ** An sqlite3_changegroup object is used to combine two or more changesets ** (or patchsets) into a single changeset (or patchset). A single changegroup @@ -9727,6 +9843,7 @@ SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp); /* ** CAPI3REF: Add A Changeset To A Changegroup +** METHOD: sqlite3_changegroup ** ** Add all changes within the changeset (or patchset) in buffer pData (size ** nData bytes) to the changegroup. @@ -9804,6 +9921,7 @@ SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pDa /* ** CAPI3REF: Obtain A Composite Changeset From A Changegroup +** METHOD: sqlite3_changegroup ** ** Obtain a buffer containing a changeset (or patchset) representing the ** current contents of the changegroup. If the inputs to the changegroup @@ -9834,25 +9952,25 @@ SQLITE_API int sqlite3changegroup_output( /* ** CAPI3REF: Delete A Changegroup Object +** DESTRUCTOR: sqlite3_changegroup */ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*); /* ** CAPI3REF: Apply A Changeset To A Database ** -** Apply a changeset to a database. This function attempts to update the -** "main" database attached to handle db with the changes found in the -** changeset passed via the second and third arguments. +** Apply a changeset or patchset to a database. These functions attempt to +** update the "main" database attached to handle db with the changes found in +** the changeset passed via the second and third arguments. ** -** The fourth argument (xFilter) passed to this function is the "filter +** The fourth argument (xFilter) passed to these functions is the "filter ** callback". If it is not NULL, then for each table affected by at least one ** change in the changeset, the filter callback is invoked with ** the table name as the second argument, and a copy of the context pointer -** passed as the sixth argument to this function as the first. If the "filter -** callback" returns zero, then no attempt is made to apply any changes to -** the table. Otherwise, if the return value is non-zero or the xFilter -** argument to this function is NULL, all changes related to the table are -** attempted. +** passed as the sixth argument as the first. If the "filter callback" +** returns zero, then no attempt is made to apply any changes to the table. +** Otherwise, if the return value is non-zero or the xFilter argument to +** is NULL, all changes related to the table are attempted. ** ** For each table that is not excluded by the filter callback, this function ** tests that the target database contains a compatible table. A table is @@ -9897,7 +10015,7 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*); ** **
    **
    DELETE Changes
    -** For each DELETE change, this function checks if the target database +** For each DELETE change, the function checks if the target database ** contains a row with the same primary key value (or values) as the ** original row values stored in the changeset. If it does, and the values ** stored in all non-primary key columns also match the values stored in @@ -9942,7 +10060,7 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*); ** [SQLITE_CHANGESET_REPLACE]. ** **
    UPDATE Changes
    -** For each UPDATE change, this function checks if the target database +** For each UPDATE change, the function checks if the target database ** contains a row with the same primary key value (or values) as the ** original row values stored in the changeset. If it does, and the values ** stored in all modified non-primary key columns also match the values @@ -9973,11 +10091,28 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*); ** This can be used to further customize the applications conflict ** resolution strategy. ** -** All changes made by this function are enclosed in a savepoint transaction. +** All changes made by these functions are enclosed in a savepoint transaction. ** If any other error (aside from a constraint failure when attempting to ** write to the target database) occurs, then the savepoint transaction is ** rolled back, restoring the target database to its original state, and an ** SQLite error code returned. +** +** If the output parameters (ppRebase) and (pnRebase) are non-NULL and +** the input is a changeset (not a patchset), then sqlite3changeset_apply_v2() +** may set (*ppRebase) to point to a "rebase" that may be used with the +** sqlite3_rebaser APIs buffer before returning. In this case (*pnRebase) +** is set to the size of the buffer in bytes. It is the responsibility of the +** caller to eventually free any such buffer using sqlite3_free(). The buffer +** is only allocated and populated if one or more conflicts were encountered +** while applying the patchset. See comments surrounding the sqlite3_rebaser +** APIs for further details. +** +** The behavior of sqlite3changeset_apply_v2() and its streaming equivalent +** may be modified by passing a combination of +** [SQLITE_CHANGESETAPPLY_NOSAVEPOINT | supported flags] as the 9th parameter. +** +** Note that the sqlite3changeset_apply_v2() API is still experimental +** and therefore subject to change. */ SQLITE_API int sqlite3changeset_apply( sqlite3 *db, /* Apply change to "main" db of this handle */ @@ -9994,6 +10129,41 @@ SQLITE_API int sqlite3changeset_apply( ), void *pCtx /* First argument passed to xConflict */ ); +SQLITE_API int sqlite3changeset_apply_v2( + sqlite3 *db, /* Apply change to "main" db of this handle */ + int nChangeset, /* Size of changeset in bytes */ + void *pChangeset, /* Changeset blob */ + int(*xFilter)( + void *pCtx, /* Copy of sixth arg to _apply() */ + const char *zTab /* Table name */ + ), + int(*xConflict)( + void *pCtx, /* Copy of sixth arg to _apply() */ + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ + sqlite3_changeset_iter *p /* Handle describing change and conflict */ + ), + void *pCtx, /* First argument passed to xConflict */ + void **ppRebase, int *pnRebase, /* OUT: Rebase data */ + int flags /* Combination of SESSION_APPLY_* flags */ +); + +/* +** CAPI3REF: Flags for sqlite3changeset_apply_v2 +** +** The following flags may passed via the 9th parameter to +** [sqlite3changeset_apply_v2] and [sqlite3changeset_apply_v2_strm]: +** +**
    +**
    SQLITE_CHANGESETAPPLY_NOSAVEPOINT
    +** Usually, the sessions module encloses all operations performed by +** a single call to apply_v2() or apply_v2_strm() in a [SAVEPOINT]. The +** SAVEPOINT is committed if the changeset or patchset is successfully +** applied, or rolled back if an error occurs. Specifying this flag +** causes the sessions module to omit this savepoint. In this case, if the +** caller has an open transaction or savepoint when apply_v2() is called, +** it may revert the partially applied changeset by rolling it back. +*/ +#define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001 /* ** CAPI3REF: Constants Passed To The Conflict Handler @@ -10091,6 +10261,161 @@ SQLITE_API int sqlite3changeset_apply( #define SQLITE_CHANGESET_REPLACE 1 #define SQLITE_CHANGESET_ABORT 2 +/* +** CAPI3REF: Rebasing changesets +** EXPERIMENTAL +** +** Suppose there is a site hosting a database in state S0. And that +** modifications are made that move that database to state S1 and a +** changeset recorded (the "local" changeset). Then, a changeset based +** on S0 is received from another site (the "remote" changeset) and +** applied to the database. The database is then in state +** (S1+"remote"), where the exact state depends on any conflict +** resolution decisions (OMIT or REPLACE) made while applying "remote". +** Rebasing a changeset is to update it to take those conflict +** resolution decisions into account, so that the same conflicts +** do not have to be resolved elsewhere in the network. +** +** For example, if both the local and remote changesets contain an +** INSERT of the same key on "CREATE TABLE t1(a PRIMARY KEY, b)": +** +** local: INSERT INTO t1 VALUES(1, 'v1'); +** remote: INSERT INTO t1 VALUES(1, 'v2'); +** +** and the conflict resolution is REPLACE, then the INSERT change is +** removed from the local changeset (it was overridden). Or, if the +** conflict resolution was "OMIT", then the local changeset is modified +** to instead contain: +** +** UPDATE t1 SET b = 'v2' WHERE a=1; +** +** Changes within the local changeset are rebased as follows: +** +**
    +**
    Local INSERT
    +** This may only conflict with a remote INSERT. If the conflict +** resolution was OMIT, then add an UPDATE change to the rebased +** changeset. Or, if the conflict resolution was REPLACE, add +** nothing to the rebased changeset. +** +**
    Local DELETE
    +** This may conflict with a remote UPDATE or DELETE. In both cases the +** only possible resolution is OMIT. If the remote operation was a +** DELETE, then add no change to the rebased changeset. If the remote +** operation was an UPDATE, then the old.* fields of change are updated +** to reflect the new.* values in the UPDATE. +** +**
    Local UPDATE
    +** This may conflict with a remote UPDATE or DELETE. If it conflicts +** with a DELETE, and the conflict resolution was OMIT, then the update +** is changed into an INSERT. Any undefined values in the new.* record +** from the update change are filled in using the old.* values from +** the conflicting DELETE. Or, if the conflict resolution was REPLACE, +** the UPDATE change is simply omitted from the rebased changeset. +** +** If conflict is with a remote UPDATE and the resolution is OMIT, then +** the old.* values are rebased using the new.* values in the remote +** change. Or, if the resolution is REPLACE, then the change is copied +** into the rebased changeset with updates to columns also updated by +** the conflicting remote UPDATE removed. If this means no columns would +** be updated, the change is omitted. +**
    +** +** A local change may be rebased against multiple remote changes +** simultaneously. If a single key is modified by multiple remote +** changesets, they are combined as follows before the local changeset +** is rebased: +** +**
      +**
    • If there has been one or more REPLACE resolutions on a +** key, it is rebased according to a REPLACE. +** +**
    • If there have been no REPLACE resolutions on a key, then +** the local changeset is rebased according to the most recent +** of the OMIT resolutions. +**
    +** +** Note that conflict resolutions from multiple remote changesets are +** combined on a per-field basis, not per-row. This means that in the +** case of multiple remote UPDATE operations, some fields of a single +** local change may be rebased for REPLACE while others are rebased for +** OMIT. +** +** In order to rebase a local changeset, the remote changeset must first +** be applied to the local database using sqlite3changeset_apply_v2() and +** the buffer of rebase information captured. Then: +** +**
      +**
    1. An sqlite3_rebaser object is created by calling +** sqlite3rebaser_create(). +**
    2. The new object is configured with the rebase buffer obtained from +** sqlite3changeset_apply_v2() by calling sqlite3rebaser_configure(). +** If the local changeset is to be rebased against multiple remote +** changesets, then sqlite3rebaser_configure() should be called +** multiple times, in the same order that the multiple +** sqlite3changeset_apply_v2() calls were made. +**
    3. Each local changeset is rebased by calling sqlite3rebaser_rebase(). +**
    4. The sqlite3_rebaser object is deleted by calling +** sqlite3rebaser_delete(). +**
    +*/ +typedef struct sqlite3_rebaser sqlite3_rebaser; + +/* +** CAPI3REF: Create a changeset rebaser object. +** EXPERIMENTAL +** +** Allocate a new changeset rebaser object. If successful, set (*ppNew) to +** point to the new object and return SQLITE_OK. Otherwise, if an error +** occurs, return an SQLite error code (e.g. SQLITE_NOMEM) and set (*ppNew) +** to NULL. +*/ +SQLITE_API int sqlite3rebaser_create(sqlite3_rebaser **ppNew); + +/* +** CAPI3REF: Configure a changeset rebaser object. +** EXPERIMENTAL +** +** Configure the changeset rebaser object to rebase changesets according +** to the conflict resolutions described by buffer pRebase (size nRebase +** bytes), which must have been obtained from a previous call to +** sqlite3changeset_apply_v2(). +*/ +SQLITE_API int sqlite3rebaser_configure( + sqlite3_rebaser*, + int nRebase, const void *pRebase +); + +/* +** CAPI3REF: Rebase a changeset +** EXPERIMENTAL +** +** Argument pIn must point to a buffer containing a changeset nIn bytes +** in size. This function allocates and populates a buffer with a copy +** of the changeset rebased rebased according to the configuration of the +** rebaser object passed as the first argument. If successful, (*ppOut) +** is set to point to the new buffer containing the rebased changset and +** (*pnOut) to its size in bytes and SQLITE_OK returned. It is the +** responsibility of the caller to eventually free the new buffer using +** sqlite3_free(). Otherwise, if an error occurs, (*ppOut) and (*pnOut) +** are set to zero and an SQLite error code returned. +*/ +SQLITE_API int sqlite3rebaser_rebase( + sqlite3_rebaser*, + int nIn, const void *pIn, + int *pnOut, void **ppOut +); + +/* +** CAPI3REF: Delete a changeset rebaser object. +** EXPERIMENTAL +** +** Delete the changeset rebaser object and all associated resources. There +** should be one call to this function for each successful invocation +** of sqlite3rebaser_create(). +*/ +SQLITE_API void sqlite3rebaser_delete(sqlite3_rebaser *p); + /* ** CAPI3REF: Streaming Versions of API functions. ** @@ -10100,6 +10425,7 @@ SQLITE_API int sqlite3changeset_apply( ** ** **
    Streaming functionNon-streaming equivalent
    sqlite3changeset_apply_strm[sqlite3changeset_apply] +**
    sqlite3changeset_apply_strm_v2[sqlite3changeset_apply_v2] **
    sqlite3changeset_concat_strm[sqlite3changeset_concat] **
    sqlite3changeset_invert_strm[sqlite3changeset_invert] **
    sqlite3changeset_start_strm[sqlite3changeset_start] @@ -10195,6 +10521,23 @@ SQLITE_API int sqlite3changeset_apply_strm( ), void *pCtx /* First argument passed to xConflict */ ); +SQLITE_API int sqlite3changeset_apply_v2_strm( + sqlite3 *db, /* Apply change to "main" db of this handle */ + int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */ + void *pIn, /* First arg for xInput */ + int(*xFilter)( + void *pCtx, /* Copy of sixth arg to _apply() */ + const char *zTab /* Table name */ + ), + int(*xConflict)( + void *pCtx, /* Copy of sixth arg to _apply() */ + int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */ + sqlite3_changeset_iter *p /* Handle describing change and conflict */ + ), + void *pCtx, /* First argument passed to xConflict */ + void **ppRebase, int *pnRebase, + int flags +); SQLITE_API int sqlite3changeset_concat_strm( int (*xInputA)(void *pIn, void *pData, int *pnData), void *pInA, @@ -10232,6 +10575,13 @@ SQLITE_API int sqlite3changegroup_output_strm(sqlite3_changegroup*, int (*xOutput)(void *pOut, const void *pData, int nData), void *pOut ); +SQLITE_API int sqlite3rebaser_rebase_strm( + sqlite3_rebaser *pRebaser, + int (*xInput)(void *pIn, void *pData, int *pnData), + void *pIn, + int (*xOutput)(void *pOut, const void *pData, int nData), + void *pOut +); /* diff --git a/src/corelib/doc/src/objectmodel/properties.qdoc b/src/corelib/doc/src/objectmodel/properties.qdoc index ab35e7c178..9ef08cce07 100644 --- a/src/corelib/doc/src/objectmodel/properties.qdoc +++ b/src/corelib/doc/src/objectmodel/properties.qdoc @@ -133,7 +133,7 @@ editable property for (checkable) buttons. Note that QItemDelegate gets and sets a widget's \c USER property. - \li The presence of the \c CONSTANT attibute indicates that the property + \li The presence of the \c CONSTANT attribute indicates that the property value is constant. For a given object instance, the READ method of a constant property must return the same value every time it is called. This constant value may be different for different instances of the object. A diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 9db182e1a9..6d55803e80 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -2295,17 +2295,13 @@ static void QT_FASTCALL fetchTransformedBilinearARGB32PM_downscale_helper(uint * #endif while (b < boundedEnd) { int x = (fx >> 16); -#if defined(__SSE2__) || defined(__ARM_NEON__) - int distx8 = (fx & 0x0000ffff) >> 8; - *b = interpolate_4_pixels(s1 + x, s2 + x, distx8, disty8); -#else - uint tl = s1[x]; - uint tr = s1[x + 1]; - uint bl = s2[x]; - uint br = s2[x + 1]; - int distx4 = ((fx & 0x0000ffff) + 0x0800) >> 12; - *b = interpolate_4_pixels_16(tl, tr, bl, br, distx4, disty4); -#endif + if (hasFastInterpolate4()) { + int distx8 = (fx & 0x0000ffff) >> 8; + *b = interpolate_4_pixels(s1 + x, s2 + x, distx8, disty8); + } else { + int distx4 = ((fx & 0x0000ffff) + 0x0800) >> 12; + *b = interpolate_4_pixels_16(s1[x], s1[x + 1], s2[x], s2[x + 1], distx4, disty4); + } fx += fdx; ++b; } @@ -2319,14 +2315,13 @@ static void QT_FASTCALL fetchTransformedBilinearARGB32PM_downscale_helper(uint * uint tr = s1[x2]; uint bl = s2[x1]; uint br = s2[x2]; -#if defined(__SSE2__) || defined(__ARM_NEON__) - // The optimized interpolate_4_pixels are faster than interpolate_4_pixels_16. - int distx8 = (fx & 0x0000ffff) >> 8; - *b = interpolate_4_pixels(tl, tr, bl, br, distx8, disty8); -#else - int distx4 = ((fx & 0x0000ffff) + 0x0800) >> 12; - *b = interpolate_4_pixels_16(tl, tr, bl, br, distx4, disty4); -#endif + if (hasFastInterpolate4()) { + int distx8 = (fx & 0x0000ffff) >> 8; + *b = interpolate_4_pixels(tl, tr, bl, br, distx8, disty8); + } else { + int distx4 = ((fx & 0x0000ffff) + 0x0800) >> 12; + *b = interpolate_4_pixels_16(tl, tr, bl, br, distx4, disty4); + } fx += fdx; ++b; } @@ -2391,15 +2386,15 @@ static void QT_FASTCALL fetchTransformedBilinearARGB32PM_fast_rotate_helper(uint uint tr = s1[x2]; uint bl = s2[x1]; uint br = s2[x2]; -#if defined(__SSE2__) || defined(__ARM_NEON__) - int distx = (fx & 0x0000ffff) >> 8; - int disty = (fy & 0x0000ffff) >> 8; - *b = interpolate_4_pixels(tl, tr, bl, br, distx, disty); -#else - int distx = ((fx & 0x0000ffff) + 0x0800) >> 12; - int disty = ((fy & 0x0000ffff) + 0x0800) >> 12; - *b = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty); -#endif + if (hasFastInterpolate4()) { + int distx = (fx & 0x0000ffff) >> 8; + int disty = (fy & 0x0000ffff) >> 8; + *b = interpolate_4_pixels(tl, tr, bl, br, distx, disty); + } else { + int distx = ((fx & 0x0000ffff) + 0x0800) >> 12; + int disty = ((fy & 0x0000ffff) + 0x0800) >> 12; + *b = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty); + } fx += fdx; fy += fdy; ++b; @@ -2541,19 +2536,15 @@ static void QT_FASTCALL fetchTransformedBilinearARGB32PM_fast_rotate_helper(uint const uint *s1 = (const uint *)image.scanLine(y); const uint *s2 = (const uint *)image.scanLine(y + 1); -#if defined(__SSE2__) || defined(__ARM_NEON__) - int distx = (fx & 0x0000ffff) >> 8; - int disty = (fy & 0x0000ffff) >> 8; - *b = interpolate_4_pixels(s1 + x, s2 + x, distx, disty); -#else - uint tl = s1[x]; - uint tr = s1[x + 1]; - uint bl = s2[x]; - uint br = s2[x + 1]; - int distx = ((fx & 0x0000ffff) + 0x0800) >> 12; - int disty = ((fy & 0x0000ffff) + 0x0800) >> 12; - *b = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty); -#endif + if (hasFastInterpolate4()) { + int distx = (fx & 0x0000ffff) >> 8; + int disty = (fy & 0x0000ffff) >> 8; + *b = interpolate_4_pixels(s1 + x, s2 + x, distx, disty); + } else { + int distx = ((fx & 0x0000ffff) + 0x0800) >> 12; + int disty = ((fy & 0x0000ffff) + 0x0800) >> 12; + *b = interpolate_4_pixels_16(s1[x], s1[x + 1], s2[x], s2[x + 1], distx, disty); + } fx += fdx; fy += fdy; @@ -2578,16 +2569,15 @@ static void QT_FASTCALL fetchTransformedBilinearARGB32PM_fast_rotate_helper(uint uint bl = s2[x1]; uint br = s2[x2]; -#if defined(__SSE2__) || defined(__ARM_NEON__) - // The optimized interpolate_4_pixels are faster than interpolate_4_pixels_16. - int distx = (fx & 0x0000ffff) >> 8; - int disty = (fy & 0x0000ffff) >> 8; - *b = interpolate_4_pixels(tl, tr, bl, br, distx, disty); -#else - int distx = ((fx & 0x0000ffff) + 0x0800) >> 12; - int disty = ((fy & 0x0000ffff) + 0x0800) >> 12; - *b = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty); -#endif + if (hasFastInterpolate4()) { + int distx = (fx & 0x0000ffff) >> 8; + int disty = (fy & 0x0000ffff) >> 8; + *b = interpolate_4_pixels(tl, tr, bl, br, distx, disty); + } else { + int distx = ((fx & 0x0000ffff) + 0x0800) >> 12; + int disty = ((fy & 0x0000ffff) + 0x0800) >> 12; + *b = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty); + } fx += fdx; fy += fdy; @@ -2981,7 +2971,7 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper layout->convertToARGB32PM(buf1, buf1, len * 2, clut, 0); layout->convertToARGB32PM(buf2, buf2, len * 2, clut, 0); - if (qAbs(data->m22) < qreal(1./8.)) { // scale up more than 8x (on Y) + if (hasFastInterpolate4() || qAbs(data->m22) < qreal(1./8.)) { // scale up more than 8x (on Y) int disty = (fy & 0x0000ffff) >> 8; for (int i = 0; i < len; ++i) { int distx = (fx & 0x0000ffff) >> 8; @@ -3016,7 +3006,7 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper layout->convertToARGB32PM(buf1, buf1, len * 2, clut, 0); layout->convertToARGB32PM(buf2, buf2, len * 2, clut, 0); - if (qAbs(data->m11) < qreal(1./8.)|| qAbs(data->m22) < qreal(1./8.)) { + if (hasFastInterpolate4() || qAbs(data->m11) < qreal(1./8.) || qAbs(data->m22) < qreal(1./8.)) { // If we are zooming more than 8 times, we use 8bit precision for the position. for (int i = 0; i < len; ++i) { int distx = (fx & 0x0000ffff) >> 8; diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h index 4940026abb..c0214e9c11 100644 --- a/src/gui/painting/qdrawhelper_p.h +++ b/src/gui/painting/qdrawhelper_p.h @@ -685,6 +685,9 @@ static inline uint interpolate_4_pixels(const uint t[], const uint b[], uint dis __m128i vb = _mm_loadl_epi64((const __m128i*)b); return interpolate_4_pixels_sse2(vt, vb, distx, disty); } + +static constexpr inline bool hasFastInterpolate4() { return true; } + #elif defined(__ARM_NEON__) static Q_ALWAYS_INLINE uint interpolate_4_pixels_neon(uint32x2_t vt32, uint32x2_t vb32, uint distx, uint disty) { @@ -717,6 +720,9 @@ static inline uint interpolate_4_pixels(const uint t[], const uint b[], uint dis uint32x2_t vb32 = vld1_u32(b); return interpolate_4_pixels_neon(vt32, vb32, distx, disty); } + +static constexpr inline bool hasFastInterpolate4() { return true; } + #else static inline uint interpolate_4_pixels(uint tl, uint tr, uint bl, uint br, uint distx, uint disty) { @@ -731,6 +737,9 @@ static inline uint interpolate_4_pixels(const uint t[], const uint b[], uint dis { return interpolate_4_pixels(t[0], t[1], b[0], b[1], distx, disty); } + +static constexpr inline bool hasFastInterpolate4() { return false; } + #endif #if Q_BYTE_ORDER == Q_BIG_ENDIAN diff --git a/src/network/access/qhttp2protocolhandler.cpp b/src/network/access/qhttp2protocolhandler.cpp index 5420e713b5..22541e83ba 100644 --- a/src/network/access/qhttp2protocolhandler.cpp +++ b/src/network/access/qhttp2protocolhandler.cpp @@ -212,6 +212,9 @@ QHttp2ProtocolHandler::QHttp2ProtocolHandler(QHttpNetworkConnectionChannel *chan void QHttp2ProtocolHandler::_q_uploadDataReadyRead() { + if (!sender()) // QueuedConnection, firing after sender (byte device) was deleted. + return; + auto data = qobject_cast(sender()); Q_ASSERT(data); const qint32 streamID = data->property("HTTP2StreamID").toInt(); @@ -1110,6 +1113,17 @@ void QHttp2ProtocolHandler::updateStream(Stream &stream, const HPack::HttpHeader if (QHttpNetworkReply::isHttpRedirect(statusCode) && redirectUrl.isValid()) httpReply->setRedirectUrl(redirectUrl); + if (QHttpNetworkReply::isHttpRedirect(statusCode) + || statusCode == 401 || statusCode == 407) { + // These are the status codes that can trigger uploadByteDevice->reset() + // in QHttpNetworkConnectionChannel::handleStatus. Alas, we have no + // single request/reply, we multiplex several requests and thus we never + // simply call 'handleStatus'. If we have byte-device - we try to reset + // it here, we don't (and can't) handle any error during reset operation. + if (stream.data()) + stream.data()->reset(); + } + if (connectionType == Qt::DirectConnection) emit httpReply->headerChanged(); else diff --git a/src/network/ssl/qssl.cpp b/src/network/ssl/qssl.cpp index 0102956097..ee6e64706a 100644 --- a/src/network/ssl/qssl.cpp +++ b/src/network/ssl/qssl.cpp @@ -117,7 +117,7 @@ Q_LOGGING_CATEGORY(lcSsl, "qt.network.ssl"); Describes the protocol of the cipher. \value SslV3 SSLv3. When using the WinRT backend this option will also enable TLSv1.0 - \value SslV2 SSLv2 + \value SslV2 SSLv2. Note, SSLv2 support was removed in OpenSSL 1.1. \value TlsV1_0 TLSv1.0 \value TlsV1_0OrLater TLSv1.0 and later versions. This option is not available when using the WinRT backend due to platform limitations. \value TlsV1 Obsolete, means the same as TlsV1_0 @@ -129,8 +129,8 @@ Q_LOGGING_CATEGORY(lcSsl, "qt.network.ssl"); \value DtlsV1_2 DTLSv1.2 \value DtlsV1_2OrLater DTLSv1.2 and later versions. \value UnknownProtocol The cipher's protocol cannot be determined. - \value AnyProtocol The socket understands SSLv2, SSLv3, and TLSv1.0. This - value is used by QSslSocket only. + \value AnyProtocol The socket understands SSLv2, SSLv3, TLSv1.0 and all + supported later versions of TLS. This value is used by QSslSocket only. \value TlsV1SslV3 On the client side, this will send a TLS 1.0 Client Hello, enabling TLSv1_0 and SSLv3 connections. On the server side, this will enable both SSLv3 and TLSv1_0 connections. diff --git a/src/network/ssl/qsslcontext_openssl11.cpp b/src/network/ssl/qsslcontext_openssl11.cpp index 7be7be46b8..5c68ed41db 100644 --- a/src/network/ssl/qsslcontext_openssl11.cpp +++ b/src/network/ssl/qsslcontext_openssl11.cpp @@ -100,6 +100,68 @@ init_context: return; } + long minVersion = TLS_ANY_VERSION; + long maxVersion = TLS_ANY_VERSION; + switch (sslContext->sslConfiguration.protocol()) { + // The single-protocol versions first: + case QSsl::SslV3: + minVersion = SSL3_VERSION; + maxVersion = SSL3_VERSION; + break; + case QSsl::TlsV1_0: + minVersion = TLS1_VERSION; + maxVersion = TLS1_VERSION; + break; + case QSsl::TlsV1_1: + minVersion = TLS1_1_VERSION; + maxVersion = TLS1_1_VERSION; + break; + case QSsl::TlsV1_2: + minVersion = TLS1_2_VERSION; + maxVersion = TLS1_2_VERSION; + break; + // Ranges: + case QSsl::TlsV1SslV3: + case QSsl::AnyProtocol: + minVersion = SSL3_VERSION; + maxVersion = TLS_MAX_VERSION; + break; + case QSsl::SecureProtocols: + case QSsl::TlsV1_0OrLater: + minVersion = TLS1_VERSION; + maxVersion = TLS_MAX_VERSION; + break; + case QSsl::TlsV1_1OrLater: + minVersion = TLS1_1_VERSION; + maxVersion = TLS_MAX_VERSION; + break; + case QSsl::TlsV1_2OrLater: + minVersion = TLS1_2_VERSION; + maxVersion = TLS_MAX_VERSION; + break; + case QSsl::SslV2: + // This protocol is not supported by OpenSSL 1.1 and we handle + // it as an error (see the code above). + Q_UNREACHABLE(); + break; + case QSsl::UnknownProtocol: + break; + } + + if (minVersion != TLS_ANY_VERSION + && !q_SSL_CTX_set_min_proto_version(sslContext->ctx, minVersion)) { + sslContext->errorStr = QSslSocket::tr("Error while setting the minimal protocol version"); + sslContext->errorCode = QSslError::UnspecifiedError; + return; + } + + if (maxVersion != TLS_ANY_VERSION + && !q_SSL_CTX_set_max_proto_version(sslContext->ctx, maxVersion)) { + sslContext->errorStr = QSslSocket::tr("Error while setting the maximum protocol version"); + sslContext->errorCode = QSslError::UnspecifiedError; + return; + } + // Enable bug workarounds. long options = QSslSocketBackendPrivate::setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions); q_SSL_CTX_set_options(sslContext->ctx, options); diff --git a/src/network/ssl/qsslsocket_openssl11_symbols_p.h b/src/network/ssl/qsslsocket_openssl11_symbols_p.h index 60134726fe..1ceddecbb7 100644 --- a/src/network/ssl/qsslsocket_openssl11_symbols_p.h +++ b/src/network/ssl/qsslsocket_openssl11_symbols_p.h @@ -168,4 +168,10 @@ void q_BIO_set_init(BIO *a, int init); int q_BIO_get_shutdown(BIO *a); void q_BIO_set_shutdown(BIO *a, int shut); +#define q_SSL_CTX_set_min_proto_version(ctx, version) \ + q_SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MIN_PROTO_VERSION, version, nullptr) + +#define q_SSL_CTX_set_max_proto_version(ctx, version) \ + q_SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MAX_PROTO_VERSION, version, nullptr) + #endif diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index 8d03ed9783..9b1162149d 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -240,6 +240,24 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QVerticalSplitView); } @end +#if !QT_CONFIG(appstore_compliant) + +// This API was requested to Apple in rdar #36197888. +// We know it's safe to use up to macOS 10.13.3. +// See drawComplexControl(CC_ComboBox) for its usage. + +@interface NSComboBoxCell (QtButtonCell) +@property (readonly) NSButtonCell *qt_buttonCell; +@end + +@implementation NSComboBoxCell (QtButtonCell) +- (NSButtonCell *)qt_buttonCell { + return self->_buttonCell; +} +@end + +#endif + QT_BEGIN_NAMESPACE // The following constants are used for adjusting the size @@ -322,6 +340,12 @@ static const int headerSectionArrowHeight = 6; static const int headerSectionSeparatorInset = 2; // One for each of QStyleHelper::WidgetSizePolicy +static const QMarginsF comboBoxFocusRingMargins[3] = { + { 0.5, 2, 3.5, 4 }, + { 0.5, 1, 2.5, 4 }, + { 0.5, 1.5, 2.5, 3.5 } +}; + static const QMarginsF pullDownButtonShadowMargins[3] = { { 0.5, -1, 0.5, 2 }, { 0.5, -1.5, 0.5, 2.5 }, @@ -338,6 +362,10 @@ static const QMarginsF pushButtonShadowMargins[3] = { // Alignemnet rectangle's heights match for push and popup buttons // with respective values 21, 18 and 15. +static const qreal comboBoxDefaultHeight[3] = { + 26, 22, 19 +}; + static const qreal pushButtonDefaultHeight[3] = { 32, 28, 16 }; @@ -600,32 +628,6 @@ static inline bool isTreeView(const QWidget *widget) } #endif -#if QT_CONFIG(tabbar) -static inline ThemeTabDirection getTabDirection(QTabBar::Shape shape) -{ - ThemeTabDirection ttd; - switch (shape) { - case QTabBar::RoundedSouth: - case QTabBar::TriangularSouth: - ttd = kThemeTabSouth; - break; - case QTabBar::RoundedNorth: - case QTabBar::TriangularNorth: - ttd = kThemeTabNorth; - break; - case QTabBar::RoundedWest: - case QTabBar::TriangularWest: - ttd = kThemeTabWest; - break; - case QTabBar::RoundedEast: - case QTabBar::TriangularEast: - ttd = kThemeTabEast; - break; - } - return ttd; -} -#endif - static QString qt_mac_removeMnemonics(const QString &original) { QString returnText(original.size(), 0); @@ -684,7 +686,6 @@ static bool qt_macWindowMainWindow(const QWidget *window) /***************************************************************************** QMacCGStyle globals *****************************************************************************/ -const int qt_mac_hitheme_version = 0; //the HITheme version we speak const int macItemFrame = 2; // menu item frame width const int macItemHMargin = 3; // menu item hor text margin const int macRightBorder = 12; // right border on mac @@ -692,10 +693,6 @@ const int macRightBorder = 12; // right border on mac /***************************************************************************** QMacCGStyle utility functions *****************************************************************************/ -static inline int qt_mac_hitheme_tab_version() -{ - return 1; -} enum QAquaMetric { // Prepend kThemeMetric to get the HIToolBox constant. @@ -1160,79 +1157,27 @@ static QStyleHelper::WidgetSizePolicy qt_aqua_guess_size(const QWidget *widg, QS } #endif -void QMacStylePrivate::drawFocusRing(QPainter *p, const QRect &targetRect, int hMargin, int vMargin, qreal radius) const -{ - const qreal pixelRatio = p->device()->devicePixelRatioF(); - static const QString keyFormat = QLatin1String("$qt_focusring%1-%2-%3-%4"); - const QString &key = keyFormat.arg(hMargin).arg(vMargin).arg(radius).arg(pixelRatio); - QPixmap focusRingPixmap; - - if (!QPixmapCache::find(key, focusRingPixmap)) { - const qreal size = radius * 2 + 5; - focusRingPixmap = QPixmap((QSize(size, size) + 2 * QSize(hMargin, vMargin)) * pixelRatio); - focusRingPixmap.fill(Qt::transparent); - focusRingPixmap.setDevicePixelRatio(pixelRatio); - - static const qreal focusRingWidth = 3.5; - const auto focusRingRect = QRectF(hMargin, vMargin, size, size); - QPainterPath focusRingPath; - focusRingPath.setFillRule(Qt::OddEvenFill); - const auto innerRect = radius > 0 ? focusRingRect : focusRingRect.adjusted(0.5, 0.5, -0.5, -0.5); - if (radius > 0) - focusRingPath.addRoundedRect(innerRect, radius, radius); - else - focusRingPath.addRect(innerRect); - - const auto outterRect = innerRect.adjusted(-focusRingWidth, -focusRingWidth, focusRingWidth, focusRingWidth); - const auto outterRadius = radius + focusRingWidth; - focusRingPath.addRoundedRect(outterRect, outterRadius, outterRadius); - - QPainter pp(&focusRingPixmap); - pp.setOpacity(0.5); - pp.setRenderHint(QPainter::Antialiasing); - const auto focusRingColor = qt_mac_toQColor(NSColor.keyboardFocusIndicatorColor.CGColor); - pp.fillPath(focusRingPath, focusRingColor); - - QPixmapCache::insert(key, focusRingPixmap); - } - - // Add 2 for the actual ring tickness going inwards - const qreal hCornerSize = 2 + hMargin + radius; - const qreal vCornerSize = 2 + vMargin + radius; - const qreal shCornerSize = hCornerSize * pixelRatio; - const qreal svCornerSize = vCornerSize * pixelRatio; - // top-left corner - p->drawPixmap(QPointF(targetRect.left(), targetRect.top()), focusRingPixmap, - QRectF(0, 0, shCornerSize, svCornerSize)); - // top-right corner - p->drawPixmap(QPointF(targetRect.right() - hCornerSize + 1, targetRect.top()), focusRingPixmap, - QRectF(focusRingPixmap.width() - shCornerSize, 0, shCornerSize, svCornerSize)); - // bottom-left corner - p->drawPixmap(QPointF(targetRect.left(), targetRect.bottom() - vCornerSize + 1), focusRingPixmap, - QRectF(0, focusRingPixmap.height() - svCornerSize, shCornerSize, svCornerSize)); - // bottom-right corner - p->drawPixmap(QPointF(targetRect.right() - hCornerSize + 1, targetRect.bottom() - vCornerSize + 1), focusRingPixmap, - QRect(focusRingPixmap.width() - shCornerSize, focusRingPixmap.height() - svCornerSize, shCornerSize, svCornerSize)); - // top edge - p->drawPixmap(QRectF(targetRect.left() + hCornerSize, targetRect.top(), targetRect.width() - 2 * hCornerSize, vCornerSize), focusRingPixmap, - QRect(shCornerSize, 0, focusRingPixmap.width() - 2 * shCornerSize, svCornerSize)); - // bottom edge - p->drawPixmap(QRectF(targetRect.left() + hCornerSize, targetRect.bottom() - vCornerSize + 1, targetRect.width() - 2 * hCornerSize, vCornerSize), focusRingPixmap, - QRect(shCornerSize, focusRingPixmap.height() - svCornerSize, focusRingPixmap.width() - 2 * shCornerSize, svCornerSize)); - // left edge - p->drawPixmap(QRectF(targetRect.left(), targetRect.top() + vCornerSize, hCornerSize, targetRect.height() - 2 * vCornerSize), focusRingPixmap, - QRect(0, svCornerSize, shCornerSize, focusRingPixmap.width() - 2 * svCornerSize)); - // right edge - p->drawPixmap(QRectF(targetRect.right() - hCornerSize + 1, targetRect.top() + vCornerSize, hCornerSize, targetRect.height() - 2 * vCornerSize), focusRingPixmap, - QRect(focusRingPixmap.width() - shCornerSize, svCornerSize, shCornerSize, focusRingPixmap.width() - 2 * svCornerSize)); -} - void QMacStylePrivate::drawFocusRing(QPainter *p, const QRectF &targetRect, int hMargin, int vMargin, const CocoaControl &cw) const { QPainterPath focusRingPath; + focusRingPath.setFillRule(Qt::OddEvenFill); + qreal hOffset = 0.0; qreal vOffset = 0.0; switch (cw.type) { + case Box: + case Button_SquareButton: + case SegmentedControl_Middle: + case TextField: { + auto innerRect = targetRect; + if (cw.type == TextField) + innerRect = innerRect.adjusted(hMargin, vMargin, -hMargin, -vMargin).adjusted(0.5, 0.5, -0.5, -0.5); + const auto outterRect = innerRect.adjusted(-focusRingWidth, -focusRingWidth, focusRingWidth, focusRingWidth); + const auto outterRadius = focusRingWidth; + focusRingPath.addRect(innerRect); + focusRingPath.addRoundedRect(outterRect, outterRadius, outterRadius); + break; + } case Button_CheckBox: { const auto cbInnerRadius = (cw.size == QStyleHelper::SizeMini ? 2.0 : 3.0); const auto cbSize = cw.size == QStyleHelper::SizeLarge ? 13 : @@ -1243,7 +1188,6 @@ void QMacStylePrivate::drawFocusRing(QPainter *p, const QRectF &targetRect, int const auto cbInnerRect = QRectF(0, 0, cbSize, cbSize); const auto cbOutterRadius = cbInnerRadius + focusRingWidth; const auto cbOutterRect = cbInnerRect.adjusted(-focusRingWidth, -focusRingWidth, focusRingWidth, focusRingWidth); - focusRingPath.setFillRule(Qt::OddEvenFill); focusRingPath.addRoundedRect(cbOutterRect, cbOutterRadius, cbOutterRadius); focusRingPath.addRoundedRect(cbInnerRect, cbInnerRadius, cbInnerRadius); break; @@ -1256,25 +1200,62 @@ void QMacStylePrivate::drawFocusRing(QPainter *p, const QRectF &targetRect, int vOffset = 0.5 * qreal(targetRect.height() - rbSize); const auto rbInnerRect = QRectF(0, 0, rbSize, rbSize); const auto rbOutterRect = rbInnerRect.adjusted(-focusRingWidth, -focusRingWidth, focusRingWidth, focusRingWidth); - focusRingPath.setFillRule(Qt::OddEvenFill); focusRingPath.addEllipse(rbInnerRect); focusRingPath.addEllipse(rbOutterRect); break; } case Button_PopupButton: case Button_PullDown: - case Button_PushButton: { - const qreal innerRadius = cw.type == Button_PullDown ? 4 : 3; + case Button_PushButton: + case SegmentedControl_Single: { + const qreal innerRadius = cw.type == Button_PushButton ? 3 : 4; const qreal outterRadius = innerRadius + focusRingWidth; hOffset = targetRect.left(); vOffset = targetRect.top(); const auto innerRect = targetRect.translated(-targetRect.topLeft()); const auto outterRect = innerRect.adjusted(-hMargin, -vMargin, hMargin, vMargin); - focusRingPath.setFillRule(Qt::OddEvenFill); focusRingPath.addRoundedRect(innerRect, innerRadius, innerRadius); focusRingPath.addRoundedRect(outterRect, outterRadius, outterRadius); break; } + case ComboBox: + case SegmentedControl_First: + case SegmentedControl_Last: { + hOffset = targetRect.left(); + vOffset = targetRect.top(); + const qreal innerRadius = 8; + const qreal outterRadius = innerRadius + focusRingWidth; + const auto innerRect = targetRect.translated(-targetRect.topLeft()); + const auto outterRect = innerRect.adjusted(-hMargin, -vMargin, hMargin, vMargin); + + const auto cbFocusFramePath = [](const QRectF &rect, qreal tRadius, qreal bRadius) { + QPainterPath path; + + if (tRadius > 0) { + const auto topLeftCorner = QRectF(rect.topLeft(), QSizeF(tRadius, tRadius)); + path.arcMoveTo(topLeftCorner, 180); + path.arcTo(topLeftCorner, 180, -90); + } else { + path.moveTo(rect.topLeft()); + } + const auto rightEdge = rect.right() - bRadius; + path.arcTo(rightEdge, rect.top(), bRadius, bRadius, 90, -90); + path.arcTo(rightEdge, rect.bottom() - bRadius, bRadius, bRadius, 0, -90); + if (tRadius > 0) + path.arcTo(rect.left(), rect.bottom() - tRadius, tRadius, tRadius, 270, -90); + else + path.lineTo(rect.bottomLeft()); + path.closeSubpath(); + + return path; + }; + + const auto innerPath = cbFocusFramePath(innerRect, 0, innerRadius); + focusRingPath.addPath(innerPath); + const auto outterPath = cbFocusFramePath(outterRect, 2 * focusRingWidth, outterRadius); + focusRingPath.addPath(outterPath); + break; + } default: Q_UNREACHABLE(); } @@ -1284,6 +1265,9 @@ void QMacStylePrivate::drawFocusRing(QPainter *p, const QRectF &targetRect, int p->save(); p->setRenderHint(QPainter::Antialiasing); p->setOpacity(0.5); + if (cw.type == SegmentedControl_First) { + // TODO Flip left-right + } p->translate(hOffset, vOffset); p->fillPath(focusRingPath, focusRingColor); p->restore(); @@ -1409,6 +1393,25 @@ void QMacStylePrivate::tabLayout(const QStyleOptionTab *opt, const QWidget *widg *textRect = tr; } + +QMacStylePrivate::Direction QMacStylePrivate::tabDirection(QTabBar::Shape shape) +{ + switch (shape) { + case QTabBar::RoundedSouth: + case QTabBar::TriangularSouth: + return South; + case QTabBar::RoundedNorth: + case QTabBar::TriangularNorth: + return North; + case QTabBar::RoundedWest: + case QTabBar::TriangularWest: + return West; + case QTabBar::RoundedEast: + case QTabBar::TriangularEast: + return East; + } +} + #endif // QT_CONFIG(tabbar) QStyleHelper::WidgetSizePolicy QMacStylePrivate::effectiveAquaSizeConstrain(const QStyleOption *option, @@ -1529,35 +1532,41 @@ QSizeF QMacStylePrivate::CocoaControl::defaultFrameSize() const || type == Button_PullDown) return QSizeF(-1, popupButtonDefaultHeight[size]); + if (type == ComboBox) + return QSizeF(-1, comboBoxDefaultHeight[size]); + return QSizeF(); } QRectF QMacStylePrivate::CocoaControl::adjustedControlFrame(const QRectF &rect) const { QRectF frameRect; + const auto frameSize = defaultFrameSize(); if (type == QMacStylePrivate::Button_SquareButton) { frameRect = rect.adjusted(3, 1, -3, -5) .adjusted(focusRingWidth, focusRingWidth, -focusRingWidth, -focusRingWidth); + } else if (type == QMacStylePrivate::Button_PushButton) { + // Start from the style option's top-left corner. + frameRect = QRectF(rect.topLeft(), + QSizeF(rect.width(), frameSize.height())); + if (size == QStyleHelper::SizeSmall) + frameRect = frameRect.translated(0, 1.5); + else if (size == QStyleHelper::SizeMini) + frameRect = frameRect.adjusted(0, 0, -8, 0).translated(4, 4); } else { - const auto frameSize = defaultFrameSize(); - if (type == QMacStylePrivate::Button_PullDown) { - // Center in the style option's rect. - frameRect = QRectF(QPointF(0, (rect.height() - frameSize.height()) / 2.0), - QSizeF(rect.width(), frameSize.height())); + // Center in the style option's rect. + frameRect = QRectF(QPointF(0, (rect.height() - frameSize.height()) / 2.0), + QSizeF(rect.width(), frameSize.height())); + frameRect = frameRect.translated(rect.topLeft()); + if (type == QMacStylePrivate::Button_PullDown || type == QMacStylePrivate::Button_PopupButton) { if (size == QStyleHelper::SizeLarge) frameRect = frameRect.adjusted(0, 0, -6, 0).translated(3, -1); else if (size == QStyleHelper::SizeSmall) frameRect = frameRect.adjusted(0, 0, -4, 0).translated(2, 1); else if (size == QStyleHelper::SizeMini) frameRect = frameRect.adjusted(0, 0, -9, 0).translated(5, 0); - } else if (type == QMacStylePrivate::Button_PushButton) { - // Start from the style option's top-left corner. - frameRect = QRectF(rect.topLeft(), - QSizeF(rect.width(), frameSize.height())); - if (size == QStyleHelper::SizeSmall) - frameRect = frameRect.translated(0, 1.5); - else if (size == QStyleHelper::SizeMini) - frameRect = frameRect.adjusted(0, 0, -8, 0).translated(4, 4); + } else if (type == QMacStylePrivate::ComboBox) { + frameRect = frameRect.adjusted(0, 0, -6, 0).translated(4, 0); } } @@ -1581,7 +1590,7 @@ QMarginsF QMacStylePrivate::CocoaControl::titleMargins() const if (size == QStyleHelper::SizeSmall) return QMarginsF(7.5, 2, 20.5, 4); if (size == QStyleHelper::SizeMini) - return QMarginsF(4.5, 1, 16.5, 2); + return QMarginsF(4.5, 0, 16.5, 2); } if (type == QMacStylePrivate::Button_SquareButton) @@ -1637,113 +1646,23 @@ QMacStylePrivate::CocoaControlType cocoaControlType(const QStyleOption *opt, con QMacStylePrivate::Button_PushButton); } - return QMacStylePrivate::NoControl; -} - -/** - Creates a HIThemeButtonDrawInfo structure that specifies the correct button - kind and other details to use for drawing the given combobox. Which button - kind depends on the size of the combo, wether or not it is editable, - explicit user style settings, etc. -*/ -void QMacStylePrivate::initComboboxBdi(const QStyleOptionComboBox *combo, HIThemeButtonDrawInfo *bdi, - CocoaControl *cw, - const QWidget *widget, const ThemeDrawState &tds) const -{ - bdi->version = qt_mac_hitheme_version; - bdi->adornment = kThemeAdornmentArrowLeftArrow; - bdi->value = kThemeButtonOff; - if (combo->state & QStyle::State_HasFocus) - bdi->adornment = kThemeAdornmentFocus; - if (combo->activeSubControls & QStyle::SC_ComboBoxArrow) - bdi->state = kThemeStatePressed; - else - bdi->state = tds; - - QStyleHelper::WidgetSizePolicy aSize = aquaSizeConstrain(combo, widget); - cw->type = combo->editable ? ComboBox : Button_PopupButton; - cw->size = aSize; - switch (aSize) { - case QStyleHelper::SizeMini: - bdi->kind = combo->editable ? ThemeButtonKind(kThemeComboBoxMini) - : ThemeButtonKind(kThemePopupButtonMini); - break; - case QStyleHelper::SizeSmall: - bdi->kind = combo->editable ? ThemeButtonKind(kThemeComboBoxSmall) - : ThemeButtonKind(kThemePopupButtonSmall); - break; - case QStyleHelper::SizeLarge: - case QStyleHelper::SizeDefault: - // Unless the user explicitly specified large buttons, determine the - // kind by looking at the combox size. - // ... specifying small and mini-buttons it not a current feature of - // Qt (e.g. QWidget::getAttribute(WA_ButtonSize)). But when it is, add - // an extra check here before using the mini and small buttons. - int h = combo->rect.size().height(); - if (combo->editable){ -#if QT_CONFIG(datetimeedit) - if (qobject_cast(widget)) { - // Except when, you know, we get a QDateTimeEdit with calendarPopup - // enabled. And then things get weird, basically because it's a - // transvestite spinbox with editable combobox tendencies. Meaning - // that it wants to look a combobox, except that it isn't one, so it - // doesn't get all those extra free margins around. (Don't know whose - // idea those margins were, but now it looks like we're stuck with - // them forever). So anyway, the height threshold should be smaller - // in this case, or the style gets confused when it needs to render - // or return any subcontrol size of the poor thing. - if (h < 9) { - bdi->kind = kThemeComboBoxMini; - cw->size = QStyleHelper::SizeMini; - } else if (h < 22) { - bdi->kind = kThemeComboBoxSmall; - cw->size = QStyleHelper::SizeSmall; - } else { - bdi->kind = kThemeComboBox; - cw->size = QStyleHelper::SizeLarge; - } - } else -#endif - { - if (h < 21) { - bdi->kind = kThemeComboBoxMini; - cw->size = QStyleHelper::SizeMini; - } else if (h < 26) { - bdi->kind = kThemeComboBoxSmall; - cw->size = QStyleHelper::SizeSmall; - } else { - bdi->kind = kThemeComboBox; - cw->size = QStyleHelper::SizeLarge; - } - } - } else { - // Even if we specify that we want the kThemePopupButton, Carbon - // will use the kThemePopupButtonSmall if the size matches. So we - // do the same size check explicit to have the size of the inner - // text field be correct. Therefore, do this even if the user specifies - // the use of LargeButtons explicit. - if (h < 21) { - bdi->kind = kThemePopupButtonMini; - cw->size = QStyleHelper::SizeMini; - } else if (h < 26) { - bdi->kind = kThemePopupButtonSmall; - cw->size = QStyleHelper::SizeSmall; - } else { - bdi->kind = kThemePopupButton; - cw->size = QStyleHelper::SizeLarge; - } - } - break; + if (const auto *combo = qstyleoption_cast(opt)) { + if (combo->editable) + return QMacStylePrivate::ComboBox; + // TODO Me may support square, non-editable combo boxes, but not more than that + return QMacStylePrivate::Button_PopupButton; } + + return QMacStylePrivate::NoControl; } /** Carbon draws comboboxes (and other views) outside the rect given as argument. Use this function to obtain the corresponding inner rect for drawing the same combobox so that it stays inside the given outerBounds. */ -CGRect QMacStylePrivate::comboboxInnerBounds(const CGRect &outerBounds, const CocoaControl &cocoaWidget) +CGRect QMacStylePrivate::comboboxInnerBounds(const CGRect &outterBounds, const CocoaControl &cocoaWidget) { - CGRect innerBounds = outerBounds; + CGRect innerBounds = outterBounds; // Carbon draw parts of the view outside the rect. // So make the rect a bit smaller to compensate // (I wish HIThemeGetButtonBackgroundBounds worked) @@ -1798,87 +1717,46 @@ CGRect QMacStylePrivate::comboboxInnerBounds(const CGRect &outerBounds, const Co Inside a combobox Qt places a line edit widget. The size of this widget should depend on the kind of combobox we choose to draw. This function calculates and returns this size. */ -QRect QMacStylePrivate::comboboxEditBounds(const QRect &outerBounds, const HIThemeButtonDrawInfo &bdi) +QRectF QMacStylePrivate::comboboxEditBounds(const QRectF &outterBounds, const CocoaControl &cw) { - QRect ret = outerBounds; - switch (bdi.kind){ - case kThemeComboBox: - ret.adjust(5, 5, -22, -5); - break; - case kThemeComboBoxSmall: - ret.adjust(4, 5, -18, 0); - ret.setHeight(16); - break; - case kThemeComboBoxMini: - ret.adjust(4, 5, -16, 0); - ret.setHeight(13); - break; - case kThemePopupButton: - ret.adjust(10, 2, -23, -4); - break; - case kThemePopupButtonSmall: - ret.adjust(9, 3, -20, -3); - break; - case kThemePopupButtonMini: - ret.adjust(8, 3, -19, 0); - ret.setHeight(13); - break; + QRectF ret = outterBounds; + if (cw.type == ComboBox) { + switch (cw.size) { + case QStyleHelper::SizeLarge: + ret = ret.adjusted(0, 0, -28, 0).translated(3, 4.5); + ret.setHeight(16); + break; + case QStyleHelper::SizeSmall: + ret = ret.adjusted(0, 0, -24, 0).translated(3, 2); + ret.setHeight(14); + break; + case QStyleHelper::SizeMini: + ret = ret.adjusted(0, 0, -21, 0).translated(2, 3); + ret.setHeight(11); + break; + default: + break; + } + } else if (cw.type == Button_PopupButton) { + switch (cw.size) { + case QStyleHelper::SizeLarge: + ret.adjust(14, 1, -23, -4); + break; + case QStyleHelper::SizeSmall: + ret.adjust(13, 4, -20, -3); + break; + case QStyleHelper::SizeMini: + // FIXME Wrong + ret.adjust(16, 5, -19, 0); + ret.setHeight(13); + break; + default: + break; + } } return ret; } -/** - Carbon comboboxes don't scale (sight). If the size of the combo suggest a scaled version, - create it manually by drawing a small Carbon combo onto a pixmap (use pixmap cache), chop - it up, and copy it back onto the widget. Othervise, draw the combobox supplied by Carbon directly. -*/ -void QMacStylePrivate::drawCombobox(const CGRect &outerBounds, const HIThemeButtonDrawInfo &bdi, const CocoaControl &cw, QPainter *p) -{ - if (!(bdi.kind == kThemeComboBox && outerBounds.size.height > 28)){ - // We have an unscaled combobox, or popup-button; use Carbon directly. - const CGRect innerBounds = QMacStylePrivate::comboboxInnerBounds(outerBounds, cw); - HIThemeDrawButton(&innerBounds, &bdi, QMacCGContext(p), kHIThemeOrientationNormal, 0); - } else { - QPixmap buffer; - QString key = QString(QLatin1String("$qt_cbox%1-%2")).arg(int(bdi.state)).arg(int(bdi.adornment)); - if (!QPixmapCache::find(key, buffer)) { - CGRect innerBoundsSmallCombo = {{3, 3}, {29, 25}}; - buffer = QPixmap(35, 28); - buffer.fill(Qt::transparent); - QPainter buffPainter(&buffer); - HIThemeDrawButton(&innerBoundsSmallCombo, &bdi, QMacCGContext(&buffPainter), kHIThemeOrientationNormal, 0); - buffPainter.end(); - QPixmapCache::insert(key, buffer); - } - - const int bwidth = 20; - const int fwidth = 10; - const int fheight = 10; - int w = qRound(outerBounds.size.width); - int h = qRound(outerBounds.size.height); - int bstart = w - bwidth; - int blower = fheight + 1; - int flower = h - fheight; - int sheight = flower - fheight; - int center = qRound(outerBounds.size.height + outerBounds.origin.y) / 2; - - // Draw upper and lower gap - p->drawPixmap(fwidth, 0, bstart - fwidth, fheight, buffer, fwidth, 0, 1, fheight); - p->drawPixmap(fwidth, flower, bstart - fwidth, fheight, buffer, fwidth, buffer.height() - fheight, 1, fheight); - // Draw left and right gap. Right gap is drawn top and bottom separatly - p->drawPixmap(0, fheight, fwidth, sheight, buffer, 0, fheight, fwidth, 1); - p->drawPixmap(bstart, fheight, bwidth, center - fheight, buffer, buffer.width() - bwidth, fheight - 1, bwidth, 1); - p->drawPixmap(bstart, center, bwidth, sheight / 2, buffer, buffer.width() - bwidth, fheight + 6, bwidth, 1); - // Draw arrow - p->drawPixmap(bstart, center - 4, bwidth - 3, 6, buffer, buffer.width() - bwidth, fheight, bwidth - 3, 6); - // Draw corners - p->drawPixmap(0, 0, fwidth, fheight, buffer, 0, 0, fwidth, fheight); - p->drawPixmap(bstart, 0, bwidth, fheight, buffer, buffer.width() - bwidth, 0, bwidth, fheight); - p->drawPixmap(0, flower, fwidth, fheight, buffer, 0, buffer.height() - fheight, fwidth, fheight); - p->drawPixmap(bstart, h - blower, bwidth, blower, buffer, buffer.width() - bwidth, buffer.height() - blower, bwidth, blower); - } -} - QMacStylePrivate::QMacStylePrivate() : backingStoreNSView(nil) { @@ -1897,6 +1775,7 @@ QMacStylePrivate::~QMacStylePrivate() [cell release]; } +#if 0 ThemeDrawState QMacStylePrivate::getDrawState(QStyle::State flags) { ThemeDrawState tds = kThemeStateActive; @@ -1913,62 +1792,7 @@ ThemeDrawState QMacStylePrivate::getDrawState(QStyle::State flags) } return tds; } - - QMacStylePrivate::CocoaControl QMacStylePrivate::cocoaControlFromHIThemeButtonKind(ThemeButtonKind kind) -{ - CocoaControl w; - - switch (kind) { - case kThemePopupButton: - case kThemePopupButtonSmall: - case kThemePopupButtonMini: - w.type = Button_PopupButton; - break; - case kThemeComboBox: - w.type = ComboBox; - break; - case kThemeArrowButton: - w.type = Button_Disclosure; - break; - case kThemeCheckBox: - case kThemeCheckBoxSmall: - case kThemeCheckBoxMini: - w.type = Button_CheckBox; - break; - case kThemeRadioButton: - case kThemeRadioButtonSmall: - case kThemeRadioButtonMini: - w.type = Button_RadioButton; - break; - case kThemePushButton: - case kThemePushButtonSmall: - case kThemePushButtonMini: - w.type = Button_PushButton; - break; - default: - break; - } - - switch (kind) { - case kThemePushButtonSmall: - case kThemePopupButtonSmall: - case kThemeCheckBoxSmall: - case kThemeRadioButtonSmall: - w.size = QStyleHelper::SizeSmall; - break; - case kThemePushButtonMini: - case kThemePopupButtonMini: - case kThemeCheckBoxMini: - case kThemeRadioButtonMini: - w.size = QStyleHelper::SizeMini; - break; - default: - w.size = QStyleHelper::SizeLarge; - break; - } - - return w; -} +#endif NSView *QMacStylePrivate::cocoaControl(CocoaControl widget) const { @@ -2156,19 +1980,11 @@ NSCell *QMacStylePrivate::cocoaCell(CocoaControl widget) const void QMacStylePrivate::drawNSViewInRect(CocoaControl widget, NSView *view, const QRectF &qtRect, QPainter *p, bool isQWidget, __attribute__((noescape)) DrawRectBlock drawRectBlock) const { Q_UNUSED(isQWidget); - QPoint offset; - if (widget == CocoaControl(Button_PopupButton, QStyleHelper::SizeSmall)) - offset.setY(1); - else if (widget == CocoaControl(Button_PopupButton, QStyleHelper::SizeMini)) - offset = QPoint(2, -1); - else if (widget == CocoaControl(ComboBox, QStyleHelper::SizeLarge)) - offset = QPoint(3, 0); + Q_UNUSED(widget); QMacCGContext ctx(p); setupNSGraphicsContext(ctx, YES); - CGContextTranslateCTM(ctx, offset.x(), offset.y()); - const CGRect rect = CGRectMake(qtRect.x(), qtRect.y(), qtRect.width(), qtRect.height()); [backingStoreNSView addSubview:view]; @@ -2187,148 +2003,6 @@ void QMacStylePrivate::resolveCurrentNSView(QWindow *window) const backingStoreNSView = window ? (NSView *)window->winId() : nil; } -void QMacStylePrivate::drawColorlessButton(const CGRect &macRect, HIThemeButtonDrawInfo *bdi, const CocoaControl &cw, - QPainter *p, const QStyleOption *opt) const -{ - int xoff = 0, - yoff = 0, - extraWidth = 0, - extraHeight = 0, - finalyoff = 0; - - const bool combo = opt->type == QStyleOption::SO_ComboBox; - const bool editableCombo = bdi->kind == kThemeComboBox - || bdi->kind == kThemeComboBoxSmall - || bdi->kind == kThemeComboBoxMini; - const bool button = opt->type == QStyleOption::SO_Button; - const bool viewItem = opt->type == QStyleOption::SO_ViewItem; - const bool pressed = bdi->state == kThemeStatePressed; - - if (button && pressed) { - if (bdi->kind == kThemePushButton) { - extraHeight = 2; - } else if (bdi->kind == kThemePushButtonSmall) { - xoff = 1; - extraWidth = 2; - extraHeight = 5; - } - } - - int devicePixelRatio = p->device()->devicePixelRatioF(); - int width = devicePixelRatio * (int(macRect.size.width) + extraWidth); - int height = devicePixelRatio * (int(macRect.size.height) + extraHeight); - - if (width <= 0 || height <= 0) - return; // nothing to draw - - QString key = QLatin1String("$qt_mac_style_ctb_") + QString::number(bdi->kind) + QLatin1Char('_') - + QString::number(bdi->value) + QLatin1Char('_') - + (button ? QString::number(bdi->state) + QLatin1Char('_') : QString()) - + QLatin1Char('_') + QString::number(width) + QLatin1Char('_') + QString::number(height); - QPixmap pm; - if (!QPixmapCache::find(key, pm)) { - QPixmap activePixmap(width, height); - activePixmap.setDevicePixelRatio(devicePixelRatio); - activePixmap.fill(Qt::transparent); - { - if (combo){ - // Carbon combos don't scale. Therefore we draw it - // ourselves, if a scaled version is needed. - QPainter tmpPainter(&activePixmap); - QMacStylePrivate::drawCombobox(macRect, *bdi, cw, &tmpPainter); - } else { - QMacCGContext cg(&activePixmap); - CGRect newRect = CGRectMake(xoff, yoff, macRect.size.width, macRect.size.height); - if (button && pressed) - bdi->state = kThemeStateActive; - else if (viewItem) - bdi->state = kThemeStateInactive; - HIThemeDrawButton(&newRect, bdi, cg, kHIThemeOrientationNormal, 0); - } - } - - if (!combo && !button && bdi->value == kThemeButtonOff) { - pm = activePixmap; - } else if ((combo && !editableCombo) || button) { - CocoaControl cw = cocoaControlFromHIThemeButtonKind(bdi->kind); - NSButton *bc = (NSButton *)cocoaControl(cw); - [bc highlight:pressed]; - bc.enabled = bdi->state != kThemeStateUnavailable && bdi->state != kThemeStateUnavailableInactive; - bc.allowsMixedState = YES; - bc.state = bdi->value == kThemeButtonOn ? NSOnState : - bdi->value == kThemeButtonMixed ? NSMixedState : NSOffState; - // The view frame may differ from what we pass to HITheme - QRect rect = opt->rect; - if (bdi->kind == kThemePopupButtonMini) - rect.adjust(0, 0, -5, 0); - drawNSViewInRect(cw, bc, rect, p); - return; - } else if (editableCombo || viewItem) { - QImage image = activePixmap.toImage(); - - for (int y = 0; y < height; ++y) { - QRgb *scanLine = reinterpret_cast(image.scanLine(y)); - - for (int x = 0; x < width; ++x) { - QRgb &pixel = scanLine[x]; - int gray = qRed(pixel); // We know the image is grayscale - int alpha = qAlpha(pixel); - - if (gray == 128 && alpha == 128) { - pixel = qRgba(255, 255, 255, 255); - } else if (alpha == 0) { - pixel = 0; - } else { - bool belowThreshold = (alpha * gray) / 255 + 255 - alpha < 128; - gray = belowThreshold ? 0 : 2 * gray - 255; - alpha = belowThreshold ? 0 : 2 * alpha - 255; - pixel = qRgba(gray, gray, gray, alpha); - } - } - } - pm = QPixmap::fromImage(image); - } else { - QImage activeImage = activePixmap.toImage(); - QImage colorlessImage; - { - QPixmap colorlessPixmap(width, height); - colorlessPixmap.setDevicePixelRatio(devicePixelRatio); - colorlessPixmap.fill(Qt::transparent); - - QMacCGContext cg(&colorlessPixmap); - CGRect newRect = CGRectMake(xoff, yoff, macRect.size.width, macRect.size.height); - int oldValue = bdi->value; - bdi->value = kThemeButtonOff; - HIThemeDrawButton(&newRect, bdi, cg, kHIThemeOrientationNormal, 0); - bdi->value = oldValue; - colorlessImage = colorlessPixmap.toImage(); - } - - for (int y = 0; y < height; ++y) { - QRgb *colorlessScanLine = reinterpret_cast(colorlessImage.scanLine(y)); - const QRgb *activeScanLine = reinterpret_cast(activeImage.scanLine(y)); - - for (int x = 0; x < width; ++x) { - QRgb &colorlessPixel = colorlessScanLine[x]; - QRgb activePixel = activeScanLine[x]; - - if (activePixel != colorlessPixel) { - int max = qMax(qMax(qRed(activePixel), qGreen(activePixel)), - qBlue(activePixel)); - QRgb newPixel = qRgba(max, max, max, qAlpha(activePixel)); - if (qGray(newPixel) < qGray(colorlessPixel) - || qAlpha(newPixel) > qAlpha(colorlessPixel)) - colorlessPixel = newPixel; - } - } - } - pm = QPixmap::fromImage(colorlessImage); - } - QPixmapCache::insert(key, pm); - } - p->drawPixmap(int(macRect.origin.x) - xoff, int(macRect.origin.y) + finalyoff, width / devicePixelRatio, height / devicePixelRatio , pm); -} - QMacStyle::QMacStyle() : QCommonStyle(*new QMacStylePrivate) { @@ -3218,7 +2892,6 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai const QWidget *w) const { Q_D(const QMacStyle); - ThemeDrawState tds = d->getDrawState(opt->state); QMacCGContext cg(p); QWindow *window = w && w->window() ? w->window()->windowHandle() : QStyleHelper::styleObjectWindow(opt->styleObject); @@ -3287,17 +2960,17 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai QStyleOptionTabWidgetFrame twf; twf.QStyleOption::operator=(*tbb); twf.shape = tbb->shape; - switch (getTabDirection(twf.shape)) { - case kThemeTabNorth: + switch (QMacStylePrivate::tabDirection(twf.shape)) { + case QMacStylePrivate::North: twf.rect = twf.rect.adjusted(0, 0, 0, 10); break; - case kThemeTabSouth: + case QMacStylePrivate::South: twf.rect = twf.rect.adjusted(0, -10, 0, 0); break; - case kThemeTabWest: + case QMacStylePrivate::West: twf.rect = twf.rect.adjusted(0, 0, 10, 0); break; - case kThemeTabEast: + case QMacStylePrivate::East: twf.rect = twf.rect.adjusted(0, -10, 0, 0); break; } @@ -3310,20 +2983,25 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai p->fillRect(opt->rect, opt->palette.brush(QPalette::ToolTipBase)); break; case PE_FrameGroupBox: - if (const QStyleOptionFrame *groupBox = qstyleoption_cast(opt)) { + if (const auto *groupBox = qstyleoption_cast(opt)) if (groupBox->features & QStyleOptionFrame::Flat) { QCommonStyle::drawPrimitive(pe, groupBox, p, w); - } else { - const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::Box, QStyleHelper::SizeDefault); - auto *box = static_cast(d->cocoaControl(cw)); - d->drawNSViewInRect(cw, box, groupBox->rect, p, w != nullptr, ^(CGContextRef ctx, const CGRect &rect) { - CGContextTranslateCTM(ctx, 0, rect.origin.y + rect.size.height); - CGContextScaleCTM(ctx, 1, -1); - [box drawRect:rect]; - }); + break; } - } +#if QT_CONFIG(tabwidget) + Q_FALLTHROUGH(); + case PE_FrameTabWidget: +#endif + { + const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::Box, QStyleHelper::SizeDefault); + auto *box = static_cast(d->cocoaControl(cw)); + d->drawNSViewInRect(cw, box, opt->rect, p, w != nullptr, ^(CGContextRef ctx, const CGRect &rect) { + CGContextTranslateCTM(ctx, 0, rect.origin.y + rect.size.height); + CGContextScaleCTM(ctx, 1, -1); + [box drawRect:rect]; + }); break; + } case PE_IndicatorToolBarSeparator: { QPainterPath path; if (opt->state & State_Horizontal) { @@ -3556,22 +3234,6 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai } break; -#if QT_CONFIG(tabwidget) - case PE_FrameTabWidget: - if (const QStyleOptionTabWidgetFrame *twf - = qstyleoption_cast(opt)) { - CGRect cgRect = twf->rect.toCGRect(); - HIThemeTabPaneDrawInfo tpdi; - tpdi.version = qt_mac_hitheme_tab_version(); - tpdi.state = tds; - tpdi.direction = getTabDirection(twf->shape); - tpdi.size = kHIThemeTabSizeNormal; - tpdi.kind = kHIThemeTabKindNormal; - tpdi.adornment = kHIThemeTabPaneAdornmentNormal; - HIThemeDrawTabPane(&cgRect, &tpdi, cg, kHIThemeOrientationNormal); - } - break; -#endif case PE_PanelScrollAreaCorner: { const QBrush brush(opt->palette.brush(QPalette::Base)); p->fillRect(opt->rect, brush); @@ -3883,6 +3545,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter d->drawNSViewInRect(cw, pb, frameRect, p, true, ^(CGContextRef __unused ctx, const CGRect &r) { [pb.cell drawBezelWithFrame:r inView:pb.superview]; }); + [pb highlight:NO]; if (hasMenu && cw.type == QMacStylePrivate::Button_SquareButton) { // Using -[NSPopuButtonCell drawWithFrame:inView:] above won't do @@ -3911,17 +3574,17 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter // TODO Remove and use QFocusFrame instead. const int hMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin, btn, w); const int vMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin, btn, w); + QRectF focusRect; if (cw.type == QMacStylePrivate::Button_SquareButton) { - const auto focusRect = frameRect.adjusted(-focusRingWidth, -focusRingWidth, focusRingWidth, focusRingWidth); - d->drawFocusRing(p, focusRect.toAlignedRect(), hMargin, vMargin, 0); + focusRect = frameRect; } else { - auto focusRect = QRectF::fromCGRect([pb alignmentRectForFrame:pb.frame]); + focusRect = QRectF::fromCGRect([pb alignmentRectForFrame:pb.frame]); if (cw.type == QMacStylePrivate::Button_PushButton) focusRect -= pushButtonShadowMargins[cw.size]; else if (cw.type == QMacStylePrivate::Button_PullDown) focusRect -= pullDownButtonShadowMargins[cw.size]; - d->drawFocusRing(p, focusRect, hMargin, vMargin, cw); } + d->drawFocusRing(p, focusRect, hMargin, vMargin, cw); } } break; @@ -3993,16 +3656,19 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter } } break; +#if QT_CONFIG(combobox) case CE_ComboBoxLabel: - if (const QStyleOptionComboBox *cb = qstyleoption_cast(opt)) { - QStyleOptionComboBox comboCopy = *cb; + if (const auto *cb = qstyleoption_cast(opt)) { + auto comboCopy = *cb; comboCopy.direction = Qt::LeftToRight; + // The rectangle will be adjusted to SC_ComboBoxEditField with comboboxEditBounds() QCommonStyle::drawControl(CE_ComboBoxLabel, &comboCopy, p, w); } break; +#endif // #if QT_CONFIG(combobox) #if QT_CONFIG(tabbar) case CE_TabBarTabShape: - if (const QStyleOptionTab *tabOpt = qstyleoption_cast(opt)) { + if (const auto *tabOpt = qstyleoption_cast(opt)) { if (tabOpt->documentMode) { p->save(); bool isUnified = false; @@ -4019,111 +3685,157 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter return; } - HIThemeTabDrawInfo tdi; - tdi.version = 1; - tdi.style = kThemeTabNonFront; - tdi.direction = getTabDirection(tabOpt->shape); - switch (d->aquaSizeConstrain(opt, w)) { - case QStyleHelper::SizeDefault: - case QStyleHelper::SizeLarge: - tdi.size = kHIThemeTabSizeNormal; - break; - case QStyleHelper::SizeSmall: - tdi.size = kHIThemeTabSizeSmall; - break; - case QStyleHelper::SizeMini: - tdi.size = kHIThemeTabSizeMini; - break; - } - bool verticalTabs = tdi.direction == kThemeTabWest || tdi.direction == kThemeTabEast; - QRect tabRect = tabOpt->rect; - - bool selected = tabOpt->state & State_Selected; - if (selected) { - if (!(tabOpt->state & State_Active)) - tdi.style = kThemeTabFrontUnavailable; - else if (!(tabOpt->state & State_Enabled)) - tdi.style = kThemeTabFrontInactive; - else - tdi.style = kThemeTabFront; - } else if (!(tabOpt->state & State_Active)) { - tdi.style = kThemeTabNonFrontUnavailable; - } else if (!(tabOpt->state & State_Enabled)) { - tdi.style = kThemeTabNonFrontInactive; - } else if (tabOpt->state & State_Sunken) { - tdi.style = kThemeTabNonFrontPressed; - } - if (tabOpt->state & State_HasFocus) - tdi.adornment = kHIThemeTabAdornmentFocus; - else - tdi.adornment = kHIThemeTabAdornmentNone; - tdi.kind = kHIThemeTabKindNormal; + const bool isEnabled = tabOpt->state & State_Enabled; + const bool isPressed = tabOpt->state & State_Sunken; + const bool isSelected = tabOpt->state & State_Selected; + const auto tabDirection = QMacStylePrivate::tabDirection(tabOpt->shape); + const bool verticalTabs = tabDirection == QMacStylePrivate::East + || tabDirection == QMacStylePrivate::West; QStyleOptionTab::TabPosition tp = tabOpt->position; QStyleOptionTab::SelectedPosition sp = tabOpt->selectedPosition; if (tabOpt->direction == Qt::RightToLeft && !verticalTabs) { + if (tp == QStyleOptionTab::Beginning) + tp = QStyleOptionTab::End; + else if (tp == QStyleOptionTab::End) + tp = QStyleOptionTab::Beginning; + if (sp == QStyleOptionTab::NextIsSelected) sp = QStyleOptionTab::PreviousIsSelected; else if (sp == QStyleOptionTab::PreviousIsSelected) sp = QStyleOptionTab::NextIsSelected; - switch (tp) { - case QStyleOptionTab::Beginning: - tp = QStyleOptionTab::End; - break; - case QStyleOptionTab::End: - tp = QStyleOptionTab::Beginning; - break; - default: - break; - } } - bool stretchTabs = (!verticalTabs && tabRect.height() > 22) || (verticalTabs && tabRect.width() > 22); + // Alas, NSSegmentedControl and NSSegmentedCell are letting us down. + // We're not able to draw it at will, either calling -[drawSegment: + // inFrame:withView:], -[drawRect:] or anything in between. Besides, + // there's no public API do draw the pressed state, AFAICS. We'll use + // a push NSButton instead and clip the CGContext. + + const auto cs = d->effectiveAquaSizeConstrain(opt, w); + // Extra hack to get the proper pressed appreance when not selected + const auto ct = isSelected || tp == QStyleOptionTab::OnlyOneTab ? + QMacStylePrivate::Button_PushButton : + QMacStylePrivate::Button_PopupButton; + const auto cw = QMacStylePrivate::CocoaControl(ct, cs); + auto *pb = static_cast(d->cocoaControl(cw)); + auto vOffset = isSelected ? 2 : 1; + if (tabDirection == QMacStylePrivate::East) + vOffset -= 1; + const auto outterAdjust = isSelected ? 4 : 1; + const auto innerAdjust = isSelected ? 10 : 20; + QRectF frameRect = tabOpt->rect; + if (verticalTabs) + frameRect = QRectF(frameRect.y(), frameRect.x(), frameRect.height(), frameRect.width()); + // Adjust before clipping + frameRect = frameRect.translated(0, vOffset); switch (tp) { case QStyleOptionTab::Beginning: - tdi.position = kHIThemeTabPositionFirst; - if (sp != QStyleOptionTab::NextIsSelected || stretchTabs) - tdi.adornment |= kHIThemeTabAdornmentTrailingSeparator; + // Pressed state hack: tweak adjustments in preparation for flip below + if (!isSelected && tabDirection == QMacStylePrivate::West) + frameRect = frameRect.adjusted(-innerAdjust, 0, outterAdjust, 0); + else + frameRect = frameRect.adjusted(-outterAdjust, 0, innerAdjust, 0); break; case QStyleOptionTab::Middle: - tdi.position = kHIThemeTabPositionMiddle; - if (selected) - tdi.adornment |= kHIThemeTabAdornmentLeadingSeparator; - if (sp != QStyleOptionTab::NextIsSelected || stretchTabs) // Also when we're selected. - tdi.adornment |= kHIThemeTabAdornmentTrailingSeparator; + frameRect = frameRect.adjusted(-innerAdjust, 0, innerAdjust, 0); break; case QStyleOptionTab::End: - tdi.position = kHIThemeTabPositionLast; - if (selected) - tdi.adornment |= kHIThemeTabAdornmentLeadingSeparator; + // Pressed state hack: tweak adjustments in preparation for flip below + if (isSelected || tabDirection == QMacStylePrivate::West) + frameRect = frameRect.adjusted(-innerAdjust, 0, outterAdjust, 0); + else + frameRect = frameRect.adjusted(-outterAdjust, 0, innerAdjust, 0); break; case QStyleOptionTab::OnlyOneTab: - tdi.position = kHIThemeTabPositionOnly; + frameRect = frameRect.adjusted(-outterAdjust, 0, outterAdjust, 0); break; } - // HITheme doesn't stretch its tabs. Therefore we have to cheat and do the job ourselves. - if (stretchTabs) { - CGRect cgRect = CGRectMake(0, 0, 23, 23); - QPixmap pm(23, 23); - pm.fill(Qt::transparent); - { - QMacCGContext pmcg(&pm); - HIThemeDrawTab(&cgRect, &tdi, pmcg, kHIThemeOrientationNormal, 0); + pb.frame = frameRect.toCGRect(); + + pb.enabled = isEnabled; + [pb highlight:isPressed]; + pb.state = isSelected && !isPressed ? NSOnState : NSOffState; + d->drawNSViewInRect(cw, pb, frameRect, p, true, ^(CGContextRef ctx, const CGRect &r) { + CGContextClipToRect(ctx, opt->rect.toCGRect()); + if (!isSelected) { + // Final stage of the pressed state hack: flip NSPopupButton rendering + if (!verticalTabs && tp == QStyleOptionTab::End) { + CGContextTranslateCTM(ctx, opt->rect.right(), 0); + CGContextScaleCTM(ctx, -1, 1); + CGContextTranslateCTM(ctx, -frameRect.left(), 0); + } else if (tabDirection == QMacStylePrivate::West && tp == QStyleOptionTab::Beginning) { + CGContextScaleCTM(ctx, 1, -1); + CGContextTranslateCTM(ctx, 0, -frameRect.right()); + } else if (tabDirection == QMacStylePrivate::East && tp == QStyleOptionTab::End) { + CGContextTranslateCTM(ctx, 0, opt->rect.bottom()); + CGContextScaleCTM(ctx, 1, -1); + CGContextTranslateCTM(ctx, 0, -frameRect.left()); + } + } + + // Rotate and translate CTM when vertical + // On macOS: positive angle is CW, negative is CCW + if (tabDirection == QMacStylePrivate::West) { + CGContextTranslateCTM(ctx, 0, frameRect.right()); + CGContextRotateCTM(ctx, -M_PI_2); + CGContextTranslateCTM(ctx, -frameRect.left(), 0); + } else if (tabDirection == QMacStylePrivate::East) { + CGContextTranslateCTM(ctx, opt->rect.right(), 0); + CGContextRotateCTM(ctx, M_PI_2); + } + + [pb.cell drawBezelWithFrame:r inView:pb.superview]; + }); + + if (!isSelected && sp != QStyleOptionTab::NextIsSelected + && tp != QStyleOptionTab::End + && tp != QStyleOptionTab::OnlyOneTab) { + static const QPen separatorPen(Qt::black, 1.0); + p->save(); + p->setOpacity(isEnabled ? 0.105 : 0.06); // As measured + p->setPen(separatorPen); + if (tabDirection == QMacStylePrivate::West) { + p->drawLine(QLineF(opt->rect.left() + 1.5, opt->rect.bottom(), + opt->rect.right() - 0.5, opt->rect.bottom())); + } else if (tabDirection == QMacStylePrivate::East) { + p->drawLine(QLineF(opt->rect.left(), opt->rect.bottom(), + opt->rect.right() - 0.5, opt->rect.bottom())); + } else { + p->drawLine(QLineF(opt->rect.right(), opt->rect.top() + 1.0, + opt->rect.right(), opt->rect.bottom() - 0.5)); + } + p->restore(); + } + + // TODO Needs size adjustment to fit the focus ring + if (tabOpt->state & State_HasFocus) { + QMacStylePrivate::CocoaControlType focusRingType; + switch (tp) { + case QStyleOptionTab::Beginning: + focusRingType = verticalTabs ? QMacStylePrivate::SegmentedControl_Last + : QMacStylePrivate::SegmentedControl_First; + break; + case QStyleOptionTab::Middle: + focusRingType = QMacStylePrivate::SegmentedControl_Middle; + break; + case QStyleOptionTab::End: + focusRingType = verticalTabs ? QMacStylePrivate::SegmentedControl_First + : QMacStylePrivate::SegmentedControl_Last; + break; + case QStyleOptionTab::OnlyOneTab: + focusRingType = QMacStylePrivate::SegmentedControl_Single; + break; } - QStyleHelper::drawBorderPixmap(pm, p, tabRect, 7, 7, 7, 7); - } else { - CGRect cgRect = tabRect.toCGRect(); - HIThemeDrawTab(&cgRect, &tdi, cg, kHIThemeOrientationNormal, 0); } } break; case CE_TabBarTabLabel: - if (const QStyleOptionTab *tab = qstyleoption_cast(opt)) { + if (const auto *tab = qstyleoption_cast(opt)) { QStyleOptionTab myTab = *tab; - const bool verticalTabs = tab->shape == QTabBar::RoundedWest - || tab->shape == QTabBar::RoundedEast - || tab->shape == QTabBar::TriangularWest - || tab->shape == QTabBar::TriangularEast; + const auto tabDirection = QMacStylePrivate::tabDirection(tab->shape); + const bool verticalTabs = tabDirection == QMacStylePrivate::East + || tabDirection == QMacStylePrivate::West; // Check to see if we use have the same as the system font // (QComboMenuItem is internal and should never be seen by the @@ -4198,20 +3910,19 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter return QMacStylePrivate::Button_CheckBox; if (ffw->inherits("QRadioButton")) return QMacStylePrivate::Button_RadioButton; + if (ffw->inherits("QLineEdit") || ffw->inherits("QTextEdit")) + return QMacStylePrivate::TextField; } return QMacStylePrivate::Box; // Not really, just make it the default } (); + const auto cs = ffw ? (ffw->testAttribute(Qt::WA_MacMiniSize) ? QStyleHelper::SizeMini : + ffw->testAttribute(Qt::WA_MacSmallSize) ? QStyleHelper::SizeSmall : + QStyleHelper::SizeLarge) : + QStyleHelper::SizeLarge; const int hMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin, opt, w); const int vMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin, opt, w); - if (ct == QMacStylePrivate::Box) { - d->drawFocusRing(p, opt->rect, hMargin, vMargin); - } else if (ffw) { - const auto cs = ffw->testAttribute(Qt::WA_MacMiniSize) ? QStyleHelper::SizeMini : - ffw->testAttribute(Qt::WA_MacSmallSize) ? QStyleHelper::SizeSmall : - QStyleHelper::SizeLarge; - d->drawFocusRing(p, opt->rect, hMargin, vMargin, QMacStylePrivate::CocoaControl(ct, cs)); - } + d->drawFocusRing(p, opt->rect, hMargin, vMargin, QMacStylePrivate::CocoaControl(ct, cs)); break; } case CE_MenuEmptyArea: // Skip: PE_PanelMenu fills in everything @@ -4732,23 +4443,9 @@ QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt, rect = opt->rect; break; case SE_TreeViewDisclosureItem: { - CGRect inRect = CGRectMake(opt->rect.x(), opt->rect.y(), - opt->rect.width(), opt->rect.height()); - HIThemeButtonDrawInfo bdi; - bdi.version = qt_mac_hitheme_version; - bdi.state = kThemeStateActive; - bdi.kind = kThemeDisclosureButton; - bdi.value = kThemeDisclosureRight; - bdi.adornment = kThemeAdornmentNone; - CGRect contentRect; - HIThemeGetButtonContentBounds(&inRect, &bdi, &contentRect); - QCFType shape; - CGRect outRect; - HIThemeGetButtonShape(&inRect, &bdi, &shape); - HIShapeGetBounds(shape, &outRect); - rect = QRect(int(outRect.origin.x + DisclosureOffset), int(outRect.origin.y), - int(contentRect.origin.x - outRect.origin.x + DisclosureOffset), - int(outRect.size.height)); + rect = opt->rect; + // As previously returned by HIThemeGetButtonContentBounds + rect.setLeft(rect.left() + 2 + DisclosureOffset); break; } #if QT_CONFIG(tabwidget) @@ -4794,20 +4491,19 @@ QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt, break; case SE_TabWidgetTabContents: rect = QCommonStyle::subElementRect(sr, opt, widget); - if (const QStyleOptionTabWidgetFrame *twf - = qstyleoption_cast(opt)) { + if (const auto *twf = qstyleoption_cast(opt)) { if (twf->lineWidth != 0) { - switch (getTabDirection(twf->shape)) { - case kThemeTabNorth: + switch (QMacStylePrivate::tabDirection(twf->shape)) { + case QMacStylePrivate::North: rect.adjust(+1, +14, -1, -1); break; - case kThemeTabSouth: + case QMacStylePrivate::South: rect.adjust(+1, +1, -1, -14); break; - case kThemeTabWest: + case QMacStylePrivate::West: rect.adjust(+14, +1, -1, -1); break; - case kThemeTabEast: + case QMacStylePrivate::East: rect.adjust(+1, +1, -14, -1); } } @@ -5177,7 +4873,6 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex const QWidget *widget) const { Q_D(const QMacStyle); - ThemeDrawState tds = d->getDrawState(opt->state); QMacCGContext cg(p); QWindow *window = widget && widget->window() ? widget->window()->windowHandle() : QStyleHelper::styleObjectWindow(opt->styleObject); @@ -5531,25 +5226,69 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex } break; #endif +#if QT_CONFIG(combobox) case CC_ComboBox: - if (const QStyleOptionComboBox *combo = qstyleoption_cast(opt)){ - HIThemeButtonDrawInfo bdi; - QMacStylePrivate::CocoaControl cw; - d->initComboboxBdi(combo, &bdi, &cw, widget, tds); - CGRect rect = combo->rect.toCGRect(); - if (combo->editable) - rect.origin.y += tds == kThemeStateInactive ? 1 : 2; - if (tds != kThemeStateInactive) - QMacStylePrivate::drawCombobox(rect, bdi, cw, p); - else if (!widget && combo->editable) { - const auto cw = QMacStylePrivate::cocoaControlFromHIThemeButtonKind(bdi.kind); - NSView *cb = d->cocoaControl(cw); - QRect r = combo->rect.adjusted(3, 0, 0, 0); - d->drawNSViewInRect(cw, cb, r, p, widget != 0); - } else - d->drawColorlessButton(rect, &bdi, cw, p, opt); + if (const auto *combo = qstyleoption_cast(opt)) { + const bool isEnabled = combo->state & State_Enabled; + const bool isPressed = combo->state & State_Sunken; + + const auto ct = cocoaControlType(combo, widget); + const auto cs = d->effectiveAquaSizeConstrain(combo, widget); + const auto cw = QMacStylePrivate::CocoaControl(ct, cs); + auto *cc = static_cast(d->cocoaControl(cw)); + cc.enabled = isEnabled; + QRectF frameRect = cw.adjustedControlFrame(combo->rect);; + if (cw.type == QMacStylePrivate::Button_PopupButton) { + // Non-editable QComboBox + auto *pb = static_cast(cc); + // FIXME Old offsets. Try to move to adjustedControlFrame() + if (cw.size == QStyleHelper::SizeSmall) { + frameRect = frameRect.translated(0, 1); + } else if (cw.size == QStyleHelper::SizeMini) { + // Same 0.5 pt misalignment as AppKit and fit the focus ring + frameRect = frameRect.translated(2, -0.5); + } + pb.frame = frameRect.toCGRect(); + [pb highlight:isPressed]; + d->drawNSViewInRect(cw, pb, frameRect, p, widget != 0, ^(CGContextRef __unused ctx, const CGRect &r) { + [pb.cell drawBezelWithFrame:r inView:pb.superview]; + }); + } else if (cw.type == QMacStylePrivate::ComboBox) { + // Editable QComboBox + auto *cb = static_cast(cc); + const auto frameRect = cw.adjustedControlFrame(combo->rect); + cb.frame = frameRect.toCGRect(); +#if !QT_CONFIG(appstore_compliant) + static_cast(cc.cell).qt_buttonCell.highlighted = isPressed; +#else + // TODO Render to pixmap and darken the button manually +#endif + d->drawNSViewInRect(cw, cb, frameRect, p, widget != 0, ^(CGContextRef __unused ctx, const CGRect &r) { + // FIXME This is usually drawn in the control's superview, but we wouldn't get inactive look in this case + [cb.cell drawWithFrame:r inView:cb]; + }); + } + + if (combo->state & State_HasFocus) { + // TODO Remove and use QFocusFrame instead. + const int hMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin, combo, widget); + const int vMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin, combo, widget); + QRectF focusRect; + if (cw.type == QMacStylePrivate::Button_PopupButton) { + focusRect = QRectF::fromCGRect([cc alignmentRectForFrame:cc.frame]); + focusRect -= pullDownButtonShadowMargins[cw.size]; + if (cw.size == QStyleHelper::SizeSmall) + focusRect = focusRect.translated(0, 1); + else if (cw.size == QStyleHelper::SizeMini) + focusRect = focusRect.translated(2, -1); + } else if (cw.type == QMacStylePrivate::ComboBox) { + focusRect = frameRect - comboBoxFocusRingMargins[cw.size]; + } + d->drawFocusRing(p, focusRect, hMargin, vMargin, cw); + } } break; +#endif // QT_CONFIG(combobox) case CC_TitleBar: if (const auto *titlebar = qstyleoption_cast(opt)) { const bool isActive = (titlebar->state & State_Active) @@ -5968,32 +5707,29 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op break; case CC_ComboBox: if (const QStyleOptionComboBox *combo = qstyleoption_cast(opt)) { - HIThemeButtonDrawInfo bdi; - QMacStylePrivate::CocoaControl cw; - d->initComboboxBdi(combo, &bdi, &cw, widget, d->getDrawState(opt->state)); + const auto ct = cocoaControlType(combo, widget); + const auto cs = d->effectiveAquaSizeConstrain(combo, widget); + const auto cw = QMacStylePrivate::CocoaControl(ct, cs); + const auto editRect = QMacStylePrivate::comboboxEditBounds(cw.adjustedControlFrame(combo->rect), cw); switch (sc) { case SC_ComboBoxEditField:{ - ret = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi); - // 10.10 and above need a slight shift - ret.setHeight(ret.height() - 1); + ret = editRect.toAlignedRect(); break; } case SC_ComboBoxArrow:{ - ret = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi); + ret = editRect.toAlignedRect(); ret.setX(ret.x() + ret.width()); ret.setWidth(combo->rect.right() - ret.right()); break; } case SC_ComboBoxListBoxPopup:{ if (combo->editable) { const CGRect inner = QMacStylePrivate::comboboxInnerBounds(combo->rect.toCGRect(), cw); - QRect editRect = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi); const int comboTop = combo->rect.top(); ret = QRect(qRound(inner.origin.x), comboTop, qRound(inner.origin.x - combo->rect.left() + inner.size.width), editRect.bottom() - comboTop + 2); } else { - QRect editRect = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi); ret = QRect(combo->rect.x() + 4 - 11, combo->rect.y() + 1, editRect.width() + 10 + 11, @@ -6246,7 +5982,9 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, const int overlap = pixelMetric(PM_TabBarBaseOverlap, opt, widget); const int gapBetweenTabbarAndStackWidget = 2 + 14 - overlap; - if (getTabDirection(twf->shape) == kThemeTabNorth || getTabDirection(twf->shape) == kThemeTabSouth) { + const auto tabDirection = QMacStylePrivate::tabDirection(twf->shape); + if (tabDirection == QMacStylePrivate::North + || tabDirection == QMacStylePrivate::South) { extra = QSize(2, gapBetweenTabbarAndStackWidget + 1); } else { extra = QSize(gapBetweenTabbarAndStackWidget + 1, 2); @@ -6258,18 +5996,17 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, #if QT_CONFIG(tabbar) case QStyle::CT_TabBarTab: if (const QStyleOptionTab *tab = qstyleoption_cast(opt)) { - const QStyleHelper::WidgetSizePolicy AquaSize = d->aquaSizeConstrain(opt, widget); const bool differentFont = (widget && widget->testAttribute(Qt::WA_SetFont)) || !QApplication::desktopSettingsAware(); - ThemeTabDirection ttd = getTabDirection(tab->shape); - bool vertTabs = ttd == kThemeTabWest || ttd == kThemeTabEast; - if (vertTabs) + const auto tabDirection = QMacStylePrivate::tabDirection(tab->shape); + const bool verticalTabs = tabDirection == QMacStylePrivate::East + || tabDirection == QMacStylePrivate::West; + if (verticalTabs) sz = sz.transposed(); + int defaultTabHeight; - int extraHSpace = proxy()->pixelMetric(PM_TabBarTabHSpace, tab, widget); - QFontMetrics fm = opt->fontMetrics; - switch (AquaSize) { - case QStyleHelper::SizeDefault: + const auto cs = d->effectiveAquaSizeConstrain(opt, widget); + switch (cs) { case QStyleHelper::SizeLarge: if (tab->documentMode) defaultTabHeight = 24; @@ -6282,19 +6019,21 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, case QStyleHelper::SizeMini: defaultTabHeight = 16; break; + default: + break; } - bool setWidth = false; - if (differentFont || !tab->icon.isNull()) { - sz.rheight() = qMax(defaultTabHeight, sz.height()); - } else { - QSize textSize = fm.size(Qt::TextShowMnemonic, tab->text); - sz.rheight() = qMax(defaultTabHeight, textSize.height()); - sz.rwidth() = textSize.width(); - setWidth = true; - } - sz.rwidth() += extraHSpace; - if (vertTabs) + const bool widthSet = !differentFont && tab->icon.isNull(); + if (widthSet) { + const auto textSize = opt->fontMetrics.size(Qt::TextShowMnemonic, tab->text); + sz.rwidth() = textSize.width(); + sz.rheight() = qMax(defaultTabHeight, textSize.height()); + } else { + sz.rheight() = qMax(defaultTabHeight, sz.height()); + } + sz.rwidth() += proxy()->pixelMetric(PM_TabBarTabHSpace, tab, widget); + + if (verticalTabs) sz = sz.transposed(); int maxWidgetHeight = qMax(tab->leftButtonSize.height(), tab->rightButtonSize.height()); @@ -6314,11 +6053,11 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, widgetHeight += tab->rightButtonSize.height(); } - if (vertTabs) { - sz.setHeight(sz.height() + widgetHeight + padding); + if (verticalTabs) { sz.setWidth(qMax(sz.width(), maxWidgetWidth)); + sz.setHeight(sz.height() + widgetHeight + padding); } else { - if (setWidth) + if (widthSet) sz.setWidth(sz.width() + widgetWidth + padding); sz.setHeight(qMax(sz.height(), maxWidgetHeight)); } @@ -6413,13 +6152,35 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, sz.rwidth() += 10; sz.rheight() += 10; return sz; - case CT_ComboBox: { - sz.rwidth() += 50; - const QStyleOptionComboBox *cb = qstyleoption_cast(opt); - if (cb && !cb->editable) - sz.rheight() += 2; + case CT_ComboBox: + if (const auto *cb = qstyleoption_cast(opt)) { + const auto controlSize = d->effectiveAquaSizeConstrain(opt, widget); + if (!cb->editable) { + // Same as CT_PushButton, because we have to fit the focus + // ring and a non-editable combo box is a NSPopUpButton. + sz.rwidth() += QMacStylePrivate::PushButtonLeftOffset + QMacStylePrivate::PushButtonRightOffset + 12; + // All values as measured from HIThemeGetButtonBackgroundBounds() + if (controlSize != QStyleHelper::SizeMini) + sz.rwidth() += 12; // We like 12 over here. +#if 0 + // TODO Maybe support square combo boxes + if (controlSize == QStyleHelper::SizeLarge && sz.height() > 16) + sz.rheight() += popupButtonDefaultHeight[QStyleHelper::SizeLarge] - 16; + else +#endif + } else { + sz.rwidth() += 50; // FIXME Double check this + } + + // This should be enough to fit the focus ring + if (controlSize == QStyleHelper::SizeMini) + sz.setHeight(24); // FIXME Our previous HITheme-based logic returned this for CT_PushButton. + else + sz.setHeight(pushButtonDefaultHeight[controlSize]); + + return sz; + } break; - } case CT_Menu: { if (proxy() == this) { sz = csz; @@ -6472,13 +6233,15 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, // The sizes that Carbon and the guidelines gives us excludes the focus frame. // We compensate for this by adding some extra space here to make room for the frame when drawing: if (const QStyleOptionComboBox *combo = qstyleoption_cast(opt)){ - const auto widgetSize = d->aquaSizeConstrain(opt, widget); - QMacStylePrivate::CocoaControl cw; - cw.type = combo->editable ? QMacStylePrivate::ComboBox : QMacStylePrivate::Button_PopupButton; - cw.size = widgetSize; - const CGRect diffRect = QMacStylePrivate::comboboxInnerBounds(CGRectZero, cw); - sz.rwidth() -= qRound(diffRect.size.width); - sz.rheight() -= qRound(diffRect.size.height); + if (combo->editable) { + const auto widgetSize = d->aquaSizeConstrain(opt, widget); + QMacStylePrivate::CocoaControl cw; + cw.type = combo->editable ? QMacStylePrivate::ComboBox : QMacStylePrivate::Button_PopupButton; + cw.size = widgetSize; + const CGRect diffRect = QMacStylePrivate::comboboxInnerBounds(CGRectZero, cw); + sz.rwidth() -= qRound(diffRect.size.width); + sz.rheight() -= qRound(diffRect.size.height); + } } return sz; } diff --git a/src/plugins/styles/mac/qmacstyle_mac_p_p.h b/src/plugins/styles/mac/qmacstyle_mac_p_p.h index e43b16d0f1..705bb2b462 100644 --- a/src/plugins/styles/mac/qmacstyle_mac_p_p.h +++ b/src/plugins/styles/mac/qmacstyle_mac_p_p.h @@ -181,6 +181,10 @@ class QMacStylePrivate : public QCommonStylePrivate { Q_DECLARE_PUBLIC(QMacStyle) public: + enum Direction { + North, South, East, West + }; + enum CocoaControlType { NoControl, // For when there's no such a control in Cocoa Box, // QGroupBox @@ -188,7 +192,7 @@ public: Button_Disclosure, // Disclosure triangle, like in QTreeView Button_PopupButton, // Non-editable QComboBox Button_PullDown, // QPushButton with menu - Button_PushButton, + Button_PushButton, // Plain QPushButton and QTabBar buttons Button_RadioButton, Button_SquareButton, // Oversized QPushButton Button_WindowClose, @@ -199,6 +203,10 @@ public: ProgressIndicator_Indeterminate, Scroller_Horizontal, Scroller_Vertical, + SegmentedControl_First, // QTabBar buttons focus ring + SegmentedControl_Middle, + SegmentedControl_Last, + SegmentedControl_Single, Slider_Horizontal, Slider_Vertical, SplitView_Horizontal, @@ -207,7 +215,6 @@ public: TextField }; - struct CocoaControl { CocoaControl(); CocoaControl(CocoaControlType t, QStyleHelper::WidgetSizePolicy s); @@ -242,49 +249,24 @@ public: static const int PushButtonContentPadding; enum Animates { AquaPushButton, AquaProgressBar, AquaListViewItemOpen, AquaScrollBar }; - static ThemeDrawState getDrawState(QStyle::State flags); QStyleHelper::WidgetSizePolicy aquaSizeConstrain(const QStyleOption *option, const QWidget *widg, QStyle::ContentsType ct = QStyle::CT_CustomBase, QSize szHint=QSize(-1, -1), QSize *insz = 0) const; QStyleHelper::WidgetSizePolicy effectiveAquaSizeConstrain(const QStyleOption *option, const QWidget *widg, QStyle::ContentsType ct = QStyle::CT_CustomBase, QSize szHint=QSize(-1, -1), QSize *insz = 0) const; - void getSliderInfo(QStyle::ComplexControl cc, const QStyleOptionSlider *slider, - HIThemeTrackDrawInfo *tdi, const QWidget *needToRemoveMe) const; inline int animateSpeed(Animates) const { return 33; } // Utility functions - void drawColorlessButton(const CGRect &macRect, HIThemeButtonDrawInfo *bdi, - const CocoaControl &cw, - QPainter *p, const QStyleOption *opt) const; + static CGRect comboboxInnerBounds(const CGRect &outterBounds, const CocoaControl &cocoaWidget); - QSize pushButtonSizeFromContents(const QStyleOptionButton *btn) const; - - CGRect pushButtonContentBounds(const QStyleOptionButton *btn, - const HIThemeButtonDrawInfo *bdi) const; - - void initComboboxBdi(const QStyleOptionComboBox *combo, HIThemeButtonDrawInfo *bdi, - CocoaControl *cw, - const QWidget *widget, const ThemeDrawState &tds) const; - - static CGRect comboboxInnerBounds(const CGRect &outerBounds, const CocoaControl &cocoaWidget); - - static QRect comboboxEditBounds(const QRect &outerBounds, const HIThemeButtonDrawInfo &bdi); - - static void drawCombobox(const CGRect &outerBounds, const HIThemeButtonDrawInfo &bdi, const CocoaControl &cw, QPainter *p); - bool contentFitsInPushButton(const QStyleOptionButton *btn, HIThemeButtonDrawInfo *bdi, - ThemeButtonKind buttonKindToCheck) const; - void initHIThemePushButton(const QStyleOptionButton *btn, const QWidget *widget, - const ThemeDrawState tds, - HIThemeButtonDrawInfo *bdi) const; + static QRectF comboboxEditBounds(const QRectF &outterBounds, const CocoaControl &cw); void setAutoDefaultButton(QObject *button) const; NSView *cocoaControl(CocoaControl widget) const; NSCell *cocoaCell(CocoaControl widget) const; - static CocoaControl cocoaControlFromHIThemeButtonKind(ThemeButtonKind kind); - void setupNSGraphicsContext(CGContextRef cg, bool flipped) const; void restoreNSGraphicsContext(CGContextRef cg) const; @@ -293,7 +275,6 @@ public: void drawNSViewInRect(CocoaControl widget, NSView *view, const QRectF &rect, QPainter *p, bool isQWidget = true, __attribute__((noescape)) DrawRectBlock drawRectBlock = nil) const; void resolveCurrentNSView(QWindow *window) const; - void drawFocusRing(QPainter *p, const QRect &targetRect, int hMargin, int vMargin, qreal radius = 0) const; void drawFocusRing(QPainter *p, const QRectF &targetRect, int hMargin, int vMargin, const CocoaControl &cw) const; void drawToolbarButtonArrow(const QStyleOption *opt, QPainter *p) const; @@ -304,6 +285,7 @@ public: #if QT_CONFIG(tabbar) void tabLayout(const QStyleOptionTab *opt, const QWidget *widget, QRect *textRect, QRect *iconRect) const; + static Direction tabDirection(QTabBar::Shape shape); #endif public: diff --git a/src/widgets/widgets/qmainwindowlayout.cpp b/src/widgets/widgets/qmainwindowlayout.cpp index 9cf2e7de1f..d4ce0ffa4c 100644 --- a/src/widgets/widgets/qmainwindowlayout.cpp +++ b/src/widgets/widgets/qmainwindowlayout.cpp @@ -317,6 +317,9 @@ bool QDockWidgetGroupWindow::event(QEvent *e) // We might need to show the widget again destroyOrHideIfEmpty(); break; + case QEvent::Resize: + updateCurrentGapRect(); + emit resized(); default: break; } @@ -467,6 +470,8 @@ void QDockWidgetGroupWindow::adjustFlags() } if (oldFlags != flags) { + if (!windowHandle()) + create(); // The desired geometry is forgotten if we call setWindowFlags before having a window setWindowFlags(flags); const bool gainedNativeDecos = (oldFlags & Qt::FramelessWindowHint) && !(flags & Qt::FramelessWindowHint); const bool lostNativeDecos = !(oldFlags & Qt::FramelessWindowHint) && (flags & Qt::FramelessWindowHint); @@ -546,12 +551,18 @@ bool QDockWidgetGroupWindow::hover(QLayoutItem *widgetItem, const QPoint &mouseP currentGapPos = newGapPos; newState.insertGap(currentGapPos, widgetItem); newState.fitItems(); - currentGapRect = newState.info(currentGapPos)->itemRect(currentGapPos.last(), true); *layoutInfo() = std::move(newState); + updateCurrentGapRect(); layoutInfo()->apply(opts & QMainWindow::AnimatedDocks); return true; } +void QDockWidgetGroupWindow::updateCurrentGapRect() +{ + if (!currentGapPos.isEmpty()) + currentGapRect = layoutInfo()->info(currentGapPos)->itemRect(currentGapPos.last(), true); +} + /* Remove the gap that was created by hover() */ @@ -1977,6 +1988,8 @@ void QMainWindowLayout::setCurrentHoveredFloat(QDockWidgetGroupWindow *w) if (currentHoveredFloat) { disconnect(currentHoveredFloat.data(), &QObject::destroyed, this, &QMainWindowLayout::updateGapIndicator); + disconnect(currentHoveredFloat.data(), &QDockWidgetGroupWindow::resized, + this, &QMainWindowLayout::updateGapIndicator); if (currentHoveredFloat) currentHoveredFloat->restore(); } else if (w) { @@ -1988,6 +2001,8 @@ void QMainWindowLayout::setCurrentHoveredFloat(QDockWidgetGroupWindow *w) if (w) { connect(w, &QObject::destroyed, this, &QMainWindowLayout::updateGapIndicator, Qt::UniqueConnection); + connect(w, &QDockWidgetGroupWindow::resized, + this, &QMainWindowLayout::updateGapIndicator, Qt::UniqueConnection); } updateGapIndicator(); @@ -2559,6 +2574,7 @@ void QMainWindowLayout::hover(QLayoutItem *widgetItem, const QPoint &mousePos) dropTo->show(); dropTo->d_func()->plug(QRect()); w = floatingTabs; + widget->raise(); // raise, as our newly created drop target is now on top } Q_ASSERT(qobject_cast(w)); auto group = static_cast(w); diff --git a/src/widgets/widgets/qmainwindowlayout_p.h b/src/widgets/widgets/qmainwindowlayout_p.h index 168d4444b9..53e045aaae 100644 --- a/src/widgets/widgets/qmainwindowlayout_p.h +++ b/src/widgets/widgets/qmainwindowlayout_p.h @@ -338,12 +338,16 @@ public: bool hasNativeDecos() const; bool hover(QLayoutItem *widgetItem, const QPoint &mousePos); + void updateCurrentGapRect(); void restore(); void apply(); QRect currentGapRect; QList currentGapPos; +signals: + void resized(); + protected: bool event(QEvent *) override; void paintEvent(QPaintEvent*) override; diff --git a/tests/auto/dbus/qdbusabstractadaptor/tst_qdbusabstractadaptor.cpp b/tests/auto/dbus/qdbusabstractadaptor/tst_qdbusabstractadaptor.cpp index 80f22ad867..fdcd8b07c7 100644 --- a/tests/auto/dbus/qdbusabstractadaptor/tst_qdbusabstractadaptor.cpp +++ b/tests/auto/dbus/qdbusabstractadaptor/tst_qdbusabstractadaptor.cpp @@ -768,9 +768,8 @@ void tst_QDBusAbstractAdaptor::scriptableSignalOrNot() con.connect(con.baseService(), "/p2", "local.MyObject", "nonScriptableSignalVoid", &spy, SLOT(slot(QDBusMessage))); obj.emitSignal("scriptableSignalVoid", QVariant()); obj.emitSignal("nonScriptableSignalVoid", QVariant()); - QTest::qWait(200); - QCOMPARE(spy.count, 1); // only /p1 must have emitted + QTRY_COMPARE(spy.count, 1); // only /p1 must have emitted QCOMPARE(spy.interface, QString("local.MyObject")); QCOMPARE(spy.name, QString("scriptableSignalVoid")); QCOMPARE(spy.path, QString("/p1")); @@ -788,9 +787,8 @@ void tst_QDBusAbstractAdaptor::scriptableSignalOrNot() con.connect(con.baseService(), "/p1", "local.MyObject", "nonScriptableSignalVoid", &spy, SLOT(slot(QDBusMessage))); con.connect(con.baseService(), "/p2", "local.MyObject", "nonScriptableSignalVoid", &spy, SLOT(slot(QDBusMessage))); obj.emitSignal("nonScriptableSignalVoid", QVariant()); - QTest::qWait(200); - QCOMPARE(spy.count, 1); // only /p2 must have emitted now + QTRY_COMPARE(spy.count, 1); // only /p2 must have emitted now QCOMPARE(spy.interface, QString("local.MyObject")); QCOMPARE(spy.name, QString("nonScriptableSignalVoid")); QCOMPARE(spy.path, QString("/p2")); @@ -1306,9 +1304,8 @@ void tst_QDBusAbstractAdaptor::scriptableSignalOrNotPeer() con.connect(QString(), "/p2", "local.MyObject", "nonScriptableSignalVoid", &spy, SLOT(slot(QDBusMessage))); emitSignalPeer("local.MyObject", "scriptableSignalVoid", QVariant()); emitSignalPeer("local.MyObject", "nonScriptableSignalVoid", QVariant()); - QTest::qWait(200); - QCOMPARE(spy.count, 1); // only /p1 must have emitted + QTRY_COMPARE(spy.count, 1); // only /p1 must have emitted QCOMPARE(spy.interface, QString("local.MyObject")); QCOMPARE(spy.name, QString("scriptableSignalVoid")); QCOMPARE(spy.path, QString("/p1")); @@ -1327,9 +1324,8 @@ void tst_QDBusAbstractAdaptor::scriptableSignalOrNotPeer() con.connect(QString(), "/p1", "local.MyObject", "nonScriptableSignalVoid", &spy, SLOT(slot(QDBusMessage))); con.connect(QString(), "/p2", "local.MyObject", "nonScriptableSignalVoid", &spy, SLOT(slot(QDBusMessage))); emitSignalPeer("local.MyObject", "nonScriptableSignalVoid", QVariant()); - QTest::qWait(200); - QCOMPARE(spy.count, 1); // only /p2 must have emitted now + QTRY_COMPARE(spy.count, 1); // only /p2 must have emitted now QCOMPARE(spy.interface, QString("local.MyObject")); QCOMPARE(spy.name, QString("nonScriptableSignalVoid")); QCOMPARE(spy.path, QString("/p2")); diff --git a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp index d521c18cef..77ae6f154d 100644 --- a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp +++ b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp @@ -136,9 +136,7 @@ void tst_QDBusConnection::sendSignalToName() QVERIFY(con.send(msg)); - QTest::qWait(1000); - - QCOMPARE(spy.args.count(), 1); + QTRY_COMPARE(spy.args.count(), 1); QCOMPARE(spy.args.at(0).toString(), QString("ping")); } @@ -215,8 +213,7 @@ void tst_QDBusConnection::sendAsync() "/org/freedesktop/DBus", "org.freedesktop.DBus", "ListNames"); QVERIFY(con.callWithCallback(msg, &spy, SLOT(asyncReply(QDBusMessage)))); - QTest::qWait(1000); - + QTRY_COMPARE(spy.args.count(), 1); QCOMPARE(spy.args.value(0).typeName(), "QStringList"); QVERIFY(spy.args.at(0).toStringList().contains(con.baseService())); } @@ -239,9 +236,7 @@ void tst_QDBusConnection::connect() QVERIFY(con.send(msg)); - QTest::qWait(1000); - - QCOMPARE(spy.args.count(), 1); + QTRY_COMPARE(spy.args.count(), 1); QCOMPARE(spy.args.at(0).toString(), QString("ping")); } @@ -1072,9 +1067,8 @@ void tst_QDBusConnection::connectSignal() QVERIFY(con.connect(con.baseService(), signal.path(), signal.interface(), signal.member(), &recv, SLOT(oneSlot(QString)))); QVERIFY(con.send(signal)); - QTest::qWait(100); + QTRY_COMPARE(recv.signalsReceived, 1); QCOMPARE(recv.argumentReceived, signal.arguments().at(0).toString()); - QCOMPARE(recv.signalsReceived, 1); // disconnect and try with a signature recv.argumentReceived.clear(); @@ -1084,9 +1078,8 @@ void tst_QDBusConnection::connectSignal() QVERIFY(con.connect(con.baseService(), signal.path(), signal.interface(), signal.member(), "s", &recv, SLOT(oneSlot(QString)))); QVERIFY(con.send(signal)); - QTest::qWait(100); + QTRY_COMPARE(recv.signalsReceived, 1); QCOMPARE(recv.argumentReceived, signal.arguments().at(0).toString()); - QCOMPARE(recv.signalsReceived, 1); // confirm that we are, indeed, a unique connection recv.argumentReceived.clear(); @@ -1094,9 +1087,8 @@ void tst_QDBusConnection::connectSignal() QVERIFY(!con.connect(con.baseService(), signal.path(), signal.interface(), signal.member(), "s", &recv, SLOT(oneSlot(QString)))); QVERIFY(con.send(signal)); - QTest::qWait(100); + QTRY_COMPARE(recv.signalsReceived, 1); QCOMPARE(recv.argumentReceived, signal.arguments().at(0).toString()); - QCOMPARE(recv.signalsReceived, 1); } void tst_QDBusConnection::slotsWithLessParameters() @@ -1114,9 +1106,8 @@ void tst_QDBusConnection::slotsWithLessParameters() QVERIFY(con.connect(con.baseService(), signal.path(), signal.interface(), signal.member(), &recv, SLOT(oneSlot()))); QVERIFY(con.send(signal)); - QTest::qWait(100); + QTRY_COMPARE(recv.signalsReceived, 1); QCOMPARE(recv.argumentReceived, QString()); - QCOMPARE(recv.signalsReceived, 1); // disconnect and try with a signature recv.signalsReceived = 0; @@ -1125,18 +1116,16 @@ void tst_QDBusConnection::slotsWithLessParameters() QVERIFY(con.connect(con.baseService(), signal.path(), signal.interface(), signal.member(), "s", &recv, SLOT(oneSlot()))); QVERIFY(con.send(signal)); - QTest::qWait(100); + QTRY_COMPARE(recv.signalsReceived, 1); QCOMPARE(recv.argumentReceived, QString()); - QCOMPARE(recv.signalsReceived, 1); // confirm that we are, indeed, a unique connection recv.signalsReceived = 0; QVERIFY(!con.connect(con.baseService(), signal.path(), signal.interface(), signal.member(), "s", &recv, SLOT(oneSlot()))); QVERIFY(con.send(signal)); - QTest::qWait(100); + QTRY_COMPARE(recv.signalsReceived, 1); QCOMPARE(recv.argumentReceived, QString()); - QCOMPARE(recv.signalsReceived, 1); } void SignalReceiver::secondCallWithCallback() diff --git a/tests/auto/dbus/qdbusthreading/tst_qdbusthreading.cpp b/tests/auto/dbus/qdbusthreading/tst_qdbusthreading.cpp index 8bda5f5641..018b7c2a35 100644 --- a/tests/auto/dbus/qdbusthreading/tst_qdbusthreading.cpp +++ b/tests/auto/dbus/qdbusthreading/tst_qdbusthreading.cpp @@ -414,8 +414,7 @@ void tst_QDBusThreading::registerObjectInOtherThread() QCOMPARE(functionSpy, Object_method); QCOMPARE(threadSpy, th); - QTest::qWait(100); - QCOMPARE(signalSpy, 1); + QTRY_COMPARE(signalSpy, 1); sem2.acquire(); // the object is gone functionSpy = NoMethod; @@ -462,8 +461,7 @@ void tst_QDBusThreading::registerAdaptorInOtherThread() QCOMPARE(functionSpy, Adaptor_method); QCOMPARE(threadSpy, th); - QTest::qWait(100); - QCOMPARE(signalSpy, 1); + QTRY_COMPARE(signalSpy, 1); functionSpy = NoMethod; threadSpy = 0; diff --git a/tests/auto/gui/kernel/qopenglwindow/tst_qopenglwindow.cpp b/tests/auto/gui/kernel/qopenglwindow/tst_qopenglwindow.cpp index a971450ee8..9c36b6898a 100644 --- a/tests/auto/gui/kernel/qopenglwindow/tst_qopenglwindow.cpp +++ b/tests/auto/gui/kernel/qopenglwindow/tst_qopenglwindow.cpp @@ -156,10 +156,7 @@ void tst_QOpenGLWindow::resize() // Check that a future resize triggers resizeGL. w.resize(800, 600); - int maxWait = 1000; - while (w.resizeCount == resCount && maxWait-- >= 0) - QTest::qWait(10); - QVERIFY(w.resizeCount > resCount); + QTRY_VERIFY(w.resizeCount > resCount); } class PainterWindow : public QOpenGLWindow @@ -239,9 +236,7 @@ void tst_QOpenGLWindow::partial() for (int i = 0; i < 10; ++i) { w.paintCount = 0; w.update(); - int maxWait = 1000; - while (w.paintCount == 0 && maxWait-- >= 0) - QTest::qWait(10); + QTRY_VERIFY(w.paintCount > 0); } // Now since the painting went to an extra framebuffer, all the rects should diff --git a/tests/auto/gui/kernel/qrasterwindow/tst_qrasterwindow.cpp b/tests/auto/gui/kernel/qrasterwindow/tst_qrasterwindow.cpp index ffc440ac2d..deb4837956 100644 --- a/tests/auto/gui/kernel/qrasterwindow/tst_qrasterwindow.cpp +++ b/tests/auto/gui/kernel/qrasterwindow/tst_qrasterwindow.cpp @@ -76,11 +76,7 @@ void tst_QRasterWindow::basic() w.reset(); w.update(); - int maxWait = 1000; - while (w.paintCount == 0 && --maxWait > 0) - QTest::qWait(10); - - QVERIFY(w.paintCount >= 1); + QTRY_VERIFY(w.paintCount >= 1); } #include diff --git a/tests/auto/network/access/http2/http2srv.cpp b/tests/auto/network/access/http2/http2srv.cpp index 69e480b164..b0bae13bad 100644 --- a/tests/auto/network/access/http2/http2srv.cpp +++ b/tests/auto/network/access/http2/http2srv.cpp @@ -123,6 +123,12 @@ void Http2Server::emulateGOAWAY(int timeout) goawayTimeout = timeout; } +void Http2Server::redirectOpenStream(quint16 port) +{ + redirectWhileReading = true; + targetPort = port; +} + void Http2Server::startServer() { #ifdef QT_NO_SSL @@ -775,7 +781,19 @@ void Http2Server::sendResponse(quint32 streamID, bool emptyBody) if (emptyBody) writer.addFlag(FrameFlag::END_STREAM); - HttpHeader header = {{":status", "200"}}; + HttpHeader header; + if (redirectWhileReading) { + qDebug("server received HEADERS frame (followed by DATA frames), redirecting ..."); + Q_ASSERT(targetPort); + header.push_back({":status", "308"}); + const QString url("%1://localhost:%2/"); + header.push_back({"location", url.arg(clearTextHTTP2 ? QStringLiteral("http") : QStringLiteral("https"), + QString::number(targetPort)).toLatin1()}); + + } else { + header.push_back({":status", "200"}); + } + if (!emptyBody) { header.push_back(HPack::HeaderField("content-length", QString("%1").arg(responseBody.size()).toLatin1())); @@ -871,7 +889,13 @@ void Http2Server::processRequest() activeRequests[streamID] = decoder.decodedHeader(); if (headersFrame.flags().testFlag(FrameFlag::END_STREAM)) emit receivedRequest(streamID); - // else - we're waiting for incoming DATA frames ... + + if (redirectWhileReading) { + sendResponse(streamID, true); + // Don't try to read any DATA frames ... + socket->disconnect(); + } // else - we're waiting for incoming DATA frames ... + continuedRequest.clear(); } diff --git a/tests/auto/network/access/http2/http2srv.h b/tests/auto/network/access/http2/http2srv.h index 76c5a0ee36..14b41cc67d 100644 --- a/tests/auto/network/access/http2/http2srv.h +++ b/tests/auto/network/access/http2/http2srv.h @@ -74,6 +74,7 @@ public: void enablePushPromise(bool enabled, const QByteArray &path = QByteArray()); void setResponseBody(const QByteArray &body); void emulateGOAWAY(int timeout); + void redirectOpenStream(quint16 targetPort); // Invokables, since we can call them from the main thread, // but server (can) work on its own thread. @@ -186,6 +187,10 @@ private: // We need it for PUSH_PROMISE, with the correct port number appended, // when replying to essentially 1.1 request. QByteArray authority; + // Redirect, with status code 308, as soon as we've seen headers, while client + // may still be sending DATA frames. See tst_Http2::earlyResponse(). + bool redirectWhileReading = false; + quint16 targetPort = 0; protected slots: void ignoreErrorSlot(); }; diff --git a/tests/auto/network/access/http2/tst_http2.cpp b/tests/auto/network/access/http2/tst_http2.cpp index 51e1849512..ecf4c5814a 100644 --- a/tests/auto/network/access/http2/tst_http2.cpp +++ b/tests/auto/network/access/http2/tst_http2.cpp @@ -74,6 +74,7 @@ private slots: void pushPromise(); void goaway_data(); void goaway(); + void earlyResponse(); protected slots: // Slots to listen to our in-process server: @@ -439,6 +440,47 @@ void tst_Http2::goaway() QVERIFY(!serverGotSettingsACK); } +void tst_Http2::earlyResponse() +{ + // In this test we'd like to verify client side can handle HEADERS frame while + // its stream is in 'open' state. To achieve this, we send a POST request + // with some payload, so that the client is first sending HEADERS and then + // DATA frames without END_STREAM flag set yet (thus the stream is in Stream::open + // state). Upon receiving the client's HEADERS frame our server ('redirector') + // immediately (without trying to read any DATA frames) responds with status + // code 308. The client should properly handle this. + + clearHTTP2State(); + + serverPort = 0; + nRequests = 1; + + ServerPtr targetServer(newServer(defaultServerSettings)); + + QMetaObject::invokeMethod(targetServer.data(), "startServer", Qt::QueuedConnection); + runEventLoop(); + + QVERIFY(serverPort != 0); + + const quint16 targetPort = serverPort; + serverPort = 0; + + ServerPtr redirector(newServer(defaultServerSettings)); + redirector->redirectOpenStream(targetPort); + + QMetaObject::invokeMethod(redirector.data(), "startServer", Qt::QueuedConnection); + runEventLoop(); + + QVERIFY(serverPort); + sendRequest(1, QNetworkRequest::NormalPriority, {10000000, Qt::Uninitialized}); + + runEventLoop(); + + QVERIFY(nRequests == 0); + QVERIFY(prefaceOK); + QVERIFY(serverGotSettingsACK); +} + void tst_Http2::serverStarted(quint16 port) { serverPort = port; @@ -500,6 +542,7 @@ void tst_Http2::sendRequest(int streamNumber, QNetworkRequest request(url); request.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, QVariant(true)); + request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, QVariant(true)); request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain")); request.setPriority(priority); @@ -592,6 +635,10 @@ void tst_Http2::replyFinished() const QVariant spdyUsed(reply->attribute(QNetworkRequest::SpdyWasUsedAttribute)); QVERIFY(spdyUsed.isValid()); QVERIFY(!spdyUsed.toBool()); + const QVariant code(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute)); + QVERIFY(code.isValid()); + QVERIFY(code.canConvert()); + QCOMPARE(code.value(), 200); } --nRequests; diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp index 1332b369e7..bb01116240 100644 --- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp +++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp @@ -1188,13 +1188,7 @@ void tst_QSslSocket::protocolServerSide_data() #if !defined(OPENSSL_NO_SSL2) // OpenSSL 1.1 has removed SSL2 support. But there is no OPENSSL_NO_SSL2 macro ... #define OPENSSL_NO_SSL2 -#endif - // A client using our OpenSSL1.1 backend will negotiate up from TLS 1.0 or 1.1 - // to TLS 1.2 if the server asks for it, where our older backend fails to compromise. - // So some tests that fail for the old pass with the new. - const bool willUseTLS12 = true; -#else - const bool willUseTLS12 = false; +#endif // OPENSSL_NO_SSL2 #endif // opensslv11 #if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT) @@ -1290,7 +1284,7 @@ void tst_QSslSocket::protocolServerSide_data() QTest::newRow("tls1.1orlater-ssl3") << QSsl::TlsV1_1OrLater << QSsl::SslV3 << false; #endif - QTest::newRow("tls1.1orlater-tls1.0") << QSsl::TlsV1_1OrLater << QSsl::TlsV1_0 << willUseTLS12; + QTest::newRow("tls1.1orlater-tls1.0") << QSsl::TlsV1_1OrLater << QSsl::TlsV1_0 << false; QTest::newRow("tls1.1orlater-tls1.1") << QSsl::TlsV1_1OrLater << QSsl::TlsV1_1 << true; QTest::newRow("tls1.1orlater-tls1.2") << QSsl::TlsV1_1OrLater << QSsl::TlsV1_2 << true; @@ -1300,8 +1294,8 @@ void tst_QSslSocket::protocolServerSide_data() #if !defined(OPENSSL_NO_SSL3) QTest::newRow("tls1.2orlater-ssl3") << QSsl::TlsV1_2OrLater << QSsl::SslV3 << false; #endif - QTest::newRow("tls1.2orlater-tls1.0") << QSsl::TlsV1_2OrLater << QSsl::TlsV1_0 << willUseTLS12; - QTest::newRow("tls1.2orlater-tls1.1") << QSsl::TlsV1_2OrLater << QSsl::TlsV1_1 << willUseTLS12; + QTest::newRow("tls1.2orlater-tls1.0") << QSsl::TlsV1_2OrLater << QSsl::TlsV1_0 << false; + QTest::newRow("tls1.2orlater-tls1.1") << QSsl::TlsV1_2OrLater << QSsl::TlsV1_1 << false; QTest::newRow("tls1.2orlater-tls1.2") << QSsl::TlsV1_2OrLater << QSsl::TlsV1_2 << true; QTest::newRow("any-tls1.0") << QSsl::AnyProtocol << QSsl::TlsV1_0 << true; diff --git a/tests/auto/opengl/qgl/tst_qgl.cpp b/tests/auto/opengl/qgl/tst_qgl.cpp index 46e2345c6a..7666bf81e4 100644 --- a/tests/auto/opengl/qgl/tst_qgl.cpp +++ b/tests/auto/opengl/qgl/tst_qgl.cpp @@ -923,8 +923,7 @@ void tst_QGL::partialGLWidgetUpdates() widget.setFixedSize(150, 150); widget.setAutoFillBackground(autoFillBackground); widget.show(); - - QTest::qWait(200); + QVERIFY(QTest::qWaitForWindowExposed(&widget)); if (widget.format().doubleBuffer() != doubleBufferedContext) QSKIP("Platform does not support requested format"); diff --git a/tests/auto/widgets/dialogs/qfiledialog/qfiledialog.pro b/tests/auto/widgets/dialogs/qfiledialog/qfiledialog.pro index 4ea23a896f..1cdf10d29a 100644 --- a/tests/auto/widgets/dialogs/qfiledialog/qfiledialog.pro +++ b/tests/auto/widgets/dialogs/qfiledialog/qfiledialog.pro @@ -9,5 +9,3 @@ QT += core-private gui-private SOURCES += tst_qfiledialog.cpp DEFINES += SRCDIR=\\\"$$PWD/\\\" - -linux*: CONFIG += insignificant_test # Crashes on different Linux distros diff --git a/tests/auto/widgets/itemviews/qitemdelegate/BLACKLIST b/tests/auto/widgets/itemviews/qitemdelegate/BLACKLIST index fea108f3fd..0f7c377194 100644 --- a/tests/auto/widgets/itemviews/qitemdelegate/BLACKLIST +++ b/tests/auto/widgets/itemviews/qitemdelegate/BLACKLIST @@ -2,3 +2,6 @@ opensuse-42.3 ci [testLineEditValidation] opensuse-42.3 ci +[comboBox] +# QTBUG-67282 +opensuse diff --git a/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp b/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp index 2fed2e0c69..802a04b4bf 100644 --- a/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp +++ b/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp @@ -1389,13 +1389,12 @@ void tst_QItemDelegate::comboBox() QTableWidget widget(1, 1); widget.setItem(0, 0, item1); widget.show(); + QVERIFY(QTest::qWaitForWindowExposed(&widget)); widget.editItem(item1); - QTestEventLoop::instance().enterLoop(1); - - QComboBox *boolEditor = widget.viewport()->findChild(); - QVERIFY(boolEditor); + QComboBox *boolEditor = nullptr; + QTRY_VERIFY( (boolEditor = widget.viewport()->findChild()) ); QCOMPARE(boolEditor->currentIndex(), 1); // True is selected initially. // The data must actually be different in order for the model // to be updated. diff --git a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp index 9021be1515..1d2bb00678 100644 --- a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp +++ b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp @@ -911,7 +911,7 @@ void tst_QWidget_window::setWindowState() // Minimizing keeps other states w.showMinimized(); QCOMPARE(w.windowState(), state | Qt::WindowMinimized); - QTest::qWait(100); + QTest::qWait(200); QCOMPARE(w.windowState(), state | Qt::WindowMinimized); QCOMPARE(w.windowHandle()->windowStates(), state | Qt::WindowMinimized); } diff --git a/tests/auto/widgets/styles/qmacstyle/tst_qmacstyle.cpp b/tests/auto/widgets/styles/qmacstyle/tst_qmacstyle.cpp index 2ab2fa4c86..a78ebdb2b9 100644 --- a/tests/auto/widgets/styles/qmacstyle/tst_qmacstyle.cpp +++ b/tests/auto/widgets/styles/qmacstyle/tst_qmacstyle.cpp @@ -128,12 +128,12 @@ void tst_QMacStyle::sizeHints() QComboBox comboBox1(&w); comboBox1.setEditable(false); comboBox1.addItem("Foo"); - QCOMPARE(sh(&comboBox1).height(), SIZE(20, 17, 15)); + QCOMPARE(sh(&comboBox1).height(), SIZE(26, 17, 15)); QComboBox comboBox2(&w); comboBox2.setEditable(true); comboBox2.addItem("Foo"); - QCOMPARE(sh(&comboBox2).height(), SIZE(22, 17, 15)); + QCOMPARE(sh(&comboBox2).height(), SIZE(26, 17, 15)); // Combos in toolbars use the actual widget rect to // avoid faulty clipping: @@ -141,7 +141,7 @@ void tst_QMacStyle::sizeHints() setSize(&tb, size); QComboBox comboBox3(&tb); comboBox3.addItem("Foo"); - QCOMPARE(sh(&comboBox3).height(), SIZE(26, -1, -1)); + QCOMPARE(sh(&comboBox3).height(), SIZE(32, -1, -1)); QSlider slider1(Qt::Horizontal, &w); QCOMPARE(sh(&slider1).height(), SIZE(15, 12, 10)); diff --git a/tests/benchmarks/gui/painting/qpainter/tst_qpainter.cpp b/tests/benchmarks/gui/painting/qpainter/tst_qpainter.cpp index 71a2742ac5..ca41d7f570 100644 --- a/tests/benchmarks/gui/painting/qpainter/tst_qpainter.cpp +++ b/tests/benchmarks/gui/painting/qpainter/tst_qpainter.cpp @@ -127,7 +127,7 @@ QPixmap rasterPixmap(const QImage &image) QPlatformPixmap *data = new QRasterPlatformPixmap(QPlatformPixmap::PixmapType); - data->fromImage(image, Qt::AutoColor); + data->fromImage(image, Qt::AutoColor | Qt::NoFormatConversion); return QPixmap(data); } @@ -613,9 +613,7 @@ void tst_QPainter::drawPixmapImage_data_helper(bool pixmaps) QTest::addColumn("type"); // 0 = circle, 1 = diag line, 2 = solid rect, 3 = alpharect QList sizes; - sizes << QSize(1, 1) - << QSize(10, 10) - << QSize(100, 100) + sizes << QSize(10, 10) << QSize(1000, 1000); const char *typeNames[] = { @@ -657,7 +655,6 @@ void tst_QPainter::drawPixmapImage_data_helper(bool pixmaps) QImage::Format_RGB32, QImage::Format_ARGB32_Premultiplied, QImage::Format_RGB16, - QImage::Format_ARGB8565_Premultiplied, QImage::Format_BGR30, QImage::Format_Invalid }; @@ -682,12 +679,9 @@ void tst_QPainter::drawPixmapImage_data_helper(bool pixmaps) QImage::Format_ARGB32, QImage::Format_ARGB32_Premultiplied, QImage::Format_RGB16, - QImage::Format_ARGB8565_Premultiplied, QImage::Format_RGB888, QImage::Format_RGBX8888, QImage::Format_RGBA8888, - QImage::Format_RGBA8888_Premultiplied, - QImage::Format_A2BGR30_Premultiplied, QImage::Format_RGB30, QImage::Format_Grayscale8, QImage::Format_Invalid