summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarwin Huang <huangdarwin@chromium.org>2020-12-29 19:16:24 +0000
committerMichael Brüning <michael.bruning@qt.io>2021-03-29 09:43:22 +0000
commitf2f8da5d330489c0de4239eea994a7ad9e62709e (patch)
treeb482890ef07fccf1c175e6db6dc65e23c0dca445
parent69084e439c5e193403abd7c43bb1a5fee4a96605 (diff)
[Backport] Security bug 1161048
Manual backport (library update) of patch originally reviewed on https://chromium-review.googlesource.com/c/chromium/src/+/2600334: Roll src/third_party/sqlite/src/ 0324bd3ef..d9581878f (171 commits) https://chromium.googlesource.com/chromium/deps/sqlite.git/+log/0324bd3ef1af..d9581878fcf8 $ git log 0324bd3ef..d9581878f --date=short --no-merges --format='%ad %ae %s' 2020-12-22 huangdarwin Fix SQLITE_OMIT_WINDOWFUNC builds by moving declaration of sqlite3ExpandSubquery out of "ifndef SQLITE_OMIT_WINDOWFUNC" block. 2020-12-22 huangdarwin Amalgamations for release 3.34.0 2020-12-01 drh Version 3.34.0 2020-11-30 Dan Kennedy Update the tea/win/makefile.vc file that ships as part of the autoconf package to use "sqlite3" instead of "tclsqlite3" for the installed dll filename. 2020-11-30 drh Do not reuse the obsolete SQLITE_TESTCTRL_PRNG_RESET value for SQLITE_TESTCTRL_SEEK_COUNT. Give SEEK_COUNT its own unique value. This avoids incompatibility with legacy test code. 2020-11-27 Dan Kennedy Fix a compiler warning in fts5_aux.c. 2020-11-27 Dan Kennedy Add missing cast to fts5 bm25() code. 2020-11-27 Dan Kennedy Remove a redundant "if( rc==SQLITE_OK )" from the fts5 bm25() code. 2020-11-27 Dan Kennedy Move an "if( rc==SQLITE_OK )" to outside a loop body in the fts5 bm25() code. 2020-11-27 Dan Kennedy Fix a case in the FTS5 integrity check where a corrupt database could cause a buffer overread. 2020-11-26 Dan Kennedy Update mkunicode.tcl to match the change erroneously made to machine generated file fts5_unicode2.c in [b7b7bde9]. 2020-11-25 drh Update a requirement mark in the e_expr.test script. 2020-11-25 drh Fix harmless compiler warnings about unused function parameters. 2020-11-25 drh Fix a potential NULL pointer dereference in the geopoly_overlap() routine of the GeoPoly extension. 2020-11-25 drh Fix the shell1.test test script so that it works on windows. 2020-11-25 drh Change the -init option to the command-line shell to honor the -bail option. Also change it to report an error if the filename mentioned cannot be opened. 2020-11-24 drh Fix a typo in the sqlite3_txn_state() documentation. 2020-11-24 drh Add the new sqlite3_txn_state() interface to the set of routines accessible by run-time loadables extensions. 2020-11-24 drh Fix a harmless typo in a comment. 2020-11-24 dan Fix a bug in OOM handling code introduced by [6a28713d]. 2020-11-24 dan Ensure that super-journal and other journal filenames passed by SQLite to an sqlite3_vfs.xOpen() implementation may be safely passed to sqlite3_uri_parameter() and similar functions. 2020-11-24 drh Remove the VERSION_NUMBER macro from configure.ac as it has been unused since 2009 check-in [7f4810747b086498]. See also [forum:/forumpost/bb2c634fcd|forum post bb2c634fcd]. 2020-11-23 drh Syntactic changes to work around a bug in gcov 9.3.0. No changes to the generated code for release builds. 2020-11-23 drh In os_unix.c, put ALWAYS() on unreachable branches associated with pathname normalization. 2020-11-23 dan Fix a test script problem causing crash8.test to fail when run with leak-sanitizer. 2020-11-23 drh Allow "substring()" as an alias for "substr()" for compatibility with other SQL engines. 2020-11-20 dan Add file doc/vdbesort-memory.md, containing notes on the way vdbesort.c uses heap memory. 2020-11-19 drh More test case changes so that shared-cache mode tests all work with normalized database names. 2020-11-19 drh Fix the tkt3793 test case so that work even when filenames are normalized. 2020-11-18 drh Improvements to the mechanism that attempts to report SQLITE_CORRUPT if pread() says that the underlying filesystem is corrupt. 2020-11-18 dan Update cksumvfs.c so that if SQLITE_AMALGAMATION is defined, SQLITE_CKSUMVFS_STATIC is implied. 2020-11-18 dan Add test infrastructure for cksumvfs. And update cksumvfs so that it works in concert with version 2 VFSs. No changes to core SQLite. 2020-11-18 dan Fix a problem causing sqlite3_carray_bind() to return an undefined value. 2020-11-18 dan Update test code to fix a problem with SQLITE_OMIT_VIRTUAL_TABLE builds. 2020-11-18 drh On unix, for certain error codes of read()/pread() return SQLITE_IOERR_CORRUPTFS instead of SQLITE_IOERR_READ. And then convert this error into SQLITE_CORRUPT prior to returning back to the application. 2020-11-17 drh Claw back most of the performance lost in the previous commit. 2020-11-17 dan Fix trivial memory leaks in the shell and sqldiff programs. 2020-11-17 dan Fix test file busy2.test so that it works with the "inmemory_journal" permutation. 2020-11-17 drh Add a single-argument form to the CARRAY table-valued function, with content bound using the sqlite3_carray_bind() interface that is included with the extension. 2020-11-16 drh Enhance the unix VFS so that it removes extra "/", "/./" and "/../" from the database filename. 2020-11-14 drh Modify UPDATE so that two-pass updates on a rowid table use an ephemeral table to store rowids rather than a RowSet. This uses less memory, though it is slower. 2020-11-12 drh Improved diagnostics output with ".wheretrace 0x800". No changes to non-debug builds. 2020-11-11 drh Fix a typo in a comment. No changes to code. 2020-11-08 drh Use NEVER and ALWAYS macros to confirm that the return value from sqlite3ExprSkipCollateAndLikely() is never NULL in some of its use cases. 2020-11-06 drh Add ALWAYS() to conditionals associated with SHM locking that are always true. 2020-11-05 drh Suppress errors associated with TEMP triggers that reference objects in non-TEMP databases. This is a continuation of the fix for ticket #3810 shown in check-in [ba1afc040171810d] from [/timeline?c=trunk:200908061743|2009-08-06], based on a bug report in [forum:/forumpost/157dc791df|forum post 157dc791df] 2020-11-05 drh Remove unused variable from speedtest1.c 2020-11-02 drh Fix an another OSS-Fuzz discovered assertion fault due to ALTER TABLE and strange triggers. 2020-10-31 drh Add the -tabs command-line option to the CLI. 2020-10-31 dan Update the ALTER TABLE command to correctly handle UPDATE ... FROM statements within trigger programs. (...) 2020-09-15 drh Do not invoke usleep() for more than 999999 microseconds. 2020-09-11 dan Catch fts5 index corruption caused by issuing 'delete' commands with incorrect data earlier in some cases. Also fix a couple of test script problems. 2020-09-10 drh Try again to fix the typo in the sqlite3_txn_state() documentation. 2020-09-10 drh Fix typo in the documentation for the new sqlite3_txn_state() interface. 2020-09-10 drh If an amalgamation is created using SQLITE_ENABLE_UPDATE_DELETE_LIMIT, ensure that it can still be compiled without that option by setting the SQLITE_UDL_CAPABLE_PARSER flag in the preamble. 2020-09-07 dan Fix another (harmless in practice) tsan error in shared-cache mode. 2020-09-06 drh Remove an artifical limitation on the length of columns in the "box" output mode of the command-line shell. 2020-09-05 drh Fix a bug in Fossil that might cause it to crash if there is a multi-terminal token with a space following the "|" separator. This does not affect SQLite. 2020-09-04 dan Fix a tsan error that could occur when using shared-cache mode. 2020-09-04 dan Ensure that the busy-handler count is reset at the end of each sqlite3_file_control() and sqlite3_prepare() (and _v2() and _v3()). 2020-09-01 mistachkin Fix harmless compiler warning. 2020-09-01 drh In the Lemon output, add a prefix comment that explains that the output file is automatically generated and shows the name of the source file. 2020-09-01 drh Lemon updates: (1) include the #defines for all tokens in the generated C file, so that the C-file can be stand-alone. (2) If the grammar begins with a %include {...} directive on line one, make that directive the header for the generated C file. (3) Enhance the lemon.html documentation. 2020-09-01 drh Improvements to the IN-early-out optimization so that it works more efficiently when there are two or more indexed IN clauses on a single table. 2020-09-01 drh Fix a harmless compiler warning. 2020-08-31 drh New test-control that returns the number of calls to sqlite3BtreeMovetoUnpacked() on the main database and then resets the counter. This only works for SQLITE_DEBUG builds. 2020-08-31 drh Fix the documentation for the OP_IdxGT family of opcodes to show that the P5 operand is not used. 2020-08-29 dan Fix a sanitizer warning in zipfile.c. 2020-08-28 dan Fix handling of an xShmLock(SHARED, UNLOCK) call when the caller does not hold any lock on the specified slot, but another connection in the same process holds an EXCLUSIVE. 2020-08-28 dan Modify the unixShmLock() function to avoid iterating through the (possibly large) set of connections to the same database file. 2020-08-28 mistachkin Add the miscellaneous 'series' extension to the shell. 2020-08-28 drh Update Lemon documentation. Patches from sgbeal. 2020-08-28 drh Fix a couple of unreachable branches. 2020-08-28 dan Add fts5 test to confirm that for a table with columns a, b, c and d, "{a b}" and "-{c d}" are handled similarly. 2020-08-27 drh Remove a (harmless) redundant variable from the CLI implementation. 2020-08-27 drh Include the original text of the CHECK constraint in the error message for anonymous CHECK constraints. 2020-08-27 drh Apple the same fix for ticket [9eda2697f5cc1aba] to text-to-integer conversions that was done for floating point conversions by check-in [1c76f1d8ec0937a2]. 2020-08-27 dan Do not attempt to run test script analyze3.test as part of the "prepare" permutation. 2020-08-26 drh Enhance the ".databases" command in the CLI so that it shows the result of sqlite3_db_readonly() and sqlite3_txn_state() for each database file. 2020-08-26 drh If the argument to the ".read" command in the CLI begins with "|" then run the remainder of the argument as a command and read input from the output of that command. 2020-08-25 drh Add support for the sqlite3_txn_state() interface. 2020-08-24 drh Reduce the N in the logN term for the sorting cost associated with computing DISTINCT by B-Tree by half, under the assumption that the DISTINCT will eliminate about half the rows of output. This is really a wild guess. But we do not have any better way of estimating what the row-count reduction due to DISTINCT will actually be. 2020-08-24 dan Correctly handle expressions like "x IS (not) true/false" within the rhs of IN() expressions. Fix for [f3ff1472]. 2020-08-20 dan Fix a crash that could occur in SQLITE_MAX_EXPR_DEPTH=0 builds when processing SQL containing syntax errors. 2020-08-20 dan Avoid a buffer overrun in test code that could occur if certain test functions were passed a hex-string containing an odd number of digits. 2020-08-19 drh Try to make SQLite easier to compiler for Mac Catalyst. See [https://sqlite.org/forum/forumpost/803387a1c5|forum post 803387a1c5]. 2020-08-19 drh Do not skip over TK_IF_NULL_ROW operators when bypassing TK_COLLATE operators. Fix to check-in [ac31edd3eeafcef4] which was itself a fix for ticket [45f4bf4eb4ffd788]. 2020-08-19 dan Update releasetest_data.tcl so that the "Fast-One" configuration runs bigmmap.test as part of release testing. 2020-08-19 dan Fix a problem in test file bigmmap.test. 2020-08-17 drh Fix the -quote option on the CLI to set the correct column separator. 2020-08-16 drh Optimization to sqlite3BeginWriteOperation(). 2020-08-15 drh Optimization of the sqlite3SrcListDelete() routine. 2020-08-15 drh Remove more unnecessary sqlite3GetVdbe() calls, replacing them with assert()s. 2020-08-15 drh Avoid unnecessary calls to the sqlite3GetVdbe() routine. Add assert() statements to prove each call is unnecessary. 2020-08-15 drh Omit the unnecessary not-NULL check on the upper bound of a forward index range scan. The subsequent OP_IdxGT will always catch the NULL. Similarly, omit the not-NULL check on the lower bound of a reverse index range scan, as the SeekLE opcode will disallow the NULL. 2020-08-14 drh Update the version number to 3.34.0 for the next development cycle. 2020-08-14 drh Optimizations to the logic that converts main table accesses into equivalent index accesses. Code is now slightly smaller and faster than trunk. 2020-08-14 drh For UPDATE and DELETE, use OP_DeferredSeek always. If the seek must later be resolved, add the OP_FinishSeek opcode after all WHERE clause terms have been processed. This obviates the need for the WHERE_SEEK_TABLE and WHERE_SEEK_UNIQ_TABLE flags to sqlite3WhereBegin() and the ensuing complication, and it allows the covering index optimization to be used further into WHERE clause processing. 2020-08-14 drh Experimental change to try to get some DELETE operations to access values using the index rather than the main table, so as to avoid unnecessary main table seeks. 2020-08-14 dan Fix an inconsequential memory leak in sqldiff. Update the "Sanitize" case in wapptest.tcl to use -fsanitize=address,undefined, and to run more tests. Created with: roll-dep src/third_party/sqlite/src Bug: 1161048 Change-Id: Ieb8f0154930d6cc0597b5aee9444678cf021035b Reviewed-by: Chris Mumford <cmumford@google.com> Commit-Queue: Darwin Huang <huangdarwin@chromium.org> Cr-Commit-Position: refs/heads/master@{#839609} Reviewed-by: Jüri Valdmann <juri.valdmann@qt.io>
-rw-r--r--chromium/DEPS2
-rw-r--r--chromium/third_party/sqlite/OWNERS3
-rw-r--r--chromium/third_party/sqlite/README.chromium4
-rw-r--r--chromium/third_party/sqlite/sqlite_common_configuration_flags.gni9
-rw-r--r--chromium/third_party/sqlite/src/Makefile.in3
-rw-r--r--chromium/third_party/sqlite/src/Makefile.msc3
-rw-r--r--chromium/third_party/sqlite/src/VERSION2
-rw-r--r--chromium/third_party/sqlite/src/amalgamation/rename_exports.h637
-rw-r--r--chromium/third_party/sqlite/src/amalgamation/shell/shell.c684
-rw-r--r--chromium/third_party/sqlite/src/amalgamation/sqlite3.c2666
-rw-r--r--chromium/third_party/sqlite/src/amalgamation/sqlite3.h79
-rw-r--r--chromium/third_party/sqlite/src/amalgamation_dev/rename_exports.h637
-rw-r--r--chromium/third_party/sqlite/src/amalgamation_dev/shell/shell.c684
-rw-r--r--chromium/third_party/sqlite/src/amalgamation_dev/sqlite3.c2683
-rw-r--r--chromium/third_party/sqlite/src/amalgamation_dev/sqlite3.h79
-rw-r--r--chromium/third_party/sqlite/src/art/sqlite370.eps12
-rw-r--r--chromium/third_party/sqlite/src/autoconf/tea/win/makefile.vc2
-rwxr-xr-xchromium/third_party/sqlite/src/configure53
-rw-r--r--chromium/third_party/sqlite/src/configure.ac5
-rw-r--r--chromium/third_party/sqlite/src/doc/lemon.html499
-rw-r--r--chromium/third_party/sqlite/src/ext/expert/expert1.test41
-rw-r--r--chromium/third_party/sqlite/src/ext/expert/sqlite3expert.c4
-rw-r--r--chromium/third_party/sqlite/src/ext/fts3/unicode/mkunicode.tcl1
-rw-r--r--chromium/third_party/sqlite/src/ext/fts5/fts5Int.h32
-rw-r--r--chromium/third_party/sqlite/src/ext/fts5/fts5_aux.c22
-rw-r--r--chromium/third_party/sqlite/src/ext/fts5/fts5_config.c6
-rw-r--r--chromium/third_party/sqlite/src/ext/fts5/fts5_expr.c271
-rw-r--r--chromium/third_party/sqlite/src/ext/fts5/fts5_hash.c4
-rw-r--r--chromium/third_party/sqlite/src/ext/fts5/fts5_index.c22
-rw-r--r--chromium/third_party/sqlite/src/ext/fts5/fts5_main.c117
-rw-r--r--chromium/third_party/sqlite/src/ext/fts5/fts5_storage.c143
-rw-r--r--chromium/third_party/sqlite/src/ext/fts5/fts5_tokenize.c128
-rw-r--r--chromium/third_party/sqlite/src/ext/fts5/fts5_unicode2.c2
-rw-r--r--chromium/third_party/sqlite/src/ext/fts5/tool/fts5txt2db.tcl2
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/carray.c189
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/cksumvfs.c37
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/csv.c2
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/series.c23
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/zipfile.c16
-rw-r--r--chromium/third_party/sqlite/src/ext/rtree/geopoly.c2
-rw-r--r--chromium/third_party/sqlite/src/ext/rtree/rtree.c2
-rw-r--r--chromium/third_party/sqlite/src/ext/session/test_session.c6
-rw-r--r--chromium/third_party/sqlite/src/main.mk2
-rw-r--r--chromium/third_party/sqlite/src/manifest303
-rw-r--r--chromium/third_party/sqlite/src/manifest.uuid2
-rw-r--r--chromium/third_party/sqlite/src/src/alter.c24
-rw-r--r--chromium/third_party/sqlite/src/src/analyze.c1
-rw-r--r--chromium/third_party/sqlite/src/src/attach.c4
-rw-r--r--chromium/third_party/sqlite/src/src/backup.c8
-rw-r--r--chromium/third_party/sqlite/src/src/btree.c34
-rw-r--r--chromium/third_party/sqlite/src/src/btree.h18
-rw-r--r--chromium/third_party/sqlite/src/src/btreeInt.h17
-rw-r--r--chromium/third_party/sqlite/src/src/build.c72
-rw-r--r--chromium/third_party/sqlite/src/src/delete.c17
-rw-r--r--chromium/third_party/sqlite/src/src/expr.c13
-rw-r--r--chromium/third_party/sqlite/src/src/func.c2
-rw-r--r--chromium/third_party/sqlite/src/src/insert.c11
-rw-r--r--chromium/third_party/sqlite/src/src/loadext.c2
-rw-r--r--chromium/third_party/sqlite/src/src/main.c63
-rw-r--r--chromium/third_party/sqlite/src/src/malloc.c24
-rw-r--r--chromium/third_party/sqlite/src/src/memdb.c19
-rw-r--r--chromium/third_party/sqlite/src/src/os_unix.c219
-rw-r--r--chromium/third_party/sqlite/src/src/os_win.c6
-rw-r--r--chromium/third_party/sqlite/src/src/pager.c17
-rw-r--r--chromium/third_party/sqlite/src/src/parse.y22
-rw-r--r--chromium/third_party/sqlite/src/src/pragma.c8
-rw-r--r--chromium/third_party/sqlite/src/src/prepare.c5
-rw-r--r--chromium/third_party/sqlite/src/src/printf.c9
-rw-r--r--chromium/third_party/sqlite/src/src/resolve.c4
-rw-r--r--chromium/third_party/sqlite/src/src/select.c124
-rw-r--r--chromium/third_party/sqlite/src/src/shell.c.in227
-rw-r--r--chromium/third_party/sqlite/src/src/sqlite.h.in73
-rw-r--r--chromium/third_party/sqlite/src/src/sqlite3ext.h4
-rw-r--r--chromium/third_party/sqlite/src/src/sqliteInt.h27
-rw-r--r--chromium/third_party/sqlite/src/src/sqliteLimit.h6
-rw-r--r--chromium/third_party/sqlite/src/src/test1.c297
-rw-r--r--chromium/third_party/sqlite/src/src/test6.c12
-rw-r--r--chromium/third_party/sqlite/src/src/test_devsym.c8
-rw-r--r--chromium/third_party/sqlite/src/src/test_hexio.c6
-rw-r--r--chromium/third_party/sqlite/src/src/test_vfs.c12
-rw-r--r--chromium/third_party/sqlite/src/src/trigger.c36
-rw-r--r--chromium/third_party/sqlite/src/src/update.c42
-rw-r--r--chromium/third_party/sqlite/src/src/util.c1
-rw-r--r--chromium/third_party/sqlite/src/src/vacuum.c4
-rw-r--r--chromium/third_party/sqlite/src/src/vdbe.c258
-rw-r--r--chromium/third_party/sqlite/src/src/vdbeInt.h2
-rw-r--r--chromium/third_party/sqlite/src/src/vdbeaux.c16
-rw-r--r--chromium/third_party/sqlite/src/src/vdbesort.c5
-rw-r--r--chromium/third_party/sqlite/src/src/where.c129
-rw-r--r--chromium/third_party/sqlite/src/src/whereInt.h8
-rw-r--r--chromium/third_party/sqlite/src/src/wherecode.c61
-rw-r--r--chromium/third_party/sqlite/src/src/whereexpr.c27
-rw-r--r--chromium/third_party/sqlite/src/tool/GetFile.cs916
-rw-r--r--chromium/third_party/sqlite/src/tool/GetTclKit.bat630
-rwxr-xr-xchromium/third_party/sqlite/src/tool/build-all-msvc.bat1718
-rw-r--r--chromium/third_party/sqlite/src/tool/lemon.c80
-rw-r--r--chromium/third_party/sqlite/src/tool/lempar.c16
-rw-r--r--chromium/third_party/sqlite/src/tool/mksqlite3c.tcl12
-rw-r--r--chromium/third_party/sqlite/src/tool/restore_jrnl.tcl62
-rw-r--r--chromium/third_party/sqlite/src/tool/sqldiff.c7
100 files changed, 10577 insertions, 4993 deletions
diff --git a/chromium/DEPS b/chromium/DEPS
index 7a447ea68d4..e38fa1458fc 100644
--- a/chromium/DEPS
+++ b/chromium/DEPS
@@ -1401,7 +1401,7 @@ deps = {
Var('chromium_git') + '/external/github.com/google/snappy.git' + '@' + 'f16eda3466633b88d0a55199deb00aa5429c6219',
'src/third_party/sqlite/src':
- Var('chromium_git') + '/chromium/deps/sqlite.git' + '@' + '0324bd3ef1af08b478c9e9f82722d7e1e565d6bc',
+ Var('chromium_git') + '/chromium/deps/sqlite.git' + '@' + 'd9581878fcf81ec8beda15b079726edaddd775bb',
'src/third_party/sqlite4java': {
'packages': [
diff --git a/chromium/third_party/sqlite/OWNERS b/chromium/third_party/sqlite/OWNERS
index 674b26214c0..578d82212d8 100644
--- a/chromium/third_party/sqlite/OWNERS
+++ b/chromium/third_party/sqlite/OWNERS
@@ -4,6 +4,3 @@ huangdarwin@chromium.org
# Secondary:
cmumford@google.com
pwnall@chromium.org
-
-# TEAM: storage-dev@chromium.org
-# COMPONENT: Internals>Storage
diff --git a/chromium/third_party/sqlite/README.chromium b/chromium/third_party/sqlite/README.chromium
index cfc1abbf033..4ae58cf99eb 100644
--- a/chromium/third_party/sqlite/README.chromium
+++ b/chromium/third_party/sqlite/README.chromium
@@ -1,7 +1,7 @@
Name: sqlite
URL: https://sqlite.org/
-Version: 3.33.0
-CPEPrefix: cpe:/a:sqlite:sqlite:3.33.0
+Version: 3.34.0
+CPEPrefix: cpe:/a:sqlite:sqlite:3.34.0
Included In Release: Yes
Security Critical: Yes
License: Public domain
diff --git a/chromium/third_party/sqlite/sqlite_common_configuration_flags.gni b/chromium/third_party/sqlite/sqlite_common_configuration_flags.gni
index fbdfb852f2e..04f1c127050 100644
--- a/chromium/third_party/sqlite/sqlite_common_configuration_flags.gni
+++ b/chromium/third_party/sqlite/sqlite_common_configuration_flags.gni
@@ -40,6 +40,15 @@ sqlite_common_configuration_flags = [
# private, so our databases use stricter settings.
"SQLITE_DEFAULT_FILE_PERMISSIONS=0600",
+ # Databases are opened in EXCLUSIVE mode by default.
+ #
+ # NORMAL mode, where a database can be used by multiple processes
+ # simultaneously, can be enabled by executing "PRAGMA locking_mode=0".
+ #
+ # https://www.sqlite.org/compile.html#default_locking_mode
+ # https://www.sqlite.org/pragma.html#pragma_locking_mode
+ "SQLITE_DEFAULT_LOCKING_MODE=1",
+
# Needed by the SQL MemoryDumpProvider.
#
# Setting this to 1 is needed to collect the information reported by
diff --git a/chromium/third_party/sqlite/src/Makefile.in b/chromium/third_party/sqlite/src/Makefile.in
index 3fc984cff7a..6ab49dbe9ae 100644
--- a/chromium/third_party/sqlite/src/Makefile.in
+++ b/chromium/third_party/sqlite/src/Makefile.in
@@ -441,6 +441,7 @@ TESTSRC += \
$(TOP)/ext/expert/test_expert.c \
$(TOP)/ext/misc/amatch.c \
$(TOP)/ext/misc/carray.c \
+ $(TOP)/ext/misc/cksumvfs.c \
$(TOP)/ext/misc/closure.c \
$(TOP)/ext/misc/csv.c \
$(TOP)/ext/misc/decimal.c \
@@ -1086,6 +1087,7 @@ SHELL_SRC = \
$(TOP)/ext/misc/decimal.c \
$(TOP)/ext/misc/fileio.c \
$(TOP)/ext/misc/ieee754.c \
+ $(TOP)/ext/misc/series.c \
$(TOP)/ext/misc/shathree.c \
$(TOP)/ext/misc/sqlar.c \
$(TOP)/ext/misc/uint.c \
@@ -1232,6 +1234,7 @@ TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_STMTVTAB
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_DBPAGE_VTAB
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_BYTECODE_VTAB
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_DESERIALIZE
+TESTFIXTURE_FLAGS += -DSQLITE_CKSUMVFS_STATIC
TESTFIXTURE_SRC0 = $(TESTSRC2) libsqlite3.la
TESTFIXTURE_SRC1 = sqlite3.c
diff --git a/chromium/third_party/sqlite/src/Makefile.msc b/chromium/third_party/sqlite/src/Makefile.msc
index 47857d9d8d0..404e3b23603 100644
--- a/chromium/third_party/sqlite/src/Makefile.msc
+++ b/chromium/third_party/sqlite/src/Makefile.msc
@@ -1558,6 +1558,7 @@ TESTEXT = \
$(TOP)\ext\expert\test_expert.c \
$(TOP)\ext\misc\amatch.c \
$(TOP)\ext\misc\carray.c \
+ $(TOP)\ext\misc\cksumvfs.c \
$(TOP)\ext\misc\closure.c \
$(TOP)\ext\misc\csv.c \
$(TOP)\ext\misc\decimal.c \
@@ -2208,6 +2209,7 @@ SHELL_SRC = \
$(TOP)\ext\misc\decimal.c \
$(TOP)\ext\misc\fileio.c \
$(TOP)\ext\misc\ieee754.c \
+ $(TOP)\ext\misc\series.c \
$(TOP)\ext\misc\shathree.c \
$(TOP)\ext\misc\uint.c \
$(TOP)\ext\expert\sqlite3expert.c \
@@ -2386,6 +2388,7 @@ TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_BYTECODE_VTAB=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_JSON1=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_DESERIALIZE=1
+TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_CKSUMVFS_STATIC=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) $(TEST_CCONV_OPTS)
TESTFIXTURE_SRC0 = $(TESTEXT) $(TESTSRC2)
diff --git a/chromium/third_party/sqlite/src/VERSION b/chromium/third_party/sqlite/src/VERSION
index 949654dc3e0..5c0e0534177 100644
--- a/chromium/third_party/sqlite/src/VERSION
+++ b/chromium/third_party/sqlite/src/VERSION
@@ -1 +1 @@
-3.33.0
+3.34.0
diff --git a/chromium/third_party/sqlite/src/amalgamation/rename_exports.h b/chromium/third_party/sqlite/src/amalgamation/rename_exports.h
index 70a6c312c7b..cd7e4ad3e79 100644
--- a/chromium/third_party/sqlite/src/amalgamation/rename_exports.h
+++ b/chromium/third_party/sqlite/src/amalgamation/rename_exports.h
@@ -7,334 +7,335 @@
#ifndef THIRD_PARTY_SQLITE_AMALGAMATION_RENAME_EXPORTS_H_
#define THIRD_PARTY_SQLITE_AMALGAMATION_RENAME_EXPORTS_H_
-#define sqlite3_activate_cerod chrome_sqlite3_activate_cerod // Lines 5956-5958
-#define sqlite3_aggregate_context chrome_sqlite3_aggregate_context // Line 5517
-#define sqlite3_aggregate_count chrome_sqlite3_aggregate_count // Line 5292
-#define sqlite3_auto_extension chrome_sqlite3_auto_extension // Line 6655
-#define sqlite3_backup_finish chrome_sqlite3_backup_finish // Line 8686
-#define sqlite3_backup_init chrome_sqlite3_backup_init // Lines 8679-8684
-#define sqlite3_backup_pagecount chrome_sqlite3_backup_pagecount // Line 8688
-#define sqlite3_backup_remaining chrome_sqlite3_backup_remaining // Line 8687
-#define sqlite3_backup_step chrome_sqlite3_backup_step // Line 8685
-#define sqlite3_bind_blob chrome_sqlite3_bind_blob // Line 4396
-#define sqlite3_bind_blob64 chrome_sqlite3_bind_blob64 // Lines 4397-4398
-#define sqlite3_bind_double chrome_sqlite3_bind_double // Line 4399
-#define sqlite3_bind_int chrome_sqlite3_bind_int // Line 4400
-#define sqlite3_bind_int64 chrome_sqlite3_bind_int64 // Line 4401
-#define sqlite3_bind_null chrome_sqlite3_bind_null // Line 4402
-#define sqlite3_bind_parameter_count chrome_sqlite3_bind_parameter_count // Line 4431
-#define sqlite3_bind_parameter_index chrome_sqlite3_bind_parameter_index // Line 4477
-#define sqlite3_bind_parameter_name chrome_sqlite3_bind_parameter_name // Line 4459
-#define sqlite3_bind_pointer chrome_sqlite3_bind_pointer // Line 4408
-#define sqlite3_bind_text chrome_sqlite3_bind_text // Line 4403
-#define sqlite3_bind_text16 chrome_sqlite3_bind_text16 // Line 4404
-#define sqlite3_bind_text64 chrome_sqlite3_bind_text64 // Lines 4405-4406
-#define sqlite3_bind_value chrome_sqlite3_bind_value // Line 4407
-#define sqlite3_bind_zeroblob chrome_sqlite3_bind_zeroblob // Line 4409
-#define sqlite3_bind_zeroblob64 chrome_sqlite3_bind_zeroblob64 // Line 4410
-#define sqlite3_blob_bytes chrome_sqlite3_blob_bytes // Line 7233
-#define sqlite3_blob_close chrome_sqlite3_blob_close // Line 7217
-#define sqlite3_blob_open chrome_sqlite3_blob_open // Lines 7161-7169
-#define sqlite3_blob_read chrome_sqlite3_blob_read // Line 7262
-#define sqlite3_blob_reopen chrome_sqlite3_blob_reopen // Line 7194
-#define sqlite3_blob_write chrome_sqlite3_blob_write // Line 7304
-#define sqlite3_busy_handler chrome_sqlite3_busy_handler // Line 2658
-#define sqlite3_busy_timeout chrome_sqlite3_busy_timeout // Line 2681
-#define sqlite3_cancel_auto_extension chrome_sqlite3_cancel_auto_extension // Line 6667
-#define sqlite3_changes chrome_sqlite3_changes // Line 2487
-#define sqlite3_clear_bindings chrome_sqlite3_clear_bindings // Line 4487
+#define sqlite3_activate_cerod chrome_sqlite3_activate_cerod // Lines 5957-5959
+#define sqlite3_aggregate_context chrome_sqlite3_aggregate_context // Line 5518
+#define sqlite3_aggregate_count chrome_sqlite3_aggregate_count // Line 5293
+#define sqlite3_auto_extension chrome_sqlite3_auto_extension // Line 6707
+#define sqlite3_backup_finish chrome_sqlite3_backup_finish // Line 8739
+#define sqlite3_backup_init chrome_sqlite3_backup_init // Lines 8732-8737
+#define sqlite3_backup_pagecount chrome_sqlite3_backup_pagecount // Line 8741
+#define sqlite3_backup_remaining chrome_sqlite3_backup_remaining // Line 8740
+#define sqlite3_backup_step chrome_sqlite3_backup_step // Line 8738
+#define sqlite3_bind_blob chrome_sqlite3_bind_blob // Line 4397
+#define sqlite3_bind_blob64 chrome_sqlite3_bind_blob64 // Lines 4398-4399
+#define sqlite3_bind_double chrome_sqlite3_bind_double // Line 4400
+#define sqlite3_bind_int chrome_sqlite3_bind_int // Line 4401
+#define sqlite3_bind_int64 chrome_sqlite3_bind_int64 // Line 4402
+#define sqlite3_bind_null chrome_sqlite3_bind_null // Line 4403
+#define sqlite3_bind_parameter_count chrome_sqlite3_bind_parameter_count // Line 4432
+#define sqlite3_bind_parameter_index chrome_sqlite3_bind_parameter_index // Line 4478
+#define sqlite3_bind_parameter_name chrome_sqlite3_bind_parameter_name // Line 4460
+#define sqlite3_bind_pointer chrome_sqlite3_bind_pointer // Line 4409
+#define sqlite3_bind_text chrome_sqlite3_bind_text // Line 4404
+#define sqlite3_bind_text16 chrome_sqlite3_bind_text16 // Line 4405
+#define sqlite3_bind_text64 chrome_sqlite3_bind_text64 // Lines 4406-4407
+#define sqlite3_bind_value chrome_sqlite3_bind_value // Line 4408
+#define sqlite3_bind_zeroblob chrome_sqlite3_bind_zeroblob // Line 4410
+#define sqlite3_bind_zeroblob64 chrome_sqlite3_bind_zeroblob64 // Line 4411
+#define sqlite3_blob_bytes chrome_sqlite3_blob_bytes // Line 7285
+#define sqlite3_blob_close chrome_sqlite3_blob_close // Line 7269
+#define sqlite3_blob_open chrome_sqlite3_blob_open // Lines 7213-7221
+#define sqlite3_blob_read chrome_sqlite3_blob_read // Line 7314
+#define sqlite3_blob_reopen chrome_sqlite3_blob_reopen // Line 7246
+#define sqlite3_blob_write chrome_sqlite3_blob_write // Line 7356
+#define sqlite3_busy_handler chrome_sqlite3_busy_handler // Line 2659
+#define sqlite3_busy_timeout chrome_sqlite3_busy_timeout // Line 2682
+#define sqlite3_cancel_auto_extension chrome_sqlite3_cancel_auto_extension // Line 6719
+#define sqlite3_changes chrome_sqlite3_changes // Line 2488
+#define sqlite3_clear_bindings chrome_sqlite3_clear_bindings // Line 4488
#define sqlite3_close chrome_sqlite3_close // Line 330
#define sqlite3_close_v2 chrome_sqlite3_close_v2 // Line 331
-#define sqlite3_collation_needed chrome_sqlite3_collation_needed // Lines 5940-5944
-#define sqlite3_collation_needed16 chrome_sqlite3_collation_needed16 // Lines 5945-5949
-#define sqlite3_column_blob chrome_sqlite3_column_blob // Line 4963
-#define sqlite3_column_bytes chrome_sqlite3_column_bytes // Line 4970
-#define sqlite3_column_bytes16 chrome_sqlite3_column_bytes16 // Line 4971
-#define sqlite3_column_count chrome_sqlite3_column_count // Line 4503
-#define sqlite3_column_database_name chrome_sqlite3_column_database_name // Line 4577
-#define sqlite3_column_database_name16 chrome_sqlite3_column_database_name16 // Line 4578
-#define sqlite3_column_decltype chrome_sqlite3_column_decltype // Line 4614
-#define sqlite3_column_decltype16 chrome_sqlite3_column_decltype16 // Line 4615
-#define sqlite3_column_double chrome_sqlite3_column_double // Line 4964
-#define sqlite3_column_int chrome_sqlite3_column_int // Line 4965
-#define sqlite3_column_int64 chrome_sqlite3_column_int64 // Line 4966
-#define sqlite3_column_name chrome_sqlite3_column_name // Line 4532
-#define sqlite3_column_name16 chrome_sqlite3_column_name16 // Line 4533
-#define sqlite3_column_origin_name chrome_sqlite3_column_origin_name // Line 4581
-#define sqlite3_column_origin_name16 chrome_sqlite3_column_origin_name16 // Line 4582
-#define sqlite3_column_table_name chrome_sqlite3_column_table_name // Line 4579
-#define sqlite3_column_table_name16 chrome_sqlite3_column_table_name16 // Line 4580
-#define sqlite3_column_text chrome_sqlite3_column_text // Line 4967
-#define sqlite3_column_text16 chrome_sqlite3_column_text16 // Line 4968
-#define sqlite3_column_type chrome_sqlite3_column_type // Line 4972
-#define sqlite3_column_value chrome_sqlite3_column_value // Line 4969
-#define sqlite3_commit_hook chrome_sqlite3_commit_hook // Line 6252
+#define sqlite3_collation_needed chrome_sqlite3_collation_needed // Lines 5941-5945
+#define sqlite3_collation_needed16 chrome_sqlite3_collation_needed16 // Lines 5946-5950
+#define sqlite3_column_blob chrome_sqlite3_column_blob // Line 4964
+#define sqlite3_column_bytes chrome_sqlite3_column_bytes // Line 4971
+#define sqlite3_column_bytes16 chrome_sqlite3_column_bytes16 // Line 4972
+#define sqlite3_column_count chrome_sqlite3_column_count // Line 4504
+#define sqlite3_column_database_name chrome_sqlite3_column_database_name // Line 4578
+#define sqlite3_column_database_name16 chrome_sqlite3_column_database_name16 // Line 4579
+#define sqlite3_column_decltype chrome_sqlite3_column_decltype // Line 4615
+#define sqlite3_column_decltype16 chrome_sqlite3_column_decltype16 // Line 4616
+#define sqlite3_column_double chrome_sqlite3_column_double // Line 4965
+#define sqlite3_column_int chrome_sqlite3_column_int // Line 4966
+#define sqlite3_column_int64 chrome_sqlite3_column_int64 // Line 4967
+#define sqlite3_column_name chrome_sqlite3_column_name // Line 4533
+#define sqlite3_column_name16 chrome_sqlite3_column_name16 // Line 4534
+#define sqlite3_column_origin_name chrome_sqlite3_column_origin_name // Line 4582
+#define sqlite3_column_origin_name16 chrome_sqlite3_column_origin_name16 // Line 4583
+#define sqlite3_column_table_name chrome_sqlite3_column_table_name // Line 4580
+#define sqlite3_column_table_name16 chrome_sqlite3_column_table_name16 // Line 4581
+#define sqlite3_column_text chrome_sqlite3_column_text // Line 4968
+#define sqlite3_column_text16 chrome_sqlite3_column_text16 // Line 4969
+#define sqlite3_column_type chrome_sqlite3_column_type // Line 4973
+#define sqlite3_column_value chrome_sqlite3_column_value // Line 4970
+#define sqlite3_commit_hook chrome_sqlite3_commit_hook // Line 6304
#define sqlite3_compileoption_get chrome_sqlite3_compileoption_get // Line 191
#define sqlite3_compileoption_used chrome_sqlite3_compileoption_used // Line 190
-#define sqlite3_complete chrome_sqlite3_complete // Line 2596
-#define sqlite3_complete16 chrome_sqlite3_complete16 // Line 2597
-#define sqlite3_config chrome_sqlite3_config // Line 1581
-#define sqlite3_context_db_handle chrome_sqlite3_context_db_handle // Line 5544
-#define sqlite3_create_collation chrome_sqlite3_create_collation // Lines 5890-5896
-#define sqlite3_create_collation16 chrome_sqlite3_create_collation16 // Lines 5905-5911
-#define sqlite3_create_collation_v2 chrome_sqlite3_create_collation_v2 // Lines 5897-5904
-#define sqlite3_create_filename chrome_sqlite3_create_filename // Lines 3705-3711
-#define sqlite3_create_function chrome_sqlite3_create_function // Lines 5154-5163
-#define sqlite3_create_function16 chrome_sqlite3_create_function16 // Lines 5164-5173
-#define sqlite3_create_function_v2 chrome_sqlite3_create_function_v2 // Lines 5174-5184
-#define sqlite3_create_module chrome_sqlite3_create_module // Lines 6947-6952
-#define sqlite3_create_module_v2 chrome_sqlite3_create_module_v2 // Lines 6953-6959
-#define sqlite3_create_window_function chrome_sqlite3_create_window_function // Lines 5185-5196
-#define sqlite3_data_count chrome_sqlite3_data_count // Line 4720
-#define sqlite3_data_directory chrome_sqlite3_data_directory // Line 6073
-#define sqlite3_database_file_object chrome_sqlite3_database_file_object // Line 3658
-#define sqlite3_db_cacheflush chrome_sqlite3_db_cacheflush // Line 9376
-#define sqlite3_db_config chrome_sqlite3_db_config // Line 1600
-#define sqlite3_db_filename chrome_sqlite3_db_filename // Line 6177
-#define sqlite3_db_handle chrome_sqlite3_db_handle // Line 6145
-#define sqlite3_db_mutex chrome_sqlite3_db_mutex // Line 7612
-#define sqlite3_db_readonly chrome_sqlite3_db_readonly // Line 6187
-#define sqlite3_db_release_memory chrome_sqlite3_db_release_memory // Line 6379
-#define sqlite3_db_status chrome_sqlite3_db_status // Line 8036
-#define sqlite3_declare_vtab chrome_sqlite3_declare_vtab // Line 7033
-#define sqlite3_deserialize chrome_sqlite3_deserialize // Lines 9770-9777
-#define sqlite3_drop_modules chrome_sqlite3_drop_modules // Lines 6973-6976
-#define sqlite3_enable_load_extension chrome_sqlite3_enable_load_extension // Line 6617
-#define sqlite3_enable_shared_cache chrome_sqlite3_enable_shared_cache // Line 6349
-#define sqlite3_errcode chrome_sqlite3_errcode // Line 3766
-#define sqlite3_errmsg chrome_sqlite3_errmsg // Line 3768
-#define sqlite3_errmsg16 chrome_sqlite3_errmsg16 // Line 3769
-#define sqlite3_errstr chrome_sqlite3_errstr // Line 3770
+#define sqlite3_complete chrome_sqlite3_complete // Line 2597
+#define sqlite3_complete16 chrome_sqlite3_complete16 // Line 2598
+#define sqlite3_config chrome_sqlite3_config // Line 1582
+#define sqlite3_context_db_handle chrome_sqlite3_context_db_handle // Line 5545
+#define sqlite3_create_collation chrome_sqlite3_create_collation // Lines 5891-5897
+#define sqlite3_create_collation16 chrome_sqlite3_create_collation16 // Lines 5906-5912
+#define sqlite3_create_collation_v2 chrome_sqlite3_create_collation_v2 // Lines 5898-5905
+#define sqlite3_create_filename chrome_sqlite3_create_filename // Lines 3706-3712
+#define sqlite3_create_function chrome_sqlite3_create_function // Lines 5155-5164
+#define sqlite3_create_function16 chrome_sqlite3_create_function16 // Lines 5165-5174
+#define sqlite3_create_function_v2 chrome_sqlite3_create_function_v2 // Lines 5175-5185
+#define sqlite3_create_module chrome_sqlite3_create_module // Lines 6999-7004
+#define sqlite3_create_module_v2 chrome_sqlite3_create_module_v2 // Lines 7005-7011
+#define sqlite3_create_window_function chrome_sqlite3_create_window_function // Lines 5186-5197
+#define sqlite3_data_count chrome_sqlite3_data_count // Line 4721
+#define sqlite3_data_directory chrome_sqlite3_data_directory // Line 6074
+#define sqlite3_database_file_object chrome_sqlite3_database_file_object // Line 3659
+#define sqlite3_db_cacheflush chrome_sqlite3_db_cacheflush // Line 9437
+#define sqlite3_db_config chrome_sqlite3_db_config // Line 1601
+#define sqlite3_db_filename chrome_sqlite3_db_filename // Line 6178
+#define sqlite3_db_handle chrome_sqlite3_db_handle // Line 6146
+#define sqlite3_db_mutex chrome_sqlite3_db_mutex // Line 7664
+#define sqlite3_db_readonly chrome_sqlite3_db_readonly // Line 6188
+#define sqlite3_db_release_memory chrome_sqlite3_db_release_memory // Line 6431
+#define sqlite3_db_status chrome_sqlite3_db_status // Line 8089
+#define sqlite3_declare_vtab chrome_sqlite3_declare_vtab // Line 7085
+#define sqlite3_deserialize chrome_sqlite3_deserialize // Lines 9833-9840
+#define sqlite3_drop_modules chrome_sqlite3_drop_modules // Lines 7025-7028
+#define sqlite3_enable_load_extension chrome_sqlite3_enable_load_extension // Line 6669
+#define sqlite3_enable_shared_cache chrome_sqlite3_enable_shared_cache // Line 6401
+#define sqlite3_errcode chrome_sqlite3_errcode // Line 3767
+#define sqlite3_errmsg chrome_sqlite3_errmsg // Line 3769
+#define sqlite3_errmsg16 chrome_sqlite3_errmsg16 // Line 3770
+#define sqlite3_errstr chrome_sqlite3_errstr // Line 3771
#define sqlite3_exec chrome_sqlite3_exec // Lines 402-408
-#define sqlite3_expanded_sql chrome_sqlite3_expanded_sql // Line 4132
-#define sqlite3_expired chrome_sqlite3_expired // Line 5293
-#define sqlite3_extended_errcode chrome_sqlite3_extended_errcode // Line 3767
-#define sqlite3_extended_result_codes chrome_sqlite3_extended_result_codes // Line 2357
-#define sqlite3_file_control chrome_sqlite3_file_control // Line 7655
-#define sqlite3_filename_database chrome_sqlite3_filename_database // Line 3637
-#define sqlite3_filename_journal chrome_sqlite3_filename_journal // Line 3638
-#define sqlite3_filename_wal chrome_sqlite3_filename_wal // Line 3639
-#define sqlite3_finalize chrome_sqlite3_finalize // Line 5000
-#define sqlite3_free chrome_sqlite3_free // Line 2890
-#define sqlite3_free_filename chrome_sqlite3_free_filename // Line 3712
-#define sqlite3_free_table chrome_sqlite3_free_table // Line 2764
-#define sqlite3_get_autocommit chrome_sqlite3_get_autocommit // Line 6132
-#define sqlite3_get_auxdata chrome_sqlite3_get_auxdata // Line 5603
-#define sqlite3_get_table chrome_sqlite3_get_table // Lines 2756-2763
-#define sqlite3_global_recover chrome_sqlite3_global_recover // Line 5295
-#define sqlite3_hard_heap_limit64 chrome_sqlite3_hard_heap_limit64 // Line 6446
-#define sqlite3_initialize chrome_sqlite3_initialize // Line 1545
-#define sqlite3_interrupt chrome_sqlite3_interrupt // Line 2561
-#define sqlite3_keyword_check chrome_sqlite3_keyword_check // Line 7766
-#define sqlite3_keyword_count chrome_sqlite3_keyword_count // Line 7764
-#define sqlite3_keyword_name chrome_sqlite3_keyword_name // Line 7765
-#define sqlite3_last_insert_rowid chrome_sqlite3_last_insert_rowid // Line 2419
+#define sqlite3_expanded_sql chrome_sqlite3_expanded_sql // Line 4133
+#define sqlite3_expired chrome_sqlite3_expired // Line 5294
+#define sqlite3_extended_errcode chrome_sqlite3_extended_errcode // Line 3768
+#define sqlite3_extended_result_codes chrome_sqlite3_extended_result_codes // Line 2358
+#define sqlite3_file_control chrome_sqlite3_file_control // Line 7707
+#define sqlite3_filename_database chrome_sqlite3_filename_database // Line 3638
+#define sqlite3_filename_journal chrome_sqlite3_filename_journal // Line 3639
+#define sqlite3_filename_wal chrome_sqlite3_filename_wal // Line 3640
+#define sqlite3_finalize chrome_sqlite3_finalize // Line 5001
+#define sqlite3_free chrome_sqlite3_free // Line 2891
+#define sqlite3_free_filename chrome_sqlite3_free_filename // Line 3713
+#define sqlite3_free_table chrome_sqlite3_free_table // Line 2765
+#define sqlite3_get_autocommit chrome_sqlite3_get_autocommit // Line 6133
+#define sqlite3_get_auxdata chrome_sqlite3_get_auxdata // Line 5604
+#define sqlite3_get_table chrome_sqlite3_get_table // Lines 2757-2764
+#define sqlite3_global_recover chrome_sqlite3_global_recover // Line 5296
+#define sqlite3_hard_heap_limit64 chrome_sqlite3_hard_heap_limit64 // Line 6498
+#define sqlite3_initialize chrome_sqlite3_initialize // Line 1546
+#define sqlite3_interrupt chrome_sqlite3_interrupt // Line 2562
+#define sqlite3_keyword_check chrome_sqlite3_keyword_check // Line 7819
+#define sqlite3_keyword_count chrome_sqlite3_keyword_count // Line 7817
+#define sqlite3_keyword_name chrome_sqlite3_keyword_name // Line 7818
+#define sqlite3_last_insert_rowid chrome_sqlite3_last_insert_rowid // Line 2420
#define sqlite3_libversion chrome_sqlite3_libversion // Line 163
#define sqlite3_libversion_number chrome_sqlite3_libversion_number // Line 165
-#define sqlite3_limit chrome_sqlite3_limit // Line 3838
-#define sqlite3_load_extension chrome_sqlite3_load_extension // Lines 6585-6590
-#define sqlite3_log chrome_sqlite3_log // Line 8884
-#define sqlite3_malloc chrome_sqlite3_malloc // Line 2886
-#define sqlite3_malloc64 chrome_sqlite3_malloc64 // Line 2887
-#define sqlite3_memory_alarm chrome_sqlite3_memory_alarm // Lines 5297-5298
-#define sqlite3_memory_highwater chrome_sqlite3_memory_highwater // Line 2917
-#define sqlite3_memory_used chrome_sqlite3_memory_used // Line 2916
-#define sqlite3_mprintf chrome_sqlite3_mprintf // Line 2806
-#define sqlite3_msize chrome_sqlite3_msize // Line 2891
-#define sqlite3_mutex_alloc chrome_sqlite3_mutex_alloc // Line 7453
-#define sqlite3_mutex_enter chrome_sqlite3_mutex_enter // Line 7455
-#define sqlite3_mutex_free chrome_sqlite3_mutex_free // Line 7454
-#define sqlite3_mutex_held chrome_sqlite3_mutex_held // Line 7567
-#define sqlite3_mutex_leave chrome_sqlite3_mutex_leave // Line 7457
-#define sqlite3_mutex_notheld chrome_sqlite3_mutex_notheld // Line 7568
-#define sqlite3_mutex_try chrome_sqlite3_mutex_try // Line 7456
-#define sqlite3_next_stmt chrome_sqlite3_next_stmt // Line 6203
-#define sqlite3_normalized_sql chrome_sqlite3_normalized_sql // Line 4133
-#define sqlite3_open chrome_sqlite3_open // Lines 3524-3527
-#define sqlite3_open16 chrome_sqlite3_open16 // Lines 3528-3531
-#define sqlite3_open_v2 chrome_sqlite3_open_v2 // Lines 3532-3537
-#define sqlite3_os_end chrome_sqlite3_os_end // Line 1548
-#define sqlite3_os_init chrome_sqlite3_os_init // Line 1547
-#define sqlite3_overload_function chrome_sqlite3_overload_function // Line 7052
-#define sqlite3_prepare chrome_sqlite3_prepare // Lines 4048-4054
-#define sqlite3_prepare16 chrome_sqlite3_prepare16 // Lines 4070-4076
-#define sqlite3_prepare16_v2 chrome_sqlite3_prepare16_v2 // Lines 4077-4083
-#define sqlite3_prepare16_v3 chrome_sqlite3_prepare16_v3 // Lines 4084-4091
-#define sqlite3_prepare_v2 chrome_sqlite3_prepare_v2 // Lines 4055-4061
-#define sqlite3_prepare_v3 chrome_sqlite3_prepare_v3 // Lines 4062-4069
-#define sqlite3_preupdate_count chrome_sqlite3_preupdate_count // Line 9475
-#define sqlite3_preupdate_depth chrome_sqlite3_preupdate_depth // Line 9476
-#define sqlite3_preupdate_hook chrome_sqlite3_preupdate_hook // Lines 9461-9473
-#define sqlite3_preupdate_new chrome_sqlite3_preupdate_new // Line 9477
-#define sqlite3_preupdate_old chrome_sqlite3_preupdate_old // Line 9474
-#define sqlite3_profile chrome_sqlite3_profile // Lines 3141-3142
-#define sqlite3_progress_handler chrome_sqlite3_progress_handler // Line 3269
-#define sqlite3_randomness chrome_sqlite3_randomness // Line 2940
-#define sqlite3_realloc chrome_sqlite3_realloc // Line 2888
-#define sqlite3_realloc64 chrome_sqlite3_realloc64 // Line 2889
-#define sqlite3_release_memory chrome_sqlite3_release_memory // Line 6365
-#define sqlite3_reset chrome_sqlite3_reset // Line 5027
-#define sqlite3_reset_auto_extension chrome_sqlite3_reset_auto_extension // Line 6675
-#define sqlite3_result_blob chrome_sqlite3_result_blob // Line 5771
-#define sqlite3_result_blob64 chrome_sqlite3_result_blob64 // Lines 5772-5773
-#define sqlite3_result_double chrome_sqlite3_result_double // Line 5774
-#define sqlite3_result_error chrome_sqlite3_result_error // Line 5775
-#define sqlite3_result_error16 chrome_sqlite3_result_error16 // Line 5776
-#define sqlite3_result_error_code chrome_sqlite3_result_error_code // Line 5779
-#define sqlite3_result_error_nomem chrome_sqlite3_result_error_nomem // Line 5778
-#define sqlite3_result_error_toobig chrome_sqlite3_result_error_toobig // Line 5777
-#define sqlite3_result_int chrome_sqlite3_result_int // Line 5780
-#define sqlite3_result_int64 chrome_sqlite3_result_int64 // Line 5781
-#define sqlite3_result_null chrome_sqlite3_result_null // Line 5782
-#define sqlite3_result_pointer chrome_sqlite3_result_pointer // Line 5790
-#define sqlite3_result_subtype chrome_sqlite3_result_subtype // Line 5807
-#define sqlite3_result_text chrome_sqlite3_result_text // Line 5783
-#define sqlite3_result_text16 chrome_sqlite3_result_text16 // Line 5786
-#define sqlite3_result_text16be chrome_sqlite3_result_text16be // Line 5788
-#define sqlite3_result_text16le chrome_sqlite3_result_text16le // Line 5787
-#define sqlite3_result_text64 chrome_sqlite3_result_text64 // Lines 5784-5785
-#define sqlite3_result_value chrome_sqlite3_result_value // Line 5789
-#define sqlite3_result_zeroblob chrome_sqlite3_result_zeroblob // Line 5791
-#define sqlite3_result_zeroblob64 chrome_sqlite3_result_zeroblob64 // Line 5792
-#define sqlite3_rollback_hook chrome_sqlite3_rollback_hook // Line 6253
-#define sqlite3_rtree_geometry_callback chrome_sqlite3_rtree_geometry_callback // Lines 9857-9862
-#define sqlite3_rtree_query_callback chrome_sqlite3_rtree_query_callback // Lines 9883-9889
-#define sqlite3_serialize chrome_sqlite3_serialize // Lines 9718-9723
-#define sqlite3_set_authorizer chrome_sqlite3_set_authorizer // Lines 3031-3035
-#define sqlite3_set_auxdata chrome_sqlite3_set_auxdata // Line 5604
-#define sqlite3_set_last_insert_rowid chrome_sqlite3_set_last_insert_rowid // Line 2429
-#define sqlite3_shutdown chrome_sqlite3_shutdown // Line 1546
-#define sqlite3_sleep chrome_sqlite3_sleep // Line 5978
-#define sqlite3_snapshot_cmp chrome_sqlite3_snapshot_cmp // Lines 9652-9655
-#define sqlite3_snapshot_free chrome_sqlite3_snapshot_free // Line 9625
-#define sqlite3_snapshot_get chrome_sqlite3_snapshot_get // Lines 9559-9563
-#define sqlite3_snapshot_open chrome_sqlite3_snapshot_open // Lines 9608-9612
-#define sqlite3_snapshot_recover chrome_sqlite3_snapshot_recover // Line 9680
-#define sqlite3_snprintf chrome_sqlite3_snprintf // Line 2808
-#define sqlite3_soft_heap_limit chrome_sqlite3_soft_heap_limit // Line 6457
-#define sqlite3_soft_heap_limit64 chrome_sqlite3_soft_heap_limit64 // Line 6445
+#define sqlite3_limit chrome_sqlite3_limit // Line 3839
+#define sqlite3_load_extension chrome_sqlite3_load_extension // Lines 6637-6642
+#define sqlite3_log chrome_sqlite3_log // Line 8937
+#define sqlite3_malloc chrome_sqlite3_malloc // Line 2887
+#define sqlite3_malloc64 chrome_sqlite3_malloc64 // Line 2888
+#define sqlite3_memory_alarm chrome_sqlite3_memory_alarm // Lines 5298-5299
+#define sqlite3_memory_highwater chrome_sqlite3_memory_highwater // Line 2918
+#define sqlite3_memory_used chrome_sqlite3_memory_used // Line 2917
+#define sqlite3_mprintf chrome_sqlite3_mprintf // Line 2807
+#define sqlite3_msize chrome_sqlite3_msize // Line 2892
+#define sqlite3_mutex_alloc chrome_sqlite3_mutex_alloc // Line 7505
+#define sqlite3_mutex_enter chrome_sqlite3_mutex_enter // Line 7507
+#define sqlite3_mutex_free chrome_sqlite3_mutex_free // Line 7506
+#define sqlite3_mutex_held chrome_sqlite3_mutex_held // Line 7619
+#define sqlite3_mutex_leave chrome_sqlite3_mutex_leave // Line 7509
+#define sqlite3_mutex_notheld chrome_sqlite3_mutex_notheld // Line 7620
+#define sqlite3_mutex_try chrome_sqlite3_mutex_try // Line 7508
+#define sqlite3_next_stmt chrome_sqlite3_next_stmt // Line 6255
+#define sqlite3_normalized_sql chrome_sqlite3_normalized_sql // Line 4134
+#define sqlite3_open chrome_sqlite3_open // Lines 3525-3528
+#define sqlite3_open16 chrome_sqlite3_open16 // Lines 3529-3532
+#define sqlite3_open_v2 chrome_sqlite3_open_v2 // Lines 3533-3538
+#define sqlite3_os_end chrome_sqlite3_os_end // Line 1549
+#define sqlite3_os_init chrome_sqlite3_os_init // Line 1548
+#define sqlite3_overload_function chrome_sqlite3_overload_function // Line 7104
+#define sqlite3_prepare chrome_sqlite3_prepare // Lines 4049-4055
+#define sqlite3_prepare16 chrome_sqlite3_prepare16 // Lines 4071-4077
+#define sqlite3_prepare16_v2 chrome_sqlite3_prepare16_v2 // Lines 4078-4084
+#define sqlite3_prepare16_v3 chrome_sqlite3_prepare16_v3 // Lines 4085-4092
+#define sqlite3_prepare_v2 chrome_sqlite3_prepare_v2 // Lines 4056-4062
+#define sqlite3_prepare_v3 chrome_sqlite3_prepare_v3 // Lines 4063-4070
+#define sqlite3_preupdate_count chrome_sqlite3_preupdate_count // Line 9537
+#define sqlite3_preupdate_depth chrome_sqlite3_preupdate_depth // Line 9538
+#define sqlite3_preupdate_hook chrome_sqlite3_preupdate_hook // Lines 9523-9535
+#define sqlite3_preupdate_new chrome_sqlite3_preupdate_new // Line 9539
+#define sqlite3_preupdate_old chrome_sqlite3_preupdate_old // Line 9536
+#define sqlite3_profile chrome_sqlite3_profile // Lines 3142-3143
+#define sqlite3_progress_handler chrome_sqlite3_progress_handler // Line 3270
+#define sqlite3_randomness chrome_sqlite3_randomness // Line 2941
+#define sqlite3_realloc chrome_sqlite3_realloc // Line 2889
+#define sqlite3_realloc64 chrome_sqlite3_realloc64 // Line 2890
+#define sqlite3_release_memory chrome_sqlite3_release_memory // Line 6417
+#define sqlite3_reset chrome_sqlite3_reset // Line 5028
+#define sqlite3_reset_auto_extension chrome_sqlite3_reset_auto_extension // Line 6727
+#define sqlite3_result_blob chrome_sqlite3_result_blob // Line 5772
+#define sqlite3_result_blob64 chrome_sqlite3_result_blob64 // Lines 5773-5774
+#define sqlite3_result_double chrome_sqlite3_result_double // Line 5775
+#define sqlite3_result_error chrome_sqlite3_result_error // Line 5776
+#define sqlite3_result_error16 chrome_sqlite3_result_error16 // Line 5777
+#define sqlite3_result_error_code chrome_sqlite3_result_error_code // Line 5780
+#define sqlite3_result_error_nomem chrome_sqlite3_result_error_nomem // Line 5779
+#define sqlite3_result_error_toobig chrome_sqlite3_result_error_toobig // Line 5778
+#define sqlite3_result_int chrome_sqlite3_result_int // Line 5781
+#define sqlite3_result_int64 chrome_sqlite3_result_int64 // Line 5782
+#define sqlite3_result_null chrome_sqlite3_result_null // Line 5783
+#define sqlite3_result_pointer chrome_sqlite3_result_pointer // Line 5791
+#define sqlite3_result_subtype chrome_sqlite3_result_subtype // Line 5808
+#define sqlite3_result_text chrome_sqlite3_result_text // Line 5784
+#define sqlite3_result_text16 chrome_sqlite3_result_text16 // Line 5787
+#define sqlite3_result_text16be chrome_sqlite3_result_text16be // Line 5789
+#define sqlite3_result_text16le chrome_sqlite3_result_text16le // Line 5788
+#define sqlite3_result_text64 chrome_sqlite3_result_text64 // Lines 5785-5786
+#define sqlite3_result_value chrome_sqlite3_result_value // Line 5790
+#define sqlite3_result_zeroblob chrome_sqlite3_result_zeroblob // Line 5792
+#define sqlite3_result_zeroblob64 chrome_sqlite3_result_zeroblob64 // Line 5793
+#define sqlite3_rollback_hook chrome_sqlite3_rollback_hook // Line 6305
+#define sqlite3_rtree_geometry_callback chrome_sqlite3_rtree_geometry_callback // Lines 9920-9925
+#define sqlite3_rtree_query_callback chrome_sqlite3_rtree_query_callback // Lines 9946-9952
+#define sqlite3_serialize chrome_sqlite3_serialize // Lines 9781-9786
+#define sqlite3_set_authorizer chrome_sqlite3_set_authorizer // Lines 3032-3036
+#define sqlite3_set_auxdata chrome_sqlite3_set_auxdata // Line 5605
+#define sqlite3_set_last_insert_rowid chrome_sqlite3_set_last_insert_rowid // Line 2430
+#define sqlite3_shutdown chrome_sqlite3_shutdown // Line 1547
+#define sqlite3_sleep chrome_sqlite3_sleep // Line 5979
+#define sqlite3_snapshot_cmp chrome_sqlite3_snapshot_cmp // Lines 9715-9718
+#define sqlite3_snapshot_free chrome_sqlite3_snapshot_free // Line 9688
+#define sqlite3_snapshot_get chrome_sqlite3_snapshot_get // Lines 9622-9626
+#define sqlite3_snapshot_open chrome_sqlite3_snapshot_open // Lines 9671-9675
+#define sqlite3_snapshot_recover chrome_sqlite3_snapshot_recover // Line 9743
+#define sqlite3_snprintf chrome_sqlite3_snprintf // Line 2809
+#define sqlite3_soft_heap_limit chrome_sqlite3_soft_heap_limit // Line 6509
+#define sqlite3_soft_heap_limit64 chrome_sqlite3_soft_heap_limit64 // Line 6497
#define sqlite3_sourceid chrome_sqlite3_sourceid // Line 164
-#define sqlite3_sql chrome_sqlite3_sql // Line 4131
-#define sqlite3_status chrome_sqlite3_status // Line 7926
-#define sqlite3_status64 chrome_sqlite3_status64 // Lines 7927-7932
-#define sqlite3_step chrome_sqlite3_step // Line 4699
-#define sqlite3_stmt_busy chrome_sqlite3_stmt_busy // Line 4202
-#define sqlite3_stmt_isexplain chrome_sqlite3_stmt_isexplain // Line 4181
-#define sqlite3_stmt_readonly chrome_sqlite3_stmt_readonly // Line 4169
-#define sqlite3_stmt_scanstatus chrome_sqlite3_stmt_scanstatus // Lines 9328-9333
-#define sqlite3_stmt_scanstatus_reset chrome_sqlite3_stmt_scanstatus_reset // Line 9344
-#define sqlite3_stmt_status chrome_sqlite3_stmt_status // Line 8189
-#define sqlite3_str_append chrome_sqlite3_str_append // Line 7862
-#define sqlite3_str_appendall chrome_sqlite3_str_appendall // Line 7863
-#define sqlite3_str_appendchar chrome_sqlite3_str_appendchar // Line 7864
-#define sqlite3_str_appendf chrome_sqlite3_str_appendf // Line 7860
-#define sqlite3_str_errcode chrome_sqlite3_str_errcode // Line 7896
-#define sqlite3_str_finish chrome_sqlite3_str_finish // Line 7826
-#define sqlite3_str_length chrome_sqlite3_str_length // Line 7897
-#define sqlite3_str_new chrome_sqlite3_str_new // Line 7811
-#define sqlite3_str_reset chrome_sqlite3_str_reset // Line 7865
-#define sqlite3_str_value chrome_sqlite3_str_value // Line 7898
-#define sqlite3_str_vappendf chrome_sqlite3_str_vappendf // Line 7861
-#define sqlite3_strglob chrome_sqlite3_strglob // Line 8838
-#define sqlite3_stricmp chrome_sqlite3_stricmp // Line 8820
-#define sqlite3_strlike chrome_sqlite3_strlike // Line 8861
-#define sqlite3_strnicmp chrome_sqlite3_strnicmp // Line 8821
-#define sqlite3_system_errno chrome_sqlite3_system_errno // Line 9490
-#define sqlite3_table_column_metadata chrome_sqlite3_table_column_metadata // Lines 6529-6539
-#define sqlite3_temp_directory chrome_sqlite3_temp_directory // Line 6036
-#define sqlite3_test_control chrome_sqlite3_test_control // Line 7674
-#define sqlite3_thread_cleanup chrome_sqlite3_thread_cleanup // Line 5296
+#define sqlite3_sql chrome_sqlite3_sql // Line 4132
+#define sqlite3_status chrome_sqlite3_status // Line 7979
+#define sqlite3_status64 chrome_sqlite3_status64 // Lines 7980-7985
+#define sqlite3_step chrome_sqlite3_step // Line 4700
+#define sqlite3_stmt_busy chrome_sqlite3_stmt_busy // Line 4203
+#define sqlite3_stmt_isexplain chrome_sqlite3_stmt_isexplain // Line 4182
+#define sqlite3_stmt_readonly chrome_sqlite3_stmt_readonly // Line 4170
+#define sqlite3_stmt_scanstatus chrome_sqlite3_stmt_scanstatus // Lines 9388-9393
+#define sqlite3_stmt_scanstatus_reset chrome_sqlite3_stmt_scanstatus_reset // Line 9404
+#define sqlite3_stmt_status chrome_sqlite3_stmt_status // Line 8242
+#define sqlite3_str_append chrome_sqlite3_str_append // Line 7915
+#define sqlite3_str_appendall chrome_sqlite3_str_appendall // Line 7916
+#define sqlite3_str_appendchar chrome_sqlite3_str_appendchar // Line 7917
+#define sqlite3_str_appendf chrome_sqlite3_str_appendf // Line 7913
+#define sqlite3_str_errcode chrome_sqlite3_str_errcode // Line 7949
+#define sqlite3_str_finish chrome_sqlite3_str_finish // Line 7879
+#define sqlite3_str_length chrome_sqlite3_str_length // Line 7950
+#define sqlite3_str_new chrome_sqlite3_str_new // Line 7864
+#define sqlite3_str_reset chrome_sqlite3_str_reset // Line 7918
+#define sqlite3_str_value chrome_sqlite3_str_value // Line 7951
+#define sqlite3_str_vappendf chrome_sqlite3_str_vappendf // Line 7914
+#define sqlite3_strglob chrome_sqlite3_strglob // Line 8891
+#define sqlite3_stricmp chrome_sqlite3_stricmp // Line 8873
+#define sqlite3_strlike chrome_sqlite3_strlike // Line 8914
+#define sqlite3_strnicmp chrome_sqlite3_strnicmp // Line 8874
+#define sqlite3_system_errno chrome_sqlite3_system_errno // Line 9553
+#define sqlite3_table_column_metadata chrome_sqlite3_table_column_metadata // Lines 6581-6591
+#define sqlite3_temp_directory chrome_sqlite3_temp_directory // Line 6037
+#define sqlite3_test_control chrome_sqlite3_test_control // Line 7726
+#define sqlite3_thread_cleanup chrome_sqlite3_thread_cleanup // Line 5297
#define sqlite3_threadsafe chrome_sqlite3_threadsafe // Line 233
-#define sqlite3_total_changes chrome_sqlite3_total_changes // Line 2524
-#define sqlite3_trace chrome_sqlite3_trace // Lines 3139-3140
-#define sqlite3_trace_v2 chrome_sqlite3_trace_v2 // Lines 3230-3235
-#define sqlite3_transfer_bindings chrome_sqlite3_transfer_bindings // Line 5294
-#define sqlite3_unlock_notify chrome_sqlite3_unlock_notify // Lines 8805-8809
-#define sqlite3_update_hook chrome_sqlite3_update_hook // Lines 6304-6308
-#define sqlite3_uri_boolean chrome_sqlite3_uri_boolean // Line 3606
-#define sqlite3_uri_int64 chrome_sqlite3_uri_int64 // Line 3607
-#define sqlite3_uri_key chrome_sqlite3_uri_key // Line 3608
-#define sqlite3_uri_parameter chrome_sqlite3_uri_parameter // Line 3605
-#define sqlite3_user_data chrome_sqlite3_user_data // Line 5532
-#define sqlite3_value_blob chrome_sqlite3_value_blob // Line 5429
-#define sqlite3_value_bytes chrome_sqlite3_value_bytes // Line 5438
-#define sqlite3_value_bytes16 chrome_sqlite3_value_bytes16 // Line 5439
-#define sqlite3_value_double chrome_sqlite3_value_double // Line 5430
-#define sqlite3_value_dup chrome_sqlite3_value_dup // Line 5471
-#define sqlite3_value_free chrome_sqlite3_value_free // Line 5472
-#define sqlite3_value_frombind chrome_sqlite3_value_frombind // Line 5443
-#define sqlite3_value_int chrome_sqlite3_value_int // Line 5431
-#define sqlite3_value_int64 chrome_sqlite3_value_int64 // Line 5432
-#define sqlite3_value_nochange chrome_sqlite3_value_nochange // Line 5442
-#define sqlite3_value_numeric_type chrome_sqlite3_value_numeric_type // Line 5441
-#define sqlite3_value_pointer chrome_sqlite3_value_pointer // Line 5433
-#define sqlite3_value_subtype chrome_sqlite3_value_subtype // Line 5455
-#define sqlite3_value_text chrome_sqlite3_value_text // Line 5434
-#define sqlite3_value_text16 chrome_sqlite3_value_text16 // Line 5435
-#define sqlite3_value_text16be chrome_sqlite3_value_text16be // Line 5437
-#define sqlite3_value_text16le chrome_sqlite3_value_text16le // Line 5436
-#define sqlite3_value_type chrome_sqlite3_value_type // Line 5440
+#define sqlite3_total_changes chrome_sqlite3_total_changes // Line 2525
+#define sqlite3_trace chrome_sqlite3_trace // Lines 3140-3141
+#define sqlite3_trace_v2 chrome_sqlite3_trace_v2 // Lines 3231-3236
+#define sqlite3_transfer_bindings chrome_sqlite3_transfer_bindings // Line 5295
+#define sqlite3_txn_state chrome_sqlite3_txn_state // Line 6206
+#define sqlite3_unlock_notify chrome_sqlite3_unlock_notify // Lines 8858-8862
+#define sqlite3_update_hook chrome_sqlite3_update_hook // Lines 6356-6360
+#define sqlite3_uri_boolean chrome_sqlite3_uri_boolean // Line 3607
+#define sqlite3_uri_int64 chrome_sqlite3_uri_int64 // Line 3608
+#define sqlite3_uri_key chrome_sqlite3_uri_key // Line 3609
+#define sqlite3_uri_parameter chrome_sqlite3_uri_parameter // Line 3606
+#define sqlite3_user_data chrome_sqlite3_user_data // Line 5533
+#define sqlite3_value_blob chrome_sqlite3_value_blob // Line 5430
+#define sqlite3_value_bytes chrome_sqlite3_value_bytes // Line 5439
+#define sqlite3_value_bytes16 chrome_sqlite3_value_bytes16 // Line 5440
+#define sqlite3_value_double chrome_sqlite3_value_double // Line 5431
+#define sqlite3_value_dup chrome_sqlite3_value_dup // Line 5472
+#define sqlite3_value_free chrome_sqlite3_value_free // Line 5473
+#define sqlite3_value_frombind chrome_sqlite3_value_frombind // Line 5444
+#define sqlite3_value_int chrome_sqlite3_value_int // Line 5432
+#define sqlite3_value_int64 chrome_sqlite3_value_int64 // Line 5433
+#define sqlite3_value_nochange chrome_sqlite3_value_nochange // Line 5443
+#define sqlite3_value_numeric_type chrome_sqlite3_value_numeric_type // Line 5442
+#define sqlite3_value_pointer chrome_sqlite3_value_pointer // Line 5434
+#define sqlite3_value_subtype chrome_sqlite3_value_subtype // Line 5456
+#define sqlite3_value_text chrome_sqlite3_value_text // Line 5435
+#define sqlite3_value_text16 chrome_sqlite3_value_text16 // Line 5436
+#define sqlite3_value_text16be chrome_sqlite3_value_text16be // Line 5438
+#define sqlite3_value_text16le chrome_sqlite3_value_text16le // Line 5437
+#define sqlite3_value_type chrome_sqlite3_value_type // Line 5441
#define sqlite3_version chrome_sqlite3_version // Line 162
-#define sqlite3_vfs_find chrome_sqlite3_vfs_find // Line 7335
-#define sqlite3_vfs_register chrome_sqlite3_vfs_register // Line 7336
-#define sqlite3_vfs_unregister chrome_sqlite3_vfs_unregister // Line 7337
-#define sqlite3_vmprintf chrome_sqlite3_vmprintf // Line 2807
-#define sqlite3_vsnprintf chrome_sqlite3_vsnprintf // Line 2809
-#define sqlite3_vtab_collation chrome_sqlite3_vtab_collation // Line 9223
-#define sqlite3_vtab_config chrome_sqlite3_vtab_config // Line 9111
-#define sqlite3_vtab_nochange chrome_sqlite3_vtab_nochange // Line 9208
-#define sqlite3_vtab_on_conflict chrome_sqlite3_vtab_on_conflict // Line 9189
-#define sqlite3_wal_autocheckpoint chrome_sqlite3_wal_autocheckpoint // Line 8955
-#define sqlite3_wal_checkpoint chrome_sqlite3_wal_checkpoint // Line 8977
-#define sqlite3_wal_checkpoint_v2 chrome_sqlite3_wal_checkpoint_v2 // Lines 9071-9077
-#define sqlite3_wal_hook chrome_sqlite3_wal_hook // Lines 8920-8924
-#define sqlite3_win32_set_directory chrome_sqlite3_win32_set_directory // Lines 6094-6097
-#define sqlite3_win32_set_directory16 chrome_sqlite3_win32_set_directory16 // Line 6099
-#define sqlite3_win32_set_directory8 chrome_sqlite3_win32_set_directory8 // Line 6098
-#define sqlite3changegroup_add chrome_sqlite3changegroup_add // Line 10870
-#define sqlite3changegroup_add_strm chrome_sqlite3changegroup_add_strm // Lines 11532-11535
-#define sqlite3changegroup_delete chrome_sqlite3changegroup_delete // Line 10907
-#define sqlite3changegroup_new chrome_sqlite3changegroup_new // Line 10792
-#define sqlite3changegroup_output chrome_sqlite3changegroup_output // Lines 10897-10901
-#define sqlite3changegroup_output_strm chrome_sqlite3changegroup_output_strm // Lines 11536-11539
-#define sqlite3changeset_apply chrome_sqlite3changeset_apply // Lines 11067-11081
-#define sqlite3changeset_apply_strm chrome_sqlite3changeset_apply_strm // Lines 11465-11479
-#define sqlite3changeset_apply_v2 chrome_sqlite3changeset_apply_v2 // Lines 11082-11098
-#define sqlite3changeset_apply_v2_strm chrome_sqlite3changeset_apply_v2_strm // Lines 11480-11496
-#define sqlite3changeset_concat chrome_sqlite3changeset_concat // Lines 10738-10745
-#define sqlite3changeset_concat_strm chrome_sqlite3changeset_concat_strm // Lines 11497-11504
-#define sqlite3changeset_conflict chrome_sqlite3changeset_conflict // Lines 10624-10628
-#define sqlite3changeset_finalize chrome_sqlite3changeset_finalize // Line 10677
-#define sqlite3changeset_fk_conflicts chrome_sqlite3changeset_fk_conflicts // Lines 10641-10644
-#define sqlite3changeset_invert chrome_sqlite3changeset_invert // Lines 10707-10710
-#define sqlite3changeset_invert_strm chrome_sqlite3changeset_invert_strm // Lines 11505-11510
-#define sqlite3changeset_new chrome_sqlite3changeset_new // Lines 10596-10600
-#define sqlite3changeset_next chrome_sqlite3changeset_next // Line 10468
-#define sqlite3changeset_old chrome_sqlite3changeset_old // Lines 10562-10566
-#define sqlite3changeset_op chrome_sqlite3changeset_op // Lines 10497-10503
-#define sqlite3changeset_pk chrome_sqlite3changeset_pk // Lines 10531-10535
-#define sqlite3changeset_start chrome_sqlite3changeset_start // Lines 10419-10423
-#define sqlite3changeset_start_strm chrome_sqlite3changeset_start_strm // Lines 11511-11515
-#define sqlite3changeset_start_v2 chrome_sqlite3changeset_start_v2 // Lines 10424-10429
-#define sqlite3changeset_start_v2_strm chrome_sqlite3changeset_start_v2_strm // Lines 11516-11521
-#define sqlite3rebaser_configure chrome_sqlite3rebaser_configure // Lines 11340-11343
-#define sqlite3rebaser_create chrome_sqlite3rebaser_create // Line 11329
-#define sqlite3rebaser_delete chrome_sqlite3rebaser_delete // Line 11373
-#define sqlite3rebaser_rebase chrome_sqlite3rebaser_rebase // Lines 11359-11363
-#define sqlite3rebaser_rebase_strm chrome_sqlite3rebaser_rebase_strm // Lines 11540-11546
-#define sqlite3session_attach chrome_sqlite3session_attach // Lines 10126-10129
-#define sqlite3session_changeset chrome_sqlite3session_changeset // Lines 10255-10259
-#define sqlite3session_changeset_strm chrome_sqlite3session_changeset_strm // Lines 11522-11526
-#define sqlite3session_config chrome_sqlite3session_config // Line 11581
-#define sqlite3session_create chrome_sqlite3session_create // Lines 9996-10000
-#define sqlite3session_delete chrome_sqlite3session_delete // Line 10015
-#define sqlite3session_diff chrome_sqlite3session_diff // Lines 10318-10323
-#define sqlite3session_enable chrome_sqlite3session_enable // Line 10036
-#define sqlite3session_indirect chrome_sqlite3session_indirect // Line 10066
-#define sqlite3session_isempty chrome_sqlite3session_isempty // Line 10376
-#define sqlite3session_patchset chrome_sqlite3session_patchset // Lines 10355-10359
-#define sqlite3session_patchset_strm chrome_sqlite3session_patchset_strm // Lines 11527-11531
-#define sqlite3session_table_filter chrome_sqlite3session_table_filter // Lines 10141-10148
+#define sqlite3_vfs_find chrome_sqlite3_vfs_find // Line 7387
+#define sqlite3_vfs_register chrome_sqlite3_vfs_register // Line 7388
+#define sqlite3_vfs_unregister chrome_sqlite3_vfs_unregister // Line 7389
+#define sqlite3_vmprintf chrome_sqlite3_vmprintf // Line 2808
+#define sqlite3_vsnprintf chrome_sqlite3_vsnprintf // Line 2810
+#define sqlite3_vtab_collation chrome_sqlite3_vtab_collation // Line 9283
+#define sqlite3_vtab_config chrome_sqlite3_vtab_config // Line 9164
+#define sqlite3_vtab_nochange chrome_sqlite3_vtab_nochange // Line 9268
+#define sqlite3_vtab_on_conflict chrome_sqlite3_vtab_on_conflict // Line 9242
+#define sqlite3_wal_autocheckpoint chrome_sqlite3_wal_autocheckpoint // Line 9008
+#define sqlite3_wal_checkpoint chrome_sqlite3_wal_checkpoint // Line 9030
+#define sqlite3_wal_checkpoint_v2 chrome_sqlite3_wal_checkpoint_v2 // Lines 9124-9130
+#define sqlite3_wal_hook chrome_sqlite3_wal_hook // Lines 8973-8977
+#define sqlite3_win32_set_directory chrome_sqlite3_win32_set_directory // Lines 6095-6098
+#define sqlite3_win32_set_directory16 chrome_sqlite3_win32_set_directory16 // Line 6100
+#define sqlite3_win32_set_directory8 chrome_sqlite3_win32_set_directory8 // Line 6099
+#define sqlite3changegroup_add chrome_sqlite3changegroup_add // Line 10933
+#define sqlite3changegroup_add_strm chrome_sqlite3changegroup_add_strm // Lines 11595-11598
+#define sqlite3changegroup_delete chrome_sqlite3changegroup_delete // Line 10970
+#define sqlite3changegroup_new chrome_sqlite3changegroup_new // Line 10855
+#define sqlite3changegroup_output chrome_sqlite3changegroup_output // Lines 10960-10964
+#define sqlite3changegroup_output_strm chrome_sqlite3changegroup_output_strm // Lines 11599-11602
+#define sqlite3changeset_apply chrome_sqlite3changeset_apply // Lines 11130-11144
+#define sqlite3changeset_apply_strm chrome_sqlite3changeset_apply_strm // Lines 11528-11542
+#define sqlite3changeset_apply_v2 chrome_sqlite3changeset_apply_v2 // Lines 11145-11161
+#define sqlite3changeset_apply_v2_strm chrome_sqlite3changeset_apply_v2_strm // Lines 11543-11559
+#define sqlite3changeset_concat chrome_sqlite3changeset_concat // Lines 10801-10808
+#define sqlite3changeset_concat_strm chrome_sqlite3changeset_concat_strm // Lines 11560-11567
+#define sqlite3changeset_conflict chrome_sqlite3changeset_conflict // Lines 10687-10691
+#define sqlite3changeset_finalize chrome_sqlite3changeset_finalize // Line 10740
+#define sqlite3changeset_fk_conflicts chrome_sqlite3changeset_fk_conflicts // Lines 10704-10707
+#define sqlite3changeset_invert chrome_sqlite3changeset_invert // Lines 10770-10773
+#define sqlite3changeset_invert_strm chrome_sqlite3changeset_invert_strm // Lines 11568-11573
+#define sqlite3changeset_new chrome_sqlite3changeset_new // Lines 10659-10663
+#define sqlite3changeset_next chrome_sqlite3changeset_next // Line 10531
+#define sqlite3changeset_old chrome_sqlite3changeset_old // Lines 10625-10629
+#define sqlite3changeset_op chrome_sqlite3changeset_op // Lines 10560-10566
+#define sqlite3changeset_pk chrome_sqlite3changeset_pk // Lines 10594-10598
+#define sqlite3changeset_start chrome_sqlite3changeset_start // Lines 10482-10486
+#define sqlite3changeset_start_strm chrome_sqlite3changeset_start_strm // Lines 11574-11578
+#define sqlite3changeset_start_v2 chrome_sqlite3changeset_start_v2 // Lines 10487-10492
+#define sqlite3changeset_start_v2_strm chrome_sqlite3changeset_start_v2_strm // Lines 11579-11584
+#define sqlite3rebaser_configure chrome_sqlite3rebaser_configure // Lines 11403-11406
+#define sqlite3rebaser_create chrome_sqlite3rebaser_create // Line 11392
+#define sqlite3rebaser_delete chrome_sqlite3rebaser_delete // Line 11436
+#define sqlite3rebaser_rebase chrome_sqlite3rebaser_rebase // Lines 11422-11426
+#define sqlite3rebaser_rebase_strm chrome_sqlite3rebaser_rebase_strm // Lines 11603-11609
+#define sqlite3session_attach chrome_sqlite3session_attach // Lines 10189-10192
+#define sqlite3session_changeset chrome_sqlite3session_changeset // Lines 10318-10322
+#define sqlite3session_changeset_strm chrome_sqlite3session_changeset_strm // Lines 11585-11589
+#define sqlite3session_config chrome_sqlite3session_config // Line 11644
+#define sqlite3session_create chrome_sqlite3session_create // Lines 10059-10063
+#define sqlite3session_delete chrome_sqlite3session_delete // Line 10078
+#define sqlite3session_diff chrome_sqlite3session_diff // Lines 10381-10386
+#define sqlite3session_enable chrome_sqlite3session_enable // Line 10099
+#define sqlite3session_indirect chrome_sqlite3session_indirect // Line 10129
+#define sqlite3session_isempty chrome_sqlite3session_isempty // Line 10439
+#define sqlite3session_patchset chrome_sqlite3session_patchset // Lines 10418-10422
+#define sqlite3session_patchset_strm chrome_sqlite3session_patchset_strm // Lines 11590-11594
+#define sqlite3session_table_filter chrome_sqlite3session_table_filter // Lines 10204-10211
#endif // THIRD_PARTY_SQLITE_AMALGAMATION_RENAME_EXPORTS_H_
diff --git a/chromium/third_party/sqlite/src/amalgamation/shell/shell.c b/chromium/third_party/sqlite/src/amalgamation/shell/shell.c
index a1a77e49fa5..c13769f5e96 100644
--- a/chromium/third_party/sqlite/src/amalgamation/shell/shell.c
+++ b/chromium/third_party/sqlite/src/amalgamation/shell/shell.c
@@ -571,8 +571,6 @@ static void utf8_width_print(FILE *pOut, int w, const char *zUtf){
int i;
int n;
int aw = w<0 ? -w : w;
- char zBuf[1000];
- if( aw>(int)sizeof(zBuf)/3 ) aw = (int)sizeof(zBuf)/3;
for(i=n=0; zUtf[i]; i++){
if( (zUtf[i]&0xc0)!=0x80 ){
n++;
@@ -5315,6 +5313,444 @@ int sqlite3_ieee_init(
}
/************************* End ../ext/misc/ieee754.c ********************/
+/************************* Begin ../ext/misc/series.c ******************/
+/*
+** 2015-08-18
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file demonstrates how to create a table-valued-function using
+** a virtual table. This demo implements the generate_series() function
+** which gives similar results to the eponymous function in PostgreSQL.
+** Examples:
+**
+** SELECT * FROM generate_series(0,100,5);
+**
+** The query above returns integers from 0 through 100 counting by steps
+** of 5.
+**
+** SELECT * FROM generate_series(0,100);
+**
+** Integers from 0 through 100 with a step size of 1.
+**
+** SELECT * FROM generate_series(20) LIMIT 10;
+**
+** Integers 20 through 29.
+**
+** HOW IT WORKS
+**
+** The generate_series "function" is really a virtual table with the
+** following schema:
+**
+** CREATE TABLE generate_series(
+** value,
+** start HIDDEN,
+** stop HIDDEN,
+** step HIDDEN
+** );
+**
+** Function arguments in queries against this virtual table are translated
+** into equality constraints against successive hidden columns. In other
+** words, the following pairs of queries are equivalent to each other:
+**
+** SELECT * FROM generate_series(0,100,5);
+** SELECT * FROM generate_series WHERE start=0 AND stop=100 AND step=5;
+**
+** SELECT * FROM generate_series(0,100);
+** SELECT * FROM generate_series WHERE start=0 AND stop=100;
+**
+** SELECT * FROM generate_series(20) LIMIT 10;
+** SELECT * FROM generate_series WHERE start=20 LIMIT 10;
+**
+** The generate_series virtual table implementation leaves the xCreate method
+** set to NULL. This means that it is not possible to do a CREATE VIRTUAL
+** TABLE command with "generate_series" as the USING argument. Instead, there
+** is a single generate_series virtual table that is always available without
+** having to be created first.
+**
+** The xBestIndex method looks for equality constraints against the hidden
+** start, stop, and step columns, and if present, it uses those constraints
+** to bound the sequence of generated values. If the equality constraints
+** are missing, it uses 0 for start, 4294967295 for stop, and 1 for step.
+** xBestIndex returns a small cost when both start and stop are available,
+** and a very large cost if either start or stop are unavailable. This
+** encourages the query planner to order joins such that the bounds of the
+** series are well-defined.
+*/
+/* #include "sqlite3ext.h" */
+SQLITE_EXTENSION_INIT1
+#include <assert.h>
+#include <string.h>
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+
+
+/* series_cursor is a subclass of sqlite3_vtab_cursor which will
+** serve as the underlying representation of a cursor that scans
+** over rows of the result
+*/
+typedef struct series_cursor series_cursor;
+struct series_cursor {
+ sqlite3_vtab_cursor base; /* Base class - must be first */
+ int isDesc; /* True to count down rather than up */
+ sqlite3_int64 iRowid; /* The rowid */
+ sqlite3_int64 iValue; /* Current value ("value") */
+ sqlite3_int64 mnValue; /* Mimimum value ("start") */
+ sqlite3_int64 mxValue; /* Maximum value ("stop") */
+ sqlite3_int64 iStep; /* Increment ("step") */
+};
+
+/*
+** The seriesConnect() method is invoked to create a new
+** series_vtab that describes the generate_series virtual table.
+**
+** Think of this routine as the constructor for series_vtab objects.
+**
+** All this routine needs to do is:
+**
+** (1) Allocate the series_vtab object and initialize all fields.
+**
+** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
+** result set of queries against generate_series will look like.
+*/
+static int seriesConnect(
+ sqlite3 *db,
+ void *pUnused,
+ int argcUnused, const char *const*argvUnused,
+ sqlite3_vtab **ppVtab,
+ char **pzErrUnused
+){
+ sqlite3_vtab *pNew;
+ int rc;
+
+/* Column numbers */
+#define SERIES_COLUMN_VALUE 0
+#define SERIES_COLUMN_START 1
+#define SERIES_COLUMN_STOP 2
+#define SERIES_COLUMN_STEP 3
+
+ (void)pUnused;
+ (void)argcUnused;
+ (void)argvUnused;
+ (void)pzErrUnused;
+ rc = sqlite3_declare_vtab(db,
+ "CREATE TABLE x(value,start hidden,stop hidden,step hidden)");
+ if( rc==SQLITE_OK ){
+ pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) );
+ if( pNew==0 ) return SQLITE_NOMEM;
+ memset(pNew, 0, sizeof(*pNew));
+ sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
+ }
+ return rc;
+}
+
+/*
+** This method is the destructor for series_cursor objects.
+*/
+static int seriesDisconnect(sqlite3_vtab *pVtab){
+ sqlite3_free(pVtab);
+ return SQLITE_OK;
+}
+
+/*
+** Constructor for a new series_cursor object.
+*/
+static int seriesOpen(sqlite3_vtab *pUnused, sqlite3_vtab_cursor **ppCursor){
+ series_cursor *pCur;
+ (void)pUnused;
+ pCur = sqlite3_malloc( sizeof(*pCur) );
+ if( pCur==0 ) return SQLITE_NOMEM;
+ memset(pCur, 0, sizeof(*pCur));
+ *ppCursor = &pCur->base;
+ return SQLITE_OK;
+}
+
+/*
+** Destructor for a series_cursor.
+*/
+static int seriesClose(sqlite3_vtab_cursor *cur){
+ sqlite3_free(cur);
+ return SQLITE_OK;
+}
+
+
+/*
+** Advance a series_cursor to its next row of output.
+*/
+static int seriesNext(sqlite3_vtab_cursor *cur){
+ series_cursor *pCur = (series_cursor*)cur;
+ if( pCur->isDesc ){
+ pCur->iValue -= pCur->iStep;
+ }else{
+ pCur->iValue += pCur->iStep;
+ }
+ pCur->iRowid++;
+ return SQLITE_OK;
+}
+
+/*
+** Return values of columns for the row at which the series_cursor
+** is currently pointing.
+*/
+static int seriesColumn(
+ sqlite3_vtab_cursor *cur, /* The cursor */
+ sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
+ int i /* Which column to return */
+){
+ series_cursor *pCur = (series_cursor*)cur;
+ sqlite3_int64 x = 0;
+ switch( i ){
+ case SERIES_COLUMN_START: x = pCur->mnValue; break;
+ case SERIES_COLUMN_STOP: x = pCur->mxValue; break;
+ case SERIES_COLUMN_STEP: x = pCur->iStep; break;
+ default: x = pCur->iValue; break;
+ }
+ sqlite3_result_int64(ctx, x);
+ return SQLITE_OK;
+}
+
+/*
+** Return the rowid for the current row. In this implementation, the
+** first row returned is assigned rowid value 1, and each subsequent
+** row a value 1 more than that of the previous.
+*/
+static int seriesRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
+ series_cursor *pCur = (series_cursor*)cur;
+ *pRowid = pCur->iRowid;
+ return SQLITE_OK;
+}
+
+/*
+** Return TRUE if the cursor has been moved off of the last
+** row of output.
+*/
+static int seriesEof(sqlite3_vtab_cursor *cur){
+ series_cursor *pCur = (series_cursor*)cur;
+ if( pCur->isDesc ){
+ return pCur->iValue < pCur->mnValue;
+ }else{
+ return pCur->iValue > pCur->mxValue;
+ }
+}
+
+/* True to cause run-time checking of the start=, stop=, and/or step=
+** parameters. The only reason to do this is for testing the
+** constraint checking logic for virtual tables in the SQLite core.
+*/
+#ifndef SQLITE_SERIES_CONSTRAINT_VERIFY
+# define SQLITE_SERIES_CONSTRAINT_VERIFY 0
+#endif
+
+/*
+** This method is called to "rewind" the series_cursor object back
+** to the first row of output. This method is always called at least
+** once prior to any call to seriesColumn() or seriesRowid() or
+** seriesEof().
+**
+** The query plan selected by seriesBestIndex is passed in the idxNum
+** parameter. (idxStr is not used in this implementation.) idxNum
+** is a bitmask showing which constraints are available:
+**
+** 1: start=VALUE
+** 2: stop=VALUE
+** 4: step=VALUE
+**
+** Also, if bit 8 is set, that means that the series should be output
+** in descending order rather than in ascending order.
+**
+** This routine should initialize the cursor and position it so that it
+** is pointing at the first row, or pointing off the end of the table
+** (so that seriesEof() will return true) if the table is empty.
+*/
+static int seriesFilter(
+ sqlite3_vtab_cursor *pVtabCursor,
+ int idxNum, const char *idxStrUnused,
+ int argc, sqlite3_value **argv
+){
+ series_cursor *pCur = (series_cursor *)pVtabCursor;
+ int i = 0;
+ (void)idxStrUnused;
+ if( idxNum & 1 ){
+ pCur->mnValue = sqlite3_value_int64(argv[i++]);
+ }else{
+ pCur->mnValue = 0;
+ }
+ if( idxNum & 2 ){
+ pCur->mxValue = sqlite3_value_int64(argv[i++]);
+ }else{
+ pCur->mxValue = 0xffffffff;
+ }
+ if( idxNum & 4 ){
+ pCur->iStep = sqlite3_value_int64(argv[i++]);
+ if( pCur->iStep<1 ) pCur->iStep = 1;
+ }else{
+ pCur->iStep = 1;
+ }
+ for(i=0; i<argc; i++){
+ if( sqlite3_value_type(argv[i])==SQLITE_NULL ){
+ /* If any of the constraints have a NULL value, then return no rows.
+ ** See ticket https://www.sqlite.org/src/info/fac496b61722daf2 */
+ pCur->mnValue = 1;
+ pCur->mxValue = 0;
+ break;
+ }
+ }
+ if( idxNum & 8 ){
+ pCur->isDesc = 1;
+ pCur->iValue = pCur->mxValue;
+ if( pCur->iStep>0 ){
+ pCur->iValue -= (pCur->mxValue - pCur->mnValue)%pCur->iStep;
+ }
+ }else{
+ pCur->isDesc = 0;
+ pCur->iValue = pCur->mnValue;
+ }
+ pCur->iRowid = 1;
+ return SQLITE_OK;
+}
+
+/*
+** SQLite will invoke this method one or more times while planning a query
+** that uses the generate_series virtual table. This routine needs to create
+** a query plan for each invocation and compute an estimated cost for that
+** plan.
+**
+** In this implementation idxNum is used to represent the
+** query plan. idxStr is unused.
+**
+** The query plan is represented by bits in idxNum:
+**
+** (1) start = $value -- constraint exists
+** (2) stop = $value -- constraint exists
+** (4) step = $value -- constraint exists
+** (8) output in descending order
+*/
+static int seriesBestIndex(
+ sqlite3_vtab *tabUnused,
+ sqlite3_index_info *pIdxInfo
+){
+ int i, j; /* Loop over constraints */
+ int idxNum = 0; /* The query plan bitmask */
+ int unusableMask = 0; /* Mask of unusable constraints */
+ int nArg = 0; /* Number of arguments that seriesFilter() expects */
+ int aIdx[3]; /* Constraints on start, stop, and step */
+ const struct sqlite3_index_constraint *pConstraint;
+
+ /* This implementation assumes that the start, stop, and step columns
+ ** are the last three columns in the virtual table. */
+ assert( SERIES_COLUMN_STOP == SERIES_COLUMN_START+1 );
+ assert( SERIES_COLUMN_STEP == SERIES_COLUMN_START+2 );
+ (void)tabUnused;
+ aIdx[0] = aIdx[1] = aIdx[2] = -1;
+ pConstraint = pIdxInfo->aConstraint;
+ for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
+ int iCol; /* 0 for start, 1 for stop, 2 for step */
+ int iMask; /* bitmask for those column */
+ if( pConstraint->iColumn<SERIES_COLUMN_START ) continue;
+ iCol = pConstraint->iColumn - SERIES_COLUMN_START;
+ assert( iCol>=0 && iCol<=2 );
+ iMask = 1 << iCol;
+ if( pConstraint->usable==0 ){
+ unusableMask |= iMask;
+ continue;
+ }else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
+ idxNum |= iMask;
+ aIdx[iCol] = i;
+ }
+ }
+ for(i=0; i<3; i++){
+ if( (j = aIdx[i])>=0 ){
+ pIdxInfo->aConstraintUsage[j].argvIndex = ++nArg;
+ pIdxInfo->aConstraintUsage[j].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY;
+ }
+ }
+ if( (unusableMask & ~idxNum)!=0 ){
+ /* The start, stop, and step columns are inputs. Therefore if there
+ ** are unusable constraints on any of start, stop, or step then
+ ** this plan is unusable */
+ return SQLITE_CONSTRAINT;
+ }
+ if( (idxNum & 3)==3 ){
+ /* Both start= and stop= boundaries are available. This is the
+ ** the preferred case */
+ pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0));
+ pIdxInfo->estimatedRows = 1000;
+ if( pIdxInfo->nOrderBy==1 ){
+ if( pIdxInfo->aOrderBy[0].desc ) idxNum |= 8;
+ pIdxInfo->orderByConsumed = 1;
+ }
+ }else{
+ /* If either boundary is missing, we have to generate a huge span
+ ** of numbers. Make this case very expensive so that the query
+ ** planner will work hard to avoid it. */
+ pIdxInfo->estimatedRows = 2147483647;
+ }
+ pIdxInfo->idxNum = idxNum;
+ return SQLITE_OK;
+}
+
+/*
+** This following structure defines all the methods for the
+** generate_series virtual table.
+*/
+static sqlite3_module seriesModule = {
+ 0, /* iVersion */
+ 0, /* xCreate */
+ seriesConnect, /* xConnect */
+ seriesBestIndex, /* xBestIndex */
+ seriesDisconnect, /* xDisconnect */
+ 0, /* xDestroy */
+ seriesOpen, /* xOpen - open a cursor */
+ seriesClose, /* xClose - close a cursor */
+ seriesFilter, /* xFilter - configure scan constraints */
+ seriesNext, /* xNext - advance a cursor */
+ seriesEof, /* xEof - check for end of scan */
+ seriesColumn, /* xColumn - read data */
+ seriesRowid, /* xRowid - read data */
+ 0, /* xUpdate */
+ 0, /* xBegin */
+ 0, /* xSync */
+ 0, /* xCommit */
+ 0, /* xRollback */
+ 0, /* xFindMethod */
+ 0, /* xRename */
+ 0, /* xSavepoint */
+ 0, /* xRelease */
+ 0, /* xRollbackTo */
+ 0 /* xShadowName */
+};
+
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+#ifdef _WIN32
+
+#endif
+int sqlite3_series_init(
+ sqlite3 *db,
+ char **pzErrMsg,
+ const sqlite3_api_routines *pApi
+){
+ int rc = SQLITE_OK;
+ SQLITE_EXTENSION_INIT2(pApi);
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( sqlite3_libversion_number()<3008012 ){
+ *pzErrMsg = sqlite3_mprintf(
+ "generate_series() requires SQLite 3.8.12 or later");
+ return SQLITE_ERROR;
+ }
+ rc = sqlite3_create_module(db, "generate_series", &seriesModule, 0);
+#endif
+ return rc;
+}
+
+/************************* End ../ext/misc/series.c ********************/
#ifdef SQLITE_HAVE_ZLIB
/************************* Begin ../ext/misc/zipfile.c ******************/
/*
@@ -5842,14 +6278,16 @@ static int zipfileAppendData(
const u8 *aWrite,
int nWrite
){
- size_t n;
- fseek(pTab->pWriteFd, (long)pTab->szCurrent, SEEK_SET);
- n = fwrite(aWrite, 1, nWrite, pTab->pWriteFd);
- if( (int)n!=nWrite ){
- pTab->base.zErrMsg = sqlite3_mprintf("error in fwrite()");
- return SQLITE_ERROR;
+ if( nWrite>0 ){
+ size_t n = nWrite;
+ fseek(pTab->pWriteFd, (long)pTab->szCurrent, SEEK_SET);
+ n = fwrite(aWrite, 1, nWrite, pTab->pWriteFd);
+ if( (int)n!=nWrite ){
+ pTab->base.zErrMsg = sqlite3_mprintf("error in fwrite()");
+ return SQLITE_ERROR;
+ }
+ pTab->szCurrent += nWrite;
}
- pTab->szCurrent += nWrite;
return SQLITE_OK;
}
@@ -8494,6 +8932,7 @@ static int idxGetTableInfo(
IdxTable *pNew = 0;
int rc, rc2;
char *pCsr = 0;
+ int nPk = 0;
rc = idxPrintfPrepareStmt(db, &p1, pzErrmsg, "PRAGMA table_info=%Q", zTab);
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
@@ -8504,6 +8943,7 @@ static int idxGetTableInfo(
);
nByte += 1 + STRLEN(zCol);
nCol++;
+ nPk += (sqlite3_column_int(p1, 5)>0);
}
rc2 = sqlite3_reset(p1);
if( rc==SQLITE_OK ) rc = rc2;
@@ -8523,7 +8963,7 @@ static int idxGetTableInfo(
const char *zCol = (const char*)sqlite3_column_text(p1, 1);
int nCopy = STRLEN(zCol) + 1;
pNew->aCol[nCol].zName = pCsr;
- pNew->aCol[nCol].iPk = sqlite3_column_int(p1, 5);
+ pNew->aCol[nCol].iPk = (sqlite3_column_int(p1, 5)==1 && nPk==1);
memcpy(pCsr, zCol, nCopy);
pCsr += nCopy;
@@ -10771,6 +11211,8 @@ struct ShellState {
#define SHFLG_CountChanges 0x00000020 /* .changes setting */
#define SHFLG_Echo 0x00000040 /* .echo or --echo setting */
#define SHFLG_HeaderSet 0x00000080 /* .header has been used */
+#define SHFLG_DumpDataOnly 0x00000100 /* .dump show data only */
+#define SHFLG_DumpNoSys 0x00000200 /* .dump omits system tables */
/*
** Macros for testing and setting shellFlgs
@@ -13291,19 +13733,25 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
const char *zType;
const char *zSql;
ShellState *p = (ShellState *)pArg;
+ int dataOnly;
+ int noSys;
UNUSED_PARAMETER(azNotUsed);
if( nArg!=3 || azArg==0 ) return 0;
zTable = azArg[0];
zType = azArg[1];
zSql = azArg[2];
+ dataOnly = (p->shellFlgs & SHFLG_DumpDataOnly)!=0;
+ noSys = (p->shellFlgs & SHFLG_DumpNoSys)!=0;
- if( strcmp(zTable, "sqlite_sequence")==0 ){
- raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
- }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){
- raw_printf(p->out, "ANALYZE sqlite_schema;\n");
+ if( strcmp(zTable, "sqlite_sequence")==0 && !noSys ){
+ if( !dataOnly ) raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
+ }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 && !noSys ){
+ if( !dataOnly ) raw_printf(p->out, "ANALYZE sqlite_schema;\n");
}else if( strncmp(zTable, "sqlite_", 7)==0 ){
return 0;
+ }else if( dataOnly ){
+ /* no-op */
}else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
char *zIns;
if( !p->writableSchema ){
@@ -13476,8 +13924,10 @@ static const char *(azHelp[]) = {
".dbinfo ?DB? Show status information about the database",
".dump ?TABLE? Render database content as SQL",
" Options:",
- " --preserve-rowids Include ROWID values in the output",
+ " --data-only Output only INSERT statements",
" --newlines Allow unescaped newline characters in output",
+ " --nosys Omit system tables (ex: \"sqlite_stat1\")",
+ " --preserve-rowids Include ROWID values in the output",
" TABLE is a LIKE pattern for the tables to dump",
" Additional LIKE patterns can be given in subsequent arguments",
".echo on|off Turn command echo on or off",
@@ -13602,8 +14052,9 @@ static const char *(azHelp[]) = {
".save FILE Write in-memory database into FILE",
".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off",
".schema ?PATTERN? Show the CREATE statements matching PATTERN",
- " Options:",
- " --indent Try to pretty-print the schema",
+ " Options:",
+ " --indent Try to pretty-print the schema",
+ " --nosys Omit objects whose names start with \"sqlite_\"",
".selftest ?OPTIONS? Run tests defined in the SELFTEST table",
" Options:",
" --init Create a new SELFTEST table",
@@ -14013,6 +14464,20 @@ static void shellIdQuote(
}
/*
+** Scalar function "usleep(X)" invokes sqlite3_sleep(X) and returns X.
+*/
+static void shellUSleepFunc(
+ sqlite3_context *context,
+ int argcUnused,
+ sqlite3_value **argv
+){
+ int sleep = sqlite3_value_int(argv[0]);
+ (void)argcUnused;
+ sqlite3_sleep(sleep/1000);
+ sqlite3_result_int(context, sleep);
+}
+
+/*
** Scalar function "shell_escape_crnl" used by the .recover command.
** The argument passed to this function is the output of built-in
** function quote(). If the first character of the input is "'",
@@ -14176,6 +14641,7 @@ static void open_db(ShellState *p, int openFlags){
sqlite3_uint_init(p->db, 0, 0);
sqlite3_decimal_init(p->db, 0, 0);
sqlite3_ieee_init(p->db, 0, 0);
+ sqlite3_series_init(p->db, 0, 0);
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
sqlite3_dbdata_init(p->db, 0, 0);
#endif
@@ -14195,6 +14661,8 @@ static void open_db(ShellState *p, int openFlags){
shellInt32, 0, 0);
sqlite3_create_function(p->db, "shell_idquote", 1, SQLITE_UTF8, 0,
shellIdQuote, 0, 0);
+ sqlite3_create_function(p->db, "usleep",1,SQLITE_UTF8,0,
+ shellUSleepFunc, 0, 0);
#ifndef SQLITE_NOHAVE_SYSTEM
sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0,
editFunc, 0, 0);
@@ -17169,21 +17637,41 @@ static int do_meta_command(char *zLine, ShellState *p){
}else
if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
- ShellState data;
- char *zErrMsg = 0;
+ char **azName = 0;
+ int nName = 0;
+ sqlite3_stmt *pStmt;
+ int i;
open_db(p, 0);
- memcpy(&data, p, sizeof(data));
- data.showHeader = 0;
- data.cMode = data.mode = MODE_List;
- sqlite3_snprintf(sizeof(data.colSeparator),data.colSeparator,": ");
- data.cnt = 0;
- sqlite3_exec(p->db, "SELECT name, file FROM pragma_database_list",
- callback, &data, &zErrMsg);
- if( zErrMsg ){
- utf8_printf(stderr,"Error: %s\n", zErrMsg);
- sqlite3_free(zErrMsg);
+ rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
+ if( rc ){
+ utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
rc = 1;
+ }else{
+ while( sqlite3_step(pStmt)==SQLITE_ROW ){
+ const char *zSchema = (const char *)sqlite3_column_text(pStmt,1);
+ const char *zFile = (const char*)sqlite3_column_text(pStmt,2);
+ azName = sqlite3_realloc(azName, (nName+1)*2*sizeof(char*));
+ if( azName==0 ){ shell_out_of_memory(); /* Does not return */ }
+ azName[nName*2] = strdup(zSchema);
+ azName[nName*2+1] = strdup(zFile);
+ nName++;
+ }
}
+ sqlite3_finalize(pStmt);
+ for(i=0; i<nName; i++){
+ int eTxn = sqlite3_txn_state(p->db, azName[i*2]);
+ int bRdonly = sqlite3_db_readonly(p->db, azName[i*2]);
+ const char *z = azName[i*2+1];
+ utf8_printf(p->out, "%s: %s %s%s\n",
+ azName[i*2],
+ z && z[0] ? z : "\"\"",
+ bRdonly ? "r/o" : "r/w",
+ eTxn==SQLITE_TXN_NONE ? "" :
+ eTxn==SQLITE_TXN_READ ? " read-txn" : " write-txn");
+ free(azName[i*2]);
+ free(azName[i*2+1]);
+ }
+ sqlite3_free(azName);
}else
if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){
@@ -17242,7 +17730,9 @@ static int do_meta_command(char *zLine, ShellState *p){
int i;
int savedShowHeader = p->showHeader;
int savedShellFlags = p->shellFlgs;
- ShellClearFlag(p, SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo);
+ ShellClearFlag(p,
+ SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo
+ |SHFLG_DumpDataOnly|SHFLG_DumpNoSys);
for(i=1; i<nArg; i++){
if( azArg[i][0]=='-' ){
const char *z = azArg[i]+1;
@@ -17261,6 +17751,12 @@ static int do_meta_command(char *zLine, ShellState *p){
if( strcmp(z,"newlines")==0 ){
ShellSetFlag(p, SHFLG_Newlines);
}else
+ if( strcmp(z,"data-only")==0 ){
+ ShellSetFlag(p, SHFLG_DumpDataOnly);
+ }else
+ if( strcmp(z,"nosys")==0 ){
+ ShellSetFlag(p, SHFLG_DumpNoSys);
+ }else
{
raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
rc = 1;
@@ -17277,11 +17773,13 @@ static int do_meta_command(char *zLine, ShellState *p){
open_db(p, 0);
- /* When playing back a "dump", the content might appear in an order
- ** which causes immediate foreign key constraints to be violated.
- ** So disable foreign-key constraint enforcement to prevent problems. */
- raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
- raw_printf(p->out, "BEGIN TRANSACTION;\n");
+ if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
+ /* When playing back a "dump", the content might appear in an order
+ ** which causes immediate foreign key constraints to be violated.
+ ** So disable foreign-key constraint enforcement to prevent problems. */
+ raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
+ raw_printf(p->out, "BEGIN TRANSACTION;\n");
+ }
p->writableSchema = 0;
p->showHeader = 0;
/* Set writable_schema=ON since doing so forces SQLite to initialize
@@ -17299,14 +17797,16 @@ static int do_meta_command(char *zLine, ShellState *p){
);
run_schema_dump_query(p,zSql);
sqlite3_free(zSql);
- zSql = sqlite3_mprintf(
- "SELECT sql FROM sqlite_schema "
- "WHERE (%s) AND sql NOT NULL"
- " AND type IN ('index','trigger','view')",
- zLike
- );
- run_table_dump_query(p, zSql);
- sqlite3_free(zSql);
+ if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
+ zSql = sqlite3_mprintf(
+ "SELECT sql FROM sqlite_schema "
+ "WHERE (%s) AND sql NOT NULL"
+ " AND type IN ('index','trigger','view')",
+ zLike
+ );
+ run_table_dump_query(p, zSql);
+ sqlite3_free(zSql);
+ }
sqlite3_free(zLike);
if( p->writableSchema ){
raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
@@ -17314,7 +17814,9 @@ static int do_meta_command(char *zLine, ShellState *p){
}
sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
- raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
+ if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
+ raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
+ }
p->showHeader = savedShowHeader;
p->shellFlgs = savedShellFlags;
}else
@@ -17753,7 +18255,7 @@ static int do_meta_command(char *zLine, ShellState *p){
while( (nSkip--)>0 ){
while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
}
- zSql = sqlite3_mprintf("SELECT * FROM %s", zTable);
+ zSql = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
if( zSql==0 ){
import_cleanup(&sCtx);
shell_out_of_memory();
@@ -17762,7 +18264,7 @@ static int do_meta_command(char *zLine, ShellState *p){
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
- char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable);
+ char *zCreate = sqlite3_mprintf("CREATE TABLE \"%w\"", zTable);
char cSep = '(';
while( xRead(&sCtx) ){
zCreate = sqlite3_mprintf("%z%c\n \"%w\" TEXT", zCreate, cSep, sCtx.z);
@@ -17783,7 +18285,7 @@ static int do_meta_command(char *zLine, ShellState *p){
rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
sqlite3_free(zCreate);
if( rc ){
- utf8_printf(stderr, "CREATE TABLE %s(...) failed: %s\n", zTable,
+ utf8_printf(stderr, "CREATE TABLE \"%s\"(...) failed: %s\n", zTable,
sqlite3_errmsg(p->db));
import_cleanup(&sCtx);
rc = 1;
@@ -18548,9 +19050,16 @@ static int do_meta_command(char *zLine, ShellState *p){
rc = 1;
goto meta_command_exit;
}
- if( notNormalFile(azArg[1])
- || (p->in = fopen(azArg[1], "rb"))==0
- ){
+ if( azArg[1][0]=='|' ){
+ p->in = popen(azArg[1]+1, "r");
+ if( p->in==0 ){
+ utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
+ rc = 1;
+ }else{
+ rc = process_input(p);
+ pclose(p->in);
+ }
+ }else if( notNormalFile(azArg[1]) || (p->in = fopen(azArg[1], "rb"))==0 ){
utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
rc = 1;
}else{
@@ -18632,6 +19141,7 @@ static int do_meta_command(char *zLine, ShellState *p){
const char *zName = 0;
int iSchema = 0;
int bDebug = 0;
+ int bNoSystemTabs = 0;
int ii;
open_db(p, 0);
@@ -18644,10 +19154,16 @@ static int do_meta_command(char *zLine, ShellState *p){
data.cMode = data.mode = MODE_Pretty;
}else if( optionMatch(azArg[ii],"debug") ){
bDebug = 1;
+ }else if( optionMatch(azArg[ii],"nosys") ){
+ bNoSystemTabs = 1;
+ }else if( azArg[ii][0]=='-' ){
+ utf8_printf(stderr, "Unknown option: \"%s\"\n", azArg[ii]);
+ rc = 1;
+ goto meta_command_exit;
}else if( zName==0 ){
zName = azArg[ii];
}else{
- raw_printf(stderr, "Usage: .schema ?--indent? ?LIKE-PATTERN?\n");
+ raw_printf(stderr, "Usage: .schema ?--indent? ?--nosys? ?LIKE-PATTERN?\n");
rc = 1;
goto meta_command_exit;
}
@@ -18733,7 +19249,10 @@ static int do_meta_command(char *zLine, ShellState *p){
appendText(&sSelect, " AND ", 0);
sqlite3_free(zQarg);
}
- appendText(&sSelect, "type!='meta' AND sql IS NOT NULL"
+ if( bNoSystemTabs ){
+ appendText(&sSelect, "name NOT LIKE 'sqlite_%%' AND ", 0);
+ }
+ appendText(&sSelect, "sql IS NOT NULL"
" ORDER BY snum, rowid", 0);
if( bDebug ){
utf8_printf(p->out, "SQL: %s;\n", sSelect.z);
@@ -19430,6 +19949,7 @@ static int do_meta_command(char *zLine, ShellState *p){
{ "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE, "" },
{ "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, "" },
{ "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, "SEED ?db?" },
+ { "seek_count", SQLITE_TESTCTRL_SEEK_COUNT, "" },
};
int testctrl = -1;
int iCtrl = -1;
@@ -19492,7 +20012,6 @@ static int do_meta_command(char *zLine, ShellState *p){
/* sqlite3_test_control(int) */
case SQLITE_TESTCTRL_PRNG_SAVE:
case SQLITE_TESTCTRL_PRNG_RESTORE:
- case SQLITE_TESTCTRL_PRNG_RESET:
case SQLITE_TESTCTRL_BYTEORDER:
if( nArg==2 ){
rc2 = sqlite3_test_control(testctrl);
@@ -19566,6 +20085,14 @@ static int do_meta_command(char *zLine, ShellState *p){
}
break;
+ case SQLITE_TESTCTRL_SEEK_COUNT: {
+ u64 x = 0;
+ rc2 = sqlite3_test_control(testctrl, p->db, &x);
+ utf8_printf(p->out, "%llu\n", x);
+ isOk = 3;
+ break;
+ }
+
#ifdef YYCOVERAGE
case SQLITE_TESTCTRL_PARSER_COVERAGE:
if( nArg==2 ){
@@ -20144,8 +20671,11 @@ static void process_sqliterc(
if( stdin_is_interactive ){
utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc);
}
- process_input(p);
+ if( process_input(p) && bail_on_error ) exit(1);
fclose(p->in);
+ }else if( sqliterc_override!=0 ){
+ utf8_printf(stderr,"cannot open: \"%s\"\n", sqliterc);
+ if( bail_on_error ) exit(1);
}
p->in = inSaved;
p->lineno = savedLineno;
@@ -20204,6 +20734,7 @@ static const char zOptions[] =
#endif
" -stats print memory stats before each finalize\n"
" -table set output mode to 'table'\n"
+ " -tabs set output mode to 'tabs'\n"
" -version show SQLite version\n"
" -vfs NAME use NAME as the default VFS\n"
#ifdef SQLITE_ENABLE_VFSTRACE
@@ -20461,11 +20992,14 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
(void)cmdline_option_value(argc, argv, ++i);
#endif
}else if( strcmp(z,"-pagecache")==0 ){
- int n, sz;
- sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
+ sqlite3_int64 n, sz;
+ sz = integerValue(cmdline_option_value(argc,argv,++i));
if( sz>70000 ) sz = 70000;
if( sz<0 ) sz = 0;
- n = (int)integerValue(cmdline_option_value(argc,argv,++i));
+ n = integerValue(cmdline_option_value(argc,argv,++i));
+ if( sz>0 && n>0 && 0xffffffffffffLL/sz<n ){
+ n = 0xffffffffffffLL/sz;
+ }
sqlite3_config(SQLITE_CONFIG_PAGECACHE,
(n>0 && sz>0) ? malloc(n*sz) : 0, sz, n);
data.shellFlgs |= SHFLG_Pagecache;
@@ -20527,6 +21061,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
#endif
}else if( strcmp(z, "-memtrace")==0 ){
sqlite3MemTraceActivate(stderr);
+ }else if( strcmp(z,"-bail")==0 ){
+ bail_on_error = 1;
}
}
verify_uninitialized();
@@ -20601,6 +21137,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
data.mode = MODE_List;
}else if( strcmp(z,"-quote")==0 ){
data.mode = MODE_Quote;
+ sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Comma);
+ sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
}else if( strcmp(z,"-line")==0 ){
data.mode = MODE_Line;
}else if( strcmp(z,"-column")==0 ){
@@ -20634,10 +21172,12 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
data.openFlags |= SQLITE_OPEN_NOFOLLOW;
}else if( strcmp(z,"-ascii")==0 ){
data.mode = MODE_Ascii;
- sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
- SEP_Unit);
- sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
- SEP_Record);
+ sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Unit);
+ sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Record);
+ }else if( strcmp(z,"-tabs")==0 ){
+ data.mode = MODE_List;
+ sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Tab);
+ sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
}else if( strcmp(z,"-separator")==0 ){
sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
"%s",cmdline_option_value(argc,argv,++i));
@@ -20669,7 +21209,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
*/
ShellSetFlag(&data, SHFLG_Backslash);
}else if( strcmp(z,"-bail")==0 ){
- bail_on_error = 1;
+ /* No-op. The bail_on_error flag should already be set. */
}else if( strcmp(z,"-version")==0 ){
printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid());
return 0;
@@ -20757,20 +21297,25 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
for(i=0; i<nCmd; i++){
if( azCmd[i][0]=='.' ){
rc = do_meta_command(azCmd[i], &data);
- if( rc ) return rc==2 ? 0 : rc;
+ if( rc ){
+ free(azCmd);
+ return rc==2 ? 0 : rc;
+ }
}else{
open_db(&data, 0);
rc = shell_exec(&data, azCmd[i], &zErrMsg);
- if( zErrMsg!=0 ){
- utf8_printf(stderr,"Error: %s\n", zErrMsg);
+ if( zErrMsg || rc ){
+ if( zErrMsg!=0 ){
+ utf8_printf(stderr,"Error: %s\n", zErrMsg);
+ }else{
+ utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]);
+ }
+ sqlite3_free(zErrMsg);
+ free(azCmd);
return rc!=0 ? rc : 1;
- }else if( rc!=0 ){
- utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]);
- return rc;
}
}
}
- free(azCmd);
}else{
/* Run commands received from standard input
*/
@@ -20816,6 +21361,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
rc = process_input(&data);
}
}
+ free(azCmd);
set_table_name(&data, 0);
if( data.db ){
session_close_all(&data);
diff --git a/chromium/third_party/sqlite/src/amalgamation/sqlite3.c b/chromium/third_party/sqlite/src/amalgamation/sqlite3.c
index e10646be334..6b4a7899d33 100644
--- a/chromium/third_party/sqlite/src/amalgamation/sqlite3.c
+++ b/chromium/third_party/sqlite/src/amalgamation/sqlite3.c
@@ -1,6 +1,6 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-** version 3.33.0. By combining all the individual C code files into this
+** version 3.34.0. 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
@@ -1171,9 +1171,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.33.0"
-#define SQLITE_VERSION_NUMBER 3033000
-#define SQLITE_SOURCE_ID "2020-08-14 13:23:32 fca8dc8b578f215a969cd899336378966156154710873e68b3d9ac5881b0ff3f"
+#define SQLITE_VERSION "3.34.0"
+#define SQLITE_VERSION_NUMBER 3034000
+#define SQLITE_SOURCE_ID "2020-12-01 16:14:00 b7738010bc8ef02ba84820368e557306390a33c38adaa5c7703154bae3edalt1"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -1552,6 +1552,7 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8))
#define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8))
#define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8))
+#define SQLITE_IOERR_CORRUPTFS (SQLITE_IOERR | (33<<8))
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8))
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
@@ -7235,6 +7236,57 @@ SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName);
/*
+** CAPI3REF: Determine the transaction state of a database
+** METHOD: sqlite3
+**
+** ^The sqlite3_txn_state(D,S) interface returns the current
+** [transaction state] of schema S in database connection D. ^If S is NULL,
+** then the highest transaction state of any schema on database connection D
+** is returned. Transaction states are (in order of lowest to highest):
+** <ol>
+** <li value="0"> SQLITE_TXN_NONE
+** <li value="1"> SQLITE_TXN_READ
+** <li value="2"> SQLITE_TXN_WRITE
+** </ol>
+** ^If the S argument to sqlite3_txn_state(D,S) is not the name of
+** a valid schema, then -1 is returned.
+*/
+SQLITE_API int sqlite3_txn_state(sqlite3*,const char *zSchema);
+
+/*
+** CAPI3REF: Allowed return values from [sqlite3_txn_state()]
+** KEYWORDS: {transaction state}
+**
+** These constants define the current transaction state of a database file.
+** ^The [sqlite3_txn_state(D,S)] interface returns one of these
+** constants in order to describe the transaction state of schema S
+** in [database connection] D.
+**
+** <dl>
+** [[SQLITE_TXN_NONE]] <dt>SQLITE_TXN_NONE</dt>
+** <dd>The SQLITE_TXN_NONE state means that no transaction is currently
+** pending.</dd>
+**
+** [[SQLITE_TXN_READ]] <dt>SQLITE_TXN_READ</dt>
+** <dd>The SQLITE_TXN_READ state means that the database is currently
+** in a read transaction. Content has been read from the database file
+** but nothing in the database file has changed. The transaction state
+** will advanced to SQLITE_TXN_WRITE if any changes occur and there are
+** no other conflicting concurrent write transactions. The transaction
+** state will revert to SQLITE_TXN_NONE following a [ROLLBACK] or
+** [COMMIT].</dd>
+**
+** [[SQLITE_TXN_WRITE]] <dt>SQLITE_TXN_WRITE</dt>
+** <dd>The SQLITE_TXN_WRITE state means that the database is currently
+** in a write transaction. Content has been written to the database file
+** but has not yet committed. The transaction state will change to
+** to SQLITE_TXN_NONE at the next [ROLLBACK] or [COMMIT].</dd>
+*/
+#define SQLITE_TXN_NONE 0
+#define SQLITE_TXN_READ 1
+#define SQLITE_TXN_WRITE 2
+
+/*
** CAPI3REF: Find the next prepared statement
** METHOD: sqlite3
**
@@ -8760,7 +8812,8 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_RESULT_INTREAL 27
#define SQLITE_TESTCTRL_PRNG_SEED 28
#define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29
-#define SQLITE_TESTCTRL_LAST 29 /* Largest TESTCTRL */
+#define SQLITE_TESTCTRL_SEEK_COUNT 30
+#define SQLITE_TESTCTRL_LAST 30 /* Largest TESTCTRL */
/*
** CAPI3REF: SQL Keyword Checking
@@ -10240,10 +10293,11 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
** CAPI3REF: Determine If Virtual Table Column Access Is For UPDATE
**
** If the sqlite3_vtab_nochange(X) routine is called within the [xColumn]
-** method of a [virtual table], then it returns true if and only if the
+** method of a [virtual table], then it might return true if the
** column is being fetched as part of an UPDATE operation during which the
-** column value will not change. Applications might use this to substitute
-** a return value that is less expensive to compute and that the corresponding
+** column value will not change. The virtual table implementation can use
+** this hint as permission to substitute a return value that is less
+** expensive to compute and that the corresponding
** [xUpdate] method understands as a "no-change" value.
**
** If the [xColumn] method calls sqlite3_vtab_nochange() and finds that
@@ -10252,6 +10306,12 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
** any of the [sqlite3_result_int|sqlite3_result_xxxxx() interfaces].
** In that case, [sqlite3_value_nochange(X)] will return true for the
** same column in the [xUpdate] method.
+**
+** The sqlite3_vtab_nochange() routine is an optimization. Virtual table
+** implementations should continue to give a correct answer even if the
+** sqlite3_vtab_nochange() interface were to always return false. In the
+** current implementation, the sqlite3_vtab_nochange() interface does always
+** returns false for the enhanced [UPDATE FROM] statement.
*/
SQLITE_API int sqlite3_vtab_nochange(sqlite3_context*);
@@ -10393,6 +10453,7 @@ SQLITE_API void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
/*
** CAPI3REF: Flush caches to disk mid-transaction
+** METHOD: sqlite3
**
** ^If a write-transaction is open on [database connection] D when the
** [sqlite3_db_cacheflush(D)] interface invoked, any dirty
@@ -10425,6 +10486,7 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*);
/*
** CAPI3REF: The pre-update hook.
+** METHOD: sqlite3
**
** ^These interfaces are only available if SQLite is compiled using the
** [SQLITE_ENABLE_PREUPDATE_HOOK] compile-time option.
@@ -10465,7 +10527,7 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*);
** seventh parameter is the final rowid value of the row being inserted
** or updated. The value of the seventh parameter passed to the callback
** function is not defined for operations on WITHOUT ROWID tables, or for
-** INSERT operations on rowid tables.
+** DELETE operations on rowid tables.
**
** The [sqlite3_preupdate_old()], [sqlite3_preupdate_new()],
** [sqlite3_preupdate_count()], and [sqlite3_preupdate_depth()] interfaces
@@ -10527,6 +10589,7 @@ SQLITE_API int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **);
/*
** CAPI3REF: Low-level system error code
+** METHOD: sqlite3
**
** ^Attempt to return the underlying operating system error code or error
** number that caused the most recent I/O error or failure to open a file.
@@ -13297,11 +13360,7 @@ struct fts5_api {
** The maximum depth of an expression tree. This is limited to
** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might
** want to place more severe limits on the complexity of an
-** expression.
-**
-** A value of 0 used to mean that the limit was not enforced.
-** But that is no longer true. The limit is now strictly enforced
-** at all times.
+** expression. A value of 0 means that there is no limit.
*/
#ifndef SQLITE_MAX_EXPR_DEPTH
# define SQLITE_MAX_EXPR_DEPTH 1000
@@ -15069,16 +15128,24 @@ SQLITE_PRIVATE int sqlite3BtreeCommit(Btree*);
SQLITE_PRIVATE int sqlite3BtreeRollback(Btree*,int,int);
SQLITE_PRIVATE int sqlite3BtreeBeginStmt(Btree*,int);
SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree*, Pgno*, int flags);
-SQLITE_PRIVATE int sqlite3BtreeIsInTrans(Btree*);
-SQLITE_PRIVATE int sqlite3BtreeIsInReadTrans(Btree*);
+SQLITE_PRIVATE int sqlite3BtreeTxnState(Btree*);
SQLITE_PRIVATE int sqlite3BtreeIsInBackup(Btree*);
+
SQLITE_PRIVATE void *sqlite3BtreeSchema(Btree *, int, void(*)(void *));
SQLITE_PRIVATE int sqlite3BtreeSchemaLocked(Btree *pBtree);
#ifndef SQLITE_OMIT_SHARED_CACHE
SQLITE_PRIVATE int sqlite3BtreeLockTable(Btree *pBtree, int iTab, u8 isWriteLock);
#endif
+
+/* Savepoints are named, nestable SQL transactions mostly implemented */
+/* in vdbe.c and pager.c See https://sqlite.org/lang_savepoint.html */
SQLITE_PRIVATE int sqlite3BtreeSavepoint(Btree *, int, int);
+/* "Checkpoint" only refers to WAL. See https://sqlite.org/wal.html#ckpt */
+#ifndef SQLITE_OMIT_WAL
+SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree*, int, int *, int *);
+#endif
+
SQLITE_PRIVATE const char *sqlite3BtreeGetFilename(Btree *);
SQLITE_PRIVATE const char *sqlite3BtreeGetJournalname(Btree *);
SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *, Btree *);
@@ -15315,6 +15382,12 @@ SQLITE_PRIVATE int sqlite3BtreeCursorHasHint(BtCursor*, unsigned int mask);
SQLITE_PRIVATE int sqlite3BtreeIsReadonly(Btree *pBt);
SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void);
+#ifdef SQLITE_DEBUG
+SQLITE_PRIVATE sqlite3_uint64 sqlite3BtreeSeekCount(Btree*);
+#else
+# define sqlite3BtreeSeekCount(X) 0
+#endif
+
#ifndef NDEBUG
SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor*);
#endif
@@ -15668,64 +15741,65 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_OpenPseudo 115 /* synopsis: P3 columns in r[P2] */
#define OP_Close 116
#define OP_ColumnsUsed 117
-#define OP_SeekHit 118 /* synopsis: seekHit=P2 */
-#define OP_Sequence 119 /* synopsis: r[P2]=cursor[P1].ctr++ */
-#define OP_NewRowid 120 /* synopsis: r[P2]=rowid */
-#define OP_Insert 121 /* synopsis: intkey=r[P3] data=r[P2] */
-#define OP_Delete 122
-#define OP_ResetCount 123
-#define OP_SorterCompare 124 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
-#define OP_SorterData 125 /* synopsis: r[P2]=data */
-#define OP_RowData 126 /* synopsis: r[P2]=data */
-#define OP_Rowid 127 /* synopsis: r[P2]=rowid */
-#define OP_NullRow 128
-#define OP_SeekEnd 129
-#define OP_IdxInsert 130 /* synopsis: key=r[P2] */
-#define OP_SorterInsert 131 /* synopsis: key=r[P2] */
-#define OP_IdxDelete 132 /* synopsis: key=r[P2@P3] */
-#define OP_DeferredSeek 133 /* synopsis: Move P3 to P1.rowid if needed */
-#define OP_IdxRowid 134 /* synopsis: r[P2]=rowid */
-#define OP_FinishSeek 135
-#define OP_Destroy 136
-#define OP_Clear 137
-#define OP_ResetSorter 138
-#define OP_CreateBtree 139 /* synopsis: r[P2]=root iDb=P1 flags=P3 */
+#define OP_SeekScan 118 /* synopsis: Scan-ahead up to P1 rows */
+#define OP_SeekHit 119 /* synopsis: set P2<=seekHit<=P3 */
+#define OP_Sequence 120 /* synopsis: r[P2]=cursor[P1].ctr++ */
+#define OP_NewRowid 121 /* synopsis: r[P2]=rowid */
+#define OP_Insert 122 /* synopsis: intkey=r[P3] data=r[P2] */
+#define OP_Delete 123
+#define OP_ResetCount 124
+#define OP_SorterCompare 125 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
+#define OP_SorterData 126 /* synopsis: r[P2]=data */
+#define OP_RowData 127 /* synopsis: r[P2]=data */
+#define OP_Rowid 128 /* synopsis: r[P2]=rowid */
+#define OP_NullRow 129
+#define OP_SeekEnd 130
+#define OP_IdxInsert 131 /* synopsis: key=r[P2] */
+#define OP_SorterInsert 132 /* synopsis: key=r[P2] */
+#define OP_IdxDelete 133 /* synopsis: key=r[P2@P3] */
+#define OP_DeferredSeek 134 /* synopsis: Move P3 to P1.rowid if needed */
+#define OP_IdxRowid 135 /* synopsis: r[P2]=rowid */
+#define OP_FinishSeek 136
+#define OP_Destroy 137
+#define OP_Clear 138
+#define OP_ResetSorter 139
#define OP_Real 140 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
-#define OP_SqlExec 141
-#define OP_ParseSchema 142
-#define OP_LoadAnalysis 143
-#define OP_DropTable 144
-#define OP_DropIndex 145
-#define OP_DropTrigger 146
-#define OP_IntegrityCk 147
-#define OP_RowSetAdd 148 /* synopsis: rowset(P1)=r[P2] */
-#define OP_Param 149
-#define OP_FkCounter 150 /* synopsis: fkctr[P1]+=P2 */
-#define OP_MemMax 151 /* synopsis: r[P1]=max(r[P1],r[P2]) */
-#define OP_OffsetLimit 152 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */
-#define OP_AggInverse 153 /* synopsis: accum=r[P3] inverse(r[P2@P5]) */
-#define OP_AggStep 154 /* synopsis: accum=r[P3] step(r[P2@P5]) */
-#define OP_AggStep1 155 /* synopsis: accum=r[P3] step(r[P2@P5]) */
-#define OP_AggValue 156 /* synopsis: r[P3]=value N=P2 */
-#define OP_AggFinal 157 /* synopsis: accum=r[P1] N=P2 */
-#define OP_Expire 158
-#define OP_CursorLock 159
-#define OP_CursorUnlock 160
-#define OP_TableLock 161 /* synopsis: iDb=P1 root=P2 write=P3 */
-#define OP_VBegin 162
-#define OP_VCreate 163
-#define OP_VDestroy 164
-#define OP_VOpen 165
-#define OP_VColumn 166 /* synopsis: r[P3]=vcolumn(P2) */
-#define OP_VRename 167
-#define OP_Pagecount 168
-#define OP_MaxPgcnt 169
-#define OP_Trace 170
-#define OP_CursorHint 171
-#define OP_ReleaseReg 172 /* synopsis: release r[P1@P2] mask P3 */
-#define OP_Noop 173
-#define OP_Explain 174
-#define OP_Abortable 175
+#define OP_CreateBtree 141 /* synopsis: r[P2]=root iDb=P1 flags=P3 */
+#define OP_SqlExec 142
+#define OP_ParseSchema 143
+#define OP_LoadAnalysis 144
+#define OP_DropTable 145
+#define OP_DropIndex 146
+#define OP_DropTrigger 147
+#define OP_IntegrityCk 148
+#define OP_RowSetAdd 149 /* synopsis: rowset(P1)=r[P2] */
+#define OP_Param 150
+#define OP_FkCounter 151 /* synopsis: fkctr[P1]+=P2 */
+#define OP_MemMax 152 /* synopsis: r[P1]=max(r[P1],r[P2]) */
+#define OP_OffsetLimit 153 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */
+#define OP_AggInverse 154 /* synopsis: accum=r[P3] inverse(r[P2@P5]) */
+#define OP_AggStep 155 /* synopsis: accum=r[P3] step(r[P2@P5]) */
+#define OP_AggStep1 156 /* synopsis: accum=r[P3] step(r[P2@P5]) */
+#define OP_AggValue 157 /* synopsis: r[P3]=value N=P2 */
+#define OP_AggFinal 158 /* synopsis: accum=r[P1] N=P2 */
+#define OP_Expire 159
+#define OP_CursorLock 160
+#define OP_CursorUnlock 161
+#define OP_TableLock 162 /* synopsis: iDb=P1 root=P2 write=P3 */
+#define OP_VBegin 163
+#define OP_VCreate 164
+#define OP_VDestroy 165
+#define OP_VOpen 166
+#define OP_VColumn 167 /* synopsis: r[P3]=vcolumn(P2) */
+#define OP_VRename 168
+#define OP_Pagecount 169
+#define OP_MaxPgcnt 170
+#define OP_Trace 171
+#define OP_CursorHint 172
+#define OP_ReleaseReg 173 /* synopsis: release r[P1@P2] mask P3 */
+#define OP_Noop 174
+#define OP_Explain 175
+#define OP_Abortable 176
/* Properties such as "out2" or "jump" that are specified in
** comments following the "case" for each opcode in the vdbe.c
@@ -15752,15 +15826,15 @@ typedef struct VdbeOpList VdbeOpList;
/* 88 */ 0x20, 0x00, 0x00, 0x26, 0x26, 0x26, 0x26, 0x26,\
/* 96 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x00, 0x12, 0x10,\
/* 104 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 112 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\
-/* 120 */ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\
-/* 128 */ 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x10, 0x00,\
-/* 136 */ 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00,\
-/* 144 */ 0x00, 0x00, 0x00, 0x00, 0x06, 0x10, 0x00, 0x04,\
-/* 152 */ 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 112 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 120 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 128 */ 0x10, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x10,\
+/* 136 */ 0x00, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\
+/* 144 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10, 0x00,\
+/* 152 */ 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
/* 160 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 168 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-}
+/* 168 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 176 */ 0x00,}
/* The sqlite3P2Values() routine is able to run faster if it knows
** the value of the largest JUMP opcode. The smaller the maximum
@@ -17537,6 +17611,7 @@ struct Table {
#define TF_OOOHidden 0x0400 /* Out-of-Order hidden columns */
#define TF_HasNotNull 0x0800 /* Contains NOT NULL constraints */
#define TF_Shadow 0x1000 /* True for a shadow table */
+#define TF_HasStat4 0x2000 /* STAT4 info available for this table */
/*
** Test to see whether or not a table is a virtual table. This is
@@ -18065,7 +18140,7 @@ struct Expr {
#define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */
#define EP_Win 0x008000 /* Contains window functions */
#define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */
- /* 0x020000 // available for reuse */
+#define EP_IfNullRow 0x020000 /* The TK_IF_NULL_ROW opcode */
#define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */
#define EP_ConstFunc 0x080000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */
#define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */
@@ -18303,9 +18378,9 @@ struct SrcList {
#define WHERE_DISTINCTBY 0x0080 /* pOrderby is really a DISTINCT clause */
#define WHERE_WANT_DISTINCT 0x0100 /* All output needs to be distinct */
#define WHERE_SORTBYGROUP 0x0200 /* Support sqlite3WhereIsSorted() */
-#define WHERE_SEEK_TABLE 0x0400 /* Do not defer seeks on main table */
+ /* 0x0400 not currently used */
#define WHERE_ORDERBY_LIMIT 0x0800 /* ORDERBY+LIMIT on the inner loop */
-#define WHERE_SEEK_UNIQ_TABLE 0x1000 /* Do not defer seeks if unique */
+ /* 0x1000 not currently used */
/* 0x2000 not currently used */
#define WHERE_USE_LIMIT 0x4000 /* Use the LIMIT in cost estimates */
/* 0x8000 not currently used */
@@ -18502,9 +18577,6 @@ struct Select {
** statements within triggers whose only purpose is
** the side-effects of functions.
**
-** All of the above are free to ignore their ORDER BY clause. Those that
-** follow must honor the ORDER BY clause.
-**
** SRT_Output Generate a row of output (using the OP_ResultRow
** opcode) for each row in the result set.
**
@@ -18561,13 +18633,18 @@ struct Select {
#define SRT_Except 2 /* Remove result from a UNION index */
#define SRT_Exists 3 /* Store 1 if the result is not empty */
#define SRT_Discard 4 /* Do not save the results anywhere */
-#define SRT_Fifo 5 /* Store result as data with an automatic rowid */
-#define SRT_DistFifo 6 /* Like SRT_Fifo, but unique results only */
+#define SRT_DistFifo 5 /* Like SRT_Fifo, but unique results only */
+#define SRT_DistQueue 6 /* Like SRT_Queue, but unique results only */
+
+/* The DISTINCT clause is ignored for all of the above. Not that
+** IgnorableDistinct() implies IgnorableOrderby() */
+#define IgnorableDistinct(X) ((X->eDest)<=SRT_DistQueue)
+
#define SRT_Queue 7 /* Store result in an queue */
-#define SRT_DistQueue 8 /* Like SRT_Queue, but unique results only */
+#define SRT_Fifo 8 /* Store result as data with an automatic rowid */
/* The ORDER BY clause is ignored for all of the above */
-#define IgnorableOrderby(X) ((X->eDest)<=SRT_DistQueue)
+#define IgnorableOrderby(X) ((X->eDest)<=SRT_Fifo)
#define SRT_Output 9 /* Output each row of result */
#define SRT_Mem 10 /* Store result in a memory cell */
@@ -19222,7 +19299,6 @@ SQLITE_PRIVATE int sqlite3WindowCompare(Parse*, Window*, Window*, int);
SQLITE_PRIVATE void sqlite3WindowCodeInit(Parse*, Select*);
SQLITE_PRIVATE void sqlite3WindowCodeStep(Parse*, Select*, WhereInfo*, int, int);
SQLITE_PRIVATE int sqlite3WindowRewrite(Parse*, Select*);
-SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse*, struct SrcList_item*);
SQLITE_PRIVATE void sqlite3WindowUpdate(Parse*, Window*, Window*, FuncDef*);
SQLITE_PRIVATE Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p);
SQLITE_PRIVATE Window *sqlite3WindowListDup(sqlite3 *db, Window *p);
@@ -19534,7 +19610,7 @@ SQLITE_PRIVATE void sqlite3ColumnPropertiesFromName(Table*, Column*);
SQLITE_PRIVATE void sqlite3AddColumn(Parse*,Token*,Token*);
SQLITE_PRIVATE void sqlite3AddNotNull(Parse*, int);
SQLITE_PRIVATE void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int);
-SQLITE_PRIVATE void sqlite3AddCheckConstraint(Parse*, Expr*);
+SQLITE_PRIVATE void sqlite3AddCheckConstraint(Parse*, Expr*, const char*, const char*);
SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,Expr*,const char*,const char*);
SQLITE_PRIVATE void sqlite3AddCollateType(Parse*, Token*);
SQLITE_PRIVATE void sqlite3AddGenerated(Parse*,Expr*,Token*);
@@ -19960,6 +20036,7 @@ SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*, int);
SQLITE_PRIVATE void sqlite3CodeRhsOfIN(Parse*, Expr*, int);
SQLITE_PRIVATE int sqlite3CodeSubselect(Parse*, Expr*);
SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*);
+SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse*, struct SrcList_item*);
SQLITE_PRIVATE void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p);
SQLITE_PRIVATE int sqlite3MatchEName(
const struct ExprList_item*,
@@ -20782,7 +20859,7 @@ struct VdbeCursor {
Bool isEphemeral:1; /* True for an ephemeral table */
Bool useRandomRowid:1; /* Generate new record numbers semi-randomly */
Bool isOrdered:1; /* True if the table is not BTREE_UNORDERED */
- Bool seekHit:1; /* See the OP_SeekHit and OP_IfNoHope opcodes */
+ u16 seekHit; /* See the OP_SeekHit and OP_IfNoHope opcodes */
Btree *pBtx; /* Separate file holding temporary table */
i64 seqCount; /* Sequence counter */
u32 *aAltMap; /* Mapping from table to index column numbers */
@@ -27778,12 +27855,17 @@ SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, u64 nBytes){
if( nOld==nNew ){
pNew = pOld;
}else if( sqlite3GlobalConfig.bMemstat ){
+ sqlite3_int64 nUsed;
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, (int)nBytes);
nDiff = nNew - nOld;
- if( nDiff>0 && sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >=
+ if( nDiff>0 && (nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED)) >=
mem0.alarmThreshold-nDiff ){
sqlite3MallocAlarm(nDiff);
+ if( mem0.hardLimit>0 && nUsed >= mem0.hardLimit - nDiff ){
+ sqlite3_mutex_leave(mem0.mutex);
+ return 0;
+ }
}
pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
@@ -28090,12 +28172,15 @@ SQLITE_PRIVATE void sqlite3OomClear(sqlite3 *db){
}
/*
-** Take actions at the end of an API call to indicate an OOM error
+** Take actions at the end of an API call to deal with error codes.
*/
-static SQLITE_NOINLINE int apiOomError(sqlite3 *db){
- sqlite3OomClear(db);
- sqlite3Error(db, SQLITE_NOMEM);
- return SQLITE_NOMEM_BKPT;
+static SQLITE_NOINLINE int apiHandleError(sqlite3 *db, int rc){
+ if( db->mallocFailed || rc==SQLITE_IOERR_NOMEM ){
+ sqlite3OomClear(db);
+ sqlite3Error(db, SQLITE_NOMEM);
+ return SQLITE_NOMEM_BKPT;
+ }
+ return rc & db->errMask;
}
/*
@@ -28117,8 +28202,8 @@ SQLITE_PRIVATE int sqlite3ApiExit(sqlite3* db, int rc){
*/
assert( db!=0 );
assert( sqlite3_mutex_held(db->mutex) );
- if( db->mallocFailed || rc==SQLITE_IOERR_NOMEM ){
- return apiOomError(db);
+ if( db->mallocFailed || rc ){
+ return apiHandleError(db, rc);
}
return rc & db->errMask;
}
@@ -28554,11 +28639,10 @@ SQLITE_API void sqlite3_str_vappendf(
v = va_arg(ap,int);
}
if( v<0 ){
- if( v==SMALLEST_INT64 ){
- longvalue = ((u64)1)<<63;
- }else{
- longvalue = -v;
- }
+ testcase( v==SMALLEST_INT64 );
+ testcase( v==(-1) );
+ longvalue = ~v;
+ longvalue++;
prefix = '-';
}else{
longvalue = v;
@@ -31854,6 +31938,7 @@ SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc
incr = 1;
}else{
incr = 2;
+ length &= ~1;
assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
for(i=3-enc; i<length && zNum[i]==0; i+=2){}
nonNum = i<length;
@@ -33270,64 +33355,65 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 115 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
/* 116 */ "Close" OpHelp(""),
/* 117 */ "ColumnsUsed" OpHelp(""),
- /* 118 */ "SeekHit" OpHelp("seekHit=P2"),
- /* 119 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
- /* 120 */ "NewRowid" OpHelp("r[P2]=rowid"),
- /* 121 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
- /* 122 */ "Delete" OpHelp(""),
- /* 123 */ "ResetCount" OpHelp(""),
- /* 124 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
- /* 125 */ "SorterData" OpHelp("r[P2]=data"),
- /* 126 */ "RowData" OpHelp("r[P2]=data"),
- /* 127 */ "Rowid" OpHelp("r[P2]=rowid"),
- /* 128 */ "NullRow" OpHelp(""),
- /* 129 */ "SeekEnd" OpHelp(""),
- /* 130 */ "IdxInsert" OpHelp("key=r[P2]"),
- /* 131 */ "SorterInsert" OpHelp("key=r[P2]"),
- /* 132 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
- /* 133 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"),
- /* 134 */ "IdxRowid" OpHelp("r[P2]=rowid"),
- /* 135 */ "FinishSeek" OpHelp(""),
- /* 136 */ "Destroy" OpHelp(""),
- /* 137 */ "Clear" OpHelp(""),
- /* 138 */ "ResetSorter" OpHelp(""),
- /* 139 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"),
+ /* 118 */ "SeekScan" OpHelp("Scan-ahead up to P1 rows"),
+ /* 119 */ "SeekHit" OpHelp("set P2<=seekHit<=P3"),
+ /* 120 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
+ /* 121 */ "NewRowid" OpHelp("r[P2]=rowid"),
+ /* 122 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
+ /* 123 */ "Delete" OpHelp(""),
+ /* 124 */ "ResetCount" OpHelp(""),
+ /* 125 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
+ /* 126 */ "SorterData" OpHelp("r[P2]=data"),
+ /* 127 */ "RowData" OpHelp("r[P2]=data"),
+ /* 128 */ "Rowid" OpHelp("r[P2]=rowid"),
+ /* 129 */ "NullRow" OpHelp(""),
+ /* 130 */ "SeekEnd" OpHelp(""),
+ /* 131 */ "IdxInsert" OpHelp("key=r[P2]"),
+ /* 132 */ "SorterInsert" OpHelp("key=r[P2]"),
+ /* 133 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
+ /* 134 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"),
+ /* 135 */ "IdxRowid" OpHelp("r[P2]=rowid"),
+ /* 136 */ "FinishSeek" OpHelp(""),
+ /* 137 */ "Destroy" OpHelp(""),
+ /* 138 */ "Clear" OpHelp(""),
+ /* 139 */ "ResetSorter" OpHelp(""),
/* 140 */ "Real" OpHelp("r[P2]=P4"),
- /* 141 */ "SqlExec" OpHelp(""),
- /* 142 */ "ParseSchema" OpHelp(""),
- /* 143 */ "LoadAnalysis" OpHelp(""),
- /* 144 */ "DropTable" OpHelp(""),
- /* 145 */ "DropIndex" OpHelp(""),
- /* 146 */ "DropTrigger" OpHelp(""),
- /* 147 */ "IntegrityCk" OpHelp(""),
- /* 148 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
- /* 149 */ "Param" OpHelp(""),
- /* 150 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
- /* 151 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
- /* 152 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
- /* 153 */ "AggInverse" OpHelp("accum=r[P3] inverse(r[P2@P5])"),
- /* 154 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"),
- /* 155 */ "AggStep1" OpHelp("accum=r[P3] step(r[P2@P5])"),
- /* 156 */ "AggValue" OpHelp("r[P3]=value N=P2"),
- /* 157 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
- /* 158 */ "Expire" OpHelp(""),
- /* 159 */ "CursorLock" OpHelp(""),
- /* 160 */ "CursorUnlock" OpHelp(""),
- /* 161 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
- /* 162 */ "VBegin" OpHelp(""),
- /* 163 */ "VCreate" OpHelp(""),
- /* 164 */ "VDestroy" OpHelp(""),
- /* 165 */ "VOpen" OpHelp(""),
- /* 166 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
- /* 167 */ "VRename" OpHelp(""),
- /* 168 */ "Pagecount" OpHelp(""),
- /* 169 */ "MaxPgcnt" OpHelp(""),
- /* 170 */ "Trace" OpHelp(""),
- /* 171 */ "CursorHint" OpHelp(""),
- /* 172 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"),
- /* 173 */ "Noop" OpHelp(""),
- /* 174 */ "Explain" OpHelp(""),
- /* 175 */ "Abortable" OpHelp(""),
+ /* 141 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"),
+ /* 142 */ "SqlExec" OpHelp(""),
+ /* 143 */ "ParseSchema" OpHelp(""),
+ /* 144 */ "LoadAnalysis" OpHelp(""),
+ /* 145 */ "DropTable" OpHelp(""),
+ /* 146 */ "DropIndex" OpHelp(""),
+ /* 147 */ "DropTrigger" OpHelp(""),
+ /* 148 */ "IntegrityCk" OpHelp(""),
+ /* 149 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
+ /* 150 */ "Param" OpHelp(""),
+ /* 151 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
+ /* 152 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
+ /* 153 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
+ /* 154 */ "AggInverse" OpHelp("accum=r[P3] inverse(r[P2@P5])"),
+ /* 155 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"),
+ /* 156 */ "AggStep1" OpHelp("accum=r[P3] step(r[P2@P5])"),
+ /* 157 */ "AggValue" OpHelp("r[P3]=value N=P2"),
+ /* 158 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
+ /* 159 */ "Expire" OpHelp(""),
+ /* 160 */ "CursorLock" OpHelp(""),
+ /* 161 */ "CursorUnlock" OpHelp(""),
+ /* 162 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
+ /* 163 */ "VBegin" OpHelp(""),
+ /* 164 */ "VCreate" OpHelp(""),
+ /* 165 */ "VDestroy" OpHelp(""),
+ /* 166 */ "VOpen" OpHelp(""),
+ /* 167 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
+ /* 168 */ "VRename" OpHelp(""),
+ /* 169 */ "Pagecount" OpHelp(""),
+ /* 170 */ "MaxPgcnt" OpHelp(""),
+ /* 171 */ "Trace" OpHelp(""),
+ /* 172 */ "CursorHint" OpHelp(""),
+ /* 173 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"),
+ /* 174 */ "Noop" OpHelp(""),
+ /* 175 */ "Explain" OpHelp(""),
+ /* 176 */ "Abortable" OpHelp(""),
};
return azName[i];
}
@@ -33459,7 +33545,8 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
# if defined(__APPLE__) && ((__MAC_OS_X_VERSION_MIN_REQUIRED > 1050) || \
(__IPHONE_OS_VERSION_MIN_REQUIRED > 2000))
# if (!defined(TARGET_OS_EMBEDDED) || (TARGET_OS_EMBEDDED==0)) \
- && (!defined(TARGET_IPHONE_SIMULATOR) || (TARGET_IPHONE_SIMULATOR==0))
+ && (!defined(TARGET_IPHONE_SIMULATOR) || (TARGET_IPHONE_SIMULATOR==0))\
+ && (!defined(TARGET_OS_MACCATALYST) || (TARGET_OS_MACCATALYST==0))
# undef HAVE_GETHOSTUUID
# define HAVE_GETHOSTUUID 1
# else
@@ -35079,6 +35166,9 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
return rc;
}
+/* Forward declaration*/
+static int unixSleep(sqlite3_vfs*,int);
+
/*
** Set a posix-advisory-lock.
**
@@ -35108,7 +35198,7 @@ static int osSetPosixAdvisoryLock(
** 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);
+ unixSleep(0,1000);
rc = osFcntl(h,F_SETLK,pLock);
tm--;
}
@@ -35679,6 +35769,7 @@ static int unixClose(sqlite3_file *id){
}
sqlite3_mutex_leave(pInode->pLockMutex);
releaseInodeInfo(pFile);
+ assert( pFile->pShm==0 );
rc = closeUnixFile(id);
unixLeaveMutex();
return rc;
@@ -36905,7 +36996,24 @@ static int unixRead(
if( got==amt ){
return SQLITE_OK;
}else if( got<0 ){
- /* lastErrno set by seekAndRead */
+ /* pFile->lastErrno has been set by seekAndRead().
+ ** Usually we return SQLITE_IOERR_READ here, though for some
+ ** kinds of errors we return SQLITE_IOERR_CORRUPTFS. The
+ ** SQLITE_IOERR_CORRUPTFS will be converted into SQLITE_CORRUPT
+ ** prior to returning to the application by the sqlite3ApiExit()
+ ** routine.
+ */
+ switch( pFile->lastErrno ){
+ case ERANGE:
+ case EIO:
+#ifdef ENXIO
+ case ENXIO:
+#endif
+#ifdef EDEVERR
+ case EDEVERR:
+#endif
+ return SQLITE_IOERR_CORRUPTFS;
+ }
return SQLITE_IOERR_READ;
}else{
storeLastErrno(pFile, 0); /* not a system error */
@@ -37789,6 +37897,7 @@ struct unixShmNode {
char **apRegion; /* Array of mapped shared-memory regions */
int nRef; /* Number of unixShm objects pointing to this */
unixShm *pFirst; /* All unixShm objects pointing to this */
+ int aLock[SQLITE_SHM_NLOCK]; /* # shared locks on slot, -1==excl lock */
#ifdef SQLITE_DEBUG
u8 exclMask; /* Mask of exclusive locks held */
u8 sharedMask; /* Mask of shared locks held */
@@ -38330,6 +38439,38 @@ shmpage_out:
}
/*
+** Check that the pShmNode->aLock[] array comports with the locking bitmasks
+** held by each client. Return true if it does, or false otherwise. This
+** is to be used in an assert(). e.g.
+**
+** assert( assertLockingArrayOk(pShmNode) );
+*/
+#ifdef SQLITE_DEBUG
+static int assertLockingArrayOk(unixShmNode *pShmNode){
+ unixShm *pX;
+ int aLock[SQLITE_SHM_NLOCK];
+ assert( sqlite3_mutex_held(pShmNode->pShmMutex) );
+
+ memset(aLock, 0, sizeof(aLock));
+ for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
+ int i;
+ for(i=0; i<SQLITE_SHM_NLOCK; i++){
+ if( pX->exclMask & (1<<i) ){
+ assert( aLock[i]==0 );
+ aLock[i] = -1;
+ }else if( pX->sharedMask & (1<<i) ){
+ assert( aLock[i]>=0 );
+ aLock[i]++;
+ }
+ }
+ }
+
+ assert( 0==memcmp(pShmNode->aLock, aLock, sizeof(aLock)) );
+ return (memcmp(pShmNode->aLock, aLock, sizeof(aLock))==0);
+}
+#endif
+
+/*
** Change the lock state for a shared-memory segment.
**
** Note that the relationship between SHAREd and EXCLUSIVE locks is a little
@@ -38345,10 +38486,10 @@ static int unixShmLock(
){
unixFile *pDbFd = (unixFile*)fd; /* Connection holding shared memory */
unixShm *p = pDbFd->pShm; /* The shared memory being locked */
- unixShm *pX; /* For looping over all siblings */
unixShmNode *pShmNode = p->pShmNode; /* The underlying file iNode */
int rc = SQLITE_OK; /* Result code */
u16 mask; /* Mask of locks to take or release */
+ int *aLock = pShmNode->aLock;
assert( pShmNode==pDbFd->pInode->pShmNode );
assert( pShmNode->pInode==pDbFd->pInode );
@@ -38387,78 +38528,76 @@ static int unixShmLock(
mask = (1<<(ofst+n)) - (1<<ofst);
assert( n>1 || mask==(1<<ofst) );
sqlite3_mutex_enter(pShmNode->pShmMutex);
+ assert( assertLockingArrayOk(pShmNode) );
if( flags & SQLITE_SHM_UNLOCK ){
- u16 allMask = 0; /* Mask of locks held by siblings */
+ if( (p->exclMask|p->sharedMask) & mask ){
+ int ii;
+ int bUnlock = 1;
- /* See if any siblings hold this same lock */
- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
- if( pX==p ) continue;
- assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
- allMask |= pX->sharedMask;
- }
+ for(ii=ofst; ii<ofst+n; ii++){
+ if( aLock[ii]>((p->sharedMask & (1<<ii)) ? 1 : 0) ){
+ bUnlock = 0;
+ }
+ }
- /* Unlock the system-level locks */
- if( (mask & allMask)==0 ){
- rc = unixShmSystemLock(pDbFd, F_UNLCK, ofst+UNIX_SHM_BASE, n);
- }else{
- rc = SQLITE_OK;
- }
+ if( bUnlock ){
+ rc = unixShmSystemLock(pDbFd, F_UNLCK, ofst+UNIX_SHM_BASE, n);
+ if( rc==SQLITE_OK ){
+ memset(&aLock[ofst], 0, sizeof(int)*n);
+ }
+ }else if( ALWAYS(p->sharedMask & (1<<ofst)) ){
+ assert( n==1 && aLock[ofst]>1 );
+ aLock[ofst]--;
+ }
- /* Undo the local locks */
- if( rc==SQLITE_OK ){
- p->exclMask &= ~mask;
- p->sharedMask &= ~mask;
+ /* Undo the local locks */
+ if( rc==SQLITE_OK ){
+ p->exclMask &= ~mask;
+ p->sharedMask &= ~mask;
+ }
}
}else if( flags & SQLITE_SHM_SHARED ){
- u16 allShared = 0; /* Union of locks held by connections other than "p" */
-
- /* Find out which shared locks are already held by sibling connections.
- ** If any sibling already holds an exclusive lock, go ahead and return
- ** SQLITE_BUSY.
- */
- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
- if( (pX->exclMask & mask)!=0 ){
+ assert( n==1 );
+ assert( (p->exclMask & (1<<ofst))==0 );
+ if( (p->sharedMask & mask)==0 ){
+ if( aLock[ofst]<0 ){
rc = SQLITE_BUSY;
- break;
- }
- allShared |= pX->sharedMask;
- }
-
- /* Get shared locks at the system level, if necessary */
- if( rc==SQLITE_OK ){
- if( (allShared & mask)==0 ){
+ }else if( aLock[ofst]==0 ){
rc = unixShmSystemLock(pDbFd, F_RDLCK, ofst+UNIX_SHM_BASE, n);
- }else{
- rc = SQLITE_OK;
}
- }
- /* Get the local shared locks */
- if( rc==SQLITE_OK ){
- p->sharedMask |= mask;
+ /* Get the local shared locks */
+ if( rc==SQLITE_OK ){
+ p->sharedMask |= mask;
+ aLock[ofst]++;
+ }
}
}else{
/* Make sure no sibling connections hold locks that will block this
- ** lock. If any do, return SQLITE_BUSY right away.
- */
- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
- if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){
+ ** lock. If any do, return SQLITE_BUSY right away. */
+ int ii;
+ for(ii=ofst; ii<ofst+n; ii++){
+ assert( (p->sharedMask & mask)==0 );
+ if( ALWAYS((p->exclMask & (1<<ii))==0) && aLock[ii] ){
rc = SQLITE_BUSY;
break;
}
}
- /* Get the exclusive locks at the system level. Then if successful
- ** also mark the local connection as being locked.
- */
+ /* Get the exclusive locks at the system level. Then if successful
+ ** also update the in-memory values. */
if( rc==SQLITE_OK ){
rc = unixShmSystemLock(pDbFd, F_WRLCK, ofst+UNIX_SHM_BASE, n);
if( rc==SQLITE_OK ){
assert( (p->sharedMask & mask)==0 );
p->exclMask |= mask;
+ for(ii=ofst; ii<ofst+n; ii++){
+ aLock[ii] = -1;
+ }
}
}
}
+ assert( assertLockingArrayOk(pShmNode) );
sqlite3_mutex_leave(pShmNode->pShmMutex);
OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n",
p->id, osGetpid(0), p->sharedMask, p->exclMask));
@@ -39835,7 +39974,26 @@ static int unixAccess(
}
/*
+** If the last component of the pathname in z[0]..z[j-1] is something
+** other than ".." then back it out and return true. If the last
+** component is empty or if it is ".." then return false.
+*/
+static int unixBackupDir(const char *z, int *pJ){
+ int j = *pJ;
+ int i;
+ if( j<=0 ) return 0;
+ for(i=j-1; ALWAYS(i>0) && z[i-1]!='/'; i--){}
+ if( z[i]=='.' && i==j-2 && z[i+1]=='.' ) return 0;
+ *pJ = i-1;
+ return 1;
+}
+
+/*
+** Convert a relative pathname into a full pathname. Also
+** simplify the pathname as follows:
**
+** Remove all instances of /./
+** Remove all isntances of /X/../ for any X
*/
static int mkFullPathname(
const char *zPath, /* Input path */
@@ -39844,6 +40002,7 @@ static int mkFullPathname(
){
int nPath = sqlite3Strlen30(zPath);
int iOff = 0;
+ int i, j;
if( zPath[0]!='/' ){
if( osGetcwd(zOut, nOut-2)==0 ){
return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath);
@@ -39858,6 +40017,41 @@ static int mkFullPathname(
return SQLITE_CANTOPEN_BKPT;
}
sqlite3_snprintf(nOut-iOff, &zOut[iOff], "%s", zPath);
+
+ /* Remove duplicate '/' characters. Except, two // at the beginning
+ ** of a pathname is allowed since this is important on windows. */
+ for(i=j=1; zOut[i]; i++){
+ zOut[j++] = zOut[i];
+ while( zOut[i]=='/' && zOut[i+1]=='/' ) i++;
+ }
+ zOut[j] = 0;
+
+ assert( zOut[0]=='/' );
+ for(i=j=0; zOut[i]; i++){
+ if( zOut[i]=='/' ){
+ /* Skip over internal "/." directory components */
+ if( zOut[i+1]=='.' && zOut[i+2]=='/' ){
+ i += 1;
+ continue;
+ }
+
+ /* If this is a "/.." directory component then back out the
+ ** previous term of the directory if it is something other than "..".
+ */
+ if( zOut[i+1]=='.'
+ && zOut[i+2]=='.'
+ && zOut[i+3]=='/'
+ && unixBackupDir(zOut, &j)
+ ){
+ i += 2;
+ continue;
+ }
+ }
+ if( ALWAYS(j>=0) ) zOut[j] = zOut[i];
+ j++;
+ }
+ if( NEVER(j==0) ) zOut[j++] = '/';
+ zOut[j] = 0;
return SQLITE_OK;
}
@@ -40078,7 +40272,8 @@ static int unixSleep(sqlite3_vfs *NotUsed, int microseconds){
UNUSED_PARAMETER(NotUsed);
return microseconds;
#elif defined(HAVE_USLEEP) && HAVE_USLEEP
- usleep(microseconds);
+ if( microseconds>=1000000 ) sleep(microseconds/1000000);
+ if( microseconds%1000000 ) usleep(microseconds%1000000);
UNUSED_PARAMETER(NotUsed);
return microseconds;
#else
@@ -40651,7 +40846,7 @@ static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){
if( nTries==1 ){
conchModTime = buf.st_mtimespec;
- usleep(500000); /* wait 0.5 sec and try the lock again*/
+ unixSleep(0,500000); /* wait 0.5 sec and try the lock again*/
continue;
}
@@ -40677,7 +40872,7 @@ static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){
/* don't break the lock on short read or a version mismatch */
return SQLITE_BUSY;
}
- usleep(10000000); /* wait 10 sec and try the lock again */
+ unixSleep(0,10000000); /* wait 10 sec and try the lock again */
continue;
}
@@ -46798,7 +46993,11 @@ static int winOpen(
dwCreationDisposition = OPEN_EXISTING;
}
- dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
+ if( 0==sqlite3_uri_boolean(zName, "exclusive", 0) ){
+ dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
+ }else{
+ dwShareMode = 0;
+ }
if( isDelete ){
#if SQLITE_OS_WINCE
@@ -47951,11 +48150,14 @@ static const sqlite3_io_methods memdb_io_methods = {
** Close an memdb-file.
**
** The pData pointer is owned by the application, so there is nothing
-** to free.
+** to free. Unless the SQLITE_DESERIALIZE_FREEONCLOSE flag is set,
+** in which case we own the pData pointer and need to free it.
*/
static int memdbClose(sqlite3_file *pFile){
MemFile *p = (MemFile *)pFile;
- if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ) sqlite3_free(p->aData);
+ if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ){
+ sqlite3_free(p->aData);
+ }
return SQLITE_OK;
}
@@ -48398,8 +48600,12 @@ SQLITE_API int sqlite3_deserialize(
goto end_deserialize;
}
zSql = sqlite3_mprintf("ATTACH x AS %Q", zSchema);
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
- sqlite3_free(zSql);
+ if( zSql==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ 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;
@@ -48414,6 +48620,7 @@ SQLITE_API int sqlite3_deserialize(
rc = SQLITE_ERROR;
}else{
p->aData = pData;
+ pData = 0;
p->sz = szDb;
p->szAlloc = szBuf;
p->szMax = szBuf;
@@ -48426,6 +48633,9 @@ SQLITE_API int sqlite3_deserialize(
end_deserialize:
sqlite3_finalize(pStmt);
+ if( pData && (mFlags & SQLITE_DESERIALIZE_FREEONCLOSE)!=0 ){
+ sqlite3_free(pData);
+ }
sqlite3_mutex_leave(db->mutex);
return rc;
}
@@ -54181,6 +54391,7 @@ static int pager_delsuper(Pager *pPager, const char *zSuper){
i64 nSuperJournal; /* Size of super-journal file */
char *zJournal; /* Pointer to one journal within MJ file */
char *zSuperPtr; /* Space to hold super-journal filename */
+ char *zFree = 0; /* Free this buffer */
int nSuperPtr; /* Amount of space allocated to zSuperPtr[] */
/* Allocate space for both the pJournal and pSuper file descriptors.
@@ -54205,11 +54416,13 @@ static int pager_delsuper(Pager *pPager, const char *zSuper){
rc = sqlite3OsFileSize(pSuper, &nSuperJournal);
if( rc!=SQLITE_OK ) goto delsuper_out;
nSuperPtr = pVfs->mxPathname+1;
- zSuperJournal = sqlite3Malloc(nSuperJournal + nSuperPtr + 2);
- if( !zSuperJournal ){
+ zFree = sqlite3Malloc(4 + nSuperJournal + nSuperPtr + 2);
+ if( !zFree ){
rc = SQLITE_NOMEM_BKPT;
goto delsuper_out;
}
+ zFree[0] = zFree[1] = zFree[2] = zFree[3] = 0;
+ zSuperJournal = &zFree[4];
zSuperPtr = &zSuperJournal[nSuperJournal+2];
rc = sqlite3OsRead(pSuper, zSuperJournal, (int)nSuperJournal, 0);
if( rc!=SQLITE_OK ) goto delsuper_out;
@@ -54257,7 +54470,7 @@ static int pager_delsuper(Pager *pPager, const char *zSuper){
rc = sqlite3OsDelete(pVfs, zSuper, 0);
delsuper_out:
- sqlite3_free(zSuperJournal);
+ sqlite3_free(zFree);
if( pSuper ){
sqlite3OsClose(pSuper);
assert( !isOpen(pJournal) );
@@ -54595,7 +54808,11 @@ end_playback:
pPager->changeCountDone = pPager->tempFile;
if( rc==SQLITE_OK ){
- zSuper = pPager->pTmpSpace;
+ /* Leave 4 bytes of space before the super-journal filename in memory.
+ ** This is because it may end up being passed to sqlite3OsOpen(), in
+ ** which case it requires 4 0x00 bytes in memory immediately before
+ ** the filename. */
+ zSuper = &pPager->pTmpSpace[4];
rc = readSuperJournal(pPager->jfd, zSuper, pPager->pVfs->mxPathname+1);
testcase( rc!=SQLITE_OK );
}
@@ -54612,6 +54829,8 @@ end_playback:
/* If there was a super-journal and this routine will return success,
** see if it is possible to delete the super-journal.
*/
+ assert( zSuper==&pPager->pTmpSpace[4] );
+ memset(&zSuper[-4], 0, 4);
rc = pager_delsuper(pPager, zSuper);
testcase( rc!=SQLITE_OK );
}
@@ -63815,6 +64034,9 @@ struct Btree {
u32 iDataVersion; /* Combines with pBt->pPager->iDataVersion */
Btree *pNext; /* List of other sharable Btrees from the same db */
Btree *pPrev; /* Back pointer of the same list */
+#ifdef SQLITE_DEBUG
+ u64 nSeek; /* Calls to sqlite3BtreeMovetoUnpacked() */
+#endif
#ifndef SQLITE_OMIT_SHARED_CACHE
BtLock lock; /* Object used to lock page 1 */
#endif
@@ -63826,11 +64048,25 @@ struct Btree {
** If the shared-data extension is enabled, there may be multiple users
** of the Btree structure. At most one of these may open a write transaction,
** but any number may have active read transactions.
+**
+** These values must match SQLITE_TXN_NONE, SQLITE_TXN_READ, and
+** SQLITE_TXN_WRITE
*/
#define TRANS_NONE 0
#define TRANS_READ 1
#define TRANS_WRITE 2
+#if TRANS_NONE!=SQLITE_TXN_NONE
+# error wrong numeric code for no-transaction
+#endif
+#if TRANS_READ!=SQLITE_TXN_READ
+# error wrong numeric code for read-transaction
+#endif
+#if TRANS_WRITE!=SQLITE_TXN_WRITE
+# error wrong numeric code for write-transaction
+#endif
+
+
/*
** An instance of this object represents a single database file.
**
@@ -64582,6 +64818,17 @@ SQLITE_API int sqlite3_enable_shared_cache(int enable){
#define hasReadConflicts(a, b) 0
#endif
+#ifdef SQLITE_DEBUG
+/*
+** Return and reset the seek counter for a Btree object.
+*/
+SQLITE_PRIVATE sqlite3_uint64 sqlite3BtreeSeekCount(Btree *pBt){
+ u64 n = pBt->nSeek;
+ pBt->nSeek = 0;
+ return n;
+}
+#endif
+
/*
** Implementation of the SQLITE_CORRUPT_PAGE() macro. Takes a single
** (MemPage*) as an argument. The (MemPage*) must not be NULL.
@@ -67075,7 +67322,7 @@ btree_open_out:
** do not change the pager-cache size.
*/
if( sqlite3BtreeSchema(p, 0, 0)==0 ){
- sqlite3PagerSetCachesize(p->pBt->pPager, SQLITE_DEFAULT_CACHE_SIZE);
+ sqlite3BtreeSetCacheSize(p, SQLITE_DEFAULT_CACHE_SIZE);
}
pFile = sqlite3PagerFile(pBt->pPager);
@@ -69929,6 +70176,10 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
}
}
+#ifdef SQLITE_DEBUG
+ pCur->pBtree->nSeek++; /* Performance measurement during testing */
+#endif
+
if( pIdxKey ){
xRecordCompare = sqlite3VdbeFindCompare(pIdxKey);
pIdxKey->errCode = 0;
@@ -70205,7 +70456,7 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur){
pPage = pCur->pPage;
idx = ++pCur->ix;
- if( !pPage->isInit ){
+ if( !pPage->isInit || sqlite3FaultSim(412) ){
/* The only known way for this to happen is for there to be a
** recursive SQL function that does a DELETE operation as part of a
** SELECT which deletes content out from under an active cursor
@@ -74780,11 +75031,12 @@ SQLITE_PRIVATE const char *sqlite3BtreeGetJournalname(Btree *p){
}
/*
-** Return non-zero if a transaction is active.
+** Return one of SQLITE_TXN_NONE, SQLITE_TXN_READ, or SQLITE_TXN_WRITE
+** to describe the current transaction state of Btree p.
*/
-SQLITE_PRIVATE int sqlite3BtreeIsInTrans(Btree *p){
+SQLITE_PRIVATE int sqlite3BtreeTxnState(Btree *p){
assert( p==0 || sqlite3_mutex_held(p->db->mutex) );
- return (p && (p->inTrans==TRANS_WRITE));
+ return p ? p->inTrans : 0;
}
#ifndef SQLITE_OMIT_WAL
@@ -74813,14 +75065,8 @@ SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree *p, int eMode, int *pnLog, int *
#endif
/*
-** Return non-zero if a read (or write) transaction is active.
+** Return true if there is currently a backup running on Btree p.
*/
-SQLITE_PRIVATE int sqlite3BtreeIsInReadTrans(Btree *p){
- assert( p );
- assert( sqlite3_mutex_held(p->db->mutex) );
- return p->inTrans!=TRANS_NONE;
-}
-
SQLITE_PRIVATE int sqlite3BtreeIsInBackup(Btree *p){
assert( p );
assert( sqlite3_mutex_held(p->db->mutex) );
@@ -75166,7 +75412,7 @@ static int setDestPgsz(sqlite3_backup *p){
** message in database handle db.
*/
static int checkReadTransaction(sqlite3 *db, Btree *p){
- if( sqlite3BtreeIsInReadTrans(p) ){
+ if( sqlite3BtreeTxnState(p)!=SQLITE_TXN_NONE ){
sqlite3ErrorWithMsg(db, SQLITE_ERROR, "destination database is in use");
return SQLITE_ERROR;
}
@@ -75397,7 +75643,7 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
** one now. If a transaction is opened here, then it will be closed
** before this function exits.
*/
- if( rc==SQLITE_OK && 0==sqlite3BtreeIsInReadTrans(p->pSrc) ){
+ if( rc==SQLITE_OK && SQLITE_TXN_NONE==sqlite3BtreeTxnState(p->pSrc) ){
rc = sqlite3BtreeBeginTrans(p->pSrc, 0, 0);
bCloseTrans = 1;
}
@@ -75769,7 +76015,7 @@ SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
sqlite3BtreeEnter(pTo);
sqlite3BtreeEnter(pFrom);
- assert( sqlite3BtreeIsInTrans(pTo) );
+ assert( sqlite3BtreeTxnState(pTo)==SQLITE_TXN_WRITE );
pFd = sqlite3PagerFile(sqlite3BtreePager(pTo));
if( pFd->pMethods ){
i64 nByte = sqlite3BtreeGetPageSize(pFrom)*(i64)sqlite3BtreeLastPage(pFrom);
@@ -75805,7 +76051,7 @@ SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
sqlite3PagerClearCache(sqlite3BtreePager(b.pDest));
}
- assert( sqlite3BtreeIsInTrans(pTo)==0 );
+ assert( sqlite3BtreeTxnState(pTo)!=SQLITE_TXN_WRITE );
copy_finished:
sqlite3BtreeLeave(pFrom);
sqlite3BtreeLeave(pTo);
@@ -78200,6 +78446,7 @@ SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere){
int j;
sqlite3VdbeAddOp4(p, OP_ParseSchema, iDb, 0, 0, zWhere, P4_DYNAMIC);
for(j=0; j<p->db->nDb; j++) sqlite3VdbeUsesBtree(p, j);
+ sqlite3MayAbort(p->pParse);
}
/*
@@ -78428,7 +78675,7 @@ SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename
|| opcode==OP_VDestroy
|| opcode==OP_VCreate
- || (opcode==OP_ParseSchema && pOp->p4.z==0)
+ || opcode==OP_ParseSchema
|| ((opcode==OP_Halt || opcode==OP_HaltIfNull)
&& ((pOp->p1)!=SQLITE_OK && pOp->p2==OE_Abort))
){
@@ -79246,7 +79493,7 @@ SQLITE_PRIVATE char *sqlite3VdbeDisplayComment(
sqlite3_str_appendf(&x, "%d", v1);
}else if( pCtx->argc>1 ){
sqlite3_str_appendf(&x, "%d..%d", v1, v1+pCtx->argc-1);
- }else{
+ }else if( x.accError==0 ){
assert( x.nChar>2 );
x.nChar -= 2;
ii++;
@@ -80388,7 +80635,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
*/
for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
- if( sqlite3BtreeIsInTrans(pBt) ){
+ if( sqlite3BtreeTxnState(pBt)==SQLITE_TXN_WRITE ){
/* Whether or not a database might need a super-journal depends upon
** its journal mode (among other things). This matrix determines which
** journal modes use a super-journal and which do not */
@@ -80523,7 +80770,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
*/
for(i=0; i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
- if( sqlite3BtreeIsInTrans(pBt) ){
+ if( sqlite3BtreeTxnState(pBt)==SQLITE_TXN_WRITE ){
char const *zFile = sqlite3BtreeGetJournalname(pBt);
if( zFile==0 ){
continue; /* Ignore TEMP and :memory: databases */
@@ -82019,9 +82266,12 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3BlobCompare(const Mem *pB1, const Mem
static int sqlite3IntFloatCompare(i64 i, double r){
if( sizeof(LONGDOUBLE_TYPE)>8 ){
LONGDOUBLE_TYPE x = (LONGDOUBLE_TYPE)i;
+ testcase( x<r );
+ testcase( x>r );
+ testcase( x==r );
if( x<r ) return -1;
- if( x>r ) return +1;
- return 0;
+ if( x>r ) return +1; /*NO_TEST*/ /* work around bugs in gcov */
+ return 0; /*NO_TEST*/ /* work around bugs in gcov */
}else{
i64 y;
double s;
@@ -88801,7 +89051,8 @@ case OP_AutoCommit: {
** active.
** If P2 is non-zero, then a write-transaction is started, or if a
** read-transaction is already active, it is upgraded to a write-transaction.
-** If P2 is zero, then a read-transaction is started.
+** If P2 is zero, then a read-transaction is started. If P2 is 2 or more
+** then an exclusive transaction is started.
**
** P1 is the index of the database file on which the transaction is
** started. Index 0 is the main database file and index 1 is the
@@ -88835,6 +89086,7 @@ case OP_Transaction: {
assert( p->bIsReader );
assert( p->readOnly==0 || pOp->p2==0 );
+ assert( pOp->p2>=0 && pOp->p2<=2 );
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( DbMaskTest(p->btreeMask, pOp->p1) );
if( pOp->p2 && (db->flags & SQLITE_QueryOnly)!=0 ){
@@ -88860,7 +89112,7 @@ case OP_Transaction: {
&& pOp->p2
&& (db->autoCommit==0 || db->nVdbeRead>1)
){
- assert( sqlite3BtreeIsInTrans(pBt) );
+ assert( sqlite3BtreeTxnState(pBt)==SQLITE_TXN_WRITE );
if( p->iStatement==0 ){
assert( db->nStatement>=0 && db->nSavepoint>=0 );
db->nStatement++;
@@ -89213,7 +89465,7 @@ case OP_OpenDup: {
}
-/* Opcode: OpenEphemeral P1 P2 * P4 P5
+/* Opcode: OpenEphemeral P1 P2 P3 P4 P5
** Synopsis: nColumn=P2
**
** Open a new cursor P1 to a transient table.
@@ -89233,6 +89485,10 @@ case OP_OpenDup: {
** in btree.h. These flags control aspects of the operation of
** the btree. The BTREE_OMIT_JOURNAL and BTREE_SINGLE flags are
** added automatically.
+**
+** If P3 is positive, then reg[P3] is modified slightly so that it
+** can be used as zero-length data for OP_Insert. This is an optimization
+** that avoids an extra OP_Blob opcode to initialize that register.
*/
/* Opcode: OpenAutoindex P1 P2 * P4 *
** Synopsis: nColumn=P2
@@ -89255,6 +89511,15 @@ case OP_OpenEphemeral: {
SQLITE_OPEN_TRANSIENT_DB;
assert( pOp->p1>=0 );
assert( pOp->p2>=0 );
+ if( pOp->p3>0 ){
+ /* Make register reg[P3] into a value that can be used as the data
+ ** form sqlite3BtreeInsert() where the length of the data is zero. */
+ assert( pOp->p2==0 ); /* Only used when number of columns is zero */
+ assert( pOp->opcode==OP_OpenEphemeral );
+ assert( aMem[pOp->p3].flags & MEM_Null );
+ aMem[pOp->p3].n = 0;
+ aMem[pOp->p3].z = "";
+ }
pCx = p->apCsr[pOp->p1];
if( pCx && pCx->pBtx ){
/* If the ephermeral table is already open, erase all existing content
@@ -89697,22 +89962,172 @@ seek_not_found:
break;
}
-/* Opcode: SeekHit P1 P2 * * *
-** Synopsis: seekHit=P2
+
+/* Opcode: SeekScan P1 P2 * * *
+** Synopsis: Scan-ahead up to P1 rows
+**
+** This opcode is a prefix opcode to OP_SeekGE. In other words, this
+** opcode must be immediately followed by OP_SeekGE. This constraint is
+** checked by assert() statements.
+**
+** This opcode uses the P1 through P4 operands of the subsequent
+** OP_SeekGE. In the text that follows, the operands of the subsequent
+** OP_SeekGE opcode are denoted as SeekOP.P1 through SeekOP.P4. Only
+** the P1 and P2 operands of this opcode are also used, and are called
+** This.P1 and This.P2.
+**
+** This opcode helps to optimize IN operators on a multi-column index
+** where the IN operator is on the later terms of the index by avoiding
+** unnecessary seeks on the btree, substituting steps to the next row
+** of the b-tree instead. A correct answer is obtained if this opcode
+** is omitted or is a no-op.
+**
+** The SeekGE.P3 and SeekGE.P4 operands identify an unpacked key which
+** is the desired entry that we want the cursor SeekGE.P1 to be pointing
+** to. Call this SeekGE.P4/P5 row the "target".
+**
+** If the SeekGE.P1 cursor is not currently pointing to a valid row,
+** then this opcode is a no-op and control passes through into the OP_SeekGE.
+**
+** If the SeekGE.P1 cursor is pointing to a valid row, then that row
+** might be the target row, or it might be near and slightly before the
+** target row. This opcode attempts to position the cursor on the target
+** row by, perhaps by invoking sqlite3BtreeStep() on the cursor
+** between 0 and This.P1 times.
+**
+** There are three possible outcomes from this opcode:<ol>
+**
+** <li> If after This.P1 steps, the cursor is still point to a place that
+** is earlier in the btree than the target row,
+** then fall through into the subsquence OP_SeekGE opcode.
+**
+** <li> If the cursor is successfully moved to the target row by 0 or more
+** sqlite3BtreeNext() calls, then jump to This.P2, which will land just
+** past the OP_IdxGT opcode that follows the OP_SeekGE.
+**
+** <li> If the cursor ends up past the target row (indicating the the target
+** row does not exist in the btree) then jump to SeekOP.P2.
+** </ol>
+*/
+case OP_SeekScan: {
+ VdbeCursor *pC;
+ int res;
+ int nStep;
+ UnpackedRecord r;
+
+ assert( pOp[1].opcode==OP_SeekGE );
+
+ /* pOp->p2 points to the first instruction past the OP_IdxGT that
+ ** follows the OP_SeekGE. */
+ assert( pOp->p2>=(int)(pOp-aOp)+2 );
+ assert( aOp[pOp->p2-1].opcode==OP_IdxGT );
+ assert( pOp[1].p1==aOp[pOp->p2-1].p1 );
+ assert( pOp[1].p2==aOp[pOp->p2-1].p2 );
+ assert( pOp[1].p3==aOp[pOp->p2-1].p3 );
+
+ assert( pOp->p1>0 );
+ pC = p->apCsr[pOp[1].p1];
+ assert( pC!=0 );
+ assert( pC->eCurType==CURTYPE_BTREE );
+ assert( !pC->isTable );
+ if( !sqlite3BtreeCursorIsValidNN(pC->uc.pCursor) ){
+#ifdef SQLITE_DEBUG
+ if( db->flags&SQLITE_VdbeTrace ){
+ printf("... cursor not valid - fall through\n");
+ }
+#endif
+ break;
+ }
+ nStep = pOp->p1;
+ assert( nStep>=1 );
+ r.pKeyInfo = pC->pKeyInfo;
+ r.nField = (u16)pOp[1].p4.i;
+ r.default_rc = 0;
+ r.aMem = &aMem[pOp[1].p3];
+#ifdef SQLITE_DEBUG
+ {
+ int i;
+ for(i=0; i<r.nField; i++){
+ assert( memIsValid(&r.aMem[i]) );
+ REGISTER_TRACE(pOp[1].p3+i, &aMem[pOp[1].p3+i]);
+ }
+ }
+#endif
+ res = 0; /* Not needed. Only used to silence a warning. */
+ while(1){
+ rc = sqlite3VdbeIdxKeyCompare(db, pC, &r, &res);
+ if( rc ) goto abort_due_to_error;
+ if( res>0 ){
+ seekscan_search_fail:
+#ifdef SQLITE_DEBUG
+ if( db->flags&SQLITE_VdbeTrace ){
+ printf("... %d steps and then skip\n", pOp->p1 - nStep);
+ }
+#endif
+ VdbeBranchTaken(1,3);
+ pOp++;
+ goto jump_to_p2;
+ }
+ if( res==0 ){
+#ifdef SQLITE_DEBUG
+ if( db->flags&SQLITE_VdbeTrace ){
+ printf("... %d steps and then success\n", pOp->p1 - nStep);
+ }
+#endif
+ VdbeBranchTaken(2,3);
+ goto jump_to_p2;
+ break;
+ }
+ if( nStep<=0 ){
+#ifdef SQLITE_DEBUG
+ if( db->flags&SQLITE_VdbeTrace ){
+ printf("... fall through after %d steps\n", pOp->p1);
+ }
+#endif
+ VdbeBranchTaken(0,3);
+ break;
+ }
+ nStep--;
+ rc = sqlite3BtreeNext(pC->uc.pCursor, 0);
+ if( rc ){
+ if( rc==SQLITE_DONE ){
+ rc = SQLITE_OK;
+ goto seekscan_search_fail;
+ }else{
+ goto abort_due_to_error;
+ }
+ }
+ }
+
+ break;
+}
+
+
+/* Opcode: SeekHit P1 P2 P3 * *
+** Synopsis: set P2<=seekHit<=P3
**
-** Set the seekHit flag on cursor P1 to the value in P2.
-** The seekHit flag is used by the IfNoHope opcode.
+** Increase or decrease the seekHit value for cursor P1, if necessary,
+** so that it is no less than P2 and no greater than P3.
**
-** P1 must be a valid b-tree cursor. P2 must be a boolean value,
-** either 0 or 1.
+** The seekHit integer represents the maximum of terms in an index for which
+** there is known to be at least one match. If the seekHit value is smaller
+** than the total number of equality terms in an index lookup, then the
+** OP_IfNoHope opcode might run to see if the IN loop can be abandoned
+** early, thus saving work. This is part of the IN-early-out optimization.
+**
+** P1 must be a valid b-tree cursor.
*/
case OP_SeekHit: {
VdbeCursor *pC;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
- assert( pOp->p2==0 || pOp->p2==1 );
- pC->seekHit = pOp->p2 & 1;
+ assert( pOp->p3>=pOp->p2 );
+ if( pC->seekHit<pOp->p2 ){
+ pC->seekHit = pOp->p2;
+ }else if( pC->seekHit>pOp->p3 ){
+ pC->seekHit = pOp->p3;
+ }
break;
}
@@ -89770,16 +90185,20 @@ case OP_IfNotOpen: { /* jump */
** Synopsis: key=r[P3@P4]
**
** Register P3 is the first of P4 registers that form an unpacked
-** record.
+** record. Cursor P1 is an index btree. P2 is a jump destination.
+** In other words, the operands to this opcode are the same as the
+** operands to OP_NotFound and OP_IdxGT.
**
-** Cursor P1 is on an index btree. If the seekHit flag is set on P1, then
-** this opcode is a no-op. But if the seekHit flag of P1 is clear, then
-** check to see if there is any entry in P1 that matches the
-** prefix identified by P3 and P4. If no entry matches the prefix,
-** jump to P2. Otherwise fall through.
+** This opcode is an optimization attempt only. If this opcode always
+** falls through, the correct answer is still obtained, but extra works
+** is performed.
**
-** This opcode behaves like OP_NotFound if the seekHit
-** flag is clear and it behaves like OP_Noop if the seekHit flag is set.
+** A value of N in the seekHit flag of cursor P1 means that there exists
+** a key P3:N that will match some record in the index. We want to know
+** if it is possible for a record P3:P4 to match some record in the
+** index. If it is not possible, we can skips some work. So if seekHit
+** is less than P4, attempt to find out if a match is possible by running
+** OP_NotFound.
**
** This opcode is used in IN clause processing for a multi-column key.
** If an IN clause is attached to an element of the key other than the
@@ -89821,7 +90240,7 @@ case OP_IfNoHope: { /* jump, in3 */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
- if( pC->seekHit ) break;
+ if( pC->seekHit>=pOp->p4.i ) break;
/* Fall through into OP_NotFound */
/* no break */ deliberate_fall_through
}
@@ -89903,6 +90322,7 @@ case OP_Found: { /* jump, in3 */
}else{
VdbeBranchTaken(takeJump||alreadyExists==0,2);
if( takeJump || !alreadyExists ) goto jump_to_p2;
+ if( pOp->opcode==OP_IfNoHope ) pC->seekHit = pOp->p4.i;
}
break;
}
@@ -90259,7 +90679,7 @@ case OP_Insert: {
if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = x.nKey;
- assert( pData->flags & (MEM_Blob|MEM_Str) );
+ assert( (pData->flags & (MEM_Blob|MEM_Str))!=0 || pData->n==0 );
x.pData = pData->z;
x.nData = pData->n;
seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0);
@@ -91135,7 +91555,7 @@ case OP_FinishSeek: {
break;
}
-/* Opcode: IdxGE P1 P2 P3 P4 P5
+/* Opcode: IdxGE P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
** The P4 register values beginning with P3 form an unpacked index
@@ -91146,7 +91566,7 @@ case OP_FinishSeek: {
** If the P1 index entry is greater than or equal to the key value
** then jump to P2. Otherwise fall through to the next instruction.
*/
-/* Opcode: IdxGT P1 P2 P3 P4 P5
+/* Opcode: IdxGT P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
** The P4 register values beginning with P3 form an unpacked index
@@ -91157,7 +91577,7 @@ case OP_FinishSeek: {
** If the P1 index entry is greater than the key value
** then jump to P2. Otherwise fall through to the next instruction.
*/
-/* Opcode: IdxLT P1 P2 P3 P4 P5
+/* Opcode: IdxLT P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
** The P4 register values beginning with P3 form an unpacked index
@@ -91168,7 +91588,7 @@ case OP_FinishSeek: {
** If the P1 index entry is less than the key value then jump to P2.
** Otherwise fall through to the next instruction.
*/
-/* Opcode: IdxLE P1 P2 P3 P4 P5
+/* Opcode: IdxLE P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
** The P4 register values beginning with P3 form an unpacked index
@@ -91194,7 +91614,6 @@ case OP_IdxGE: { /* jump */
assert( pC->eCurType==CURTYPE_BTREE );
assert( pC->uc.pCursor!=0);
assert( pC->deferredMoveto==0 );
- assert( pOp->p5==0 || pOp->p5==1 );
assert( pOp->p4type==P4_INT32 );
r.pKeyInfo = pC->pKeyInfo;
r.nField = (u16)pOp->p4.i;
@@ -91215,8 +91634,31 @@ case OP_IdxGE: { /* jump */
}
}
#endif
- res = 0; /* Not needed. Only used to silence a warning. */
- rc = sqlite3VdbeIdxKeyCompare(db, pC, &r, &res);
+
+ /* Inlined version of sqlite3VdbeIdxKeyCompare() */
+ {
+ i64 nCellKey = 0;
+ BtCursor *pCur;
+ Mem m;
+
+ assert( pC->eCurType==CURTYPE_BTREE );
+ pCur = pC->uc.pCursor;
+ assert( sqlite3BtreeCursorIsValid(pCur) );
+ nCellKey = sqlite3BtreePayloadSize(pCur);
+ /* nCellKey will always be between 0 and 0xffffffff because of the way
+ ** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */
+ if( nCellKey<=0 || nCellKey>0x7fffffff ){
+ rc = SQLITE_CORRUPT_BKPT;
+ goto abort_due_to_error;
+ }
+ sqlite3VdbeMemInit(&m, db, 0);
+ rc = sqlite3VdbeMemFromBtreeZeroOffset(pCur, (u32)nCellKey, &m);
+ if( rc ) goto abort_due_to_error;
+ res = sqlite3VdbeRecordCompareWithSkip(m.n, m.z, &r, 0);
+ sqlite3VdbeMemRelease(&m);
+ }
+ /* End of inlined sqlite3VdbeIdxKeyCompare() */
+
assert( (OP_IdxLE&1)==(OP_IdxLT&1) && (OP_IdxGE&1)==(OP_IdxGT&1) );
if( (pOp->opcode&1)==(OP_IdxLT&1) ){
assert( pOp->opcode==OP_IdxLE || pOp->opcode==OP_IdxLT );
@@ -91226,7 +91668,7 @@ case OP_IdxGE: { /* jump */
res++;
}
VdbeBranchTaken(res>0,2);
- if( rc ) goto abort_due_to_error;
+ assert( rc==SQLITE_OK );
if( res>0 ) goto jump_to_p2;
break;
}
@@ -92352,7 +92794,7 @@ case OP_JournalMode: { /* out2 */
/* Open a transaction on the database file. Regardless of the journal
** mode, this transaction always uses a rollback journal.
*/
- assert( sqlite3BtreeIsInTrans(pBt)==0 );
+ assert( sqlite3BtreeTxnState(pBt)!=SQLITE_TXN_WRITE );
if( rc==SQLITE_OK ){
rc = sqlite3BtreeSetVersion(pBt, (eNew==PAGER_JOURNALMODE_WAL ? 2 : 1));
}
@@ -93292,7 +93734,11 @@ default: { /* This is really OP_Noop, OP_Explain */
** an error of some kind.
*/
abort_due_to_error:
- if( db->mallocFailed ) rc = SQLITE_NOMEM_BKPT;
+ if( db->mallocFailed ){
+ rc = SQLITE_NOMEM_BKPT;
+ }else if( rc==SQLITE_IOERR_CORRUPTFS ){
+ rc = SQLITE_CORRUPT_BKPT;
+ }
assert( rc );
if( p->zErrMsg==0 && rc!=SQLITE_IOERR_NOMEM ){
sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc));
@@ -94841,13 +95287,16 @@ SQLITE_PRIVATE int sqlite3VdbeSorterInit(
if( pSorter==0 ){
rc = SQLITE_NOMEM_BKPT;
}else{
+ Btree *pBt = db->aDb[0].pBt;
pSorter->pKeyInfo = pKeyInfo = (KeyInfo*)((u8*)pSorter + sz);
memcpy(pKeyInfo, pCsr->pKeyInfo, szKeyInfo);
pKeyInfo->db = 0;
if( nField && nWorker==0 ){
pKeyInfo->nKeyField = nField;
}
- pSorter->pgsz = pgsz = sqlite3BtreeGetPageSize(db->aDb[0].pBt);
+ sqlite3BtreeEnter(pBt);
+ pSorter->pgsz = pgsz = sqlite3BtreeGetPageSize(pBt);
+ sqlite3BtreeLeave(pBt);
pSorter->nTask = nWorker + 1;
pSorter->iPrev = (u8)(nWorker - 1);
pSorter->bUseThreads = (pSorter->nTask>1);
@@ -98817,7 +99266,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
assert( !ExprHasProperty(pExpr, EP_Reduced) );
/* Handle special cases of "x IS TRUE", "x IS FALSE", "x IS NOT TRUE",
** and "x IS NOT FALSE". */
- if( pRight && pRight->op==TK_ID ){
+ if( pRight && (pRight->op==TK_ID || pRight->op==TK_TRUEFALSE) ){
int rc = resolveExprStep(pWalker, pRight);
if( rc==WRC_Abort ) return WRC_Abort;
if( pRight->op==TK_TRUEFALSE ){
@@ -99026,6 +99475,7 @@ static int resolveCompoundOrderBy(
Expr *pE, *pDup;
if( pItem->done ) continue;
pE = sqlite3ExprSkipCollateAndLikely(pItem->pExpr);
+ if( NEVER(pE==0) ) continue;
if( sqlite3ExprIsInteger(pE, &iCol) ){
if( iCol<=0 || iCol>pEList->nExpr ){
resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr);
@@ -99205,6 +99655,7 @@ static int resolveOrderGroupBy(
for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
Expr *pE = pItem->pExpr;
Expr *pE2 = sqlite3ExprSkipCollateAndLikely(pE);
+ if( NEVER(pE2==0) ) continue;
if( zType[0]!='G' ){
iCol = resolveAsName(pParse, pSelect->pEList, pE2);
if( iCol>0 ){
@@ -99745,8 +100196,10 @@ SQLITE_PRIVATE char sqlite3TableColumnAffinity(Table *pTab, int iCol){
*/
SQLITE_PRIVATE char sqlite3ExprAffinity(const Expr *pExpr){
int op;
- while( ExprHasProperty(pExpr, EP_Skip) ){
- assert( pExpr->op==TK_COLLATE || pExpr->op==TK_IF_NULL_ROW );
+ while( ExprHasProperty(pExpr, EP_Skip|EP_IfNullRow) ){
+ assert( pExpr->op==TK_COLLATE
+ || pExpr->op==TK_IF_NULL_ROW
+ || (pExpr->op==TK_REGISTER && pExpr->op2==TK_IF_NULL_ROW) );
pExpr = pExpr->pLeft;
assert( pExpr!=0 );
}
@@ -99816,7 +100269,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, con
*/
SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr *pExpr){
while( pExpr && ExprHasProperty(pExpr, EP_Skip) ){
- assert( pExpr->op==TK_COLLATE || pExpr->op==TK_IF_NULL_ROW );
+ assert( pExpr->op==TK_COLLATE );
pExpr = pExpr->pLeft;
}
return pExpr;
@@ -99835,7 +100288,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprSkipCollateAndLikely(Expr *pExpr){
assert( pExpr->op==TK_FUNCTION );
pExpr = pExpr->x.pList->a[0].pExpr;
}else{
- assert( pExpr->op==TK_COLLATE || pExpr->op==TK_IF_NULL_ROW );
+ assert( pExpr->op==TK_COLLATE );
pExpr = pExpr->pLeft;
}
}
@@ -100469,6 +100922,7 @@ SQLITE_PRIVATE int sqlite3SelectExprHeight(Select *p){
** Expr.flags.
*/
SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){
+ if( pParse->nErr ) return;
if( p && p->x.pList && !ExprHasProperty(p, EP_xIsSelect) ){
p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList);
}
@@ -103321,6 +103775,7 @@ SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int n
*/
static void exprToRegister(Expr *pExpr, int iReg){
Expr *p = sqlite3ExprSkipCollateAndLikely(pExpr);
+ if( NEVER(p==0) ) return;
p->op2 = p->op;
p->op = TK_REGISTER;
p->iTable = iReg;
@@ -104308,6 +104763,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){
int r2;
pExpr = sqlite3ExprSkipCollateAndLikely(pExpr);
if( ConstFactorOk(pParse)
+ && ALWAYS(pExpr!=0)
&& pExpr->op!=TK_REGISTER
&& sqlite3ExprIsConstantNotJoin(pExpr)
){
@@ -106982,13 +107438,21 @@ static int renameResolveTrigger(Parse *pParse){
int i;
for(i=0; i<pSrc->nSrc && rc==SQLITE_OK; i++){
struct SrcList_item *p = &pSrc->a[i];
- p->pTab = sqlite3LocateTableItem(pParse, 0, p);
p->iCursor = pParse->nTab++;
- if( p->pTab==0 ){
- rc = SQLITE_ERROR;
+ if( p->pSelect ){
+ sqlite3SelectPrep(pParse, p->pSelect, 0);
+ sqlite3ExpandSubquery(pParse, p);
+ assert( i>0 );
+ assert( pStep->pFrom->a[i-1].pSelect );
+ sqlite3SelectPrep(pParse, pStep->pFrom->a[i-1].pSelect, 0);
}else{
- p->pTab->nTabRef++;
- rc = sqlite3ViewGetColumnNames(pParse, p->pTab);
+ p->pTab = sqlite3LocateTableItem(pParse, 0, p);
+ if( p->pTab==0 ){
+ rc = SQLITE_ERROR;
+ }else{
+ p->pTab->nTabRef++;
+ rc = sqlite3ViewGetColumnNames(pParse, p->pTab);
+ }
}
}
sNC.pSrcList = pSrc;
@@ -107050,6 +107514,12 @@ static void renameWalkTrigger(Walker *pWalker, Trigger *pTrigger){
sqlite3WalkExpr(pWalker, pUpsert->pUpsertWhere);
sqlite3WalkExpr(pWalker, pUpsert->pUpsertTargetWhere);
}
+ if( pStep->pFrom ){
+ int i;
+ for(i=0; i<pStep->pFrom->nSrc; i++){
+ sqlite3WalkSelect(pWalker, pStep->pFrom->a[i].pSelect);
+ }
+ }
}
}
@@ -109308,6 +109778,7 @@ static int loadStatTbl(
}
pSpace = (tRowcnt*)&pIdx->aSample[nSample];
pIdx->aAvgEq = pSpace; pSpace += nIdxCol;
+ pIdx->pTable->tabFlags |= TF_HasStat4;
for(i=0; i<nSample; i++){
pIdx->aSample[i].anEq = pSpace; pSpace += nIdxCol;
pIdx->aSample[i].anLt = pSpace; pSpace += nIdxCol;
@@ -109774,7 +110245,9 @@ static void detachFunc(
sqlite3_snprintf(sizeof(zErr),zErr, "cannot detach database %s", zName);
goto detach_error;
}
- if( sqlite3BtreeIsInReadTrans(pDb->pBt) || sqlite3BtreeIsInBackup(pDb->pBt) ){
+ if( sqlite3BtreeTxnState(pDb->pBt)!=SQLITE_TXN_NONE
+ || sqlite3BtreeIsInBackup(pDb->pBt)
+ ){
sqlite3_snprintf(sizeof(zErr),zErr, "database %s is locked", zName);
goto detach_error;
}
@@ -110434,7 +110907,7 @@ SQLITE_PRIVATE void sqlite3TableLock(
u8 isWriteLock, /* True for a write lock */
const char *zName /* Name of the table to be locked */
){
- Parse *pToplevel = sqlite3ParseToplevel(pParse);
+ Parse *pToplevel;
int i;
int nBytes;
TableLock *p;
@@ -110442,6 +110915,7 @@ SQLITE_PRIVATE void sqlite3TableLock(
if( iDb==1 ) return;
if( !sqlite3BtreeSharable(pParse->db->aDb[iDb].pBt) ) return;
+ pToplevel = sqlite3ParseToplevel(pParse);
for(i=0; i<pToplevel->nTableLock; i++){
p = &pToplevel->aTableLock[i];
if( p->iDb==iDb && p->iTab==iTab ){
@@ -110471,10 +110945,8 @@ SQLITE_PRIVATE void sqlite3TableLock(
*/
static void codeTableLocks(Parse *pParse){
int i;
- Vdbe *pVdbe;
-
- pVdbe = sqlite3GetVdbe(pParse);
- assert( pVdbe!=0 ); /* sqlite3GetVdbe cannot fail: VDBE already allocated */
+ Vdbe *pVdbe = pParse->pVdbe;
+ assert( pVdbe!=0 );
for(i=0; i<pParse->nTableLock; i++){
TableLock *p = &pParse->aTableLock[i];
@@ -111999,8 +112471,10 @@ primary_key_exit:
** Add a new CHECK constraint to the table currently under construction.
*/
SQLITE_PRIVATE void sqlite3AddCheckConstraint(
- Parse *pParse, /* Parsing context */
- Expr *pCheckExpr /* The check expression */
+ Parse *pParse, /* Parsing context */
+ Expr *pCheckExpr, /* The check expression */
+ const char *zStart, /* Opening "(" */
+ const char *zEnd /* Closing ")" */
){
#ifndef SQLITE_OMIT_CHECK
Table *pTab = pParse->pNewTable;
@@ -112011,6 +112485,13 @@ SQLITE_PRIVATE void sqlite3AddCheckConstraint(
pTab->pCheck = sqlite3ExprListAppend(pParse, pTab->pCheck, pCheckExpr);
if( pParse->constraintName.n ){
sqlite3ExprListSetName(pParse, pTab->pCheck, &pParse->constraintName, 1);
+ }else{
+ Token t;
+ for(zStart++; sqlite3Isspace(zStart[0]); zStart++){}
+ while( sqlite3Isspace(zEnd[-1]) ){ zEnd--; }
+ t.z = zStart;
+ t.n = (int)(zEnd - t.z);
+ sqlite3ExprListSetName(pParse, pTab->pCheck, &t, 1);
}
}else
#endif
@@ -112029,7 +112510,7 @@ SQLITE_PRIVATE void sqlite3AddCollateType(Parse *pParse, Token *pToken){
char *zColl; /* Dequoted name of collation sequence */
sqlite3 *db;
- if( (p = pParse->pNewTable)==0 ) return;
+ if( (p = pParse->pNewTable)==0 || IN_RENAME_OBJECT ) return;
i = p->nCol-1;
db = pParse->db;
zColl = sqlite3NameFromToken(db, pToken);
@@ -112264,12 +112745,15 @@ static int resizeIndexObject(sqlite3 *db, Index *pIdx, int N){
int nByte;
if( pIdx->nColumn>=N ) return SQLITE_OK;
assert( pIdx->isResized==0 );
- nByte = (sizeof(char*) + sizeof(i16) + 1)*N;
+ nByte = (sizeof(char*) + sizeof(LogEst) + sizeof(i16) + 1)*N;
zExtra = sqlite3DbMallocZero(db, nByte);
if( zExtra==0 ) return SQLITE_NOMEM_BKPT;
memcpy(zExtra, pIdx->azColl, sizeof(char*)*pIdx->nColumn);
pIdx->azColl = (const char**)zExtra;
zExtra += sizeof(char*)*N;
+ memcpy(zExtra, pIdx->aiRowLogEst, sizeof(LogEst)*(pIdx->nKeyCol+1));
+ pIdx->aiRowLogEst = (LogEst*)zExtra;
+ zExtra += sizeof(LogEst)*N;
memcpy(zExtra, pIdx->aiColumn, sizeof(i16)*pIdx->nColumn);
pIdx->aiColumn = (i16*)zExtra;
zExtra += sizeof(i16)*N;
@@ -114830,7 +115314,7 @@ SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){
assert(pList || pParse->db->mallocFailed );
if( pList ){
for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
- if( pItem->iCursor>=0 ) break;
+ if( pItem->iCursor>=0 ) continue;
pItem->iCursor = pParse->nTab++;
if( pItem->pSelect ){
sqlite3SrcListAssignCursors(pParse, pItem->pSelect->pSrc);
@@ -114847,15 +115331,15 @@ SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
struct SrcList_item *pItem;
if( pList==0 ) return;
for(pItem=pList->a, i=0; i<pList->nSrc; i++, pItem++){
- sqlite3DbFree(db, pItem->zDatabase);
+ if( pItem->zDatabase ) sqlite3DbFreeNN(db, pItem->zDatabase);
sqlite3DbFree(db, pItem->zName);
- sqlite3DbFree(db, pItem->zAlias);
+ if( pItem->zAlias ) sqlite3DbFreeNN(db, pItem->zAlias);
if( pItem->fg.isIndexedBy ) sqlite3DbFree(db, pItem->u1.zIndexedBy);
if( pItem->fg.isTabFunc ) sqlite3ExprListDelete(db, pItem->u1.pFuncArg);
sqlite3DeleteTable(db, pItem->pTab);
- sqlite3SelectDelete(db, pItem->pSelect);
- sqlite3ExprDelete(db, pItem->pOn);
- sqlite3IdListDelete(db, pItem->pUsing);
+ if( pItem->pSelect ) sqlite3SelectDelete(db, pItem->pSelect);
+ if( pItem->pOn ) sqlite3ExprDelete(db, pItem->pOn);
+ if( pItem->pUsing ) sqlite3IdListDelete(db, pItem->pUsing);
}
sqlite3DbFreeNN(db, pList);
}
@@ -115027,7 +115511,16 @@ SQLITE_PRIVATE void sqlite3BeginTransaction(Parse *pParse, int type){
if( !v ) return;
if( type!=TK_DEFERRED ){
for(i=0; i<db->nDb; i++){
- sqlite3VdbeAddOp2(v, OP_Transaction, i, (type==TK_EXCLUSIVE)+1);
+ int eTxnType;
+ Btree *pBt = db->aDb[i].pBt;
+ if( pBt && sqlite3BtreeIsReadonly(pBt) ){
+ eTxnType = 0; /* Read txn */
+ }else if( type==TK_EXCLUSIVE ){
+ eTxnType = 2; /* Exclusive txn */
+ }else{
+ eTxnType = 1; /* Write txn */
+ }
+ sqlite3VdbeAddOp2(v, OP_Transaction, i, eTxnType);
sqlite3VdbeUsesBtree(v, i);
}
}
@@ -115116,13 +115609,11 @@ SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *pParse){
** will occur at the end of the top-level VDBE and will be generated
** later, by sqlite3FinishCoding().
*/
-SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
- Parse *pToplevel = sqlite3ParseToplevel(pParse);
-
- assert( iDb>=0 && iDb<pParse->db->nDb );
- assert( pParse->db->aDb[iDb].pBt!=0 || iDb==1 );
+static void sqlite3CodeVerifySchemaAtToplevel(Parse *pToplevel, int iDb){
+ assert( iDb>=0 && iDb<pToplevel->db->nDb );
+ assert( pToplevel->db->aDb[iDb].pBt!=0 || iDb==1 );
assert( iDb<SQLITE_MAX_ATTACHED+2 );
- assert( sqlite3SchemaMutexHeld(pParse->db, iDb, 0) );
+ assert( sqlite3SchemaMutexHeld(pToplevel->db, iDb, 0) );
if( DbMaskTest(pToplevel->cookieMask, iDb)==0 ){
DbMaskSet(pToplevel->cookieMask, iDb);
if( !OMIT_TEMPDB && iDb==1 ){
@@ -115130,6 +115621,10 @@ SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
}
}
}
+SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
+ sqlite3CodeVerifySchemaAtToplevel(sqlite3ParseToplevel(pParse), iDb);
+}
+
/*
** If argument zDb is NULL, then call sqlite3CodeVerifySchema() for each
@@ -115161,7 +115656,7 @@ SQLITE_PRIVATE void sqlite3CodeVerifyNamedSchema(Parse *pParse, const char *zDb)
*/
SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){
Parse *pToplevel = sqlite3ParseToplevel(pParse);
- sqlite3CodeVerifySchema(pParse, iDb);
+ sqlite3CodeVerifySchemaAtToplevel(pToplevel, iDb);
DbMaskSet(pToplevel->writeMask, iDb);
pToplevel->isMultiWrite |= setStatement;
}
@@ -115212,7 +115707,9 @@ SQLITE_PRIVATE void sqlite3HaltConstraint(
i8 p4type, /* P4_STATIC or P4_TRANSIENT */
u8 p5Errmsg /* P5_ErrMsg type */
){
- Vdbe *v = sqlite3GetVdbe(pParse);
+ Vdbe *v;
+ assert( pParse->pVdbe!=0 );
+ v = sqlite3GetVdbe(pParse);
assert( (errCode&0xff)==SQLITE_CONSTRAINT || pParse->nested );
if( onError==OE_Abort ){
sqlite3MayAbort(pParse);
@@ -116493,7 +116990,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
}else
#endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */
{
- u16 wcf = WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK|WHERE_SEEK_TABLE;
+ u16 wcf = WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK;
if( sNC.ncFlags & NC_VarSelect ) bComplex = 1;
wcf |= (bComplex ? 0 : WHERE_ONEPASS_MULTIROW);
if( HasRowid(pTab) ){
@@ -116529,6 +117026,9 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
assert( IsVirtual(pTab)==0 || eOnePass!=ONEPASS_MULTI );
assert( IsVirtual(pTab) || bComplex || eOnePass!=ONEPASS_OFF );
if( eOnePass!=ONEPASS_SINGLE ) sqlite3MultiWrite(pParse);
+ if( sqlite3WhereUsesDeferredSeek(pWInfo) ){
+ sqlite3VdbeAddOp1(v, OP_FinishSeek, iTabCur);
+ }
/* Keep track of the number of rows to be deleted */
if( memCnt ){
@@ -116563,6 +117063,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iTabCur] = 0;
if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iTabCur] = 0;
if( addrEphOpen ) sqlite3VdbeChangeToNoop(v, addrEphOpen);
+ addrBypass = sqlite3VdbeMakeLabel(pParse);
}else{
if( pPk ){
/* Add the PK key for this row to the temporary table */
@@ -116576,13 +117077,6 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
nKey = 1; /* OP_DeferredSeek always uses a single rowid */
sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, iKey);
}
- }
-
- /* If this DELETE cannot use the ONEPASS strategy, this is the
- ** end of the WHERE loop */
- if( eOnePass!=ONEPASS_OFF ){
- addrBypass = sqlite3VdbeMakeLabel(pParse);
- }else{
sqlite3WhereEnd(pWInfo);
}
@@ -117013,10 +117507,6 @@ SQLITE_PRIVATE int sqlite3GenerateIndexKey(
}
if( regOut ){
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regOut);
- if( pIdx->pTable->pSelect ){
- const char *zAff = sqlite3IndexAffinityStr(pParse->db, pIdx);
- sqlite3VdbeChangeP4(v, -1, zAff, P4_TRANSIENT);
- }
}
sqlite3ReleaseTempRange(pParse, regBase, nCol);
return regBase;
@@ -119032,6 +119522,8 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){
FUNCTION(zeroblob, 1, 0, 0, zeroblobFunc ),
FUNCTION(substr, 2, 0, 0, substrFunc ),
FUNCTION(substr, 3, 0, 0, substrFunc ),
+ FUNCTION(substring, 2, 0, 0, substrFunc ),
+ FUNCTION(substring, 3, 0, 0, substrFunc ),
WAGGREGATE(sum, 1,0,0, sumStep, sumFinalize, sumFinalize, sumInverse, 0),
WAGGREGATE(total, 1,0,0, sumStep,totalFinalize,totalFinalize,sumInverse, 0),
WAGGREGATE(avg, 1,0,0, sumStep, avgFinalize, avgFinalize, sumInverse, 0),
@@ -120572,7 +121064,8 @@ SQLITE_PRIVATE void sqlite3OpenTable(
){
Vdbe *v;
assert( !IsVirtual(pTab) );
- v = sqlite3GetVdbe(pParse);
+ assert( pParse->pVdbe!=0 );
+ v = pParse->pVdbe;
assert( opcode==OP_OpenWrite || opcode==OP_OpenRead );
sqlite3TableLock(pParse, iDb, pTab->tnum,
(opcode==OP_OpenWrite)?1:0, pTab->zName);
@@ -122071,7 +122564,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
isUpdate = regOldData!=0;
db = pParse->db;
- v = sqlite3GetVdbe(pParse);
+ v = pParse->pVdbe;
assert( v!=0 );
assert( pTab->pSelect==0 ); /* This table is not a VIEW */
nCol = pTab->nCol;
@@ -122225,7 +122718,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
sqlite3VdbeGoto(v, ignoreDest);
}else{
char *zName = pCheck->a[i].zEName;
- if( zName==0 ) zName = pTab->zName;
+ assert( zName!=0 || pParse->db->mallocFailed );
if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-26383-51744 */
sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_CHECK,
onError, zName, P4_TRANSIENT,
@@ -122844,7 +123337,7 @@ SQLITE_PRIVATE void sqlite3CompleteInsertion(
|| update_flags==(OPFLAG_ISUPDATE|OPFLAG_SAVEPOSITION)
);
- v = sqlite3GetVdbe(pParse);
+ v = pParse->pVdbe;
assert( v!=0 );
assert( pTab->pSelect==0 ); /* This table is not a VIEW */
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
@@ -122945,7 +123438,7 @@ SQLITE_PRIVATE int sqlite3OpenTableAndIndices(
return 0;
}
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
- v = sqlite3GetVdbe(pParse);
+ v = pParse->pVdbe;
assert( v!=0 );
if( iBase<0 ) iBase = pParse->nTab;
iDataCur = iBase++;
@@ -123917,6 +124410,8 @@ struct sqlite3_api_routines {
int,const char**);
void (*free_filename)(char*);
sqlite3_file *(*database_file_object)(const char*);
+ /* Version 3.34.0 and later */
+ int (*txn_state)(sqlite3*,const char*);
};
/*
@@ -124221,6 +124716,8 @@ typedef int (*sqlite3_loadext_entry)(
#define sqlite3_create_filename sqlite3_api->create_filename
#define sqlite3_free_filename sqlite3_api->free_filename
#define sqlite3_database_file_object sqlite3_api->database_file_object
+/* Version 3.34.0 and later */
+#define sqlite3_txn_state sqlite3_api->txn_state
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
@@ -124703,6 +125200,8 @@ static const sqlite3_api_routines sqlite3Apis = {
sqlite3_create_filename,
sqlite3_free_filename,
sqlite3_database_file_object,
+ /* Version 3.34.0 and later */
+ sqlite3_txn_state,
};
/* True if x is the directory separator character
@@ -125863,7 +126362,9 @@ static int getTempStore(const char *z){
static int invalidateTempStorage(Parse *pParse){
sqlite3 *db = pParse->db;
if( db->aDb[1].pBt!=0 ){
- if( !db->autoCommit || sqlite3BtreeIsInReadTrans(db->aDb[1].pBt) ){
+ if( !db->autoCommit
+ || sqlite3BtreeTxnState(db->aDb[1].pBt)!=SQLITE_TXN_NONE
+ ){
sqlite3ErrorMsg(pParse, "temporary storage cannot be changed "
"from within a transaction");
return SQLITE_ERROR;
@@ -127183,7 +127684,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
aiCols = 0;
if( pParent ){
x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols);
- assert( x==0 );
+ assert( x==0 || db->mallocFailed );
}
addrOk = sqlite3VdbeMakeLabel(pParse);
@@ -127208,7 +127709,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
int jmp = sqlite3VdbeCurrentAddr(v)+2;
sqlite3VdbeAddOp3(v, OP_SeekRowid, i, jmp, regRow); VdbeCoverage(v);
sqlite3VdbeGoto(v, addrOk);
- assert( pFK->nCol==1 );
+ assert( pFK->nCol==1 || db->mallocFailed );
}
/* Generate code to report an FK violation to the caller. */
@@ -128566,7 +129067,7 @@ SQLITE_PRIVATE int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFl
** on the b-tree database, open one now. If a transaction is opened, it
** will be closed before this function returns. */
sqlite3BtreeEnter(pDb->pBt);
- if( !sqlite3BtreeIsInReadTrans(pDb->pBt) ){
+ if( sqlite3BtreeTxnState(pDb->pBt)==SQLITE_TXN_NONE ){
rc = sqlite3BtreeBeginTrans(pDb->pBt, 0, 0);
if( rc!=SQLITE_OK ){
sqlite3SetString(pzErrMsg, db, sqlite3ErrStr(rc));
@@ -128809,7 +129310,7 @@ static void schemaIsValid(Parse *pParse){
/* If there is not already a read-only (or read-write) transaction opened
** on the b-tree database, open one now. If a transaction is opened, it
** will be closed immediately after reading the meta-value. */
- if( !sqlite3BtreeIsInReadTrans(pBt) ){
+ if( sqlite3BtreeTxnState(pBt)==SQLITE_TXN_NONE ){
rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
sqlite3OomFault(db);
@@ -129072,6 +129573,7 @@ static int sqlite3LockAndPrepare(
sqlite3BtreeLeaveAll(db);
rc = sqlite3ApiExit(db, rc);
assert( (rc&db->errMask)==rc );
+ db->busyHandler.nBusy = 0;
sqlite3_mutex_leave(db->mutex);
return rc;
}
@@ -131258,6 +131760,7 @@ SQLITE_PRIVATE int sqlite3ColumnsFromExprList(
char *zName; /* Column name */
int nName; /* Size of name in zName[] */
Hash ht; /* Hash table of column names */
+ Table *pTab;
sqlite3HashInit(&ht);
if( pEList ){
@@ -131280,15 +131783,13 @@ SQLITE_PRIVATE int sqlite3ColumnsFromExprList(
/* If the column contains an "AS <name>" phrase, use <name> as the name */
}else{
Expr *pColExpr = sqlite3ExprSkipCollateAndLikely(pEList->a[i].pExpr);
- while( pColExpr->op==TK_DOT ){
+ while( ALWAYS(pColExpr!=0) && pColExpr->op==TK_DOT ){
pColExpr = pColExpr->pRight;
assert( pColExpr!=0 );
}
- if( pColExpr->op==TK_COLUMN ){
+ if( pColExpr->op==TK_COLUMN && (pTab = pColExpr->y.pTab)!=0 ){
/* For columns use the column name name */
int iCol = pColExpr->iColumn;
- Table *pTab = pColExpr->y.pTab;
- assert( pTab!=0 );
if( iCol<0 ) iCol = pTab->iPKey;
zName = iCol>=0 ? pTab->aCol[iCol].zName : "rowid";
}else if( pColExpr->op==TK_ID ){
@@ -131626,6 +132127,7 @@ static void generateWithRecursiveQuery(
int nCol = p->pEList->nExpr; /* Number of columns in the recursive table */
Vdbe *v = pParse->pVdbe; /* The prepared statement under construction */
Select *pSetup = p->pPrior; /* The setup query */
+ Select *pFirstRec; /* Left-most recursive term */
int addrTop; /* Top of the loop */
int addrCont, addrBreak; /* CONTINUE and BREAK addresses */
int iCurrent = 0; /* The Current table */
@@ -131701,7 +132203,25 @@ static void generateWithRecursiveQuery(
/* Detach the ORDER BY clause from the compound SELECT */
p->pOrderBy = 0;
+ /* Figure out how many elements of the compound SELECT are part of the
+ ** recursive query. Make sure no recursive elements use aggregate
+ ** functions. Mark the recursive elements as UNION ALL even if they
+ ** are really UNION because the distinctness will be enforced by the
+ ** iDistinct table. pFirstRec is left pointing to the left-most
+ ** recursive term of the CTE.
+ */
+ pFirstRec = p;
+ for(pFirstRec=p; ALWAYS(pFirstRec!=0); pFirstRec=pFirstRec->pPrior){
+ if( pFirstRec->selFlags & SF_Aggregate ){
+ sqlite3ErrorMsg(pParse, "recursive aggregate queries not supported");
+ goto end_of_recursive_query;
+ }
+ pFirstRec->op = TK_ALL;
+ if( (pFirstRec->pPrior->selFlags & SF_Recursive)==0 ) break;
+ }
+
/* Store the results of the setup-query in Queue. */
+ pSetup = pFirstRec->pPrior;
pSetup->pNext = 0;
ExplainQueryPlan((pParse, 1, "SETUP"));
rc = sqlite3Select(pParse, pSetup, &destQueue);
@@ -131734,15 +132254,11 @@ static void generateWithRecursiveQuery(
/* Execute the recursive SELECT taking the single row in Current as
** the value for the recursive-table. Store the results in the Queue.
*/
- if( p->selFlags & SF_Aggregate ){
- sqlite3ErrorMsg(pParse, "recursive aggregate queries not supported");
- }else{
- p->pPrior = 0;
- ExplainQueryPlan((pParse, 1, "RECURSIVE STEP"));
- sqlite3Select(pParse, p, &destQueue);
- assert( p->pPrior==0 );
- p->pPrior = pSetup;
- }
+ pFirstRec->pPrior = 0;
+ ExplainQueryPlan((pParse, 1, "RECURSIVE STEP"));
+ sqlite3Select(pParse, p, &destQueue);
+ assert( pFirstRec->pPrior==0 );
+ pFirstRec->pPrior = pSetup;
/* Keep running the loop until the Queue is empty */
sqlite3VdbeGoto(v, addrTop);
@@ -131812,6 +132328,16 @@ static int multiSelectValues(
}
/*
+** Return true if the SELECT statement which is known to be the recursive
+** part of a recursive CTE still has its anchor terms attached. If the
+** anchor terms have already been removed, then return false.
+*/
+static int hasAnchor(Select *p){
+ while( p && (p->selFlags & SF_Recursive)!=0 ){ p = p->pPrior; }
+ return p!=0;
+}
+
+/*
** This routine is called to process a compound query form from
** two or more separate queries using UNION, UNION ALL, EXCEPT, or
** INTERSECT
@@ -131896,7 +132422,7 @@ static int multiSelect(
assert( p->pEList->nExpr==pPrior->pEList->nExpr );
#ifndef SQLITE_OMIT_CTE
- if( p->selFlags & SF_Recursive ){
+ if( (p->selFlags & SF_Recursive)!=0 && hasAnchor(p) ){
generateWithRecursiveQuery(pParse, p, &dest);
}else
#endif
@@ -131988,6 +132514,7 @@ static int multiSelect(
assert( p->pEList );
}
+
/* Code the SELECT statements to our left
*/
assert( !pPrior->pOrderBy );
@@ -132792,7 +133319,7 @@ static Expr *substExpr(
ifNullRow.op = TK_IF_NULL_ROW;
ifNullRow.pLeft = pCopy;
ifNullRow.iTable = pSubst->iNewTable;
- ifNullRow.flags = EP_Skip;
+ ifNullRow.flags = EP_IfNullRow;
pCopy = &ifNullRow;
}
testcase( ExprHasProperty(pCopy, EP_Subquery) );
@@ -132801,8 +133328,7 @@ static Expr *substExpr(
ExprSetProperty(pNew, EP_CanBeNull);
}
if( pNew && ExprHasProperty(pExpr,EP_FromJoin) ){
- pNew->iRightJoinTable = pExpr->iRightJoinTable;
- ExprSetProperty(pNew, EP_FromJoin);
+ sqlite3SetJoinExpr(pNew, pExpr->iRightJoinTable);
}
sqlite3ExprDelete(db, pExpr);
pExpr = pNew;
@@ -134081,8 +134607,10 @@ static int withExpand(
ExprList *pEList;
Select *pSel;
Select *pLeft; /* Left-most SELECT statement */
+ Select *pRecTerm; /* Left-most recursive term */
int bMayRecursive; /* True if compound joined by UNION [ALL] */
With *pSavedWith; /* Initial value of pParse->pWith */
+ int iRecTab = -1; /* Cursor for recursive table */
/* If pCte->zCteErr is non-NULL at this point, then this is an illegal
** recursive reference to CTE pCte. Leave an error in pParse and return
@@ -134107,44 +134635,48 @@ static int withExpand(
assert( pFrom->pSelect );
/* Check if this is a recursive CTE. */
- pSel = pFrom->pSelect;
+ pRecTerm = pSel = pFrom->pSelect;
bMayRecursive = ( pSel->op==TK_ALL || pSel->op==TK_UNION );
- if( bMayRecursive ){
+ while( bMayRecursive && pRecTerm->op==pSel->op ){
int i;
- SrcList *pSrc = pFrom->pSelect->pSrc;
+ SrcList *pSrc = pRecTerm->pSrc;
+ assert( pRecTerm->pPrior!=0 );
for(i=0; i<pSrc->nSrc; i++){
struct SrcList_item *pItem = &pSrc->a[i];
if( pItem->zDatabase==0
&& pItem->zName!=0
&& 0==sqlite3StrICmp(pItem->zName, pCte->zName)
- ){
+ ){
pItem->pTab = pTab;
- pItem->fg.isRecursive = 1;
pTab->nTabRef++;
- pSel->selFlags |= SF_Recursive;
+ pItem->fg.isRecursive = 1;
+ if( pRecTerm->selFlags & SF_Recursive ){
+ sqlite3ErrorMsg(pParse,
+ "multiple references to recursive table: %s", pCte->zName
+ );
+ return SQLITE_ERROR;
+ }
+ pRecTerm->selFlags |= SF_Recursive;
+ if( iRecTab<0 ) iRecTab = pParse->nTab++;
+ pItem->iCursor = iRecTab;
}
}
+ if( (pRecTerm->selFlags & SF_Recursive)==0 ) break;
+ pRecTerm = pRecTerm->pPrior;
}
- /* Only one recursive reference is permitted. */
- if( pTab->nTabRef>2 ){
- sqlite3ErrorMsg(
- pParse, "multiple references to recursive table: %s", pCte->zName
- );
- return SQLITE_ERROR;
- }
- assert( pTab->nTabRef==1 ||
- ((pSel->selFlags&SF_Recursive) && pTab->nTabRef==2 ));
-
pCte->zCteErr = "circular reference: %s";
pSavedWith = pParse->pWith;
pParse->pWith = pWith;
- if( bMayRecursive ){
- Select *pPrior = pSel->pPrior;
- assert( pPrior->pWith==0 );
- pPrior->pWith = pSel->pWith;
- sqlite3WalkSelect(pWalker, pPrior);
- pPrior->pWith = 0;
+ if( pSel->selFlags & SF_Recursive ){
+ assert( pRecTerm!=0 );
+ assert( (pRecTerm->selFlags & SF_Recursive)==0 );
+ assert( pRecTerm->pNext!=0 );
+ assert( (pRecTerm->pNext->selFlags & SF_Recursive)!=0 );
+ assert( pRecTerm->pWith==0 );
+ pRecTerm->pWith = pSel->pWith;
+ sqlite3WalkSelect(pWalker, pRecTerm);
+ pRecTerm->pWith = 0;
}else{
sqlite3WalkSelect(pWalker, pSel);
}
@@ -135096,13 +135628,11 @@ SQLITE_PRIVATE int sqlite3Select(
assert( p->pOrderBy==0 || pDest->eDest!=SRT_Fifo );
assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistQueue );
assert( p->pOrderBy==0 || pDest->eDest!=SRT_Queue );
- if( IgnorableOrderby(pDest) ){
- assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union ||
- pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard ||
- pDest->eDest==SRT_Queue || pDest->eDest==SRT_DistFifo ||
- pDest->eDest==SRT_DistQueue || pDest->eDest==SRT_Fifo);
- /* If ORDER BY makes no difference in the output then neither does
- ** DISTINCT so it can be removed too. */
+ if( IgnorableDistinct(pDest) ){
+ assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union ||
+ pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard ||
+ pDest->eDest==SRT_DistQueue || pDest->eDest==SRT_DistFifo );
+ /* All of these destinations are also able to ignore the ORDER BY clause */
sqlite3ExprListDelete(db, p->pOrderBy);
p->pOrderBy = 0;
p->selFlags &= ~SF_Distinct;
@@ -136536,22 +137066,11 @@ SQLITE_PRIVATE void sqlite3BeginTrigger(
pTab = sqlite3SrcListLookup(pParse, pTableName);
if( !pTab ){
/* The table does not exist. */
- if( db->init.iDb==1 ){
- /* Ticket #3810.
- ** Normally, whenever a table is dropped, all associated triggers are
- ** dropped too. But if a TEMP trigger is created on a non-TEMP table
- ** and the table is dropped by a different database connection, the
- ** trigger is not visible to the database connection that does the
- ** drop so the trigger cannot be dropped. This results in an
- ** "orphaned trigger" - a trigger whose associated table is missing.
- */
- db->init.orphanTrigger = 1;
- }
- goto trigger_cleanup;
+ goto trigger_orphan_error;
}
if( IsVirtual(pTab) ){
sqlite3ErrorMsg(pParse, "cannot create triggers on virtual tables");
- goto trigger_cleanup;
+ goto trigger_orphan_error;
}
/* Check that the trigger name is not reserved and that no trigger of the
@@ -136589,12 +137108,12 @@ SQLITE_PRIVATE void sqlite3BeginTrigger(
if( pTab->pSelect && tr_tm!=TK_INSTEAD ){
sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S",
(tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0);
- goto trigger_cleanup;
+ goto trigger_orphan_error;
}
if( !pTab->pSelect && tr_tm==TK_INSTEAD ){
sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF"
" trigger on table: %S", pTableName, 0);
- goto trigger_cleanup;
+ goto trigger_orphan_error;
}
#ifndef SQLITE_OMIT_AUTHORIZATION
@@ -136654,6 +137173,23 @@ trigger_cleanup:
}else{
assert( pParse->pNewTrigger==pTrigger );
}
+ return;
+
+trigger_orphan_error:
+ if( db->init.iDb==1 ){
+ /* Ticket #3810.
+ ** Normally, whenever a table is dropped, all associated triggers are
+ ** dropped too. But if a TEMP trigger is created on a non-TEMP table
+ ** and the table is dropped by a different database connection, the
+ ** trigger is not visible to the database connection that does the
+ ** drop so the trigger cannot be dropped. This results in an
+ ** "orphaned trigger" - a trigger whose associated table is missing.
+ **
+ ** 2020-11-05 see also https://sqlite.org/forum/forumpost/157dc791df
+ */
+ db->init.orphanTrigger = 1;
+ }
+ goto trigger_cleanup;
}
/*
@@ -137824,7 +138360,7 @@ static void updateFromSelect(
#endif
pList = sqlite3ExprListAppend(pParse, pList, pNew);
}
- eDest = SRT_Upfrom;
+ eDest = IsVirtual(pTab) ? SRT_Table : SRT_Upfrom;
}else if( pTab->pSelect ){
for(i=0; i<pTab->nCol; i++){
pList = sqlite3ExprListAppend(pParse, pList, exprRowColumn(pParse, i));
@@ -138241,6 +138777,8 @@ SQLITE_PRIVATE void sqlite3Update(
if( nChangeFrom==0 && HasRowid(pTab) ){
sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid);
+ iEph = pParse->nTab++;
+ addrOpen = sqlite3VdbeAddOp3(v, OP_OpenEphemeral, iEph, 0, regRowSet);
}else{
assert( pPk!=0 || HasRowid(pTab) );
nPk = pPk ? pPk->nKeyCol : 0;
@@ -138295,7 +138833,7 @@ SQLITE_PRIVATE void sqlite3Update(
** be deleted as a result of REPLACE conflict handling. Any of these
** things might disturb a cursor being used to scan through the table
** or index, causing a single-pass approach to malfunction. */
- flags = WHERE_ONEPASS_DESIRED|WHERE_SEEK_UNIQ_TABLE;
+ flags = WHERE_ONEPASS_DESIRED;
if( !pParse->nested && !pTrigger && !hasFK && !chngKey && !bReplace ){
flags |= WHERE_ONEPASS_MULTIROW;
}
@@ -138332,9 +138870,10 @@ SQLITE_PRIVATE void sqlite3Update(
** leave it in register regOldRowid. */
sqlite3VdbeAddOp2(v, OP_Rowid, iDataCur, regOldRowid);
if( eOnePass==ONEPASS_OFF ){
- /* We need to use regRowSet, so reallocate aRegIdx[nAllIdx] */
aRegIdx[nAllIdx] = ++pParse->nMem;
- sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid);
+ sqlite3VdbeAddOp3(v, OP_Insert, iEph, regRowSet, regOldRowid);
+ }else{
+ if( ALWAYS(addrOpen) ) sqlite3VdbeChangeToNoop(v, addrOpen);
}
}else{
/* Read the PK of the current row into an array of registers. In
@@ -138422,8 +138961,9 @@ SQLITE_PRIVATE void sqlite3Update(
VdbeCoverage(v);
}
}else{
- labelContinue = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet,labelBreak,
- regOldRowid);
+ sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v);
+ labelContinue = sqlite3VdbeMakeLabel(pParse);
+ addrTop = sqlite3VdbeAddOp2(v, OP_Rowid, iEph, regOldRowid);
VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid);
VdbeCoverage(v);
@@ -138673,11 +139213,9 @@ SQLITE_PRIVATE void sqlite3Update(
}else if( eOnePass==ONEPASS_MULTI ){
sqlite3VdbeResolveLabel(v, labelContinue);
sqlite3WhereEnd(pWInfo);
- }else if( pPk || nChangeFrom ){
+ }else{
sqlite3VdbeResolveLabel(v, labelContinue);
sqlite3VdbeAddOp2(v, OP_Next, iEph, addrTop); VdbeCoverage(v);
- }else{
- sqlite3VdbeGoto(v, labelContinue);
}
sqlite3VdbeResolveLabel(v, labelBreak);
@@ -138777,12 +139315,26 @@ static void updateVirtualTable(
regArg = pParse->nMem + 1;
pParse->nMem += nArg;
if( pSrc->nSrc>1 ){
+ Index *pPk = 0;
Expr *pRow;
ExprList *pList;
- if( pRowid ){
- pRow = sqlite3ExprDup(db, pRowid, 0);
+ if( HasRowid(pTab) ){
+ if( pRowid ){
+ pRow = sqlite3ExprDup(db, pRowid, 0);
+ }else{
+ pRow = sqlite3PExpr(pParse, TK_ROW, 0, 0);
+ }
}else{
- pRow = sqlite3PExpr(pParse, TK_ROW, 0, 0);
+ i16 iPk; /* PRIMARY KEY column */
+ pPk = sqlite3PrimaryKeyIndex(pTab);
+ assert( pPk!=0 );
+ assert( pPk->nKeyCol==1 );
+ iPk = pPk->aiColumn[0];
+ if( aXRef[iPk]>=0 ){
+ pRow = sqlite3ExprDup(db, pChanges->a[aXRef[iPk]].pExpr, 0);
+ }else{
+ pRow = exprRowColumn(pParse, iPk);
+ }
}
pList = sqlite3ExprListAppend(pParse, 0, pRow);
@@ -138796,7 +139348,7 @@ static void updateVirtualTable(
}
}
- updateFromSelect(pParse, ephemTab, 0, pList, pSrc, pWhere, 0, 0);
+ updateFromSelect(pParse, ephemTab, pPk, pList, pSrc, pWhere, 0, 0);
sqlite3ExprListDelete(db, pList);
eOnePass = ONEPASS_OFF;
}else{
@@ -139498,8 +140050,8 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3RunVacuum(
BTREE_APPLICATION_ID, 0, /* Preserve the application id */
};
- assert( 1==sqlite3BtreeIsInTrans(pTemp) );
- assert( pOut!=0 || 1==sqlite3BtreeIsInTrans(pMain) );
+ assert( SQLITE_TXN_WRITE==sqlite3BtreeTxnState(pTemp) );
+ assert( pOut!=0 || SQLITE_TXN_WRITE==sqlite3BtreeTxnState(pMain) );
/* Copy Btree meta values */
for(i=0; i<ArraySize(aCopy); i+=2){
@@ -141170,9 +141722,11 @@ struct WhereTerm {
u8 eMatchOp; /* Op for vtab MATCH/LIKE/GLOB/REGEXP terms */
int iParent; /* Disable pWC->a[iParent] when this term disabled */
int leftCursor; /* Cursor number of X in "X <op> <expr>" */
- int iField; /* Field in (?,?,?) IN (SELECT...) vector */
union {
- int leftColumn; /* Column number of X in "X <op> <expr>" */
+ struct {
+ int leftColumn; /* Column number of X in "X <op> <expr>" */
+ int iField; /* Field in (?,?,?) IN (SELECT...) vector */
+ } x; /* Opcode other than OP_OR or OP_AND */
WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */
WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */
} u;
@@ -141397,6 +141951,7 @@ struct WhereInfo {
unsigned sorted :1; /* True if really sorted (not just grouped) */
LogEst nRowOut; /* Estimated number of output rows */
int iTop; /* The very beginning of the WHERE loop */
+ int iEndWhere; /* End of the WHERE clause itself */
WhereLoop *pLoops; /* List of all WhereLoop objects */
WhereExprMod *pExprMods; /* Expression modifications */
Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
@@ -141525,6 +142080,7 @@ SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereC
#define WHERE_PARTIALIDX 0x00020000 /* The automatic index is partial */
#define WHERE_IN_EARLYOUT 0x00040000 /* Perhaps quit IN loops early */
#define WHERE_BIGNULL_SORT 0x00080000 /* Column nEq of index is BIGNULL */
+#define WHERE_IN_SEEKSCAN 0x00100000 /* Seek-scan optimization for IN */
#endif /* !defined(SQLITE_WHEREINT_H) */
@@ -141938,7 +142494,7 @@ static Expr *removeUnindexableInClauseTerms(
for(i=iEq; i<pLoop->nLTerm; i++){
if( pLoop->aLTerm[i]->pExpr==pX ){
- int iField = pLoop->aLTerm[i]->iField - 1;
+ int iField = pLoop->aLTerm[i]->u.x.iField - 1;
if( pOrigRhs->a[iField].pExpr==0 ) continue; /* Duplicate PK column */
pRhs = sqlite3ExprListAppend(pParse, pRhs, pOrigRhs->a[iField].pExpr);
pOrigRhs->a[iField].pExpr = 0;
@@ -142081,6 +142637,9 @@ static int codeEqualityTerm(
if( pLevel->u.in.nIn==0 ){
pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse);
}
+ if( iEq>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0 ){
+ pLoop->wsFlags |= WHERE_IN_EARLYOUT;
+ }
i = pLevel->u.in.nIn;
pLevel->u.in.nIn += nEq;
@@ -142107,7 +142666,6 @@ static int codeEqualityTerm(
if( iEq>0 ){
pIn->iBase = iReg - i;
pIn->nPrefix = i;
- pLoop->wsFlags |= WHERE_IN_EARLYOUT;
}else{
pIn->nPrefix = 0;
}
@@ -142117,6 +142675,14 @@ static int codeEqualityTerm(
pIn++;
}
}
+ testcase( iEq>0
+ && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0
+ && (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 );
+ if( iEq>0
+ && (pLoop->wsFlags & (WHERE_IN_SEEKSCAN|WHERE_VIRTUALTABLE))==0
+ ){
+ sqlite3VdbeAddOp3(v, OP_SeekHit, pLevel->iIdxCur, 0, iEq);
+ }
}else{
pLevel->u.in.nIn = 0;
}
@@ -142903,6 +143469,9 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
pLoop->u.vtab.needFree ? P4_DYNAMIC : P4_STATIC);
VdbeCoverage(v);
pLoop->u.vtab.needFree = 0;
+ /* An OOM inside of AddOp4(OP_VFilter) instruction above might have freed
+ ** the u.vtab.idxStr. NULL it out to prevent a use-after-free */
+ if( db->mallocFailed ) pLoop->u.vtab.idxStr = 0;
pLevel->p1 = iCur;
pLevel->op = pWInfo->eOnePass ? OP_Noop : OP_VNext;
pLevel->p2 = sqlite3VdbeCurrentAddr(v);
@@ -143161,6 +143730,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
u8 bStopAtNull = 0; /* Add condition to terminate at NULLs */
int omitTable; /* True if we use the index only */
int regBignull = 0; /* big-null flag register */
+ int addrSeekScan = 0; /* Opcode of the OP_SeekScan, if any */
pIdx = pLoop->u.btree.pIndex;
iIdxCur = pLevel->iIdxCur;
@@ -143299,9 +143869,6 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
** above has already left the cursor sitting on the correct row,
** so no further seeking is needed */
}else{
- if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){
- sqlite3VdbeAddOp1(v, OP_SeekHit, iIdxCur);
- }
if( regBignull ){
sqlite3VdbeAddOp2(v, OP_Integer, 1, regBignull);
VdbeComment((v, "NULL-scan pass ctr"));
@@ -143309,6 +143876,20 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
assert( op!=0 );
+ if( (pLoop->wsFlags & WHERE_IN_SEEKSCAN)!=0 && op==OP_SeekGE ){
+ assert( regBignull==0 );
+ /* TUNING: The OP_SeekScan opcode seeks to reduce the number
+ ** of expensive seek operations by replacing a single seek with
+ ** 1 or more step operations. The question is, how many steps
+ ** should we try before giving up and going with a seek. The cost
+ ** of a seek is proportional to the logarithm of the of the number
+ ** of entries in the tree, so basing the number of steps to try
+ ** on the estimated number of rows in the btree seems like a good
+ ** guess. */
+ addrSeekScan = sqlite3VdbeAddOp1(v, OP_SeekScan,
+ (pIdx->aiRowLogEst[0]+9)/10);
+ VdbeCoverage(v);
+ }
sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
VdbeCoverage(v);
VdbeCoverageIf(v, op==OP_Rewind); testcase( op==OP_Rewind );
@@ -143391,6 +143972,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
testcase( op==OP_IdxGE ); VdbeCoverageIf(v, op==OP_IdxGE );
testcase( op==OP_IdxLT ); VdbeCoverageIf(v, op==OP_IdxLT );
testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE );
+ if( addrSeekScan ) sqlite3VdbeJumpHere(v, addrSeekScan);
}
if( regBignull ){
/* During a NULL-scan, check to see if we have reached the end of
@@ -143410,8 +143992,8 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE );
}
- if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){
- sqlite3VdbeAddOp2(v, OP_SeekHit, iIdxCur, 1);
+ if( (pLoop->wsFlags & WHERE_IN_EARLYOUT)!=0 ){
+ sqlite3VdbeAddOp3(v, OP_SeekHit, iIdxCur, nEq, nEq);
}
/* Seek the table cursor, if required */
@@ -143420,17 +144002,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
if( omitTable ){
/* pIdx is a covering index. No need to access the main table. */
}else if( HasRowid(pIdx->pTable) ){
- if( (pWInfo->wctrlFlags & WHERE_SEEK_TABLE)
- || ( (pWInfo->wctrlFlags & WHERE_SEEK_UNIQ_TABLE)!=0
- && (pWInfo->eOnePass==ONEPASS_SINGLE || pLoop->nLTerm==0) )
- ){
- iRowidReg = ++pParse->nMem;
- sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg);
- sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowidReg);
- VdbeCoverage(v);
- }else{
- codeDeferredSeek(pWInfo, pIdx, iCur, iIdxCur);
- }
+ codeDeferredSeek(pWInfo, pIdx, iCur, iIdxCur);
}else if( iCur!=iIdxCur ){
Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable);
iRowidReg = sqlite3GetTempRange(pParse, pPk->nKeyCol);
@@ -143557,7 +144129,6 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
int iRetInit; /* Address of regReturn init */
int untestedTerms = 0; /* Some terms not completely tested */
int ii; /* Loop counter */
- u16 wctrlFlags; /* Flags for sub-WHERE clause */
Expr *pAndExpr = 0; /* An ".. AND (...)" expression */
Table *pTab = pTabItem->pTab;
@@ -143658,7 +144229,6 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
** eliminating duplicates from other WHERE clauses, the action for each
** sub-WHERE clause is to to invoke the main loop body as a subroutine.
*/
- wctrlFlags = WHERE_OR_SUBCLAUSE | (pWInfo->wctrlFlags & WHERE_SEEK_TABLE);
ExplainQueryPlan((pParse, 1, "MULTI-INDEX OR"));
for(ii=0; ii<pOrWc->nTerm; ii++){
WhereTerm *pOrTerm = &pOrWc->a[ii];
@@ -143677,7 +144247,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
ExplainQueryPlan((pParse, 1, "INDEX %d", ii+1));
WHERETRACE(0xffff, ("Subplan for OR-clause:\n"));
pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
- wctrlFlags, iCovCur);
+ WHERE_OR_SUBCLAUSE, iCovCur);
assert( pSubWInfo || pParse->nErr || db->mallocFailed );
if( pSubWInfo ){
WhereLoop *pSubLoop;
@@ -143775,6 +144345,9 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
}else{
pCov = 0;
}
+ if( sqlite3WhereUsesDeferredSeek(pSubWInfo) ){
+ pWInfo->bDeferredSeek = 1;
+ }
/* Finish the loop through table entries that match term pOrTerm. */
sqlite3WhereEnd(pSubWInfo);
@@ -143927,7 +144500,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
#endif
assert( !ExprHasProperty(pE, EP_FromJoin) );
assert( (pTerm->prereqRight & pLevel->notReady)!=0 );
- pAlt = sqlite3WhereFindTerm(pWC, iCur, pTerm->u.leftColumn, notReady,
+ pAlt = sqlite3WhereFindTerm(pWC, iCur, pTerm->u.x.leftColumn, notReady,
WO_EQ|WO_IN|WO_IS, 0);
if( pAlt==0 ) continue;
if( pAlt->wtFlags & (TERM_CODED) ) continue;
@@ -144783,7 +145356,7 @@ static void exprAnalyzeOrTerm(
assert( pOrTerm->wtFlags & (TERM_COPIED|TERM_VIRTUAL) );
continue;
}
- iColumn = pOrTerm->u.leftColumn;
+ iColumn = pOrTerm->u.x.leftColumn;
iCursor = pOrTerm->leftCursor;
pLeft = pOrTerm->pExpr->pLeft;
break;
@@ -144805,7 +145378,7 @@ static void exprAnalyzeOrTerm(
assert( pOrTerm->eOperator & WO_EQ );
if( pOrTerm->leftCursor!=iCursor ){
pOrTerm->wtFlags &= ~TERM_OR_OK;
- }else if( pOrTerm->u.leftColumn!=iColumn || (iColumn==XN_EXPR
+ }else if( pOrTerm->u.x.leftColumn!=iColumn || (iColumn==XN_EXPR
&& sqlite3ExprCompare(pParse, pOrTerm->pExpr->pLeft, pLeft, -1)
)){
okToChngToIN = 0;
@@ -144840,7 +145413,7 @@ static void exprAnalyzeOrTerm(
if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue;
assert( pOrTerm->eOperator & WO_EQ );
assert( pOrTerm->leftCursor==iCursor );
- assert( pOrTerm->u.leftColumn==iColumn );
+ assert( pOrTerm->u.x.leftColumn==iColumn );
pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0);
pList = sqlite3ExprListAppend(pWInfo->pParse, pList, pDup);
pLeft = pOrTerm->pExpr->pLeft;
@@ -145076,15 +145649,15 @@ static void exprAnalyze(
Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight);
u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV;
- if( pTerm->iField>0 ){
+ if( pTerm->u.x.iField>0 ){
assert( op==TK_IN );
assert( pLeft->op==TK_VECTOR );
- pLeft = pLeft->x.pList->a[pTerm->iField-1].pExpr;
+ pLeft = pLeft->x.pList->a[pTerm->u.x.iField-1].pExpr;
}
if( exprMightBeIndexed(pSrc, prereqLeft, aiCurCol, pLeft, op) ){
pTerm->leftCursor = aiCurCol[0];
- pTerm->u.leftColumn = aiCurCol[1];
+ pTerm->u.x.leftColumn = aiCurCol[1];
pTerm->eOperator = operatorMask(op) & opMask;
}
if( op==TK_IS ) pTerm->wtFlags |= TERM_IS;
@@ -145094,7 +145667,7 @@ static void exprAnalyze(
WhereTerm *pNew;
Expr *pDup;
u16 eExtraOp = 0; /* Extra bits for pNew->eOperator */
- assert( pTerm->iField==0 );
+ assert( pTerm->u.x.iField==0 );
if( pTerm->leftCursor>=0 ){
int idxNew;
pDup = sqlite3ExprDup(db, pExpr, 0);
@@ -145120,7 +145693,7 @@ static void exprAnalyze(
}
pNew->wtFlags |= exprCommute(pParse, pDup);
pNew->leftCursor = aiCurCol[0];
- pNew->u.leftColumn = aiCurCol[1];
+ pNew->u.x.leftColumn = aiCurCol[1];
testcase( (prereqLeft | extraRight) != prereqLeft );
pNew->prereqRight = prereqLeft | extraRight;
pNew->prereqAll = prereqAll;
@@ -145294,7 +145867,7 @@ static void exprAnalyze(
pNewTerm = &pWC->a[idxNew];
pNewTerm->prereqRight = prereqExpr;
pNewTerm->leftCursor = pLeft->iTable;
- pNewTerm->u.leftColumn = pLeft->iColumn;
+ pNewTerm->u.x.leftColumn = pLeft->iColumn;
pNewTerm->eOperator = WO_AUX;
pNewTerm->eMatchOp = eOp2;
markTermAsChild(pWC, idxNew, idxTerm);
@@ -145341,13 +145914,13 @@ static void exprAnalyze(
/* If there is a vector IN term - e.g. "(a, b) IN (SELECT ...)" - create
** a virtual term for each vector component. The expression object
** used by each such virtual term is pExpr (the full vector IN(...)
- ** expression). The WhereTerm.iField variable identifies the index within
+ ** expression). The WhereTerm.u.x.iField variable identifies the index within
** the vector on the LHS that the virtual term represents.
**
** This only works if the RHS is a simple SELECT (not a compound) that does
** not use window functions.
*/
- if( pWC->op==TK_AND && pExpr->op==TK_IN && pTerm->iField==0
+ if( pWC->op==TK_AND && pExpr->op==TK_IN && pTerm->u.x.iField==0
&& pExpr->pLeft->op==TK_VECTOR
&& pExpr->x.pSelect->pPrior==0
#ifndef SQLITE_OMIT_WINDOWFUNC
@@ -145358,7 +145931,7 @@ static void exprAnalyze(
for(i=0; i<sqlite3ExprVectorSize(pExpr->pLeft); i++){
int idxNew;
idxNew = whereClauseInsert(pWC, pExpr, TERM_VIRTUAL);
- pWC->a[idxNew].iField = i+1;
+ pWC->a[idxNew].u.x.iField = i+1;
exprAnalyze(pSrc, pWC, idxNew);
markTermAsChild(pWC, idxNew, idxTerm);
}
@@ -145393,7 +145966,7 @@ static void exprAnalyze(
pNewTerm = &pWC->a[idxNew];
pNewTerm->prereqRight = 0;
pNewTerm->leftCursor = pLeft->iTable;
- pNewTerm->u.leftColumn = pLeft->iColumn;
+ pNewTerm->u.x.leftColumn = pLeft->iColumn;
pNewTerm->eOperator = WO_GT;
markTermAsChild(pWC, idxNew, idxTerm);
pTerm = &pWC->a[idxTerm];
@@ -145436,6 +146009,7 @@ static void exprAnalyze(
SQLITE_PRIVATE void sqlite3WhereSplit(WhereClause *pWC, Expr *pExpr, u8 op){
Expr *pE2 = sqlite3ExprSkipCollateAndLikely(pExpr);
pWC->op = op;
+ assert( pE2!=0 || pExpr==0 );
if( pE2==0 ) return;
if( pE2->op!=op ){
whereClauseInsert(pWC, pExpr, 0);
@@ -145836,6 +146410,16 @@ static void createMask(WhereMaskSet *pMaskSet, int iCursor){
}
/*
+** If the right-hand branch of the expression is a TK_COLUMN, then return
+** a pointer to the right-hand branch. Otherwise, return NULL.
+*/
+static Expr *whereRightSubexprIsColumn(Expr *p){
+ p = sqlite3ExprSkipCollateAndLikely(p->pRight);
+ if( ALWAYS(p!=0) && p->op==TK_COLUMN ) return p;
+ return 0;
+}
+
+/*
** Advance to the next WhereTerm that matches according to the criteria
** established when the pScan object was initialized by whereScanInit().
** Return NULL if there are no more matching WhereTerms.
@@ -145857,7 +146441,7 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
do{
for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){
if( pTerm->leftCursor==iCur
- && pTerm->u.leftColumn==iColumn
+ && pTerm->u.x.leftColumn==iColumn
&& (iColumn!=XN_EXPR
|| sqlite3ExprCompareSkip(pTerm->pExpr->pLeft,
pScan->pIdxExpr,iCur)==0)
@@ -145865,8 +146449,7 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
){
if( (pTerm->eOperator & WO_EQUIV)!=0
&& pScan->nEquiv<ArraySize(pScan->aiCur)
- && (pX = sqlite3ExprSkipCollateAndLikely(pTerm->pExpr->pRight))->op
- ==TK_COLUMN
+ && (pX = whereRightSubexprIsColumn(pTerm->pExpr))!=0
){
int j;
for(j=0; j<pScan->nEquiv; j++){
@@ -146062,7 +146645,8 @@ static int findIndexCol(
for(i=0; i<pList->nExpr; i++){
Expr *p = sqlite3ExprSkipCollateAndLikely(pList->a[i].pExpr);
- if( p->op==TK_COLUMN
+ if( ALWAYS(p!=0)
+ && p->op==TK_COLUMN
&& p->iColumn==pIdx->aiColumn[iCol]
&& p->iTable==iBase
){
@@ -146126,6 +146710,7 @@ static int isDistinctRedundant(
*/
for(i=0; i<pDistinct->nExpr; i++){
Expr *p = sqlite3ExprSkipCollateAndLikely(pDistinct->a[i].pExpr);
+ if( NEVER(p==0) ) continue;
if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1;
}
@@ -146279,8 +146864,8 @@ static int termCanDriveIndex(
return 0;
}
if( (pTerm->prereqRight & notReady)!=0 ) return 0;
- if( pTerm->u.leftColumn<0 ) return 0;
- aff = pSrc->pTab->aCol[pTerm->u.leftColumn].affinity;
+ if( pTerm->u.x.leftColumn<0 ) return 0;
+ aff = pSrc->pTab->aCol[pTerm->u.x.leftColumn].affinity;
if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0;
testcase( pTerm->pExpr->op==TK_IS );
return 1;
@@ -146351,7 +146936,7 @@ static void constructAutomaticIndex(
sqlite3ExprDup(pParse->db, pExpr, 0));
}
if( termCanDriveIndex(pTerm, pSrc, notReady) ){
- int iCol = pTerm->u.leftColumn;
+ int iCol = pTerm->u.x.leftColumn;
Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol);
testcase( iCol==BMS );
testcase( iCol==BMS-1 );
@@ -146404,14 +146989,14 @@ static void constructAutomaticIndex(
idxCols = 0;
for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
if( termCanDriveIndex(pTerm, pSrc, notReady) ){
- int iCol = pTerm->u.leftColumn;
+ int iCol = pTerm->u.x.leftColumn;
Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol);
testcase( iCol==BMS-1 );
testcase( iCol==BMS );
if( (idxCols & cMask)==0 ){
Expr *pX = pTerm->pExpr;
idxCols |= cMask;
- pIdx->aiColumn[n] = pTerm->u.leftColumn;
+ pIdx->aiColumn[n] = pTerm->u.x.leftColumn;
pColl = sqlite3ExprCompareCollSeq(pParse, pX);
assert( pColl!=0 || pParse->nErr>0 ); /* TH3 collate01.800 */
pIdx->azColl[n] = pColl ? pColl->zName : sqlite3StrBINARY;
@@ -146532,7 +147117,7 @@ static sqlite3_index_info *allocateIndexInfo(
testcase( pTerm->eOperator & WO_ALL );
if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue;
if( pTerm->wtFlags & TERM_VNULL ) continue;
- assert( pTerm->u.leftColumn>=(-1) );
+ assert( pTerm->u.x.leftColumn>=(-1) );
nTerm++;
}
@@ -146592,8 +147177,8 @@ static sqlite3_index_info *allocateIndexInfo(
){
continue;
}
- assert( pTerm->u.leftColumn>=(-1) );
- pIdxCons[j].iColumn = pTerm->u.leftColumn;
+ assert( pTerm->u.x.leftColumn>=(-1) );
+ pIdxCons[j].iColumn = pTerm->u.x.leftColumn;
pIdxCons[j].iTermOffset = i;
op = pTerm->eOperator & WO_ALL;
if( op==WO_IN ) op = WO_EQ;
@@ -147356,9 +147941,9 @@ SQLITE_PRIVATE void sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm){
if( pTerm->wtFlags & TERM_CODED ) zType[3] = 'C';
if( pTerm->eOperator & WO_SINGLE ){
sqlite3_snprintf(sizeof(zLeft),zLeft,"left={%d:%d}",
- pTerm->leftCursor, pTerm->u.leftColumn);
+ pTerm->leftCursor, pTerm->u.x.leftColumn);
}else if( (pTerm->eOperator & WO_OR)!=0 && pTerm->u.pOrInfo!=0 ){
- sqlite3_snprintf(sizeof(zLeft),zLeft,"indexable=0x%lld",
+ sqlite3_snprintf(sizeof(zLeft),zLeft,"indexable=0x%llx",
pTerm->u.pOrInfo->indexable);
}else{
sqlite3_snprintf(sizeof(zLeft),zLeft,"left=%d", pTerm->leftCursor);
@@ -147372,8 +147957,8 @@ SQLITE_PRIVATE void sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm){
sqlite3DebugPrintf(" prob=%-3d prereq=%llx,%llx",
pTerm->truthProb, (u64)pTerm->prereqAll, (u64)pTerm->prereqRight);
}
- if( pTerm->iField ){
- sqlite3DebugPrintf(" iField=%d", pTerm->iField);
+ if( pTerm->u.x.iField ){
+ sqlite3DebugPrintf(" iField=%d", pTerm->u.x.iField);
}
if( pTerm->iParent>=0 ){
sqlite3DebugPrintf(" iParent=%d", pTerm->iParent);
@@ -148040,9 +148625,9 @@ static int whereLoopAddBtreeIndex(
pNew = pBuilder->pNew;
if( db->mallocFailed ) return SQLITE_NOMEM_BKPT;
- WHERETRACE(0x800, ("BEGIN %s.addBtreeIdx(%s), nEq=%d, nSkip=%d\n",
+ WHERETRACE(0x800, ("BEGIN %s.addBtreeIdx(%s), nEq=%d, nSkip=%d, rRun=%d\n",
pProbe->pTable->zName,pProbe->zName,
- pNew->u.btree.nEq, pNew->nSkip));
+ pNew->u.btree.nEq, pNew->nSkip, pNew->rRun));
assert( (pNew->wsFlags & WHERE_VIRTUALTABLE)==0 );
assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 );
@@ -148136,7 +148721,7 @@ static int whereLoopAddBtreeIndex(
/* "x IN (value, value, ...)" */
nIn = sqlite3LogEst(pExpr->x.pList->nExpr);
}
- if( pProbe->hasStat1 ){
+ if( pProbe->hasStat1 && rLogSize>=10 ){
LogEst M, logK, safetyMargin;
/* Let:
** N = the total number of rows in the table
@@ -148155,7 +148740,8 @@ static int whereLoopAddBtreeIndex(
** a safety margin of 2 (LogEst: 10) that favors using the IN operator
** with the index, as using an index has better worst-case behavior.
** If we do not have real sqlite_stat1 data, always prefer to use
- ** the index.
+ ** the index. Do not bother with this optimization on very small
+ ** tables (less than 2 rows) as it is pointless in that case.
*/
M = pProbe->aiRowLogEst[saved_nEq];
logK = estLog(nIn);
@@ -148164,7 +148750,7 @@ static int whereLoopAddBtreeIndex(
WHERETRACE(0x40,
("Scan preferred over IN operator on column %d of \"%s\" (%d<%d)\n",
saved_nEq, pProbe->zName, M+logK+10, nIn+rLogSize));
- continue;
+ pNew->wsFlags |= WHERE_IN_SEEKSCAN;
}else{
WHERETRACE(0x40,
("IN operator preferred on column %d of \"%s\" (%d>=%d)\n",
@@ -148410,6 +148996,7 @@ static int indexMightHelpWithOrderBy(
if( (pOB = pBuilder->pWInfo->pOrderBy)==0 ) return 0;
for(ii=0; ii<pOB->nExpr; ii++){
Expr *pExpr = sqlite3ExprSkipCollateAndLikely(pOB->a[ii].pExpr);
+ if( NEVER(pExpr==0) ) continue;
if( pExpr->op==TK_COLUMN && pExpr->iTable==iCursor ){
if( pExpr->iColumn<0 ) return 1;
for(jj=0; jj<pIndex->nKeyCol; jj++){
@@ -148641,8 +149228,23 @@ static int whereLoopAddBtree(
/* Full table scan */
pNew->iSortIdx = b ? iSortIdx : 0;
- /* TUNING: Cost of full table scan is (N*3.0). */
+ /* TUNING: Cost of full table scan is 3.0*N. The 3.0 factor is an
+ ** extra cost designed to discourage the use of full table scans,
+ ** since index lookups have better worst-case performance if our
+ ** stat guesses are wrong. Reduce the 3.0 penalty slightly
+ ** (to 2.75) if we have valid STAT4 information for the table.
+ ** At 2.75, a full table scan is preferred over using an index on
+ ** a column with just two distinct values where each value has about
+ ** an equal number of appearances. Without STAT4 data, we still want
+ ** to use an index in that case, since the constraint might be for
+ ** the scarcer of the two values, and in that case an index lookup is
+ ** better.
+ */
+#ifdef SQLITE_ENABLE_STAT4
+ pNew->rRun = rSize + 16 - 2*((pTab->tabFlags & TF_HasStat4)!=0);
+#else
pNew->rRun = rSize + 16;
+#endif
ApplyCostMultiplier(pNew->rRun, pTab->costMult);
whereLoopOutputAdjust(pWC, pNew, rSize);
rc = whereLoopInsert(pBuilder, pNew);
@@ -149373,6 +149975,7 @@ static i8 wherePathSatisfiesOrderBy(
for(i=0; i<nOrderBy; i++){
if( MASKBIT(i) & obSat ) continue;
pOBExpr = sqlite3ExprSkipCollateAndLikely(pOrderBy->a[i].pExpr);
+ if( NEVER(pOBExpr==0) ) continue;
if( pOBExpr->op!=TK_COLUMN ) continue;
if( pOBExpr->iTable!=iCur ) continue;
pTerm = sqlite3WhereFindTerm(&pWInfo->sWC, iCur, pOBExpr->iColumn,
@@ -149499,6 +150102,7 @@ static i8 wherePathSatisfiesOrderBy(
pOBExpr = sqlite3ExprSkipCollateAndLikely(pOrderBy->a[i].pExpr);
testcase( wctrlFlags & WHERE_GROUPBY );
testcase( wctrlFlags & WHERE_DISTINCTBY );
+ if( NEVER(pOBExpr==0) ) continue;
if( (wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0 ) bOnce = 0;
if( iColumn>=XN_ROWID ){
if( pOBExpr->op!=TK_COLUMN ) continue;
@@ -149653,16 +150257,24 @@ static LogEst whereSortingCost(
** cost = (3.0 * N * log(N)) * (Y/X)
**
** The (Y/X) term is implemented using stack variable rScale
- ** below. */
+ ** below.
+ */
LogEst rScale, rSortCost;
assert( nOrderBy>0 && 66==sqlite3LogEst(100) );
rScale = sqlite3LogEst((nOrderBy-nSorted)*100/nOrderBy) - 66;
rSortCost = nRow + rScale + 16;
/* Multiple by log(M) where M is the number of output rows.
- ** Use the LIMIT for M if it is smaller */
+ ** Use the LIMIT for M if it is smaller. Or if this sort is for
+ ** a DISTINCT operator, M will be the number of distinct output
+ ** rows, so fudge it downwards a bit.
+ */
if( (pWInfo->wctrlFlags & WHERE_USE_LIMIT)!=0 && pWInfo->iLimit<nRow ){
nRow = pWInfo->iLimit;
+ }else if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT) ){
+ /* TUNING: In the sort for a DISTINCT operator, assume that the DISTINCT
+ ** reduces the number of output rows by a factor of 2 */
+ if( nRow>10 ) nRow -= 10; assert( 10==sqlite3LogEst(2) );
}
rSortCost += estLog(nRow);
return rSortCost;
@@ -150789,6 +151401,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
if( (pLoop->wsFlags & WHERE_CONSTRAINT)!=0
&& (pLoop->wsFlags & (WHERE_COLUMN_RANGE|WHERE_SKIPSCAN))==0
&& (pLoop->wsFlags & WHERE_BIGNULL_SORT)==0
+ && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0
&& (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)==0
&& pWInfo->eDistinct!=WHERE_DISTINCT_ORDERED
){
@@ -150846,6 +151459,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
/* Done. */
VdbeModuleComment((v, "Begin WHERE-core"));
+ pWInfo->iEndWhere = sqlite3VdbeCurrentAddr(v);
return pWInfo;
/* Jump here if malloc fails */
@@ -150889,6 +151503,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
WhereLoop *pLoop;
SrcList *pTabList = pWInfo->pTabList;
sqlite3 *db = pParse->db;
+ int iEnd = sqlite3VdbeCurrentAddr(v);
/* Generate loop termination code.
*/
@@ -150949,7 +151564,9 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
if( pIn->eEndLoopOp!=OP_Noop ){
if( pIn->nPrefix ){
- assert( pLoop->wsFlags & WHERE_IN_EARLYOUT );
+ int bEarlyOut =
+ (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0
+ && (pLoop->wsFlags & WHERE_IN_EARLYOUT)!=0;
if( pLevel->iLeftJoin ){
/* For LEFT JOIN queries, cursor pIn->iCur may not have been
** opened yet. This occurs for WHERE clauses such as
@@ -150960,12 +151577,10 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
** jump over the OP_Next or OP_Prev instruction about to
** be coded. */
sqlite3VdbeAddOp2(v, OP_IfNotOpen, pIn->iCur,
- sqlite3VdbeCurrentAddr(v) + 2 +
- ((pLoop->wsFlags & WHERE_VIRTUALTABLE)==0)
- );
+ sqlite3VdbeCurrentAddr(v) + 2 + bEarlyOut);
VdbeCoverage(v);
}
- if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 ){
+ if( bEarlyOut ){
sqlite3VdbeAddOp4Int(v, OP_IfNoHope, pLevel->iIdxCur,
sqlite3VdbeCurrentAddr(v)+2,
pIn->iBase, pIn->nPrefix);
@@ -151026,7 +151641,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
assert( pWInfo->nLevel<=pTabList->nSrc );
for(i=0, pLevel=pWInfo->a; i<pWInfo->nLevel; i++, pLevel++){
int k, last;
- VdbeOp *pOp;
+ VdbeOp *pOp, *pLastOp;
Index *pIdx = 0;
struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom];
Table *pTab = pTabItem->pTab;
@@ -151084,20 +151699,31 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
pIdx = pLevel->u.pCovidx;
}
if( pIdx
- && (pWInfo->eOnePass==ONEPASS_OFF || !HasRowid(pIdx->pTable))
&& !db->mallocFailed
){
- last = sqlite3VdbeCurrentAddr(v);
- k = pLevel->addrBody;
+ if( pWInfo->eOnePass==ONEPASS_OFF || !HasRowid(pIdx->pTable) ){
+ last = iEnd;
+ }else{
+ last = pWInfo->iEndWhere;
+ }
+ k = pLevel->addrBody + 1;
#ifdef SQLITE_DEBUG
if( db->flags & SQLITE_VdbeAddopTrace ){
printf("TRANSLATE opcodes in range %d..%d\n", k, last-1);
}
+ /* Proof that the "+1" on the k value above is safe */
+ pOp = sqlite3VdbeGetOp(v, k - 1);
+ assert( pOp->opcode!=OP_Column || pOp->p1!=pLevel->iTabCur );
+ assert( pOp->opcode!=OP_Rowid || pOp->p1!=pLevel->iTabCur );
+ assert( pOp->opcode!=OP_IfNullRow || pOp->p1!=pLevel->iTabCur );
#endif
pOp = sqlite3VdbeGetOp(v, k);
- for(; k<last; k++, pOp++){
- if( pOp->p1!=pLevel->iTabCur ) continue;
- if( pOp->opcode==OP_Column
+ pLastOp = pOp + (last - k);
+ assert( pOp<pLastOp );
+ do{
+ if( pOp->p1!=pLevel->iTabCur ){
+ /* no-op */
+ }else if( pOp->opcode==OP_Column
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
|| pOp->opcode==OP_Offset
#endif
@@ -151128,7 +151754,10 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
pOp->p1 = pLevel->iIdxCur;
OpcodeRewriteTrace(db, k, pOp);
}
- }
+#ifdef SQLITE_DEBUG
+ k++;
+#endif
+ }while( (++pOp)<pLastOp );
#ifdef SQLITE_DEBUG
if( db->flags & SQLITE_VdbeAddopTrace ) printf("TRANSLATE complete\n");
#endif
@@ -154197,8 +154826,10 @@ SQLITE_PRIVATE void sqlite3WindowCodeStep(
/************** End of window.c **********************************************/
/************** Begin file parse.c *******************************************/
+/* This file is automatically generated by Lemon from input grammar
+** source file "parse.y". */
/*
-** 2000-05-29
+** 2001-09-15
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
@@ -154208,22 +154839,15 @@ SQLITE_PRIVATE void sqlite3WindowCodeStep(
** May you share freely, never taking more than you give.
**
*************************************************************************
-** Driver template for the LEMON parser generator.
+** This file contains SQLite's SQL parser.
**
-** The "lemon" program processes an LALR(1) input grammar file, then uses
-** this template to construct a parser. The "lemon" program inserts text
-** at each "%%" line. Also, any "P-a-r-s-e" identifer prefix (without the
-** interstitial "-" characters) contained in this template is changed into
-** the value of the %name directive from the grammar. Otherwise, the content
-** of this template is copied straight through into the generate parser
-** source file.
-**
-** The following is the concatenation of all %include directives from the
-** input grammar file:
+** The canonical source code to this file ("parse.y") is a Lemon grammar
+** file that specifies the input grammar and actions to take while parsing.
+** That input file is processed by Lemon to generate a C-language
+** implementation of a parser for the given grammer. You might be reading
+** this comment as part of the translated C-code. Edits should be made
+** to the original parse.y sources.
*/
-/* #include <stdio.h> */
-/* #include <assert.h> */
-/************ Begin %include sections from the grammar ************************/
/* #include "sqliteInt.h" */
@@ -154407,11 +155031,178 @@ static void updateDeleteLimitError(
# error too many tokens in the grammar
#endif
/**************** End of %include directives **********************************/
-/* These constants specify the various numeric values for terminal symbols
-** in a format understandable to "makeheaders". This section is blank unless
-** "lemon" is run with the "-m" command-line option.
-***************** Begin makeheaders token definitions *************************/
-/**************** End makeheaders token definitions ***************************/
+/* These constants specify the various numeric values for terminal symbols.
+***************** Begin token definitions *************************************/
+#ifndef TK_SEMI
+#define TK_SEMI 1
+#define TK_BEGIN 2
+#define TK_TRANSACTION 3
+#define TK_DEFERRED 4
+#define TK_IMMEDIATE 5
+#define TK_EXCLUSIVE 6
+#define TK_COMMIT 7
+#define TK_END 8
+#define TK_ROLLBACK 9
+#define TK_SAVEPOINT 10
+#define TK_RELEASE 11
+#define TK_TO 12
+#define TK_TABLE 13
+#define TK_CREATE 14
+#define TK_IF 15
+#define TK_NOT 16
+#define TK_EXISTS 17
+#define TK_TEMP 18
+#define TK_LP 19
+#define TK_RP 20
+#define TK_AS 21
+#define TK_WITHOUT 22
+#define TK_COMMA 23
+#define TK_ABORT 24
+#define TK_ACTION 25
+#define TK_AFTER 26
+#define TK_ANALYZE 27
+#define TK_ASC 28
+#define TK_ATTACH 29
+#define TK_BEFORE 30
+#define TK_BY 31
+#define TK_CASCADE 32
+#define TK_CAST 33
+#define TK_CONFLICT 34
+#define TK_DATABASE 35
+#define TK_DESC 36
+#define TK_DETACH 37
+#define TK_EACH 38
+#define TK_EXPLAIN 39
+#define TK_FAIL 40
+#define TK_OR 41
+#define TK_AND 42
+#define TK_IS 43
+#define TK_MATCH 44
+#define TK_LIKE_KW 45
+#define TK_BETWEEN 46
+#define TK_IN 47
+#define TK_ISNULL 48
+#define TK_NOTNULL 49
+#define TK_NE 50
+#define TK_EQ 51
+#define TK_GT 52
+#define TK_LE 53
+#define TK_LT 54
+#define TK_GE 55
+#define TK_ESCAPE 56
+#define TK_ID 57
+#define TK_COLUMNKW 58
+#define TK_DO 59
+#define TK_FOR 60
+#define TK_IGNORE 61
+#define TK_INITIALLY 62
+#define TK_INSTEAD 63
+#define TK_NO 64
+#define TK_PLAN 65
+#define TK_QUERY 66
+#define TK_KEY 67
+#define TK_OF 68
+#define TK_OFFSET 69
+#define TK_PRAGMA 70
+#define TK_RAISE 71
+#define TK_RECURSIVE 72
+#define TK_REPLACE 73
+#define TK_RESTRICT 74
+#define TK_ROW 75
+#define TK_ROWS 76
+#define TK_TRIGGER 77
+#define TK_VACUUM 78
+#define TK_VIEW 79
+#define TK_VIRTUAL 80
+#define TK_WITH 81
+#define TK_NULLS 82
+#define TK_FIRST 83
+#define TK_LAST 84
+#define TK_GENERATED 85
+#define TK_ALWAYS 86
+#define TK_REINDEX 87
+#define TK_RENAME 88
+#define TK_CTIME_KW 89
+#define TK_ANY 90
+#define TK_BITAND 91
+#define TK_BITOR 92
+#define TK_LSHIFT 93
+#define TK_RSHIFT 94
+#define TK_PLUS 95
+#define TK_MINUS 96
+#define TK_STAR 97
+#define TK_SLASH 98
+#define TK_REM 99
+#define TK_CONCAT 100
+#define TK_COLLATE 101
+#define TK_BITNOT 102
+#define TK_ON 103
+#define TK_INDEXED 104
+#define TK_STRING 105
+#define TK_JOIN_KW 106
+#define TK_CONSTRAINT 107
+#define TK_DEFAULT 108
+#define TK_NULL 109
+#define TK_PRIMARY 110
+#define TK_UNIQUE 111
+#define TK_CHECK 112
+#define TK_REFERENCES 113
+#define TK_AUTOINCR 114
+#define TK_INSERT 115
+#define TK_DELETE 116
+#define TK_UPDATE 117
+#define TK_SET 118
+#define TK_DEFERRABLE 119
+#define TK_FOREIGN 120
+#define TK_DROP 121
+#define TK_UNION 122
+#define TK_ALL 123
+#define TK_EXCEPT 124
+#define TK_INTERSECT 125
+#define TK_SELECT 126
+#define TK_VALUES 127
+#define TK_DISTINCT 128
+#define TK_DOT 129
+#define TK_FROM 130
+#define TK_JOIN 131
+#define TK_USING 132
+#define TK_ORDER 133
+#define TK_GROUP 134
+#define TK_HAVING 135
+#define TK_LIMIT 136
+#define TK_WHERE 137
+#define TK_INTO 138
+#define TK_NOTHING 139
+#define TK_FLOAT 140
+#define TK_BLOB 141
+#define TK_INTEGER 142
+#define TK_VARIABLE 143
+#define TK_CASE 144
+#define TK_WHEN 145
+#define TK_THEN 146
+#define TK_ELSE 147
+#define TK_INDEX 148
+#define TK_ALTER 149
+#define TK_ADD 150
+#define TK_COLUMN 151
+#define TK_AGG_FUNCTION 152
+#define TK_AGG_COLUMN 153
+#define TK_TRUEFALSE 154
+#define TK_ISNOT 155
+#define TK_FUNCTION 156
+#define TK_UMINUS 157
+#define TK_UPLUS 158
+#define TK_TRUTH 159
+#define TK_REGISTER 160
+#define TK_VECTOR 161
+#define TK_SELECT_COLUMN 162
+#define TK_IF_NULL_ROW 163
+#define TK_ASTERISK 164
+#define TK_SPAN 165
+#define TK_SPACE 166
+#define TK_ILLEGAL 167
+#endif
+/**************** End token definitions ***************************************/
/* The next sections is a series of control #defines.
** various aspects of the generated parser.
@@ -155326,6 +156117,7 @@ typedef struct yyParser yyParser;
#ifndef NDEBUG
/* #include <stdio.h> */
+/* #include <assert.h> */
static FILE *yyTraceFILE = 0;
static char *yyTracePrompt = 0;
#endif /* NDEBUG */
@@ -156351,7 +157143,7 @@ static YYACTIONTYPE yy_find_shift_action(
#endif /* YYWILDCARD */
return yy_default[stateno];
}else{
- assert( i>=0 && i<sizeof(yy_action)/sizeof(yy_action[0]) );
+ assert( i>=0 && i<(int)(sizeof(yy_action)/sizeof(yy_action[0])) );
return yy_action[i];
}
}while(1);
@@ -157197,8 +157989,9 @@ static YYACTIONTYPE yy_reduce(
(void)yyLookahead;
(void)yyLookaheadToken;
yymsp = yypParser->yytos;
+ assert( yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) );
#ifndef NDEBUG
- if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
+ if( yyTraceFILE ){
yysize = yyRuleInfoNRhs[yyruleno];
if( yysize ){
fprintf(yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n",
@@ -157410,7 +158203,7 @@ static YYACTIONTYPE yy_reduce(
SQLITE_IDXTYPE_UNIQUE);}
break;
case 37: /* ccons ::= CHECK LP expr RP */
-{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy244);}
+{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy244,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy0.z);}
break;
case 38: /* ccons ::= REFERENCES nm eidlist_opt refargs */
{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy328,yymsp[0].minor.yy222);}
@@ -157489,7 +158282,7 @@ static YYACTIONTYPE yy_reduce(
SQLITE_IDXTYPE_UNIQUE);}
break;
case 66: /* tcons ::= CHECK LP expr RP onconf */
-{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy244);}
+{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy244,yymsp[-3].minor.yy0.z,yymsp[-1].minor.yy0.z);}
break;
case 67: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
{
@@ -161398,7 +162191,7 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3 *db){
sqlite3BtreeEnterAll(db);
for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
- if( pBt && sqlite3BtreeIsInTrans(pBt) ){
+ if( pBt && sqlite3BtreeTxnState(pBt)==SQLITE_TXN_WRITE ){
Pager *pPager = sqlite3BtreePager(pBt);
rc = sqlite3PagerFlush(pPager);
if( rc==SQLITE_BUSY ){
@@ -161743,6 +162536,36 @@ static int sqlite3Close(sqlite3 *db, int forceZombie){
}
/*
+** Return the transaction state for a single databse, or the maximum
+** transaction state over all attached databases if zSchema is null.
+*/
+SQLITE_API int sqlite3_txn_state(sqlite3 *db, const char *zSchema){
+ int iDb, nDb;
+ int iTxn = -1;
+#ifdef SQLITE_ENABLE_API_ARMOR
+ if( !sqlite3SafetyCheckOk(db) ){
+ (void)SQLITE_MISUSE_BKPT;
+ return -1;
+ }
+#endif
+ sqlite3_mutex_enter(db->mutex);
+ if( zSchema ){
+ nDb = iDb = sqlite3FindDbName(db, zSchema);
+ if( iDb<0 ) nDb--;
+ }else{
+ iDb = 0;
+ nDb = db->nDb-1;
+ }
+ for(; iDb<=nDb; iDb++){
+ Btree *pBt = db->aDb[iDb].pBt;
+ int x = pBt!=0 ? sqlite3BtreeTxnState(pBt) : SQLITE_TXN_NONE;
+ if( x>iTxn ) iTxn = x;
+ }
+ sqlite3_mutex_leave(db->mutex);
+ return iTxn;
+}
+
+/*
** Two variations on the public interface for closing a database
** connection. The sqlite3_close() version returns SQLITE_BUSY and
** leaves the connection option if there are unfinalized prepared
@@ -161902,7 +162725,7 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){
for(i=0; i<db->nDb; i++){
Btree *p = db->aDb[i].pBt;
if( p ){
- if( sqlite3BtreeIsInTrans(p) ){
+ if( sqlite3BtreeTxnState(p)==SQLITE_TXN_WRITE ){
inTrans = 1;
}
sqlite3BtreeRollback(p, tripCode, !schemaChange);
@@ -164323,7 +165146,9 @@ SQLITE_API int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, vo
}
rc = SQLITE_OK;
}else{
+ int nSave = db->busyHandler.nBusy;
rc = sqlite3OsFileControl(fd, op, pArg);
+ db->busyHandler.nBusy = nSave;
}
sqlite3BtreeLeave(pBtree);
}
@@ -164706,6 +165531,25 @@ SQLITE_API int sqlite3_test_control(int op, ...){
sqlite3ResultIntReal(pCtx);
break;
}
+
+ /* sqlite3_test_control(SQLITE_TESTCTRL_SEEK_COUNT,
+ ** sqlite3 *db, // Database connection
+ ** u64 *pnSeek // Write seek count here
+ ** );
+ **
+ ** This test-control queries the seek-counter on the "main" database
+ ** file. The seek-counter is written into *pnSeek and is then reset.
+ ** The seek-count is only available if compiled with SQLITE_DEBUG.
+ */
+ case SQLITE_TESTCTRL_SEEK_COUNT: {
+ sqlite3 *db = va_arg(ap, sqlite3*);
+ u64 *pn = va_arg(ap, sqlite3_uint64*);
+ *pn = sqlite3BtreeSeekCount(db->aDb->pBt);
+ (void)db; /* Silence harmless unused variable warning */
+ break;
+ }
+
+
}
va_end(ap);
#endif /* SQLITE_UNTESTABLE */
@@ -164941,7 +165785,7 @@ SQLITE_API int sqlite3_snapshot_get(
int iDb = sqlite3FindDbName(db, zDb);
if( iDb==0 || iDb>1 ){
Btree *pBt = db->aDb[iDb].pBt;
- if( 0==sqlite3BtreeIsInTrans(pBt) ){
+ if( SQLITE_TXN_WRITE!=sqlite3BtreeTxnState(pBt) ){
rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
if( rc==SQLITE_OK ){
rc = sqlite3PagerSnapshotGet(sqlite3BtreePager(pBt), ppSnapshot);
@@ -164977,10 +165821,10 @@ SQLITE_API int sqlite3_snapshot_open(
iDb = sqlite3FindDbName(db, zDb);
if( iDb==0 || iDb>1 ){
Btree *pBt = db->aDb[iDb].pBt;
- if( sqlite3BtreeIsInTrans(pBt)==0 ){
+ if( sqlite3BtreeTxnState(pBt)!=SQLITE_TXN_WRITE ){
Pager *pPager = sqlite3BtreePager(pBt);
int bUnlock = 0;
- if( sqlite3BtreeIsInReadTrans(pBt) ){
+ if( sqlite3BtreeTxnState(pBt)!=SQLITE_TXN_NONE ){
if( db->nVdbeActive==0 ){
rc = sqlite3PagerSnapshotCheck(pPager, pSnapshot);
if( rc==SQLITE_OK ){
@@ -165029,7 +165873,7 @@ SQLITE_API int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb){
iDb = sqlite3FindDbName(db, zDb);
if( iDb==0 || iDb>1 ){
Btree *pBt = db->aDb[iDb].pBt;
- if( 0==sqlite3BtreeIsInReadTrans(pBt) ){
+ if( SQLITE_TXN_NONE==sqlite3BtreeTxnState(pBt) ){
rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
if( rc==SQLITE_OK ){
rc = sqlite3PagerSnapshotRecover(sqlite3BtreePager(pBt));
@@ -188320,7 +189164,7 @@ static int nodeAcquire(
** are the leaves, and so on. If the depth as specified on the root node
** is greater than RTREE_MAX_DEPTH, the r-tree structure must be corrupt.
*/
- if( pNode && iNode==1 ){
+ if( pNode && rc==SQLITE_OK && iNode==1 ){
pRtree->iDepth = readInt16(pNode->zData);
if( pRtree->iDepth>RTREE_MAX_DEPTH ){
rc = SQLITE_CORRUPT_VTAB;
@@ -193006,7 +193850,7 @@ static int geopolyOverlap(GeoPoly *p1, GeoPoly *p2){
geopolyAddSegments(p, p1, 1);
geopolyAddSegments(p, p2, 2);
pThisEvent = geopolySortEventsByX(p->aEvent, p->nEvent);
- rX = pThisEvent->x==0.0 ? -1.0 : 0.0;
+ rX = pThisEvent && pThisEvent->x==0.0 ? -1.0 : 0.0;
memset(aOverlap, 0, sizeof(aOverlap));
while( pThisEvent ){
if( pThisEvent->x!=rX ){
@@ -208189,6 +209033,7 @@ struct Fts5Config {
Fts5Tokenizer *pTok;
fts5_tokenizer *pTokApi;
int bLock; /* True when table is preparing statement */
+ int ePattern; /* FTS_PATTERN_XXX constant */
/* Values loaded from the %_config table */
int iCookie; /* Incremented when %_config is modified */
@@ -208209,17 +209054,19 @@ struct Fts5Config {
};
/* Current expected value of %_config table 'version' field */
-#define FTS5_CURRENT_VERSION 4
+#define FTS5_CURRENT_VERSION 4
#define FTS5_CONTENT_NORMAL 0
#define FTS5_CONTENT_NONE 1
#define FTS5_CONTENT_EXTERNAL 2
-#define FTS5_DETAIL_FULL 0
-#define FTS5_DETAIL_NONE 1
-#define FTS5_DETAIL_COLUMNS 2
-
+#define FTS5_DETAIL_FULL 0
+#define FTS5_DETAIL_NONE 1
+#define FTS5_DETAIL_COLUMNS 2
+#define FTS5_PATTERN_NONE 0
+#define FTS5_PATTERN_LIKE 65 /* matches SQLITE_INDEX_CONSTRAINT_LIKE */
+#define FTS5_PATTERN_GLOB 66 /* matches SQLITE_INDEX_CONSTRAINT_GLOB */
static int sqlite3Fts5ConfigParse(
Fts5Global*, sqlite3*, int, const char **, Fts5Config**, char**
@@ -208489,7 +209336,7 @@ static int sqlite3Fts5IndexSetAverages(Fts5Index *p, const u8*, int);
/*
** Functions called by the storage module as part of integrity-check.
*/
-static int sqlite3Fts5IndexIntegrityCheck(Fts5Index*, u64 cksum);
+static int sqlite3Fts5IndexIntegrityCheck(Fts5Index*, u64 cksum, int bUseCksum);
/*
** Called during virtual module initialization to register UDF
@@ -208559,8 +209406,7 @@ static int sqlite3Fts5GetTokenizer(
Fts5Global*,
const char **azArg,
int nArg,
- Fts5Tokenizer**,
- fts5_tokenizer**,
+ Fts5Config*,
char **pzErr
);
@@ -208644,7 +209490,7 @@ static int sqlite3Fts5StorageDelete(Fts5Storage *p, i64, sqlite3_value**);
static int sqlite3Fts5StorageContentInsert(Fts5Storage *p, sqlite3_value**, i64*);
static int sqlite3Fts5StorageIndexInsert(Fts5Storage *p, sqlite3_value**, i64);
-static int sqlite3Fts5StorageIntegrity(Fts5Storage *p);
+static int sqlite3Fts5StorageIntegrity(Fts5Storage *p, int iArg);
static int sqlite3Fts5StorageStmt(Fts5Storage *p, int eStmt, sqlite3_stmt**, char**);
static void sqlite3Fts5StorageStmtRelease(Fts5Storage *p, int eStmt, sqlite3_stmt*);
@@ -208689,11 +209535,19 @@ struct Fts5Token {
/* Parse a MATCH expression. */
static int sqlite3Fts5ExprNew(
Fts5Config *pConfig,
+ int bPhraseToAnd,
int iCol, /* Column on LHS of MATCH operator */
const char *zExpr,
Fts5Expr **ppNew,
char **pzErr
);
+static int sqlite3Fts5ExprPattern(
+ Fts5Config *pConfig,
+ int bGlob,
+ int iCol,
+ const char *zText,
+ Fts5Expr **pp
+);
/*
** for(rc = sqlite3Fts5ExprFirst(pExpr, pIdx, bDesc);
@@ -208802,6 +209656,10 @@ static int sqlite3Fts5AuxInit(fts5_api*);
*/
static int sqlite3Fts5TokenizerInit(fts5_api*);
+static int sqlite3Fts5TokenizerPattern(
+ int (*xCreate)(void*, const char**, int, Fts5Tokenizer**),
+ Fts5Tokenizer *pTok
+);
/*
** End of interface to code in fts5_tokenizer.c.
**************************************************************************/
@@ -208848,6 +209706,8 @@ static void sqlite3Fts5UnicodeAscii(u8*, u8*);
#define FTS5_PLUS 14
#define FTS5_STAR 15
+/* This file is automatically generated by Lemon from input grammar
+** source file "fts5parse.y". */
/*
** 2000-05-29
**
@@ -208872,8 +209732,6 @@ static void sqlite3Fts5UnicodeAscii(u8*, u8*);
** The following is the concatenation of all %include directives from the
** input grammar file:
*/
-/* #include <stdio.h> */
-/* #include <assert.h> */
/************ Begin %include sections from the grammar ************************/
/* #include "fts5Int.h" */
@@ -208903,11 +209761,26 @@ static void sqlite3Fts5UnicodeAscii(u8*, u8*);
#define fts5YYMALLOCARGTYPE u64
/**************** End of %include directives **********************************/
-/* These constants specify the various numeric values for terminal symbols
-** in a format understandable to "makeheaders". This section is blank unless
-** "lemon" is run with the "-m" command-line option.
-***************** Begin makeheaders token definitions *************************/
-/**************** End makeheaders token definitions ***************************/
+/* These constants specify the various numeric values for terminal symbols.
+***************** Begin token definitions *************************************/
+#ifndef FTS5_OR
+#define FTS5_OR 1
+#define FTS5_AND 2
+#define FTS5_NOT 3
+#define FTS5_TERM 4
+#define FTS5_COLON 5
+#define FTS5_MINUS 6
+#define FTS5_LCP 7
+#define FTS5_RCP 8
+#define FTS5_STRING 9
+#define FTS5_LP 10
+#define FTS5_RP 11
+#define FTS5_CARET 12
+#define FTS5_COMMA 13
+#define FTS5_PLUS 14
+#define FTS5_STAR 15
+#endif
+/**************** End token definitions ***************************************/
/* The next sections is a series of control #defines.
** various aspects of the generated parser.
@@ -209190,6 +210063,7 @@ typedef struct fts5yyParser fts5yyParser;
#ifndef NDEBUG
/* #include <stdio.h> */
+/* #include <assert.h> */
static FILE *fts5yyTraceFILE = 0;
static char *fts5yyTracePrompt = 0;
#endif /* NDEBUG */
@@ -209604,7 +210478,7 @@ static fts5YYACTIONTYPE fts5yy_find_shift_action(
#endif /* fts5YYWILDCARD */
return fts5yy_default[stateno];
}else{
- assert( i>=0 && i<sizeof(fts5yy_action)/sizeof(fts5yy_action[0]) );
+ assert( i>=0 && i<(int)(sizeof(fts5yy_action)/sizeof(fts5yy_action[0])) );
return fts5yy_action[i];
}
}while(1);
@@ -209818,8 +210692,9 @@ static fts5YYACTIONTYPE fts5yy_reduce(
(void)fts5yyLookahead;
(void)fts5yyLookaheadToken;
fts5yymsp = fts5yypParser->fts5yytos;
+ assert( fts5yyruleno<(int)(sizeof(fts5yyRuleName)/sizeof(fts5yyRuleName[0])) );
#ifndef NDEBUG
- if( fts5yyTraceFILE && fts5yyruleno<(int)(sizeof(fts5yyRuleName)/sizeof(fts5yyRuleName[0])) ){
+ if( fts5yyTraceFILE ){
fts5yysize = fts5yyRuleInfoNRhs[fts5yyruleno];
if( fts5yysize ){
fprintf(fts5yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n",
@@ -210884,7 +211759,7 @@ static int fts5Bm25GetData(
int rc = SQLITE_OK; /* Return code */
Fts5Bm25Data *p; /* Object to return */
- p = pApi->xGetAuxdata(pFts, 0);
+ p = (Fts5Bm25Data*)pApi->xGetAuxdata(pFts, 0);
if( p==0 ){
int nPhrase; /* Number of phrases in query */
sqlite3_int64 nRow = 0; /* Number of rows in table */
@@ -210958,7 +211833,7 @@ static void fts5Bm25Function(
){
const double k1 = 1.2; /* Constant "k1" from BM25 formula */
const double b = 0.75; /* Constant "b" from BM25 formula */
- int rc = SQLITE_OK; /* Error code */
+ int rc; /* Error code */
double score = 0.0; /* SQL function return value */
Fts5Bm25Data *pData; /* Values allocated/calculated once only */
int i; /* Iterator variable */
@@ -210990,17 +211865,15 @@ static void fts5Bm25Function(
D = (double)nTok;
}
- /* Determine the BM25 score for the current row. */
- for(i=0; rc==SQLITE_OK && i<pData->nPhrase; i++){
- score += pData->aIDF[i] * (
- ( aFreq[i] * (k1 + 1.0) ) /
- ( aFreq[i] + k1 * (1 - b + b * D / pData->avgdl) )
- );
- }
-
- /* If no error has occurred, return the calculated score. Otherwise,
- ** throw an SQL exception. */
+ /* Determine and return the BM25 score for the current row. Or, if an
+ ** error has occurred, throw an exception. */
if( rc==SQLITE_OK ){
+ for(i=0; i<pData->nPhrase; i++){
+ score += pData->aIDF[i] * (
+ ( aFreq[i] * (k1 + 1.0) ) /
+ ( aFreq[i] + k1 * (1 - b + b * D / pData->avgdl) )
+ );
+ }
sqlite3_result_double(pCtx, -1.0 * score);
}else{
sqlite3_result_error_code(pCtx, rc);
@@ -211764,7 +212637,7 @@ static int fts5ConfigParseSpecial(
rc = SQLITE_ERROR;
}else{
rc = sqlite3Fts5GetTokenizer(pGlobal,
- (const char**)azArg, (int)nArg, &pConfig->pTok, &pConfig->pTokApi,
+ (const char**)azArg, (int)nArg, pConfig,
pzErr
);
}
@@ -211836,9 +212709,7 @@ static int fts5ConfigParseSpecial(
*/
static int fts5ConfigDefaultTokenizer(Fts5Global *pGlobal, Fts5Config *pConfig){
assert( pConfig->pTok==0 && pConfig->pTokApi==0 );
- return sqlite3Fts5GetTokenizer(
- pGlobal, 0, 0, &pConfig->pTok, &pConfig->pTokApi, 0
- );
+ return sqlite3Fts5GetTokenizer(pGlobal, 0, 0, pConfig, 0);
}
/*
@@ -212530,6 +213401,7 @@ struct Fts5Parse {
int nPhrase; /* Size of apPhrase array */
Fts5ExprPhrase **apPhrase; /* Array of all phrases */
Fts5ExprNode *pExpr; /* Result of a successful parse */
+ int bPhraseToAnd; /* Convert "a+b" to "a AND b" */
};
static void sqlite3Fts5ParseError(Fts5Parse *pParse, const char *zFmt, ...){
@@ -212618,6 +213490,7 @@ static void fts5ParseFree(void *p){ sqlite3_free(p); }
static int sqlite3Fts5ExprNew(
Fts5Config *pConfig, /* FTS5 Configuration */
+ int bPhraseToAnd,
int iCol,
const char *zExpr, /* Expression text */
Fts5Expr **ppNew,
@@ -212633,6 +213506,7 @@ static int sqlite3Fts5ExprNew(
*ppNew = 0;
*pzErr = 0;
memset(&sParse, 0, sizeof(sParse));
+ sParse.bPhraseToAnd = bPhraseToAnd;
pEngine = sqlite3Fts5ParserAlloc(fts5ParseAlloc);
if( pEngine==0 ){ return SQLITE_NOMEM; }
sParse.pConfig = pConfig;
@@ -212675,6 +213549,7 @@ static int sqlite3Fts5ExprNew(
pNew->pConfig = pConfig;
pNew->apExprPhrase = sParse.apPhrase;
pNew->nPhrase = sParse.nPhrase;
+ pNew->bDesc = 0;
sParse.apPhrase = 0;
}
}else{
@@ -212687,6 +213562,81 @@ static int sqlite3Fts5ExprNew(
}
/*
+** This function is only called when using the special 'trigram' tokenizer.
+** Argument zText contains the text of a LIKE or GLOB pattern matched
+** against column iCol. This function creates and compiles an FTS5 MATCH
+** expression that will match a superset of the rows matched by the LIKE or
+** GLOB. If successful, SQLITE_OK is returned. Otherwise, an SQLite error
+** code.
+*/
+static int sqlite3Fts5ExprPattern(
+ Fts5Config *pConfig, int bGlob, int iCol, const char *zText, Fts5Expr **pp
+){
+ i64 nText = strlen(zText);
+ char *zExpr = (char*)sqlite3_malloc64(nText*4 + 1);
+ int rc = SQLITE_OK;
+
+ if( zExpr==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ char aSpec[3];
+ int iOut = 0;
+ int i = 0;
+ int iFirst = 0;
+
+ if( bGlob==0 ){
+ aSpec[0] = '_';
+ aSpec[1] = '%';
+ aSpec[2] = 0;
+ }else{
+ aSpec[0] = '*';
+ aSpec[1] = '?';
+ aSpec[2] = '[';
+ }
+
+ while( i<=nText ){
+ if( i==nText
+ || zText[i]==aSpec[0] || zText[i]==aSpec[1] || zText[i]==aSpec[2]
+ ){
+ if( i-iFirst>=3 ){
+ int jj;
+ zExpr[iOut++] = '"';
+ for(jj=iFirst; jj<i; jj++){
+ zExpr[iOut++] = zText[jj];
+ if( zText[jj]=='"' ) zExpr[iOut++] = '"';
+ }
+ zExpr[iOut++] = '"';
+ zExpr[iOut++] = ' ';
+ }
+ if( zText[i]==aSpec[2] ){
+ i += 2;
+ if( zText[i-1]=='^' ) i++;
+ while( i<nText && zText[i]!=']' ) i++;
+ }
+ iFirst = i+1;
+ }
+ i++;
+ }
+ if( iOut>0 ){
+ int bAnd = 0;
+ if( pConfig->eDetail!=FTS5_DETAIL_FULL ){
+ bAnd = 1;
+ if( pConfig->eDetail==FTS5_DETAIL_NONE ){
+ iCol = pConfig->nCol;
+ }
+ }
+ zExpr[iOut] = '\0';
+ rc = sqlite3Fts5ExprNew(pConfig, bAnd, iCol, zExpr, pp,pConfig->pzErrmsg);
+ }else{
+ *pp = 0;
+ }
+ sqlite3_free(zExpr);
+ }
+
+ return rc;
+}
+
+/*
** Free the expression node object passed as the only argument.
*/
static void sqlite3Fts5ParseNodeFree(Fts5ExprNode *p){
@@ -214063,6 +215013,20 @@ static void sqlite3Fts5ParseFinished(Fts5Parse *pParse, Fts5ExprNode *p){
pParse->pExpr = p;
}
+static int parseGrowPhraseArray(Fts5Parse *pParse){
+ if( (pParse->nPhrase % 8)==0 ){
+ sqlite3_int64 nByte = sizeof(Fts5ExprPhrase*) * (pParse->nPhrase + 8);
+ Fts5ExprPhrase **apNew;
+ apNew = (Fts5ExprPhrase**)sqlite3_realloc64(pParse->apPhrase, nByte);
+ if( apNew==0 ){
+ pParse->rc = SQLITE_NOMEM;
+ return SQLITE_NOMEM;
+ }
+ pParse->apPhrase = apNew;
+ }
+ return SQLITE_OK;
+}
+
/*
** This function is called by the parser to process a string token. The
** string may or may not be quoted. In any case it is tokenized and a
@@ -214098,16 +215062,9 @@ static Fts5ExprPhrase *sqlite3Fts5ParseTerm(
}else{
if( pAppend==0 ){
- if( (pParse->nPhrase % 8)==0 ){
- sqlite3_int64 nByte = sizeof(Fts5ExprPhrase*) * (pParse->nPhrase + 8);
- Fts5ExprPhrase **apNew;
- apNew = (Fts5ExprPhrase**)sqlite3_realloc64(pParse->apPhrase, nByte);
- if( apNew==0 ){
- pParse->rc = SQLITE_NOMEM;
- fts5ExprPhraseFree(sCtx.pPhrase);
- return 0;
- }
- pParse->apPhrase = apNew;
+ if( parseGrowPhraseArray(pParse) ){
+ fts5ExprPhraseFree(sCtx.pPhrase);
+ return 0;
}
pParse->nPhrase++;
}
@@ -214515,6 +215472,67 @@ static void fts5ExprAddChildren(Fts5ExprNode *p, Fts5ExprNode *pSub){
}
/*
+** This function is used when parsing LIKE or GLOB patterns against
+** trigram indexes that specify either detail=column or detail=none.
+** It converts a phrase:
+**
+** abc + def + ghi
+**
+** into an AND tree:
+**
+** abc AND def AND ghi
+*/
+static Fts5ExprNode *fts5ParsePhraseToAnd(
+ Fts5Parse *pParse,
+ Fts5ExprNearset *pNear
+){
+ int nTerm = pNear->apPhrase[0]->nTerm;
+ int ii;
+ int nByte;
+ Fts5ExprNode *pRet;
+
+ assert( pNear->nPhrase==1 );
+ assert( pParse->bPhraseToAnd );
+
+ nByte = sizeof(Fts5ExprNode) + nTerm*sizeof(Fts5ExprNode*);
+ pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);
+ if( pRet ){
+ pRet->eType = FTS5_AND;
+ pRet->nChild = nTerm;
+ fts5ExprAssignXNext(pRet);
+ pParse->nPhrase--;
+ for(ii=0; ii<nTerm; ii++){
+ Fts5ExprPhrase *pPhrase = (Fts5ExprPhrase*)sqlite3Fts5MallocZero(
+ &pParse->rc, sizeof(Fts5ExprPhrase)
+ );
+ if( pPhrase ){
+ if( parseGrowPhraseArray(pParse) ){
+ fts5ExprPhraseFree(pPhrase);
+ }else{
+ pParse->apPhrase[pParse->nPhrase++] = pPhrase;
+ pPhrase->nTerm = 1;
+ pPhrase->aTerm[0].zTerm = sqlite3Fts5Strndup(
+ &pParse->rc, pNear->apPhrase[0]->aTerm[ii].zTerm, -1
+ );
+ pRet->apChild[ii] = sqlite3Fts5ParseNode(pParse, FTS5_STRING,
+ 0, 0, sqlite3Fts5ParseNearset(pParse, 0, pPhrase)
+ );
+ }
+ }
+ }
+
+ if( pParse->rc ){
+ sqlite3Fts5ParseNodeFree(pRet);
+ pRet = 0;
+ }else{
+ sqlite3Fts5ParseNearsetFree(pNear);
+ }
+ }
+
+ return pRet;
+}
+
+/*
** Allocate and return a new expression object. If anything goes wrong (i.e.
** OOM error), leave an error code in pParse and return NULL.
*/
@@ -214538,51 +215556,58 @@ static Fts5ExprNode *sqlite3Fts5ParseNode(
if( eType!=FTS5_STRING && pLeft==0 ) return pRight;
if( eType!=FTS5_STRING && pRight==0 ) return pLeft;
- if( eType==FTS5_NOT ){
- nChild = 2;
- }else if( eType==FTS5_AND || eType==FTS5_OR ){
- nChild = 2;
- if( pLeft->eType==eType ) nChild += pLeft->nChild-1;
- if( pRight->eType==eType ) nChild += pRight->nChild-1;
- }
+ if( eType==FTS5_STRING
+ && pParse->bPhraseToAnd
+ && pNear->apPhrase[0]->nTerm>1
+ ){
+ pRet = fts5ParsePhraseToAnd(pParse, pNear);
+ }else{
+ if( eType==FTS5_NOT ){
+ nChild = 2;
+ }else if( eType==FTS5_AND || eType==FTS5_OR ){
+ nChild = 2;
+ if( pLeft->eType==eType ) nChild += pLeft->nChild-1;
+ if( pRight->eType==eType ) nChild += pRight->nChild-1;
+ }
- nByte = sizeof(Fts5ExprNode) + sizeof(Fts5ExprNode*)*(nChild-1);
- pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);
+ nByte = sizeof(Fts5ExprNode) + sizeof(Fts5ExprNode*)*(nChild-1);
+ pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);
- if( pRet ){
- pRet->eType = eType;
- pRet->pNear = pNear;
- fts5ExprAssignXNext(pRet);
- if( eType==FTS5_STRING ){
- int iPhrase;
- for(iPhrase=0; iPhrase<pNear->nPhrase; iPhrase++){
- pNear->apPhrase[iPhrase]->pNode = pRet;
- if( pNear->apPhrase[iPhrase]->nTerm==0 ){
- pRet->xNext = 0;
- pRet->eType = FTS5_EOF;
+ if( pRet ){
+ pRet->eType = eType;
+ pRet->pNear = pNear;
+ fts5ExprAssignXNext(pRet);
+ if( eType==FTS5_STRING ){
+ int iPhrase;
+ for(iPhrase=0; iPhrase<pNear->nPhrase; iPhrase++){
+ pNear->apPhrase[iPhrase]->pNode = pRet;
+ if( pNear->apPhrase[iPhrase]->nTerm==0 ){
+ pRet->xNext = 0;
+ pRet->eType = FTS5_EOF;
+ }
}
- }
- if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL ){
- Fts5ExprPhrase *pPhrase = pNear->apPhrase[0];
- if( pNear->nPhrase!=1
- || pPhrase->nTerm>1
- || (pPhrase->nTerm>0 && pPhrase->aTerm[0].bFirst)
- ){
- assert( pParse->rc==SQLITE_OK );
- pParse->rc = SQLITE_ERROR;
- assert( pParse->zErr==0 );
- pParse->zErr = sqlite3_mprintf(
- "fts5: %s queries are not supported (detail!=full)",
- pNear->nPhrase==1 ? "phrase": "NEAR"
- );
- sqlite3_free(pRet);
- pRet = 0;
+ if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL ){
+ Fts5ExprPhrase *pPhrase = pNear->apPhrase[0];
+ if( pNear->nPhrase!=1
+ || pPhrase->nTerm>1
+ || (pPhrase->nTerm>0 && pPhrase->aTerm[0].bFirst)
+ ){
+ assert( pParse->rc==SQLITE_OK );
+ pParse->rc = SQLITE_ERROR;
+ assert( pParse->zErr==0 );
+ pParse->zErr = sqlite3_mprintf(
+ "fts5: %s queries are not supported (detail!=full)",
+ pNear->nPhrase==1 ? "phrase": "NEAR"
+ );
+ sqlite3_free(pRet);
+ pRet = 0;
+ }
}
+ }else{
+ fts5ExprAddChildren(pRet, pLeft);
+ fts5ExprAddChildren(pRet, pRight);
}
- }else{
- fts5ExprAddChildren(pRet, pLeft);
- fts5ExprAddChildren(pRet, pRight);
}
}
}
@@ -214803,8 +215828,17 @@ static char *fts5ExprPrint(Fts5Config *pConfig, Fts5ExprNode *pExpr){
int iTerm;
if( pNear->pColset ){
- int iCol = pNear->pColset->aiCol[0];
- zRet = fts5PrintfAppend(zRet, "%s : ", pConfig->azCol[iCol]);
+ int ii;
+ Fts5Colset *pColset = pNear->pColset;
+ if( pColset->nCol>1 ) zRet = fts5PrintfAppend(zRet, "{");
+ for(ii=0; ii<pColset->nCol; ii++){
+ zRet = fts5PrintfAppend(zRet, "%s%s",
+ pConfig->azCol[pColset->aiCol[ii]], ii==pColset->nCol-1 ? "" : " "
+ );
+ }
+ if( zRet ){
+ zRet = fts5PrintfAppend(zRet, "%s : ", pColset->nCol>1 ? "}" : "");
+ }
if( zRet==0 ) return 0;
}
@@ -214927,7 +215961,7 @@ static void fts5ExprFunction(
rc = sqlite3Fts5ConfigParse(pGlobal, db, nConfig, azConfig, &pConfig, &zErr);
if( rc==SQLITE_OK ){
- rc = sqlite3Fts5ExprNew(pConfig, pConfig->nCol, zExpr, &pExpr, &zErr);
+ rc = sqlite3Fts5ExprNew(pConfig, 0, pConfig->nCol, zExpr, &pExpr, &zErr);
}
if( rc==SQLITE_OK ){
char *zText;
@@ -215600,7 +216634,6 @@ static int sqlite3Fts5HashWrite(
p->iCol = (pHash->eDetail==FTS5_DETAIL_FULL ? 0 : -1);
}
- nIncr += p->nData;
}else{
/* Appending to an existing hash-entry. Check that there is enough
@@ -215633,8 +216666,9 @@ static int sqlite3Fts5HashWrite(
/* If this is a new rowid, append the 4-byte size field for the previous
** entry, and the new rowid for this entry. */
if( iRowid!=p->iRowid ){
+ u64 iDiff = (u64)iRowid - (u64)p->iRowid;
fts5HashAddPoslistSize(pHash, p, 0);
- p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iRowid - p->iRowid);
+ p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iDiff);
p->iRowid = iRowid;
bNew = 1;
p->iSzPoslist = p->nData;
@@ -217609,7 +218643,7 @@ static void fts5SegIterReverseInitPage(Fts5Index *p, Fts5SegIter *pIter){
ASSERT_SZLEAF_OK(pIter->pLeaf);
while( 1 ){
- i64 iDelta = 0;
+ u64 iDelta = 0;
if( eDetail==FTS5_DETAIL_NONE ){
/* todo */
@@ -217624,7 +218658,7 @@ static void fts5SegIterReverseInitPage(Fts5Index *p, Fts5SegIter *pIter){
i += nPos;
}
if( i>=n ) break;
- i += fts5GetVarint(&a[i], (u64*)&iDelta);
+ i += fts5GetVarint(&a[i], &iDelta);
pIter->iRowid += iDelta;
/* If necessary, grow the pIter->aRowidOffset[] array. */
@@ -217723,7 +218757,7 @@ static void fts5SegIterNext_Reverse(
if( pIter->iRowidOffset>0 ){
u8 *a = pIter->pLeaf->p;
int iOff;
- i64 iDelta;
+ u64 iDelta;
pIter->iRowidOffset--;
pIter->iLeafOffset = pIter->aRowidOffset[pIter->iRowidOffset];
@@ -217732,7 +218766,7 @@ static void fts5SegIterNext_Reverse(
if( p->pConfig->eDetail!=FTS5_DETAIL_NONE ){
iOff += pIter->nPos;
}
- fts5GetVarint(&a[iOff], (u64*)&iDelta);
+ fts5GetVarint(&a[iOff], &iDelta);
pIter->iRowid -= iDelta;
}else{
fts5SegIterReverseNewPage(p, pIter);
@@ -220852,7 +221886,9 @@ static void fts5MergePrefixLists(
** at most 20 bytes of unexpected space. */
fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
fts5BufferZero(&tmp);
- sqlite3Fts5BufferSize(&p->rc, &tmp, i1.nPoslist + i2.nPoslist + 10 + 10);
+ sqlite3Fts5BufferSize(&p->rc, &tmp,
+ i1.nPoslist + i2.nPoslist + 10 + 10 + FTS5_DATA_ZERO_PADDING
+ );
if( p->rc ) break;
sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
@@ -220926,9 +221962,10 @@ static void fts5MergePrefixLists(
}
assert_nc( out.n<=(p1->n+p2->n+9) );
- fts5BufferSet(&p->rc, p1, out.n, out.p);
+ fts5BufferFree(p1);
fts5BufferFree(&tmp);
- fts5BufferFree(&out);
+ memset(&out.p[out.n], 0, FTS5_DATA_ZERO_PADDING);
+ *p1 = out;
}
}
@@ -221914,7 +222951,7 @@ static void fts5IndexIntegrityCheckSegment(
** error, or some other SQLite error code if another error (e.g. OOM)
** occurs.
*/
-static int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum){
+static int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum, int bUseCksum){
int eDetail = p->pConfig->eDetail;
u64 cksum2 = 0; /* Checksum based on contents of indexes */
Fts5Buffer poslist = {0,0,0}; /* Buffer used to hold a poslist */
@@ -221975,6 +223012,7 @@ static int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum){
}else{
poslist.n = 0;
fts5SegiterPoslist(p, &pIter->aSeg[pIter->aFirst[1].iFirst], 0, &poslist);
+ fts5BufferAppendBlob(&p->rc, &poslist, 4, (const u8*)"\0\0\0\0");
while( 0==sqlite3Fts5PoslistNext64(poslist.p, poslist.n, &iOff, &iPos) ){
int iCol = FTS5_POS2COLUMN(iPos);
int iTokOff = FTS5_POS2OFFSET(iPos);
@@ -221985,7 +223023,7 @@ static int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum){
fts5TestTerm(p, &term, 0, 0, cksum2, &cksum3);
fts5MultiIterFree(pIter);
- if( p->rc==SQLITE_OK && cksum!=cksum2 ) p->rc = FTS5_CORRUPT;
+ if( p->rc==SQLITE_OK && bUseCksum && cksum!=cksum2 ) p->rc = FTS5_CORRUPT;
fts5StructureRelease(pStruct);
#ifdef SQLITE_DEBUG
@@ -222949,6 +223987,23 @@ static void fts5SetUniqueFlag(sqlite3_index_info *pIdxInfo){
#endif
}
+static int fts5UsePatternMatch(
+ Fts5Config *pConfig,
+ struct sqlite3_index_constraint *p
+){
+ assert( FTS5_PATTERN_GLOB==SQLITE_INDEX_CONSTRAINT_GLOB );
+ assert( FTS5_PATTERN_LIKE==SQLITE_INDEX_CONSTRAINT_LIKE );
+ if( pConfig->ePattern==FTS5_PATTERN_GLOB && p->op==FTS5_PATTERN_GLOB ){
+ return 1;
+ }
+ if( pConfig->ePattern==FTS5_PATTERN_LIKE
+ && (p->op==FTS5_PATTERN_LIKE || p->op==FTS5_PATTERN_GLOB)
+ ){
+ return 1;
+ }
+ return 0;
+}
+
/*
** Implementation of the xBestIndex method for FTS5 tables. Within the
** WHERE constraint, it searches for the following:
@@ -222978,7 +224033,9 @@ static void fts5SetUniqueFlag(sqlite3_index_info *pIdxInfo){
**
** Match against table column: "m"
** Match against rank column: "r"
-** Match against other column: "<column-number>"
+** Match against other column: "M<column-number>"
+** LIKE against other column: "L<column-number>"
+** GLOB against other column: "G<column-number>"
** Equality constraint against the rowid: "="
** A < or <= against the rowid: "<"
** A > or >= against the rowid: ">"
@@ -223039,7 +224096,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
return SQLITE_ERROR;
}
- idxStr = (char*)sqlite3_malloc(pInfo->nConstraint * 6 + 1);
+ idxStr = (char*)sqlite3_malloc(pInfo->nConstraint * 8 + 1);
if( idxStr==0 ) return SQLITE_NOMEM;
pInfo->idxStr = idxStr;
pInfo->needToFreeIdxStr = 1;
@@ -223063,25 +224120,29 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
if( bSeenRank ) continue;
idxStr[iIdxStr++] = 'r';
bSeenRank = 1;
- }else{
+ }else if( iCol>=0 ){
bSeenMatch = 1;
- idxStr[iIdxStr++] = 'm';
- if( iCol<nCol ){
- sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
- idxStr += strlen(&idxStr[iIdxStr]);
- assert( idxStr[iIdxStr]=='\0' );
- }
+ idxStr[iIdxStr++] = 'M';
+ sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
+ idxStr += strlen(&idxStr[iIdxStr]);
+ assert( idxStr[iIdxStr]=='\0' );
}
pInfo->aConstraintUsage[i].argvIndex = ++iCons;
pInfo->aConstraintUsage[i].omit = 1;
}
- }
- else if( p->usable && bSeenEq==0
- && p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol<0
- ){
- idxStr[iIdxStr++] = '=';
- bSeenEq = 1;
- pInfo->aConstraintUsage[i].argvIndex = ++iCons;
+ }else if( p->usable ){
+ if( iCol>=0 && iCol<nCol && fts5UsePatternMatch(pConfig, p) ){
+ assert( p->op==FTS5_PATTERN_LIKE || p->op==FTS5_PATTERN_GLOB );
+ idxStr[iIdxStr++] = p->op==FTS5_PATTERN_LIKE ? 'L' : 'G';
+ sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
+ idxStr += strlen(&idxStr[iIdxStr]);
+ pInfo->aConstraintUsage[i].argvIndex = ++iCons;
+ assert( idxStr[iIdxStr]=='\0' );
+ }else if( bSeenEq==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol<0 ){
+ idxStr[iIdxStr++] = '=';
+ bSeenEq = 1;
+ pInfo->aConstraintUsage[i].argvIndex = ++iCons;
+ }
}
}
@@ -223714,19 +224775,14 @@ static int fts5FilterMethod(
case 'r':
pRank = apVal[i];
break;
- case 'm': {
+ case 'M': {
const char *zText = (const char*)sqlite3_value_text(apVal[i]);
if( zText==0 ) zText = "";
-
- if( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' ){
- iCol = 0;
- do{
- iCol = iCol*10 + (idxStr[iIdxStr]-'0');
- iIdxStr++;
- }while( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' );
- }else{
- iCol = pConfig->nCol;
- }
+ iCol = 0;
+ do{
+ iCol = iCol*10 + (idxStr[iIdxStr]-'0');
+ iIdxStr++;
+ }while( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' );
if( zText[0]=='*' ){
/* The user has issued a query of the form "MATCH '*...'". This
@@ -223736,7 +224792,7 @@ static int fts5FilterMethod(
goto filter_out;
}else{
char **pzErr = &pTab->p.base.zErrMsg;
- rc = sqlite3Fts5ExprNew(pConfig, iCol, zText, &pExpr, pzErr);
+ rc = sqlite3Fts5ExprNew(pConfig, 0, iCol, zText, &pExpr, pzErr);
if( rc==SQLITE_OK ){
rc = sqlite3Fts5ExprAnd(&pCsr->pExpr, pExpr);
pExpr = 0;
@@ -223746,6 +224802,25 @@ static int fts5FilterMethod(
break;
}
+ case 'L':
+ case 'G': {
+ int bGlob = (idxStr[iIdxStr-1]=='G');
+ const char *zText = (const char*)sqlite3_value_text(apVal[i]);
+ iCol = 0;
+ do{
+ iCol = iCol*10 + (idxStr[iIdxStr]-'0');
+ iIdxStr++;
+ }while( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' );
+ if( zText ){
+ rc = sqlite3Fts5ExprPattern(pConfig, bGlob, iCol, zText, &pExpr);
+ }
+ if( rc==SQLITE_OK ){
+ rc = sqlite3Fts5ExprAnd(&pCsr->pExpr, pExpr);
+ pExpr = 0;
+ }
+ if( rc!=SQLITE_OK ) goto filter_out;
+ break;
+ }
case '=':
pRowidEq = apVal[i];
break;
@@ -223993,7 +225068,8 @@ static int fts5SpecialInsert(
int nMerge = sqlite3_value_int(pVal);
rc = sqlite3Fts5StorageMerge(pTab->pStorage, nMerge);
}else if( 0==sqlite3_stricmp("integrity-check", zCmd) ){
- rc = sqlite3Fts5StorageIntegrity(pTab->pStorage);
+ int iArg = sqlite3_value_int(pVal);
+ rc = sqlite3Fts5StorageIntegrity(pTab->pStorage, iArg);
#ifdef SQLITE_DEBUG
}else if( 0==sqlite3_stricmp("prefix-index", zCmd) ){
pConfig->bPrefixIndex = sqlite3_value_int(pVal);
@@ -225156,8 +226232,7 @@ static int sqlite3Fts5GetTokenizer(
Fts5Global *pGlobal,
const char **azArg,
int nArg,
- Fts5Tokenizer **ppTok,
- fts5_tokenizer **ppTokApi,
+ Fts5Config *pConfig,
char **pzErr
){
Fts5TokenizerModule *pMod;
@@ -225169,16 +226244,22 @@ static int sqlite3Fts5GetTokenizer(
rc = SQLITE_ERROR;
*pzErr = sqlite3_mprintf("no such tokenizer: %s", azArg[0]);
}else{
- rc = pMod->x.xCreate(pMod->pUserData, &azArg[1], (nArg?nArg-1:0), ppTok);
- *ppTokApi = &pMod->x;
- if( rc!=SQLITE_OK && pzErr ){
- *pzErr = sqlite3_mprintf("error in tokenizer constructor");
+ rc = pMod->x.xCreate(
+ pMod->pUserData, &azArg[1], (nArg?nArg-1:0), &pConfig->pTok
+ );
+ pConfig->pTokApi = &pMod->x;
+ if( rc!=SQLITE_OK ){
+ if( pzErr ) *pzErr = sqlite3_mprintf("error in tokenizer constructor");
+ }else{
+ pConfig->ePattern = sqlite3Fts5TokenizerPattern(
+ pMod->x.xCreate, pConfig->pTok
+ );
}
}
if( rc!=SQLITE_OK ){
- *ppTokApi = 0;
- *ppTok = 0;
+ pConfig->pTokApi = 0;
+ pConfig->pTok = 0;
}
return rc;
@@ -225227,7 +226308,7 @@ static void fts5SourceIdFunc(
){
assert( nArg==0 );
UNUSED_PARAM2(nArg, apUnused);
- sqlite3_result_text(pCtx, "fts5: 2020-08-14 13:23:32 fca8dc8b578f215a969cd899336378966156154710873e68b3d9ac5881b0ff3f", -1, SQLITE_TRANSIENT);
+ sqlite3_result_text(pCtx, "fts5: 2020-12-01 16:14:00 0000000000000000000000000000000000000000000000000000000000000000", -1, SQLITE_TRANSIENT);
}
/*
@@ -225790,9 +226871,16 @@ static int fts5StorageDeleteFromIndex(
zText, nText, (void*)&ctx, fts5StorageInsertCallback
);
p->aTotalSize[iCol-1] -= (i64)ctx.szCol;
+ if( p->aTotalSize[iCol-1]<0 ){
+ rc = FTS5_CORRUPT;
+ }
}
}
- p->nTotalRow--;
+ if( rc==SQLITE_OK && p->nTotalRow<1 ){
+ rc = FTS5_CORRUPT;
+ }else{
+ p->nTotalRow--;
+ }
rc2 = sqlite3_reset(pSeek);
if( rc==SQLITE_OK ) rc = rc2;
@@ -226235,13 +227323,14 @@ static int fts5StorageIntegrityCallback(
** some other SQLite error code if an error occurs while attempting to
** determine this.
*/
-static int sqlite3Fts5StorageIntegrity(Fts5Storage *p){
+static int sqlite3Fts5StorageIntegrity(Fts5Storage *p, int iArg){
Fts5Config *pConfig = p->pConfig;
- int rc; /* Return code */
+ int rc = SQLITE_OK; /* Return code */
int *aColSize; /* Array of size pConfig->nCol */
i64 *aTotalSize; /* Array of size pConfig->nCol */
Fts5IntegrityCtx ctx;
sqlite3_stmt *pScan;
+ int bUseCksum;
memset(&ctx, 0, sizeof(Fts5IntegrityCtx));
ctx.pConfig = p->pConfig;
@@ -226250,83 +227339,88 @@ static int sqlite3Fts5StorageIntegrity(Fts5Storage *p){
aColSize = (int*)&aTotalSize[pConfig->nCol];
memset(aTotalSize, 0, sizeof(i64) * pConfig->nCol);
- /* Generate the expected index checksum based on the contents of the
- ** %_content table. This block stores the checksum in ctx.cksum. */
- rc = fts5StorageGetStmt(p, FTS5_STMT_SCAN, &pScan, 0);
- if( rc==SQLITE_OK ){
- int rc2;
- while( SQLITE_ROW==sqlite3_step(pScan) ){
- int i;
- ctx.iRowid = sqlite3_column_int64(pScan, 0);
- ctx.szCol = 0;
- if( pConfig->bColumnsize ){
- rc = sqlite3Fts5StorageDocsize(p, ctx.iRowid, aColSize);
- }
- if( rc==SQLITE_OK && pConfig->eDetail==FTS5_DETAIL_NONE ){
- rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
- }
- for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
- if( pConfig->abUnindexed[i] ) continue;
- ctx.iCol = i;
+ bUseCksum = (pConfig->eContent==FTS5_CONTENT_NORMAL
+ || (pConfig->eContent==FTS5_CONTENT_EXTERNAL && iArg)
+ );
+ if( bUseCksum ){
+ /* Generate the expected index checksum based on the contents of the
+ ** %_content table. This block stores the checksum in ctx.cksum. */
+ rc = fts5StorageGetStmt(p, FTS5_STMT_SCAN, &pScan, 0);
+ if( rc==SQLITE_OK ){
+ int rc2;
+ while( SQLITE_ROW==sqlite3_step(pScan) ){
+ int i;
+ ctx.iRowid = sqlite3_column_int64(pScan, 0);
ctx.szCol = 0;
- if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
- rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
+ if( pConfig->bColumnsize ){
+ rc = sqlite3Fts5StorageDocsize(p, ctx.iRowid, aColSize);
}
- if( rc==SQLITE_OK ){
- const char *zText = (const char*)sqlite3_column_text(pScan, i+1);
- int nText = sqlite3_column_bytes(pScan, i+1);
- rc = sqlite3Fts5Tokenize(pConfig,
- FTS5_TOKENIZE_DOCUMENT,
- zText, nText,
- (void*)&ctx,
- fts5StorageIntegrityCallback
- );
- }
- if( rc==SQLITE_OK && pConfig->bColumnsize && ctx.szCol!=aColSize[i] ){
- rc = FTS5_CORRUPT;
+ if( rc==SQLITE_OK && pConfig->eDetail==FTS5_DETAIL_NONE ){
+ rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
}
- aTotalSize[i] += ctx.szCol;
- if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
- sqlite3Fts5TermsetFree(ctx.pTermset);
- ctx.pTermset = 0;
+ for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
+ if( pConfig->abUnindexed[i] ) continue;
+ ctx.iCol = i;
+ ctx.szCol = 0;
+ if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
+ rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
+ }
+ if( rc==SQLITE_OK ){
+ const char *zText = (const char*)sqlite3_column_text(pScan, i+1);
+ int nText = sqlite3_column_bytes(pScan, i+1);
+ rc = sqlite3Fts5Tokenize(pConfig,
+ FTS5_TOKENIZE_DOCUMENT,
+ zText, nText,
+ (void*)&ctx,
+ fts5StorageIntegrityCallback
+ );
+ }
+ if( rc==SQLITE_OK && pConfig->bColumnsize && ctx.szCol!=aColSize[i] ){
+ rc = FTS5_CORRUPT;
+ }
+ aTotalSize[i] += ctx.szCol;
+ if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
+ sqlite3Fts5TermsetFree(ctx.pTermset);
+ ctx.pTermset = 0;
+ }
}
- }
- sqlite3Fts5TermsetFree(ctx.pTermset);
- ctx.pTermset = 0;
+ sqlite3Fts5TermsetFree(ctx.pTermset);
+ ctx.pTermset = 0;
- if( rc!=SQLITE_OK ) break;
+ if( rc!=SQLITE_OK ) break;
+ }
+ rc2 = sqlite3_reset(pScan);
+ if( rc==SQLITE_OK ) rc = rc2;
}
- rc2 = sqlite3_reset(pScan);
- if( rc==SQLITE_OK ) rc = rc2;
- }
- /* Test that the "totals" (sometimes called "averages") record looks Ok */
- if( rc==SQLITE_OK ){
- int i;
- rc = fts5StorageLoadTotals(p, 0);
- for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
- if( p->aTotalSize[i]!=aTotalSize[i] ) rc = FTS5_CORRUPT;
+ /* Test that the "totals" (sometimes called "averages") record looks Ok */
+ if( rc==SQLITE_OK ){
+ int i;
+ rc = fts5StorageLoadTotals(p, 0);
+ for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
+ if( p->aTotalSize[i]!=aTotalSize[i] ) rc = FTS5_CORRUPT;
+ }
}
- }
- /* Check that the %_docsize and %_content tables contain the expected
- ** number of rows. */
- if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){
- i64 nRow = 0;
- rc = fts5StorageCount(p, "content", &nRow);
- if( rc==SQLITE_OK && nRow!=p->nTotalRow ) rc = FTS5_CORRUPT;
- }
- if( rc==SQLITE_OK && pConfig->bColumnsize ){
- i64 nRow = 0;
- rc = fts5StorageCount(p, "docsize", &nRow);
- if( rc==SQLITE_OK && nRow!=p->nTotalRow ) rc = FTS5_CORRUPT;
+ /* Check that the %_docsize and %_content tables contain the expected
+ ** number of rows. */
+ if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){
+ i64 nRow = 0;
+ rc = fts5StorageCount(p, "content", &nRow);
+ if( rc==SQLITE_OK && nRow!=p->nTotalRow ) rc = FTS5_CORRUPT;
+ }
+ if( rc==SQLITE_OK && pConfig->bColumnsize ){
+ i64 nRow = 0;
+ rc = fts5StorageCount(p, "docsize", &nRow);
+ if( rc==SQLITE_OK && nRow!=p->nTotalRow ) rc = FTS5_CORRUPT;
+ }
}
/* Pass the expected checksum down to the FTS index module. It will
** verify, amongst other things, that it matches the checksum generated by
** inspecting the index itself. */
if( rc==SQLITE_OK ){
- rc = sqlite3Fts5IndexIntegrityCheck(p->pIndex, ctx.cksum);
+ rc = sqlite3Fts5IndexIntegrityCheck(p->pIndex, ctx.cksum, bUseCksum);
}
sqlite3_free(aTotalSize);
@@ -227768,6 +228862,133 @@ static int fts5PorterTokenize(
);
}
+/**************************************************************************
+** Start of trigram implementation.
+*/
+typedef struct TrigramTokenizer TrigramTokenizer;
+struct TrigramTokenizer {
+ int bFold; /* True to fold to lower-case */
+};
+
+/*
+** Free a trigram tokenizer.
+*/
+static void fts5TriDelete(Fts5Tokenizer *p){
+ sqlite3_free(p);
+}
+
+/*
+** Allocate a trigram tokenizer.
+*/
+static int fts5TriCreate(
+ void *pUnused,
+ const char **azArg,
+ int nArg,
+ Fts5Tokenizer **ppOut
+){
+ int rc = SQLITE_OK;
+ TrigramTokenizer *pNew = (TrigramTokenizer*)sqlite3_malloc(sizeof(*pNew));
+ UNUSED_PARAM(pUnused);
+ if( pNew==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ int i;
+ pNew->bFold = 1;
+ for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
+ const char *zArg = azArg[i+1];
+ if( 0==sqlite3_stricmp(azArg[i], "case_sensitive") ){
+ if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1] ){
+ rc = SQLITE_ERROR;
+ }else{
+ pNew->bFold = (zArg[0]=='0');
+ }
+ }else{
+ rc = SQLITE_ERROR;
+ }
+ }
+ if( rc!=SQLITE_OK ){
+ fts5TriDelete((Fts5Tokenizer*)pNew);
+ pNew = 0;
+ }
+ }
+ *ppOut = (Fts5Tokenizer*)pNew;
+ return rc;
+}
+
+/*
+** Trigram tokenizer tokenize routine.
+*/
+static int fts5TriTokenize(
+ Fts5Tokenizer *pTok,
+ void *pCtx,
+ int unusedFlags,
+ const char *pText, int nText,
+ int (*xToken)(void*, int, const char*, int, int, int)
+){
+ TrigramTokenizer *p = (TrigramTokenizer*)pTok;
+ int rc = SQLITE_OK;
+ char aBuf[32];
+ const unsigned char *zIn = (const unsigned char*)pText;
+ const unsigned char *zEof = &zIn[nText];
+ u32 iCode;
+
+ UNUSED_PARAM(unusedFlags);
+ while( 1 ){
+ char *zOut = aBuf;
+ int iStart = zIn - (const unsigned char*)pText;
+ const unsigned char *zNext;
+
+ READ_UTF8(zIn, zEof, iCode);
+ if( iCode==0 ) break;
+ zNext = zIn;
+ if( zIn<zEof ){
+ if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, 0);
+ WRITE_UTF8(zOut, iCode);
+ READ_UTF8(zIn, zEof, iCode);
+ if( iCode==0 ) break;
+ }else{
+ break;
+ }
+ if( zIn<zEof ){
+ if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, 0);
+ WRITE_UTF8(zOut, iCode);
+ READ_UTF8(zIn, zEof, iCode);
+ if( iCode==0 ) break;
+ if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, 0);
+ WRITE_UTF8(zOut, iCode);
+ }else{
+ break;
+ }
+ rc = xToken(pCtx, 0, aBuf, zOut-aBuf, iStart, iStart + zOut-aBuf);
+ if( rc!=SQLITE_OK ) break;
+ zIn = zNext;
+ }
+
+ return rc;
+}
+
+/*
+** Argument xCreate is a pointer to a constructor function for a tokenizer.
+** pTok is a tokenizer previously created using the same method. This function
+** returns one of FTS5_PATTERN_NONE, FTS5_PATTERN_LIKE or FTS5_PATTERN_GLOB
+** indicating the style of pattern matching that the tokenizer can support.
+** In practice, this is:
+**
+** "trigram" tokenizer, case_sensitive=1 - FTS5_PATTERN_GLOB
+** "trigram" tokenizer, case_sensitive=0 (the default) - FTS5_PATTERN_LIKE
+** all other tokenizers - FTS5_PATTERN_NONE
+*/
+static int sqlite3Fts5TokenizerPattern(
+ int (*xCreate)(void*, const char**, int, Fts5Tokenizer**),
+ Fts5Tokenizer *pTok
+){
+ if( xCreate==fts5TriCreate ){
+ TrigramTokenizer *p = (TrigramTokenizer*)pTok;
+ return p->bFold ? FTS5_PATTERN_LIKE : FTS5_PATTERN_GLOB;
+ }
+ return FTS5_PATTERN_NONE;
+}
+
/*
** Register all built-in tokenizers with FTS5.
*/
@@ -227779,6 +229000,7 @@ static int sqlite3Fts5TokenizerInit(fts5_api *pApi){
{ "unicode61", {fts5UnicodeCreate, fts5UnicodeDelete, fts5UnicodeTokenize}},
{ "ascii", {fts5AsciiCreate, fts5AsciiDelete, fts5AsciiTokenize }},
{ "porter", {fts5PorterCreate, fts5PorterDelete, fts5PorterTokenize }},
+ { "trigram", {fts5TriCreate, fts5TriDelete, fts5TriTokenize}},
};
int rc = SQLITE_OK; /* Return code */
@@ -228571,8 +229793,10 @@ static void sqlite3Fts5UnicodeAscii(u8 *aArray, u8 *aAscii){
}
iTbl++;
}
+ aAscii[0] = 0; /* 0x00 is never a token character */
}
+
/*
** 2015 May 30
**
@@ -230010,9 +231234,9 @@ SQLITE_API int sqlite3_stmt_init(
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
/************** End of stmt.c ************************************************/
-#if __LINE__!=230011
+#if __LINE__!=231237
#undef SQLITE_SOURCE_ID
-#define SQLITE_SOURCE_ID "2020-08-14 13:23:32 fca8dc8b578f215a969cd899336378966156154710873e68b3d9ac5881b0alt2"
+#define SQLITE_SOURCE_ID "2020-12-01 16:14:00 b7738010bc8ef02ba84820368e557306390a33c38adaa5c7703154bae3edalt2"
#endif
/* Return the source-id for this library */
SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
diff --git a/chromium/third_party/sqlite/src/amalgamation/sqlite3.h b/chromium/third_party/sqlite/src/amalgamation/sqlite3.h
index 910b687aa7d..44be7872663 100644
--- a/chromium/third_party/sqlite/src/amalgamation/sqlite3.h
+++ b/chromium/third_party/sqlite/src/amalgamation/sqlite3.h
@@ -123,9 +123,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.33.0"
-#define SQLITE_VERSION_NUMBER 3033000
-#define SQLITE_SOURCE_ID "2020-08-14 13:23:32 fca8dc8b578f215a969cd899336378966156154710873e68b3d9ac5881b0ff3f"
+#define SQLITE_VERSION "3.34.0"
+#define SQLITE_VERSION_NUMBER 3034000
+#define SQLITE_SOURCE_ID "2020-12-01 16:14:00 b7738010bc8ef02ba84820368e557306390a33c38adaa5c7703154bae3edalt1"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -504,6 +504,7 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8))
#define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8))
#define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8))
+#define SQLITE_IOERR_CORRUPTFS (SQLITE_IOERR | (33<<8))
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8))
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
@@ -6187,6 +6188,57 @@ SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName);
/*
+** CAPI3REF: Determine the transaction state of a database
+** METHOD: sqlite3
+**
+** ^The sqlite3_txn_state(D,S) interface returns the current
+** [transaction state] of schema S in database connection D. ^If S is NULL,
+** then the highest transaction state of any schema on database connection D
+** is returned. Transaction states are (in order of lowest to highest):
+** <ol>
+** <li value="0"> SQLITE_TXN_NONE
+** <li value="1"> SQLITE_TXN_READ
+** <li value="2"> SQLITE_TXN_WRITE
+** </ol>
+** ^If the S argument to sqlite3_txn_state(D,S) is not the name of
+** a valid schema, then -1 is returned.
+*/
+SQLITE_API int sqlite3_txn_state(sqlite3*,const char *zSchema);
+
+/*
+** CAPI3REF: Allowed return values from [sqlite3_txn_state()]
+** KEYWORDS: {transaction state}
+**
+** These constants define the current transaction state of a database file.
+** ^The [sqlite3_txn_state(D,S)] interface returns one of these
+** constants in order to describe the transaction state of schema S
+** in [database connection] D.
+**
+** <dl>
+** [[SQLITE_TXN_NONE]] <dt>SQLITE_TXN_NONE</dt>
+** <dd>The SQLITE_TXN_NONE state means that no transaction is currently
+** pending.</dd>
+**
+** [[SQLITE_TXN_READ]] <dt>SQLITE_TXN_READ</dt>
+** <dd>The SQLITE_TXN_READ state means that the database is currently
+** in a read transaction. Content has been read from the database file
+** but nothing in the database file has changed. The transaction state
+** will advanced to SQLITE_TXN_WRITE if any changes occur and there are
+** no other conflicting concurrent write transactions. The transaction
+** state will revert to SQLITE_TXN_NONE following a [ROLLBACK] or
+** [COMMIT].</dd>
+**
+** [[SQLITE_TXN_WRITE]] <dt>SQLITE_TXN_WRITE</dt>
+** <dd>The SQLITE_TXN_WRITE state means that the database is currently
+** in a write transaction. Content has been written to the database file
+** but has not yet committed. The transaction state will change to
+** to SQLITE_TXN_NONE at the next [ROLLBACK] or [COMMIT].</dd>
+*/
+#define SQLITE_TXN_NONE 0
+#define SQLITE_TXN_READ 1
+#define SQLITE_TXN_WRITE 2
+
+/*
** CAPI3REF: Find the next prepared statement
** METHOD: sqlite3
**
@@ -7712,7 +7764,8 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_RESULT_INTREAL 27
#define SQLITE_TESTCTRL_PRNG_SEED 28
#define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29
-#define SQLITE_TESTCTRL_LAST 29 /* Largest TESTCTRL */
+#define SQLITE_TESTCTRL_SEEK_COUNT 30
+#define SQLITE_TESTCTRL_LAST 30 /* Largest TESTCTRL */
/*
** CAPI3REF: SQL Keyword Checking
@@ -9192,10 +9245,11 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
** CAPI3REF: Determine If Virtual Table Column Access Is For UPDATE
**
** If the sqlite3_vtab_nochange(X) routine is called within the [xColumn]
-** method of a [virtual table], then it returns true if and only if the
+** method of a [virtual table], then it might return true if the
** column is being fetched as part of an UPDATE operation during which the
-** column value will not change. Applications might use this to substitute
-** a return value that is less expensive to compute and that the corresponding
+** column value will not change. The virtual table implementation can use
+** this hint as permission to substitute a return value that is less
+** expensive to compute and that the corresponding
** [xUpdate] method understands as a "no-change" value.
**
** If the [xColumn] method calls sqlite3_vtab_nochange() and finds that
@@ -9204,6 +9258,12 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
** any of the [sqlite3_result_int|sqlite3_result_xxxxx() interfaces].
** In that case, [sqlite3_value_nochange(X)] will return true for the
** same column in the [xUpdate] method.
+**
+** The sqlite3_vtab_nochange() routine is an optimization. Virtual table
+** implementations should continue to give a correct answer even if the
+** sqlite3_vtab_nochange() interface were to always return false. In the
+** current implementation, the sqlite3_vtab_nochange() interface does always
+** returns false for the enhanced [UPDATE FROM] statement.
*/
SQLITE_API int sqlite3_vtab_nochange(sqlite3_context*);
@@ -9345,6 +9405,7 @@ SQLITE_API void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
/*
** CAPI3REF: Flush caches to disk mid-transaction
+** METHOD: sqlite3
**
** ^If a write-transaction is open on [database connection] D when the
** [sqlite3_db_cacheflush(D)] interface invoked, any dirty
@@ -9377,6 +9438,7 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*);
/*
** CAPI3REF: The pre-update hook.
+** METHOD: sqlite3
**
** ^These interfaces are only available if SQLite is compiled using the
** [SQLITE_ENABLE_PREUPDATE_HOOK] compile-time option.
@@ -9417,7 +9479,7 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*);
** seventh parameter is the final rowid value of the row being inserted
** or updated. The value of the seventh parameter passed to the callback
** function is not defined for operations on WITHOUT ROWID tables, or for
-** INSERT operations on rowid tables.
+** DELETE operations on rowid tables.
**
** The [sqlite3_preupdate_old()], [sqlite3_preupdate_new()],
** [sqlite3_preupdate_count()], and [sqlite3_preupdate_depth()] interfaces
@@ -9479,6 +9541,7 @@ SQLITE_API int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **);
/*
** CAPI3REF: Low-level system error code
+** METHOD: sqlite3
**
** ^Attempt to return the underlying operating system error code or error
** number that caused the most recent I/O error or failure to open a file.
diff --git a/chromium/third_party/sqlite/src/amalgamation_dev/rename_exports.h b/chromium/third_party/sqlite/src/amalgamation_dev/rename_exports.h
index 70a6c312c7b..cd7e4ad3e79 100644
--- a/chromium/third_party/sqlite/src/amalgamation_dev/rename_exports.h
+++ b/chromium/third_party/sqlite/src/amalgamation_dev/rename_exports.h
@@ -7,334 +7,335 @@
#ifndef THIRD_PARTY_SQLITE_AMALGAMATION_RENAME_EXPORTS_H_
#define THIRD_PARTY_SQLITE_AMALGAMATION_RENAME_EXPORTS_H_
-#define sqlite3_activate_cerod chrome_sqlite3_activate_cerod // Lines 5956-5958
-#define sqlite3_aggregate_context chrome_sqlite3_aggregate_context // Line 5517
-#define sqlite3_aggregate_count chrome_sqlite3_aggregate_count // Line 5292
-#define sqlite3_auto_extension chrome_sqlite3_auto_extension // Line 6655
-#define sqlite3_backup_finish chrome_sqlite3_backup_finish // Line 8686
-#define sqlite3_backup_init chrome_sqlite3_backup_init // Lines 8679-8684
-#define sqlite3_backup_pagecount chrome_sqlite3_backup_pagecount // Line 8688
-#define sqlite3_backup_remaining chrome_sqlite3_backup_remaining // Line 8687
-#define sqlite3_backup_step chrome_sqlite3_backup_step // Line 8685
-#define sqlite3_bind_blob chrome_sqlite3_bind_blob // Line 4396
-#define sqlite3_bind_blob64 chrome_sqlite3_bind_blob64 // Lines 4397-4398
-#define sqlite3_bind_double chrome_sqlite3_bind_double // Line 4399
-#define sqlite3_bind_int chrome_sqlite3_bind_int // Line 4400
-#define sqlite3_bind_int64 chrome_sqlite3_bind_int64 // Line 4401
-#define sqlite3_bind_null chrome_sqlite3_bind_null // Line 4402
-#define sqlite3_bind_parameter_count chrome_sqlite3_bind_parameter_count // Line 4431
-#define sqlite3_bind_parameter_index chrome_sqlite3_bind_parameter_index // Line 4477
-#define sqlite3_bind_parameter_name chrome_sqlite3_bind_parameter_name // Line 4459
-#define sqlite3_bind_pointer chrome_sqlite3_bind_pointer // Line 4408
-#define sqlite3_bind_text chrome_sqlite3_bind_text // Line 4403
-#define sqlite3_bind_text16 chrome_sqlite3_bind_text16 // Line 4404
-#define sqlite3_bind_text64 chrome_sqlite3_bind_text64 // Lines 4405-4406
-#define sqlite3_bind_value chrome_sqlite3_bind_value // Line 4407
-#define sqlite3_bind_zeroblob chrome_sqlite3_bind_zeroblob // Line 4409
-#define sqlite3_bind_zeroblob64 chrome_sqlite3_bind_zeroblob64 // Line 4410
-#define sqlite3_blob_bytes chrome_sqlite3_blob_bytes // Line 7233
-#define sqlite3_blob_close chrome_sqlite3_blob_close // Line 7217
-#define sqlite3_blob_open chrome_sqlite3_blob_open // Lines 7161-7169
-#define sqlite3_blob_read chrome_sqlite3_blob_read // Line 7262
-#define sqlite3_blob_reopen chrome_sqlite3_blob_reopen // Line 7194
-#define sqlite3_blob_write chrome_sqlite3_blob_write // Line 7304
-#define sqlite3_busy_handler chrome_sqlite3_busy_handler // Line 2658
-#define sqlite3_busy_timeout chrome_sqlite3_busy_timeout // Line 2681
-#define sqlite3_cancel_auto_extension chrome_sqlite3_cancel_auto_extension // Line 6667
-#define sqlite3_changes chrome_sqlite3_changes // Line 2487
-#define sqlite3_clear_bindings chrome_sqlite3_clear_bindings // Line 4487
+#define sqlite3_activate_cerod chrome_sqlite3_activate_cerod // Lines 5957-5959
+#define sqlite3_aggregate_context chrome_sqlite3_aggregate_context // Line 5518
+#define sqlite3_aggregate_count chrome_sqlite3_aggregate_count // Line 5293
+#define sqlite3_auto_extension chrome_sqlite3_auto_extension // Line 6707
+#define sqlite3_backup_finish chrome_sqlite3_backup_finish // Line 8739
+#define sqlite3_backup_init chrome_sqlite3_backup_init // Lines 8732-8737
+#define sqlite3_backup_pagecount chrome_sqlite3_backup_pagecount // Line 8741
+#define sqlite3_backup_remaining chrome_sqlite3_backup_remaining // Line 8740
+#define sqlite3_backup_step chrome_sqlite3_backup_step // Line 8738
+#define sqlite3_bind_blob chrome_sqlite3_bind_blob // Line 4397
+#define sqlite3_bind_blob64 chrome_sqlite3_bind_blob64 // Lines 4398-4399
+#define sqlite3_bind_double chrome_sqlite3_bind_double // Line 4400
+#define sqlite3_bind_int chrome_sqlite3_bind_int // Line 4401
+#define sqlite3_bind_int64 chrome_sqlite3_bind_int64 // Line 4402
+#define sqlite3_bind_null chrome_sqlite3_bind_null // Line 4403
+#define sqlite3_bind_parameter_count chrome_sqlite3_bind_parameter_count // Line 4432
+#define sqlite3_bind_parameter_index chrome_sqlite3_bind_parameter_index // Line 4478
+#define sqlite3_bind_parameter_name chrome_sqlite3_bind_parameter_name // Line 4460
+#define sqlite3_bind_pointer chrome_sqlite3_bind_pointer // Line 4409
+#define sqlite3_bind_text chrome_sqlite3_bind_text // Line 4404
+#define sqlite3_bind_text16 chrome_sqlite3_bind_text16 // Line 4405
+#define sqlite3_bind_text64 chrome_sqlite3_bind_text64 // Lines 4406-4407
+#define sqlite3_bind_value chrome_sqlite3_bind_value // Line 4408
+#define sqlite3_bind_zeroblob chrome_sqlite3_bind_zeroblob // Line 4410
+#define sqlite3_bind_zeroblob64 chrome_sqlite3_bind_zeroblob64 // Line 4411
+#define sqlite3_blob_bytes chrome_sqlite3_blob_bytes // Line 7285
+#define sqlite3_blob_close chrome_sqlite3_blob_close // Line 7269
+#define sqlite3_blob_open chrome_sqlite3_blob_open // Lines 7213-7221
+#define sqlite3_blob_read chrome_sqlite3_blob_read // Line 7314
+#define sqlite3_blob_reopen chrome_sqlite3_blob_reopen // Line 7246
+#define sqlite3_blob_write chrome_sqlite3_blob_write // Line 7356
+#define sqlite3_busy_handler chrome_sqlite3_busy_handler // Line 2659
+#define sqlite3_busy_timeout chrome_sqlite3_busy_timeout // Line 2682
+#define sqlite3_cancel_auto_extension chrome_sqlite3_cancel_auto_extension // Line 6719
+#define sqlite3_changes chrome_sqlite3_changes // Line 2488
+#define sqlite3_clear_bindings chrome_sqlite3_clear_bindings // Line 4488
#define sqlite3_close chrome_sqlite3_close // Line 330
#define sqlite3_close_v2 chrome_sqlite3_close_v2 // Line 331
-#define sqlite3_collation_needed chrome_sqlite3_collation_needed // Lines 5940-5944
-#define sqlite3_collation_needed16 chrome_sqlite3_collation_needed16 // Lines 5945-5949
-#define sqlite3_column_blob chrome_sqlite3_column_blob // Line 4963
-#define sqlite3_column_bytes chrome_sqlite3_column_bytes // Line 4970
-#define sqlite3_column_bytes16 chrome_sqlite3_column_bytes16 // Line 4971
-#define sqlite3_column_count chrome_sqlite3_column_count // Line 4503
-#define sqlite3_column_database_name chrome_sqlite3_column_database_name // Line 4577
-#define sqlite3_column_database_name16 chrome_sqlite3_column_database_name16 // Line 4578
-#define sqlite3_column_decltype chrome_sqlite3_column_decltype // Line 4614
-#define sqlite3_column_decltype16 chrome_sqlite3_column_decltype16 // Line 4615
-#define sqlite3_column_double chrome_sqlite3_column_double // Line 4964
-#define sqlite3_column_int chrome_sqlite3_column_int // Line 4965
-#define sqlite3_column_int64 chrome_sqlite3_column_int64 // Line 4966
-#define sqlite3_column_name chrome_sqlite3_column_name // Line 4532
-#define sqlite3_column_name16 chrome_sqlite3_column_name16 // Line 4533
-#define sqlite3_column_origin_name chrome_sqlite3_column_origin_name // Line 4581
-#define sqlite3_column_origin_name16 chrome_sqlite3_column_origin_name16 // Line 4582
-#define sqlite3_column_table_name chrome_sqlite3_column_table_name // Line 4579
-#define sqlite3_column_table_name16 chrome_sqlite3_column_table_name16 // Line 4580
-#define sqlite3_column_text chrome_sqlite3_column_text // Line 4967
-#define sqlite3_column_text16 chrome_sqlite3_column_text16 // Line 4968
-#define sqlite3_column_type chrome_sqlite3_column_type // Line 4972
-#define sqlite3_column_value chrome_sqlite3_column_value // Line 4969
-#define sqlite3_commit_hook chrome_sqlite3_commit_hook // Line 6252
+#define sqlite3_collation_needed chrome_sqlite3_collation_needed // Lines 5941-5945
+#define sqlite3_collation_needed16 chrome_sqlite3_collation_needed16 // Lines 5946-5950
+#define sqlite3_column_blob chrome_sqlite3_column_blob // Line 4964
+#define sqlite3_column_bytes chrome_sqlite3_column_bytes // Line 4971
+#define sqlite3_column_bytes16 chrome_sqlite3_column_bytes16 // Line 4972
+#define sqlite3_column_count chrome_sqlite3_column_count // Line 4504
+#define sqlite3_column_database_name chrome_sqlite3_column_database_name // Line 4578
+#define sqlite3_column_database_name16 chrome_sqlite3_column_database_name16 // Line 4579
+#define sqlite3_column_decltype chrome_sqlite3_column_decltype // Line 4615
+#define sqlite3_column_decltype16 chrome_sqlite3_column_decltype16 // Line 4616
+#define sqlite3_column_double chrome_sqlite3_column_double // Line 4965
+#define sqlite3_column_int chrome_sqlite3_column_int // Line 4966
+#define sqlite3_column_int64 chrome_sqlite3_column_int64 // Line 4967
+#define sqlite3_column_name chrome_sqlite3_column_name // Line 4533
+#define sqlite3_column_name16 chrome_sqlite3_column_name16 // Line 4534
+#define sqlite3_column_origin_name chrome_sqlite3_column_origin_name // Line 4582
+#define sqlite3_column_origin_name16 chrome_sqlite3_column_origin_name16 // Line 4583
+#define sqlite3_column_table_name chrome_sqlite3_column_table_name // Line 4580
+#define sqlite3_column_table_name16 chrome_sqlite3_column_table_name16 // Line 4581
+#define sqlite3_column_text chrome_sqlite3_column_text // Line 4968
+#define sqlite3_column_text16 chrome_sqlite3_column_text16 // Line 4969
+#define sqlite3_column_type chrome_sqlite3_column_type // Line 4973
+#define sqlite3_column_value chrome_sqlite3_column_value // Line 4970
+#define sqlite3_commit_hook chrome_sqlite3_commit_hook // Line 6304
#define sqlite3_compileoption_get chrome_sqlite3_compileoption_get // Line 191
#define sqlite3_compileoption_used chrome_sqlite3_compileoption_used // Line 190
-#define sqlite3_complete chrome_sqlite3_complete // Line 2596
-#define sqlite3_complete16 chrome_sqlite3_complete16 // Line 2597
-#define sqlite3_config chrome_sqlite3_config // Line 1581
-#define sqlite3_context_db_handle chrome_sqlite3_context_db_handle // Line 5544
-#define sqlite3_create_collation chrome_sqlite3_create_collation // Lines 5890-5896
-#define sqlite3_create_collation16 chrome_sqlite3_create_collation16 // Lines 5905-5911
-#define sqlite3_create_collation_v2 chrome_sqlite3_create_collation_v2 // Lines 5897-5904
-#define sqlite3_create_filename chrome_sqlite3_create_filename // Lines 3705-3711
-#define sqlite3_create_function chrome_sqlite3_create_function // Lines 5154-5163
-#define sqlite3_create_function16 chrome_sqlite3_create_function16 // Lines 5164-5173
-#define sqlite3_create_function_v2 chrome_sqlite3_create_function_v2 // Lines 5174-5184
-#define sqlite3_create_module chrome_sqlite3_create_module // Lines 6947-6952
-#define sqlite3_create_module_v2 chrome_sqlite3_create_module_v2 // Lines 6953-6959
-#define sqlite3_create_window_function chrome_sqlite3_create_window_function // Lines 5185-5196
-#define sqlite3_data_count chrome_sqlite3_data_count // Line 4720
-#define sqlite3_data_directory chrome_sqlite3_data_directory // Line 6073
-#define sqlite3_database_file_object chrome_sqlite3_database_file_object // Line 3658
-#define sqlite3_db_cacheflush chrome_sqlite3_db_cacheflush // Line 9376
-#define sqlite3_db_config chrome_sqlite3_db_config // Line 1600
-#define sqlite3_db_filename chrome_sqlite3_db_filename // Line 6177
-#define sqlite3_db_handle chrome_sqlite3_db_handle // Line 6145
-#define sqlite3_db_mutex chrome_sqlite3_db_mutex // Line 7612
-#define sqlite3_db_readonly chrome_sqlite3_db_readonly // Line 6187
-#define sqlite3_db_release_memory chrome_sqlite3_db_release_memory // Line 6379
-#define sqlite3_db_status chrome_sqlite3_db_status // Line 8036
-#define sqlite3_declare_vtab chrome_sqlite3_declare_vtab // Line 7033
-#define sqlite3_deserialize chrome_sqlite3_deserialize // Lines 9770-9777
-#define sqlite3_drop_modules chrome_sqlite3_drop_modules // Lines 6973-6976
-#define sqlite3_enable_load_extension chrome_sqlite3_enable_load_extension // Line 6617
-#define sqlite3_enable_shared_cache chrome_sqlite3_enable_shared_cache // Line 6349
-#define sqlite3_errcode chrome_sqlite3_errcode // Line 3766
-#define sqlite3_errmsg chrome_sqlite3_errmsg // Line 3768
-#define sqlite3_errmsg16 chrome_sqlite3_errmsg16 // Line 3769
-#define sqlite3_errstr chrome_sqlite3_errstr // Line 3770
+#define sqlite3_complete chrome_sqlite3_complete // Line 2597
+#define sqlite3_complete16 chrome_sqlite3_complete16 // Line 2598
+#define sqlite3_config chrome_sqlite3_config // Line 1582
+#define sqlite3_context_db_handle chrome_sqlite3_context_db_handle // Line 5545
+#define sqlite3_create_collation chrome_sqlite3_create_collation // Lines 5891-5897
+#define sqlite3_create_collation16 chrome_sqlite3_create_collation16 // Lines 5906-5912
+#define sqlite3_create_collation_v2 chrome_sqlite3_create_collation_v2 // Lines 5898-5905
+#define sqlite3_create_filename chrome_sqlite3_create_filename // Lines 3706-3712
+#define sqlite3_create_function chrome_sqlite3_create_function // Lines 5155-5164
+#define sqlite3_create_function16 chrome_sqlite3_create_function16 // Lines 5165-5174
+#define sqlite3_create_function_v2 chrome_sqlite3_create_function_v2 // Lines 5175-5185
+#define sqlite3_create_module chrome_sqlite3_create_module // Lines 6999-7004
+#define sqlite3_create_module_v2 chrome_sqlite3_create_module_v2 // Lines 7005-7011
+#define sqlite3_create_window_function chrome_sqlite3_create_window_function // Lines 5186-5197
+#define sqlite3_data_count chrome_sqlite3_data_count // Line 4721
+#define sqlite3_data_directory chrome_sqlite3_data_directory // Line 6074
+#define sqlite3_database_file_object chrome_sqlite3_database_file_object // Line 3659
+#define sqlite3_db_cacheflush chrome_sqlite3_db_cacheflush // Line 9437
+#define sqlite3_db_config chrome_sqlite3_db_config // Line 1601
+#define sqlite3_db_filename chrome_sqlite3_db_filename // Line 6178
+#define sqlite3_db_handle chrome_sqlite3_db_handle // Line 6146
+#define sqlite3_db_mutex chrome_sqlite3_db_mutex // Line 7664
+#define sqlite3_db_readonly chrome_sqlite3_db_readonly // Line 6188
+#define sqlite3_db_release_memory chrome_sqlite3_db_release_memory // Line 6431
+#define sqlite3_db_status chrome_sqlite3_db_status // Line 8089
+#define sqlite3_declare_vtab chrome_sqlite3_declare_vtab // Line 7085
+#define sqlite3_deserialize chrome_sqlite3_deserialize // Lines 9833-9840
+#define sqlite3_drop_modules chrome_sqlite3_drop_modules // Lines 7025-7028
+#define sqlite3_enable_load_extension chrome_sqlite3_enable_load_extension // Line 6669
+#define sqlite3_enable_shared_cache chrome_sqlite3_enable_shared_cache // Line 6401
+#define sqlite3_errcode chrome_sqlite3_errcode // Line 3767
+#define sqlite3_errmsg chrome_sqlite3_errmsg // Line 3769
+#define sqlite3_errmsg16 chrome_sqlite3_errmsg16 // Line 3770
+#define sqlite3_errstr chrome_sqlite3_errstr // Line 3771
#define sqlite3_exec chrome_sqlite3_exec // Lines 402-408
-#define sqlite3_expanded_sql chrome_sqlite3_expanded_sql // Line 4132
-#define sqlite3_expired chrome_sqlite3_expired // Line 5293
-#define sqlite3_extended_errcode chrome_sqlite3_extended_errcode // Line 3767
-#define sqlite3_extended_result_codes chrome_sqlite3_extended_result_codes // Line 2357
-#define sqlite3_file_control chrome_sqlite3_file_control // Line 7655
-#define sqlite3_filename_database chrome_sqlite3_filename_database // Line 3637
-#define sqlite3_filename_journal chrome_sqlite3_filename_journal // Line 3638
-#define sqlite3_filename_wal chrome_sqlite3_filename_wal // Line 3639
-#define sqlite3_finalize chrome_sqlite3_finalize // Line 5000
-#define sqlite3_free chrome_sqlite3_free // Line 2890
-#define sqlite3_free_filename chrome_sqlite3_free_filename // Line 3712
-#define sqlite3_free_table chrome_sqlite3_free_table // Line 2764
-#define sqlite3_get_autocommit chrome_sqlite3_get_autocommit // Line 6132
-#define sqlite3_get_auxdata chrome_sqlite3_get_auxdata // Line 5603
-#define sqlite3_get_table chrome_sqlite3_get_table // Lines 2756-2763
-#define sqlite3_global_recover chrome_sqlite3_global_recover // Line 5295
-#define sqlite3_hard_heap_limit64 chrome_sqlite3_hard_heap_limit64 // Line 6446
-#define sqlite3_initialize chrome_sqlite3_initialize // Line 1545
-#define sqlite3_interrupt chrome_sqlite3_interrupt // Line 2561
-#define sqlite3_keyword_check chrome_sqlite3_keyword_check // Line 7766
-#define sqlite3_keyword_count chrome_sqlite3_keyword_count // Line 7764
-#define sqlite3_keyword_name chrome_sqlite3_keyword_name // Line 7765
-#define sqlite3_last_insert_rowid chrome_sqlite3_last_insert_rowid // Line 2419
+#define sqlite3_expanded_sql chrome_sqlite3_expanded_sql // Line 4133
+#define sqlite3_expired chrome_sqlite3_expired // Line 5294
+#define sqlite3_extended_errcode chrome_sqlite3_extended_errcode // Line 3768
+#define sqlite3_extended_result_codes chrome_sqlite3_extended_result_codes // Line 2358
+#define sqlite3_file_control chrome_sqlite3_file_control // Line 7707
+#define sqlite3_filename_database chrome_sqlite3_filename_database // Line 3638
+#define sqlite3_filename_journal chrome_sqlite3_filename_journal // Line 3639
+#define sqlite3_filename_wal chrome_sqlite3_filename_wal // Line 3640
+#define sqlite3_finalize chrome_sqlite3_finalize // Line 5001
+#define sqlite3_free chrome_sqlite3_free // Line 2891
+#define sqlite3_free_filename chrome_sqlite3_free_filename // Line 3713
+#define sqlite3_free_table chrome_sqlite3_free_table // Line 2765
+#define sqlite3_get_autocommit chrome_sqlite3_get_autocommit // Line 6133
+#define sqlite3_get_auxdata chrome_sqlite3_get_auxdata // Line 5604
+#define sqlite3_get_table chrome_sqlite3_get_table // Lines 2757-2764
+#define sqlite3_global_recover chrome_sqlite3_global_recover // Line 5296
+#define sqlite3_hard_heap_limit64 chrome_sqlite3_hard_heap_limit64 // Line 6498
+#define sqlite3_initialize chrome_sqlite3_initialize // Line 1546
+#define sqlite3_interrupt chrome_sqlite3_interrupt // Line 2562
+#define sqlite3_keyword_check chrome_sqlite3_keyword_check // Line 7819
+#define sqlite3_keyword_count chrome_sqlite3_keyword_count // Line 7817
+#define sqlite3_keyword_name chrome_sqlite3_keyword_name // Line 7818
+#define sqlite3_last_insert_rowid chrome_sqlite3_last_insert_rowid // Line 2420
#define sqlite3_libversion chrome_sqlite3_libversion // Line 163
#define sqlite3_libversion_number chrome_sqlite3_libversion_number // Line 165
-#define sqlite3_limit chrome_sqlite3_limit // Line 3838
-#define sqlite3_load_extension chrome_sqlite3_load_extension // Lines 6585-6590
-#define sqlite3_log chrome_sqlite3_log // Line 8884
-#define sqlite3_malloc chrome_sqlite3_malloc // Line 2886
-#define sqlite3_malloc64 chrome_sqlite3_malloc64 // Line 2887
-#define sqlite3_memory_alarm chrome_sqlite3_memory_alarm // Lines 5297-5298
-#define sqlite3_memory_highwater chrome_sqlite3_memory_highwater // Line 2917
-#define sqlite3_memory_used chrome_sqlite3_memory_used // Line 2916
-#define sqlite3_mprintf chrome_sqlite3_mprintf // Line 2806
-#define sqlite3_msize chrome_sqlite3_msize // Line 2891
-#define sqlite3_mutex_alloc chrome_sqlite3_mutex_alloc // Line 7453
-#define sqlite3_mutex_enter chrome_sqlite3_mutex_enter // Line 7455
-#define sqlite3_mutex_free chrome_sqlite3_mutex_free // Line 7454
-#define sqlite3_mutex_held chrome_sqlite3_mutex_held // Line 7567
-#define sqlite3_mutex_leave chrome_sqlite3_mutex_leave // Line 7457
-#define sqlite3_mutex_notheld chrome_sqlite3_mutex_notheld // Line 7568
-#define sqlite3_mutex_try chrome_sqlite3_mutex_try // Line 7456
-#define sqlite3_next_stmt chrome_sqlite3_next_stmt // Line 6203
-#define sqlite3_normalized_sql chrome_sqlite3_normalized_sql // Line 4133
-#define sqlite3_open chrome_sqlite3_open // Lines 3524-3527
-#define sqlite3_open16 chrome_sqlite3_open16 // Lines 3528-3531
-#define sqlite3_open_v2 chrome_sqlite3_open_v2 // Lines 3532-3537
-#define sqlite3_os_end chrome_sqlite3_os_end // Line 1548
-#define sqlite3_os_init chrome_sqlite3_os_init // Line 1547
-#define sqlite3_overload_function chrome_sqlite3_overload_function // Line 7052
-#define sqlite3_prepare chrome_sqlite3_prepare // Lines 4048-4054
-#define sqlite3_prepare16 chrome_sqlite3_prepare16 // Lines 4070-4076
-#define sqlite3_prepare16_v2 chrome_sqlite3_prepare16_v2 // Lines 4077-4083
-#define sqlite3_prepare16_v3 chrome_sqlite3_prepare16_v3 // Lines 4084-4091
-#define sqlite3_prepare_v2 chrome_sqlite3_prepare_v2 // Lines 4055-4061
-#define sqlite3_prepare_v3 chrome_sqlite3_prepare_v3 // Lines 4062-4069
-#define sqlite3_preupdate_count chrome_sqlite3_preupdate_count // Line 9475
-#define sqlite3_preupdate_depth chrome_sqlite3_preupdate_depth // Line 9476
-#define sqlite3_preupdate_hook chrome_sqlite3_preupdate_hook // Lines 9461-9473
-#define sqlite3_preupdate_new chrome_sqlite3_preupdate_new // Line 9477
-#define sqlite3_preupdate_old chrome_sqlite3_preupdate_old // Line 9474
-#define sqlite3_profile chrome_sqlite3_profile // Lines 3141-3142
-#define sqlite3_progress_handler chrome_sqlite3_progress_handler // Line 3269
-#define sqlite3_randomness chrome_sqlite3_randomness // Line 2940
-#define sqlite3_realloc chrome_sqlite3_realloc // Line 2888
-#define sqlite3_realloc64 chrome_sqlite3_realloc64 // Line 2889
-#define sqlite3_release_memory chrome_sqlite3_release_memory // Line 6365
-#define sqlite3_reset chrome_sqlite3_reset // Line 5027
-#define sqlite3_reset_auto_extension chrome_sqlite3_reset_auto_extension // Line 6675
-#define sqlite3_result_blob chrome_sqlite3_result_blob // Line 5771
-#define sqlite3_result_blob64 chrome_sqlite3_result_blob64 // Lines 5772-5773
-#define sqlite3_result_double chrome_sqlite3_result_double // Line 5774
-#define sqlite3_result_error chrome_sqlite3_result_error // Line 5775
-#define sqlite3_result_error16 chrome_sqlite3_result_error16 // Line 5776
-#define sqlite3_result_error_code chrome_sqlite3_result_error_code // Line 5779
-#define sqlite3_result_error_nomem chrome_sqlite3_result_error_nomem // Line 5778
-#define sqlite3_result_error_toobig chrome_sqlite3_result_error_toobig // Line 5777
-#define sqlite3_result_int chrome_sqlite3_result_int // Line 5780
-#define sqlite3_result_int64 chrome_sqlite3_result_int64 // Line 5781
-#define sqlite3_result_null chrome_sqlite3_result_null // Line 5782
-#define sqlite3_result_pointer chrome_sqlite3_result_pointer // Line 5790
-#define sqlite3_result_subtype chrome_sqlite3_result_subtype // Line 5807
-#define sqlite3_result_text chrome_sqlite3_result_text // Line 5783
-#define sqlite3_result_text16 chrome_sqlite3_result_text16 // Line 5786
-#define sqlite3_result_text16be chrome_sqlite3_result_text16be // Line 5788
-#define sqlite3_result_text16le chrome_sqlite3_result_text16le // Line 5787
-#define sqlite3_result_text64 chrome_sqlite3_result_text64 // Lines 5784-5785
-#define sqlite3_result_value chrome_sqlite3_result_value // Line 5789
-#define sqlite3_result_zeroblob chrome_sqlite3_result_zeroblob // Line 5791
-#define sqlite3_result_zeroblob64 chrome_sqlite3_result_zeroblob64 // Line 5792
-#define sqlite3_rollback_hook chrome_sqlite3_rollback_hook // Line 6253
-#define sqlite3_rtree_geometry_callback chrome_sqlite3_rtree_geometry_callback // Lines 9857-9862
-#define sqlite3_rtree_query_callback chrome_sqlite3_rtree_query_callback // Lines 9883-9889
-#define sqlite3_serialize chrome_sqlite3_serialize // Lines 9718-9723
-#define sqlite3_set_authorizer chrome_sqlite3_set_authorizer // Lines 3031-3035
-#define sqlite3_set_auxdata chrome_sqlite3_set_auxdata // Line 5604
-#define sqlite3_set_last_insert_rowid chrome_sqlite3_set_last_insert_rowid // Line 2429
-#define sqlite3_shutdown chrome_sqlite3_shutdown // Line 1546
-#define sqlite3_sleep chrome_sqlite3_sleep // Line 5978
-#define sqlite3_snapshot_cmp chrome_sqlite3_snapshot_cmp // Lines 9652-9655
-#define sqlite3_snapshot_free chrome_sqlite3_snapshot_free // Line 9625
-#define sqlite3_snapshot_get chrome_sqlite3_snapshot_get // Lines 9559-9563
-#define sqlite3_snapshot_open chrome_sqlite3_snapshot_open // Lines 9608-9612
-#define sqlite3_snapshot_recover chrome_sqlite3_snapshot_recover // Line 9680
-#define sqlite3_snprintf chrome_sqlite3_snprintf // Line 2808
-#define sqlite3_soft_heap_limit chrome_sqlite3_soft_heap_limit // Line 6457
-#define sqlite3_soft_heap_limit64 chrome_sqlite3_soft_heap_limit64 // Line 6445
+#define sqlite3_limit chrome_sqlite3_limit // Line 3839
+#define sqlite3_load_extension chrome_sqlite3_load_extension // Lines 6637-6642
+#define sqlite3_log chrome_sqlite3_log // Line 8937
+#define sqlite3_malloc chrome_sqlite3_malloc // Line 2887
+#define sqlite3_malloc64 chrome_sqlite3_malloc64 // Line 2888
+#define sqlite3_memory_alarm chrome_sqlite3_memory_alarm // Lines 5298-5299
+#define sqlite3_memory_highwater chrome_sqlite3_memory_highwater // Line 2918
+#define sqlite3_memory_used chrome_sqlite3_memory_used // Line 2917
+#define sqlite3_mprintf chrome_sqlite3_mprintf // Line 2807
+#define sqlite3_msize chrome_sqlite3_msize // Line 2892
+#define sqlite3_mutex_alloc chrome_sqlite3_mutex_alloc // Line 7505
+#define sqlite3_mutex_enter chrome_sqlite3_mutex_enter // Line 7507
+#define sqlite3_mutex_free chrome_sqlite3_mutex_free // Line 7506
+#define sqlite3_mutex_held chrome_sqlite3_mutex_held // Line 7619
+#define sqlite3_mutex_leave chrome_sqlite3_mutex_leave // Line 7509
+#define sqlite3_mutex_notheld chrome_sqlite3_mutex_notheld // Line 7620
+#define sqlite3_mutex_try chrome_sqlite3_mutex_try // Line 7508
+#define sqlite3_next_stmt chrome_sqlite3_next_stmt // Line 6255
+#define sqlite3_normalized_sql chrome_sqlite3_normalized_sql // Line 4134
+#define sqlite3_open chrome_sqlite3_open // Lines 3525-3528
+#define sqlite3_open16 chrome_sqlite3_open16 // Lines 3529-3532
+#define sqlite3_open_v2 chrome_sqlite3_open_v2 // Lines 3533-3538
+#define sqlite3_os_end chrome_sqlite3_os_end // Line 1549
+#define sqlite3_os_init chrome_sqlite3_os_init // Line 1548
+#define sqlite3_overload_function chrome_sqlite3_overload_function // Line 7104
+#define sqlite3_prepare chrome_sqlite3_prepare // Lines 4049-4055
+#define sqlite3_prepare16 chrome_sqlite3_prepare16 // Lines 4071-4077
+#define sqlite3_prepare16_v2 chrome_sqlite3_prepare16_v2 // Lines 4078-4084
+#define sqlite3_prepare16_v3 chrome_sqlite3_prepare16_v3 // Lines 4085-4092
+#define sqlite3_prepare_v2 chrome_sqlite3_prepare_v2 // Lines 4056-4062
+#define sqlite3_prepare_v3 chrome_sqlite3_prepare_v3 // Lines 4063-4070
+#define sqlite3_preupdate_count chrome_sqlite3_preupdate_count // Line 9537
+#define sqlite3_preupdate_depth chrome_sqlite3_preupdate_depth // Line 9538
+#define sqlite3_preupdate_hook chrome_sqlite3_preupdate_hook // Lines 9523-9535
+#define sqlite3_preupdate_new chrome_sqlite3_preupdate_new // Line 9539
+#define sqlite3_preupdate_old chrome_sqlite3_preupdate_old // Line 9536
+#define sqlite3_profile chrome_sqlite3_profile // Lines 3142-3143
+#define sqlite3_progress_handler chrome_sqlite3_progress_handler // Line 3270
+#define sqlite3_randomness chrome_sqlite3_randomness // Line 2941
+#define sqlite3_realloc chrome_sqlite3_realloc // Line 2889
+#define sqlite3_realloc64 chrome_sqlite3_realloc64 // Line 2890
+#define sqlite3_release_memory chrome_sqlite3_release_memory // Line 6417
+#define sqlite3_reset chrome_sqlite3_reset // Line 5028
+#define sqlite3_reset_auto_extension chrome_sqlite3_reset_auto_extension // Line 6727
+#define sqlite3_result_blob chrome_sqlite3_result_blob // Line 5772
+#define sqlite3_result_blob64 chrome_sqlite3_result_blob64 // Lines 5773-5774
+#define sqlite3_result_double chrome_sqlite3_result_double // Line 5775
+#define sqlite3_result_error chrome_sqlite3_result_error // Line 5776
+#define sqlite3_result_error16 chrome_sqlite3_result_error16 // Line 5777
+#define sqlite3_result_error_code chrome_sqlite3_result_error_code // Line 5780
+#define sqlite3_result_error_nomem chrome_sqlite3_result_error_nomem // Line 5779
+#define sqlite3_result_error_toobig chrome_sqlite3_result_error_toobig // Line 5778
+#define sqlite3_result_int chrome_sqlite3_result_int // Line 5781
+#define sqlite3_result_int64 chrome_sqlite3_result_int64 // Line 5782
+#define sqlite3_result_null chrome_sqlite3_result_null // Line 5783
+#define sqlite3_result_pointer chrome_sqlite3_result_pointer // Line 5791
+#define sqlite3_result_subtype chrome_sqlite3_result_subtype // Line 5808
+#define sqlite3_result_text chrome_sqlite3_result_text // Line 5784
+#define sqlite3_result_text16 chrome_sqlite3_result_text16 // Line 5787
+#define sqlite3_result_text16be chrome_sqlite3_result_text16be // Line 5789
+#define sqlite3_result_text16le chrome_sqlite3_result_text16le // Line 5788
+#define sqlite3_result_text64 chrome_sqlite3_result_text64 // Lines 5785-5786
+#define sqlite3_result_value chrome_sqlite3_result_value // Line 5790
+#define sqlite3_result_zeroblob chrome_sqlite3_result_zeroblob // Line 5792
+#define sqlite3_result_zeroblob64 chrome_sqlite3_result_zeroblob64 // Line 5793
+#define sqlite3_rollback_hook chrome_sqlite3_rollback_hook // Line 6305
+#define sqlite3_rtree_geometry_callback chrome_sqlite3_rtree_geometry_callback // Lines 9920-9925
+#define sqlite3_rtree_query_callback chrome_sqlite3_rtree_query_callback // Lines 9946-9952
+#define sqlite3_serialize chrome_sqlite3_serialize // Lines 9781-9786
+#define sqlite3_set_authorizer chrome_sqlite3_set_authorizer // Lines 3032-3036
+#define sqlite3_set_auxdata chrome_sqlite3_set_auxdata // Line 5605
+#define sqlite3_set_last_insert_rowid chrome_sqlite3_set_last_insert_rowid // Line 2430
+#define sqlite3_shutdown chrome_sqlite3_shutdown // Line 1547
+#define sqlite3_sleep chrome_sqlite3_sleep // Line 5979
+#define sqlite3_snapshot_cmp chrome_sqlite3_snapshot_cmp // Lines 9715-9718
+#define sqlite3_snapshot_free chrome_sqlite3_snapshot_free // Line 9688
+#define sqlite3_snapshot_get chrome_sqlite3_snapshot_get // Lines 9622-9626
+#define sqlite3_snapshot_open chrome_sqlite3_snapshot_open // Lines 9671-9675
+#define sqlite3_snapshot_recover chrome_sqlite3_snapshot_recover // Line 9743
+#define sqlite3_snprintf chrome_sqlite3_snprintf // Line 2809
+#define sqlite3_soft_heap_limit chrome_sqlite3_soft_heap_limit // Line 6509
+#define sqlite3_soft_heap_limit64 chrome_sqlite3_soft_heap_limit64 // Line 6497
#define sqlite3_sourceid chrome_sqlite3_sourceid // Line 164
-#define sqlite3_sql chrome_sqlite3_sql // Line 4131
-#define sqlite3_status chrome_sqlite3_status // Line 7926
-#define sqlite3_status64 chrome_sqlite3_status64 // Lines 7927-7932
-#define sqlite3_step chrome_sqlite3_step // Line 4699
-#define sqlite3_stmt_busy chrome_sqlite3_stmt_busy // Line 4202
-#define sqlite3_stmt_isexplain chrome_sqlite3_stmt_isexplain // Line 4181
-#define sqlite3_stmt_readonly chrome_sqlite3_stmt_readonly // Line 4169
-#define sqlite3_stmt_scanstatus chrome_sqlite3_stmt_scanstatus // Lines 9328-9333
-#define sqlite3_stmt_scanstatus_reset chrome_sqlite3_stmt_scanstatus_reset // Line 9344
-#define sqlite3_stmt_status chrome_sqlite3_stmt_status // Line 8189
-#define sqlite3_str_append chrome_sqlite3_str_append // Line 7862
-#define sqlite3_str_appendall chrome_sqlite3_str_appendall // Line 7863
-#define sqlite3_str_appendchar chrome_sqlite3_str_appendchar // Line 7864
-#define sqlite3_str_appendf chrome_sqlite3_str_appendf // Line 7860
-#define sqlite3_str_errcode chrome_sqlite3_str_errcode // Line 7896
-#define sqlite3_str_finish chrome_sqlite3_str_finish // Line 7826
-#define sqlite3_str_length chrome_sqlite3_str_length // Line 7897
-#define sqlite3_str_new chrome_sqlite3_str_new // Line 7811
-#define sqlite3_str_reset chrome_sqlite3_str_reset // Line 7865
-#define sqlite3_str_value chrome_sqlite3_str_value // Line 7898
-#define sqlite3_str_vappendf chrome_sqlite3_str_vappendf // Line 7861
-#define sqlite3_strglob chrome_sqlite3_strglob // Line 8838
-#define sqlite3_stricmp chrome_sqlite3_stricmp // Line 8820
-#define sqlite3_strlike chrome_sqlite3_strlike // Line 8861
-#define sqlite3_strnicmp chrome_sqlite3_strnicmp // Line 8821
-#define sqlite3_system_errno chrome_sqlite3_system_errno // Line 9490
-#define sqlite3_table_column_metadata chrome_sqlite3_table_column_metadata // Lines 6529-6539
-#define sqlite3_temp_directory chrome_sqlite3_temp_directory // Line 6036
-#define sqlite3_test_control chrome_sqlite3_test_control // Line 7674
-#define sqlite3_thread_cleanup chrome_sqlite3_thread_cleanup // Line 5296
+#define sqlite3_sql chrome_sqlite3_sql // Line 4132
+#define sqlite3_status chrome_sqlite3_status // Line 7979
+#define sqlite3_status64 chrome_sqlite3_status64 // Lines 7980-7985
+#define sqlite3_step chrome_sqlite3_step // Line 4700
+#define sqlite3_stmt_busy chrome_sqlite3_stmt_busy // Line 4203
+#define sqlite3_stmt_isexplain chrome_sqlite3_stmt_isexplain // Line 4182
+#define sqlite3_stmt_readonly chrome_sqlite3_stmt_readonly // Line 4170
+#define sqlite3_stmt_scanstatus chrome_sqlite3_stmt_scanstatus // Lines 9388-9393
+#define sqlite3_stmt_scanstatus_reset chrome_sqlite3_stmt_scanstatus_reset // Line 9404
+#define sqlite3_stmt_status chrome_sqlite3_stmt_status // Line 8242
+#define sqlite3_str_append chrome_sqlite3_str_append // Line 7915
+#define sqlite3_str_appendall chrome_sqlite3_str_appendall // Line 7916
+#define sqlite3_str_appendchar chrome_sqlite3_str_appendchar // Line 7917
+#define sqlite3_str_appendf chrome_sqlite3_str_appendf // Line 7913
+#define sqlite3_str_errcode chrome_sqlite3_str_errcode // Line 7949
+#define sqlite3_str_finish chrome_sqlite3_str_finish // Line 7879
+#define sqlite3_str_length chrome_sqlite3_str_length // Line 7950
+#define sqlite3_str_new chrome_sqlite3_str_new // Line 7864
+#define sqlite3_str_reset chrome_sqlite3_str_reset // Line 7918
+#define sqlite3_str_value chrome_sqlite3_str_value // Line 7951
+#define sqlite3_str_vappendf chrome_sqlite3_str_vappendf // Line 7914
+#define sqlite3_strglob chrome_sqlite3_strglob // Line 8891
+#define sqlite3_stricmp chrome_sqlite3_stricmp // Line 8873
+#define sqlite3_strlike chrome_sqlite3_strlike // Line 8914
+#define sqlite3_strnicmp chrome_sqlite3_strnicmp // Line 8874
+#define sqlite3_system_errno chrome_sqlite3_system_errno // Line 9553
+#define sqlite3_table_column_metadata chrome_sqlite3_table_column_metadata // Lines 6581-6591
+#define sqlite3_temp_directory chrome_sqlite3_temp_directory // Line 6037
+#define sqlite3_test_control chrome_sqlite3_test_control // Line 7726
+#define sqlite3_thread_cleanup chrome_sqlite3_thread_cleanup // Line 5297
#define sqlite3_threadsafe chrome_sqlite3_threadsafe // Line 233
-#define sqlite3_total_changes chrome_sqlite3_total_changes // Line 2524
-#define sqlite3_trace chrome_sqlite3_trace // Lines 3139-3140
-#define sqlite3_trace_v2 chrome_sqlite3_trace_v2 // Lines 3230-3235
-#define sqlite3_transfer_bindings chrome_sqlite3_transfer_bindings // Line 5294
-#define sqlite3_unlock_notify chrome_sqlite3_unlock_notify // Lines 8805-8809
-#define sqlite3_update_hook chrome_sqlite3_update_hook // Lines 6304-6308
-#define sqlite3_uri_boolean chrome_sqlite3_uri_boolean // Line 3606
-#define sqlite3_uri_int64 chrome_sqlite3_uri_int64 // Line 3607
-#define sqlite3_uri_key chrome_sqlite3_uri_key // Line 3608
-#define sqlite3_uri_parameter chrome_sqlite3_uri_parameter // Line 3605
-#define sqlite3_user_data chrome_sqlite3_user_data // Line 5532
-#define sqlite3_value_blob chrome_sqlite3_value_blob // Line 5429
-#define sqlite3_value_bytes chrome_sqlite3_value_bytes // Line 5438
-#define sqlite3_value_bytes16 chrome_sqlite3_value_bytes16 // Line 5439
-#define sqlite3_value_double chrome_sqlite3_value_double // Line 5430
-#define sqlite3_value_dup chrome_sqlite3_value_dup // Line 5471
-#define sqlite3_value_free chrome_sqlite3_value_free // Line 5472
-#define sqlite3_value_frombind chrome_sqlite3_value_frombind // Line 5443
-#define sqlite3_value_int chrome_sqlite3_value_int // Line 5431
-#define sqlite3_value_int64 chrome_sqlite3_value_int64 // Line 5432
-#define sqlite3_value_nochange chrome_sqlite3_value_nochange // Line 5442
-#define sqlite3_value_numeric_type chrome_sqlite3_value_numeric_type // Line 5441
-#define sqlite3_value_pointer chrome_sqlite3_value_pointer // Line 5433
-#define sqlite3_value_subtype chrome_sqlite3_value_subtype // Line 5455
-#define sqlite3_value_text chrome_sqlite3_value_text // Line 5434
-#define sqlite3_value_text16 chrome_sqlite3_value_text16 // Line 5435
-#define sqlite3_value_text16be chrome_sqlite3_value_text16be // Line 5437
-#define sqlite3_value_text16le chrome_sqlite3_value_text16le // Line 5436
-#define sqlite3_value_type chrome_sqlite3_value_type // Line 5440
+#define sqlite3_total_changes chrome_sqlite3_total_changes // Line 2525
+#define sqlite3_trace chrome_sqlite3_trace // Lines 3140-3141
+#define sqlite3_trace_v2 chrome_sqlite3_trace_v2 // Lines 3231-3236
+#define sqlite3_transfer_bindings chrome_sqlite3_transfer_bindings // Line 5295
+#define sqlite3_txn_state chrome_sqlite3_txn_state // Line 6206
+#define sqlite3_unlock_notify chrome_sqlite3_unlock_notify // Lines 8858-8862
+#define sqlite3_update_hook chrome_sqlite3_update_hook // Lines 6356-6360
+#define sqlite3_uri_boolean chrome_sqlite3_uri_boolean // Line 3607
+#define sqlite3_uri_int64 chrome_sqlite3_uri_int64 // Line 3608
+#define sqlite3_uri_key chrome_sqlite3_uri_key // Line 3609
+#define sqlite3_uri_parameter chrome_sqlite3_uri_parameter // Line 3606
+#define sqlite3_user_data chrome_sqlite3_user_data // Line 5533
+#define sqlite3_value_blob chrome_sqlite3_value_blob // Line 5430
+#define sqlite3_value_bytes chrome_sqlite3_value_bytes // Line 5439
+#define sqlite3_value_bytes16 chrome_sqlite3_value_bytes16 // Line 5440
+#define sqlite3_value_double chrome_sqlite3_value_double // Line 5431
+#define sqlite3_value_dup chrome_sqlite3_value_dup // Line 5472
+#define sqlite3_value_free chrome_sqlite3_value_free // Line 5473
+#define sqlite3_value_frombind chrome_sqlite3_value_frombind // Line 5444
+#define sqlite3_value_int chrome_sqlite3_value_int // Line 5432
+#define sqlite3_value_int64 chrome_sqlite3_value_int64 // Line 5433
+#define sqlite3_value_nochange chrome_sqlite3_value_nochange // Line 5443
+#define sqlite3_value_numeric_type chrome_sqlite3_value_numeric_type // Line 5442
+#define sqlite3_value_pointer chrome_sqlite3_value_pointer // Line 5434
+#define sqlite3_value_subtype chrome_sqlite3_value_subtype // Line 5456
+#define sqlite3_value_text chrome_sqlite3_value_text // Line 5435
+#define sqlite3_value_text16 chrome_sqlite3_value_text16 // Line 5436
+#define sqlite3_value_text16be chrome_sqlite3_value_text16be // Line 5438
+#define sqlite3_value_text16le chrome_sqlite3_value_text16le // Line 5437
+#define sqlite3_value_type chrome_sqlite3_value_type // Line 5441
#define sqlite3_version chrome_sqlite3_version // Line 162
-#define sqlite3_vfs_find chrome_sqlite3_vfs_find // Line 7335
-#define sqlite3_vfs_register chrome_sqlite3_vfs_register // Line 7336
-#define sqlite3_vfs_unregister chrome_sqlite3_vfs_unregister // Line 7337
-#define sqlite3_vmprintf chrome_sqlite3_vmprintf // Line 2807
-#define sqlite3_vsnprintf chrome_sqlite3_vsnprintf // Line 2809
-#define sqlite3_vtab_collation chrome_sqlite3_vtab_collation // Line 9223
-#define sqlite3_vtab_config chrome_sqlite3_vtab_config // Line 9111
-#define sqlite3_vtab_nochange chrome_sqlite3_vtab_nochange // Line 9208
-#define sqlite3_vtab_on_conflict chrome_sqlite3_vtab_on_conflict // Line 9189
-#define sqlite3_wal_autocheckpoint chrome_sqlite3_wal_autocheckpoint // Line 8955
-#define sqlite3_wal_checkpoint chrome_sqlite3_wal_checkpoint // Line 8977
-#define sqlite3_wal_checkpoint_v2 chrome_sqlite3_wal_checkpoint_v2 // Lines 9071-9077
-#define sqlite3_wal_hook chrome_sqlite3_wal_hook // Lines 8920-8924
-#define sqlite3_win32_set_directory chrome_sqlite3_win32_set_directory // Lines 6094-6097
-#define sqlite3_win32_set_directory16 chrome_sqlite3_win32_set_directory16 // Line 6099
-#define sqlite3_win32_set_directory8 chrome_sqlite3_win32_set_directory8 // Line 6098
-#define sqlite3changegroup_add chrome_sqlite3changegroup_add // Line 10870
-#define sqlite3changegroup_add_strm chrome_sqlite3changegroup_add_strm // Lines 11532-11535
-#define sqlite3changegroup_delete chrome_sqlite3changegroup_delete // Line 10907
-#define sqlite3changegroup_new chrome_sqlite3changegroup_new // Line 10792
-#define sqlite3changegroup_output chrome_sqlite3changegroup_output // Lines 10897-10901
-#define sqlite3changegroup_output_strm chrome_sqlite3changegroup_output_strm // Lines 11536-11539
-#define sqlite3changeset_apply chrome_sqlite3changeset_apply // Lines 11067-11081
-#define sqlite3changeset_apply_strm chrome_sqlite3changeset_apply_strm // Lines 11465-11479
-#define sqlite3changeset_apply_v2 chrome_sqlite3changeset_apply_v2 // Lines 11082-11098
-#define sqlite3changeset_apply_v2_strm chrome_sqlite3changeset_apply_v2_strm // Lines 11480-11496
-#define sqlite3changeset_concat chrome_sqlite3changeset_concat // Lines 10738-10745
-#define sqlite3changeset_concat_strm chrome_sqlite3changeset_concat_strm // Lines 11497-11504
-#define sqlite3changeset_conflict chrome_sqlite3changeset_conflict // Lines 10624-10628
-#define sqlite3changeset_finalize chrome_sqlite3changeset_finalize // Line 10677
-#define sqlite3changeset_fk_conflicts chrome_sqlite3changeset_fk_conflicts // Lines 10641-10644
-#define sqlite3changeset_invert chrome_sqlite3changeset_invert // Lines 10707-10710
-#define sqlite3changeset_invert_strm chrome_sqlite3changeset_invert_strm // Lines 11505-11510
-#define sqlite3changeset_new chrome_sqlite3changeset_new // Lines 10596-10600
-#define sqlite3changeset_next chrome_sqlite3changeset_next // Line 10468
-#define sqlite3changeset_old chrome_sqlite3changeset_old // Lines 10562-10566
-#define sqlite3changeset_op chrome_sqlite3changeset_op // Lines 10497-10503
-#define sqlite3changeset_pk chrome_sqlite3changeset_pk // Lines 10531-10535
-#define sqlite3changeset_start chrome_sqlite3changeset_start // Lines 10419-10423
-#define sqlite3changeset_start_strm chrome_sqlite3changeset_start_strm // Lines 11511-11515
-#define sqlite3changeset_start_v2 chrome_sqlite3changeset_start_v2 // Lines 10424-10429
-#define sqlite3changeset_start_v2_strm chrome_sqlite3changeset_start_v2_strm // Lines 11516-11521
-#define sqlite3rebaser_configure chrome_sqlite3rebaser_configure // Lines 11340-11343
-#define sqlite3rebaser_create chrome_sqlite3rebaser_create // Line 11329
-#define sqlite3rebaser_delete chrome_sqlite3rebaser_delete // Line 11373
-#define sqlite3rebaser_rebase chrome_sqlite3rebaser_rebase // Lines 11359-11363
-#define sqlite3rebaser_rebase_strm chrome_sqlite3rebaser_rebase_strm // Lines 11540-11546
-#define sqlite3session_attach chrome_sqlite3session_attach // Lines 10126-10129
-#define sqlite3session_changeset chrome_sqlite3session_changeset // Lines 10255-10259
-#define sqlite3session_changeset_strm chrome_sqlite3session_changeset_strm // Lines 11522-11526
-#define sqlite3session_config chrome_sqlite3session_config // Line 11581
-#define sqlite3session_create chrome_sqlite3session_create // Lines 9996-10000
-#define sqlite3session_delete chrome_sqlite3session_delete // Line 10015
-#define sqlite3session_diff chrome_sqlite3session_diff // Lines 10318-10323
-#define sqlite3session_enable chrome_sqlite3session_enable // Line 10036
-#define sqlite3session_indirect chrome_sqlite3session_indirect // Line 10066
-#define sqlite3session_isempty chrome_sqlite3session_isempty // Line 10376
-#define sqlite3session_patchset chrome_sqlite3session_patchset // Lines 10355-10359
-#define sqlite3session_patchset_strm chrome_sqlite3session_patchset_strm // Lines 11527-11531
-#define sqlite3session_table_filter chrome_sqlite3session_table_filter // Lines 10141-10148
+#define sqlite3_vfs_find chrome_sqlite3_vfs_find // Line 7387
+#define sqlite3_vfs_register chrome_sqlite3_vfs_register // Line 7388
+#define sqlite3_vfs_unregister chrome_sqlite3_vfs_unregister // Line 7389
+#define sqlite3_vmprintf chrome_sqlite3_vmprintf // Line 2808
+#define sqlite3_vsnprintf chrome_sqlite3_vsnprintf // Line 2810
+#define sqlite3_vtab_collation chrome_sqlite3_vtab_collation // Line 9283
+#define sqlite3_vtab_config chrome_sqlite3_vtab_config // Line 9164
+#define sqlite3_vtab_nochange chrome_sqlite3_vtab_nochange // Line 9268
+#define sqlite3_vtab_on_conflict chrome_sqlite3_vtab_on_conflict // Line 9242
+#define sqlite3_wal_autocheckpoint chrome_sqlite3_wal_autocheckpoint // Line 9008
+#define sqlite3_wal_checkpoint chrome_sqlite3_wal_checkpoint // Line 9030
+#define sqlite3_wal_checkpoint_v2 chrome_sqlite3_wal_checkpoint_v2 // Lines 9124-9130
+#define sqlite3_wal_hook chrome_sqlite3_wal_hook // Lines 8973-8977
+#define sqlite3_win32_set_directory chrome_sqlite3_win32_set_directory // Lines 6095-6098
+#define sqlite3_win32_set_directory16 chrome_sqlite3_win32_set_directory16 // Line 6100
+#define sqlite3_win32_set_directory8 chrome_sqlite3_win32_set_directory8 // Line 6099
+#define sqlite3changegroup_add chrome_sqlite3changegroup_add // Line 10933
+#define sqlite3changegroup_add_strm chrome_sqlite3changegroup_add_strm // Lines 11595-11598
+#define sqlite3changegroup_delete chrome_sqlite3changegroup_delete // Line 10970
+#define sqlite3changegroup_new chrome_sqlite3changegroup_new // Line 10855
+#define sqlite3changegroup_output chrome_sqlite3changegroup_output // Lines 10960-10964
+#define sqlite3changegroup_output_strm chrome_sqlite3changegroup_output_strm // Lines 11599-11602
+#define sqlite3changeset_apply chrome_sqlite3changeset_apply // Lines 11130-11144
+#define sqlite3changeset_apply_strm chrome_sqlite3changeset_apply_strm // Lines 11528-11542
+#define sqlite3changeset_apply_v2 chrome_sqlite3changeset_apply_v2 // Lines 11145-11161
+#define sqlite3changeset_apply_v2_strm chrome_sqlite3changeset_apply_v2_strm // Lines 11543-11559
+#define sqlite3changeset_concat chrome_sqlite3changeset_concat // Lines 10801-10808
+#define sqlite3changeset_concat_strm chrome_sqlite3changeset_concat_strm // Lines 11560-11567
+#define sqlite3changeset_conflict chrome_sqlite3changeset_conflict // Lines 10687-10691
+#define sqlite3changeset_finalize chrome_sqlite3changeset_finalize // Line 10740
+#define sqlite3changeset_fk_conflicts chrome_sqlite3changeset_fk_conflicts // Lines 10704-10707
+#define sqlite3changeset_invert chrome_sqlite3changeset_invert // Lines 10770-10773
+#define sqlite3changeset_invert_strm chrome_sqlite3changeset_invert_strm // Lines 11568-11573
+#define sqlite3changeset_new chrome_sqlite3changeset_new // Lines 10659-10663
+#define sqlite3changeset_next chrome_sqlite3changeset_next // Line 10531
+#define sqlite3changeset_old chrome_sqlite3changeset_old // Lines 10625-10629
+#define sqlite3changeset_op chrome_sqlite3changeset_op // Lines 10560-10566
+#define sqlite3changeset_pk chrome_sqlite3changeset_pk // Lines 10594-10598
+#define sqlite3changeset_start chrome_sqlite3changeset_start // Lines 10482-10486
+#define sqlite3changeset_start_strm chrome_sqlite3changeset_start_strm // Lines 11574-11578
+#define sqlite3changeset_start_v2 chrome_sqlite3changeset_start_v2 // Lines 10487-10492
+#define sqlite3changeset_start_v2_strm chrome_sqlite3changeset_start_v2_strm // Lines 11579-11584
+#define sqlite3rebaser_configure chrome_sqlite3rebaser_configure // Lines 11403-11406
+#define sqlite3rebaser_create chrome_sqlite3rebaser_create // Line 11392
+#define sqlite3rebaser_delete chrome_sqlite3rebaser_delete // Line 11436
+#define sqlite3rebaser_rebase chrome_sqlite3rebaser_rebase // Lines 11422-11426
+#define sqlite3rebaser_rebase_strm chrome_sqlite3rebaser_rebase_strm // Lines 11603-11609
+#define sqlite3session_attach chrome_sqlite3session_attach // Lines 10189-10192
+#define sqlite3session_changeset chrome_sqlite3session_changeset // Lines 10318-10322
+#define sqlite3session_changeset_strm chrome_sqlite3session_changeset_strm // Lines 11585-11589
+#define sqlite3session_config chrome_sqlite3session_config // Line 11644
+#define sqlite3session_create chrome_sqlite3session_create // Lines 10059-10063
+#define sqlite3session_delete chrome_sqlite3session_delete // Line 10078
+#define sqlite3session_diff chrome_sqlite3session_diff // Lines 10381-10386
+#define sqlite3session_enable chrome_sqlite3session_enable // Line 10099
+#define sqlite3session_indirect chrome_sqlite3session_indirect // Line 10129
+#define sqlite3session_isempty chrome_sqlite3session_isempty // Line 10439
+#define sqlite3session_patchset chrome_sqlite3session_patchset // Lines 10418-10422
+#define sqlite3session_patchset_strm chrome_sqlite3session_patchset_strm // Lines 11590-11594
+#define sqlite3session_table_filter chrome_sqlite3session_table_filter // Lines 10204-10211
#endif // THIRD_PARTY_SQLITE_AMALGAMATION_RENAME_EXPORTS_H_
diff --git a/chromium/third_party/sqlite/src/amalgamation_dev/shell/shell.c b/chromium/third_party/sqlite/src/amalgamation_dev/shell/shell.c
index a1a77e49fa5..c13769f5e96 100644
--- a/chromium/third_party/sqlite/src/amalgamation_dev/shell/shell.c
+++ b/chromium/third_party/sqlite/src/amalgamation_dev/shell/shell.c
@@ -571,8 +571,6 @@ static void utf8_width_print(FILE *pOut, int w, const char *zUtf){
int i;
int n;
int aw = w<0 ? -w : w;
- char zBuf[1000];
- if( aw>(int)sizeof(zBuf)/3 ) aw = (int)sizeof(zBuf)/3;
for(i=n=0; zUtf[i]; i++){
if( (zUtf[i]&0xc0)!=0x80 ){
n++;
@@ -5315,6 +5313,444 @@ int sqlite3_ieee_init(
}
/************************* End ../ext/misc/ieee754.c ********************/
+/************************* Begin ../ext/misc/series.c ******************/
+/*
+** 2015-08-18
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file demonstrates how to create a table-valued-function using
+** a virtual table. This demo implements the generate_series() function
+** which gives similar results to the eponymous function in PostgreSQL.
+** Examples:
+**
+** SELECT * FROM generate_series(0,100,5);
+**
+** The query above returns integers from 0 through 100 counting by steps
+** of 5.
+**
+** SELECT * FROM generate_series(0,100);
+**
+** Integers from 0 through 100 with a step size of 1.
+**
+** SELECT * FROM generate_series(20) LIMIT 10;
+**
+** Integers 20 through 29.
+**
+** HOW IT WORKS
+**
+** The generate_series "function" is really a virtual table with the
+** following schema:
+**
+** CREATE TABLE generate_series(
+** value,
+** start HIDDEN,
+** stop HIDDEN,
+** step HIDDEN
+** );
+**
+** Function arguments in queries against this virtual table are translated
+** into equality constraints against successive hidden columns. In other
+** words, the following pairs of queries are equivalent to each other:
+**
+** SELECT * FROM generate_series(0,100,5);
+** SELECT * FROM generate_series WHERE start=0 AND stop=100 AND step=5;
+**
+** SELECT * FROM generate_series(0,100);
+** SELECT * FROM generate_series WHERE start=0 AND stop=100;
+**
+** SELECT * FROM generate_series(20) LIMIT 10;
+** SELECT * FROM generate_series WHERE start=20 LIMIT 10;
+**
+** The generate_series virtual table implementation leaves the xCreate method
+** set to NULL. This means that it is not possible to do a CREATE VIRTUAL
+** TABLE command with "generate_series" as the USING argument. Instead, there
+** is a single generate_series virtual table that is always available without
+** having to be created first.
+**
+** The xBestIndex method looks for equality constraints against the hidden
+** start, stop, and step columns, and if present, it uses those constraints
+** to bound the sequence of generated values. If the equality constraints
+** are missing, it uses 0 for start, 4294967295 for stop, and 1 for step.
+** xBestIndex returns a small cost when both start and stop are available,
+** and a very large cost if either start or stop are unavailable. This
+** encourages the query planner to order joins such that the bounds of the
+** series are well-defined.
+*/
+/* #include "sqlite3ext.h" */
+SQLITE_EXTENSION_INIT1
+#include <assert.h>
+#include <string.h>
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+
+
+/* series_cursor is a subclass of sqlite3_vtab_cursor which will
+** serve as the underlying representation of a cursor that scans
+** over rows of the result
+*/
+typedef struct series_cursor series_cursor;
+struct series_cursor {
+ sqlite3_vtab_cursor base; /* Base class - must be first */
+ int isDesc; /* True to count down rather than up */
+ sqlite3_int64 iRowid; /* The rowid */
+ sqlite3_int64 iValue; /* Current value ("value") */
+ sqlite3_int64 mnValue; /* Mimimum value ("start") */
+ sqlite3_int64 mxValue; /* Maximum value ("stop") */
+ sqlite3_int64 iStep; /* Increment ("step") */
+};
+
+/*
+** The seriesConnect() method is invoked to create a new
+** series_vtab that describes the generate_series virtual table.
+**
+** Think of this routine as the constructor for series_vtab objects.
+**
+** All this routine needs to do is:
+**
+** (1) Allocate the series_vtab object and initialize all fields.
+**
+** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
+** result set of queries against generate_series will look like.
+*/
+static int seriesConnect(
+ sqlite3 *db,
+ void *pUnused,
+ int argcUnused, const char *const*argvUnused,
+ sqlite3_vtab **ppVtab,
+ char **pzErrUnused
+){
+ sqlite3_vtab *pNew;
+ int rc;
+
+/* Column numbers */
+#define SERIES_COLUMN_VALUE 0
+#define SERIES_COLUMN_START 1
+#define SERIES_COLUMN_STOP 2
+#define SERIES_COLUMN_STEP 3
+
+ (void)pUnused;
+ (void)argcUnused;
+ (void)argvUnused;
+ (void)pzErrUnused;
+ rc = sqlite3_declare_vtab(db,
+ "CREATE TABLE x(value,start hidden,stop hidden,step hidden)");
+ if( rc==SQLITE_OK ){
+ pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) );
+ if( pNew==0 ) return SQLITE_NOMEM;
+ memset(pNew, 0, sizeof(*pNew));
+ sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
+ }
+ return rc;
+}
+
+/*
+** This method is the destructor for series_cursor objects.
+*/
+static int seriesDisconnect(sqlite3_vtab *pVtab){
+ sqlite3_free(pVtab);
+ return SQLITE_OK;
+}
+
+/*
+** Constructor for a new series_cursor object.
+*/
+static int seriesOpen(sqlite3_vtab *pUnused, sqlite3_vtab_cursor **ppCursor){
+ series_cursor *pCur;
+ (void)pUnused;
+ pCur = sqlite3_malloc( sizeof(*pCur) );
+ if( pCur==0 ) return SQLITE_NOMEM;
+ memset(pCur, 0, sizeof(*pCur));
+ *ppCursor = &pCur->base;
+ return SQLITE_OK;
+}
+
+/*
+** Destructor for a series_cursor.
+*/
+static int seriesClose(sqlite3_vtab_cursor *cur){
+ sqlite3_free(cur);
+ return SQLITE_OK;
+}
+
+
+/*
+** Advance a series_cursor to its next row of output.
+*/
+static int seriesNext(sqlite3_vtab_cursor *cur){
+ series_cursor *pCur = (series_cursor*)cur;
+ if( pCur->isDesc ){
+ pCur->iValue -= pCur->iStep;
+ }else{
+ pCur->iValue += pCur->iStep;
+ }
+ pCur->iRowid++;
+ return SQLITE_OK;
+}
+
+/*
+** Return values of columns for the row at which the series_cursor
+** is currently pointing.
+*/
+static int seriesColumn(
+ sqlite3_vtab_cursor *cur, /* The cursor */
+ sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
+ int i /* Which column to return */
+){
+ series_cursor *pCur = (series_cursor*)cur;
+ sqlite3_int64 x = 0;
+ switch( i ){
+ case SERIES_COLUMN_START: x = pCur->mnValue; break;
+ case SERIES_COLUMN_STOP: x = pCur->mxValue; break;
+ case SERIES_COLUMN_STEP: x = pCur->iStep; break;
+ default: x = pCur->iValue; break;
+ }
+ sqlite3_result_int64(ctx, x);
+ return SQLITE_OK;
+}
+
+/*
+** Return the rowid for the current row. In this implementation, the
+** first row returned is assigned rowid value 1, and each subsequent
+** row a value 1 more than that of the previous.
+*/
+static int seriesRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
+ series_cursor *pCur = (series_cursor*)cur;
+ *pRowid = pCur->iRowid;
+ return SQLITE_OK;
+}
+
+/*
+** Return TRUE if the cursor has been moved off of the last
+** row of output.
+*/
+static int seriesEof(sqlite3_vtab_cursor *cur){
+ series_cursor *pCur = (series_cursor*)cur;
+ if( pCur->isDesc ){
+ return pCur->iValue < pCur->mnValue;
+ }else{
+ return pCur->iValue > pCur->mxValue;
+ }
+}
+
+/* True to cause run-time checking of the start=, stop=, and/or step=
+** parameters. The only reason to do this is for testing the
+** constraint checking logic for virtual tables in the SQLite core.
+*/
+#ifndef SQLITE_SERIES_CONSTRAINT_VERIFY
+# define SQLITE_SERIES_CONSTRAINT_VERIFY 0
+#endif
+
+/*
+** This method is called to "rewind" the series_cursor object back
+** to the first row of output. This method is always called at least
+** once prior to any call to seriesColumn() or seriesRowid() or
+** seriesEof().
+**
+** The query plan selected by seriesBestIndex is passed in the idxNum
+** parameter. (idxStr is not used in this implementation.) idxNum
+** is a bitmask showing which constraints are available:
+**
+** 1: start=VALUE
+** 2: stop=VALUE
+** 4: step=VALUE
+**
+** Also, if bit 8 is set, that means that the series should be output
+** in descending order rather than in ascending order.
+**
+** This routine should initialize the cursor and position it so that it
+** is pointing at the first row, or pointing off the end of the table
+** (so that seriesEof() will return true) if the table is empty.
+*/
+static int seriesFilter(
+ sqlite3_vtab_cursor *pVtabCursor,
+ int idxNum, const char *idxStrUnused,
+ int argc, sqlite3_value **argv
+){
+ series_cursor *pCur = (series_cursor *)pVtabCursor;
+ int i = 0;
+ (void)idxStrUnused;
+ if( idxNum & 1 ){
+ pCur->mnValue = sqlite3_value_int64(argv[i++]);
+ }else{
+ pCur->mnValue = 0;
+ }
+ if( idxNum & 2 ){
+ pCur->mxValue = sqlite3_value_int64(argv[i++]);
+ }else{
+ pCur->mxValue = 0xffffffff;
+ }
+ if( idxNum & 4 ){
+ pCur->iStep = sqlite3_value_int64(argv[i++]);
+ if( pCur->iStep<1 ) pCur->iStep = 1;
+ }else{
+ pCur->iStep = 1;
+ }
+ for(i=0; i<argc; i++){
+ if( sqlite3_value_type(argv[i])==SQLITE_NULL ){
+ /* If any of the constraints have a NULL value, then return no rows.
+ ** See ticket https://www.sqlite.org/src/info/fac496b61722daf2 */
+ pCur->mnValue = 1;
+ pCur->mxValue = 0;
+ break;
+ }
+ }
+ if( idxNum & 8 ){
+ pCur->isDesc = 1;
+ pCur->iValue = pCur->mxValue;
+ if( pCur->iStep>0 ){
+ pCur->iValue -= (pCur->mxValue - pCur->mnValue)%pCur->iStep;
+ }
+ }else{
+ pCur->isDesc = 0;
+ pCur->iValue = pCur->mnValue;
+ }
+ pCur->iRowid = 1;
+ return SQLITE_OK;
+}
+
+/*
+** SQLite will invoke this method one or more times while planning a query
+** that uses the generate_series virtual table. This routine needs to create
+** a query plan for each invocation and compute an estimated cost for that
+** plan.
+**
+** In this implementation idxNum is used to represent the
+** query plan. idxStr is unused.
+**
+** The query plan is represented by bits in idxNum:
+**
+** (1) start = $value -- constraint exists
+** (2) stop = $value -- constraint exists
+** (4) step = $value -- constraint exists
+** (8) output in descending order
+*/
+static int seriesBestIndex(
+ sqlite3_vtab *tabUnused,
+ sqlite3_index_info *pIdxInfo
+){
+ int i, j; /* Loop over constraints */
+ int idxNum = 0; /* The query plan bitmask */
+ int unusableMask = 0; /* Mask of unusable constraints */
+ int nArg = 0; /* Number of arguments that seriesFilter() expects */
+ int aIdx[3]; /* Constraints on start, stop, and step */
+ const struct sqlite3_index_constraint *pConstraint;
+
+ /* This implementation assumes that the start, stop, and step columns
+ ** are the last three columns in the virtual table. */
+ assert( SERIES_COLUMN_STOP == SERIES_COLUMN_START+1 );
+ assert( SERIES_COLUMN_STEP == SERIES_COLUMN_START+2 );
+ (void)tabUnused;
+ aIdx[0] = aIdx[1] = aIdx[2] = -1;
+ pConstraint = pIdxInfo->aConstraint;
+ for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
+ int iCol; /* 0 for start, 1 for stop, 2 for step */
+ int iMask; /* bitmask for those column */
+ if( pConstraint->iColumn<SERIES_COLUMN_START ) continue;
+ iCol = pConstraint->iColumn - SERIES_COLUMN_START;
+ assert( iCol>=0 && iCol<=2 );
+ iMask = 1 << iCol;
+ if( pConstraint->usable==0 ){
+ unusableMask |= iMask;
+ continue;
+ }else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
+ idxNum |= iMask;
+ aIdx[iCol] = i;
+ }
+ }
+ for(i=0; i<3; i++){
+ if( (j = aIdx[i])>=0 ){
+ pIdxInfo->aConstraintUsage[j].argvIndex = ++nArg;
+ pIdxInfo->aConstraintUsage[j].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY;
+ }
+ }
+ if( (unusableMask & ~idxNum)!=0 ){
+ /* The start, stop, and step columns are inputs. Therefore if there
+ ** are unusable constraints on any of start, stop, or step then
+ ** this plan is unusable */
+ return SQLITE_CONSTRAINT;
+ }
+ if( (idxNum & 3)==3 ){
+ /* Both start= and stop= boundaries are available. This is the
+ ** the preferred case */
+ pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0));
+ pIdxInfo->estimatedRows = 1000;
+ if( pIdxInfo->nOrderBy==1 ){
+ if( pIdxInfo->aOrderBy[0].desc ) idxNum |= 8;
+ pIdxInfo->orderByConsumed = 1;
+ }
+ }else{
+ /* If either boundary is missing, we have to generate a huge span
+ ** of numbers. Make this case very expensive so that the query
+ ** planner will work hard to avoid it. */
+ pIdxInfo->estimatedRows = 2147483647;
+ }
+ pIdxInfo->idxNum = idxNum;
+ return SQLITE_OK;
+}
+
+/*
+** This following structure defines all the methods for the
+** generate_series virtual table.
+*/
+static sqlite3_module seriesModule = {
+ 0, /* iVersion */
+ 0, /* xCreate */
+ seriesConnect, /* xConnect */
+ seriesBestIndex, /* xBestIndex */
+ seriesDisconnect, /* xDisconnect */
+ 0, /* xDestroy */
+ seriesOpen, /* xOpen - open a cursor */
+ seriesClose, /* xClose - close a cursor */
+ seriesFilter, /* xFilter - configure scan constraints */
+ seriesNext, /* xNext - advance a cursor */
+ seriesEof, /* xEof - check for end of scan */
+ seriesColumn, /* xColumn - read data */
+ seriesRowid, /* xRowid - read data */
+ 0, /* xUpdate */
+ 0, /* xBegin */
+ 0, /* xSync */
+ 0, /* xCommit */
+ 0, /* xRollback */
+ 0, /* xFindMethod */
+ 0, /* xRename */
+ 0, /* xSavepoint */
+ 0, /* xRelease */
+ 0, /* xRollbackTo */
+ 0 /* xShadowName */
+};
+
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+#ifdef _WIN32
+
+#endif
+int sqlite3_series_init(
+ sqlite3 *db,
+ char **pzErrMsg,
+ const sqlite3_api_routines *pApi
+){
+ int rc = SQLITE_OK;
+ SQLITE_EXTENSION_INIT2(pApi);
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( sqlite3_libversion_number()<3008012 ){
+ *pzErrMsg = sqlite3_mprintf(
+ "generate_series() requires SQLite 3.8.12 or later");
+ return SQLITE_ERROR;
+ }
+ rc = sqlite3_create_module(db, "generate_series", &seriesModule, 0);
+#endif
+ return rc;
+}
+
+/************************* End ../ext/misc/series.c ********************/
#ifdef SQLITE_HAVE_ZLIB
/************************* Begin ../ext/misc/zipfile.c ******************/
/*
@@ -5842,14 +6278,16 @@ static int zipfileAppendData(
const u8 *aWrite,
int nWrite
){
- size_t n;
- fseek(pTab->pWriteFd, (long)pTab->szCurrent, SEEK_SET);
- n = fwrite(aWrite, 1, nWrite, pTab->pWriteFd);
- if( (int)n!=nWrite ){
- pTab->base.zErrMsg = sqlite3_mprintf("error in fwrite()");
- return SQLITE_ERROR;
+ if( nWrite>0 ){
+ size_t n = nWrite;
+ fseek(pTab->pWriteFd, (long)pTab->szCurrent, SEEK_SET);
+ n = fwrite(aWrite, 1, nWrite, pTab->pWriteFd);
+ if( (int)n!=nWrite ){
+ pTab->base.zErrMsg = sqlite3_mprintf("error in fwrite()");
+ return SQLITE_ERROR;
+ }
+ pTab->szCurrent += nWrite;
}
- pTab->szCurrent += nWrite;
return SQLITE_OK;
}
@@ -8494,6 +8932,7 @@ static int idxGetTableInfo(
IdxTable *pNew = 0;
int rc, rc2;
char *pCsr = 0;
+ int nPk = 0;
rc = idxPrintfPrepareStmt(db, &p1, pzErrmsg, "PRAGMA table_info=%Q", zTab);
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
@@ -8504,6 +8943,7 @@ static int idxGetTableInfo(
);
nByte += 1 + STRLEN(zCol);
nCol++;
+ nPk += (sqlite3_column_int(p1, 5)>0);
}
rc2 = sqlite3_reset(p1);
if( rc==SQLITE_OK ) rc = rc2;
@@ -8523,7 +8963,7 @@ static int idxGetTableInfo(
const char *zCol = (const char*)sqlite3_column_text(p1, 1);
int nCopy = STRLEN(zCol) + 1;
pNew->aCol[nCol].zName = pCsr;
- pNew->aCol[nCol].iPk = sqlite3_column_int(p1, 5);
+ pNew->aCol[nCol].iPk = (sqlite3_column_int(p1, 5)==1 && nPk==1);
memcpy(pCsr, zCol, nCopy);
pCsr += nCopy;
@@ -10771,6 +11211,8 @@ struct ShellState {
#define SHFLG_CountChanges 0x00000020 /* .changes setting */
#define SHFLG_Echo 0x00000040 /* .echo or --echo setting */
#define SHFLG_HeaderSet 0x00000080 /* .header has been used */
+#define SHFLG_DumpDataOnly 0x00000100 /* .dump show data only */
+#define SHFLG_DumpNoSys 0x00000200 /* .dump omits system tables */
/*
** Macros for testing and setting shellFlgs
@@ -13291,19 +13733,25 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
const char *zType;
const char *zSql;
ShellState *p = (ShellState *)pArg;
+ int dataOnly;
+ int noSys;
UNUSED_PARAMETER(azNotUsed);
if( nArg!=3 || azArg==0 ) return 0;
zTable = azArg[0];
zType = azArg[1];
zSql = azArg[2];
+ dataOnly = (p->shellFlgs & SHFLG_DumpDataOnly)!=0;
+ noSys = (p->shellFlgs & SHFLG_DumpNoSys)!=0;
- if( strcmp(zTable, "sqlite_sequence")==0 ){
- raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
- }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){
- raw_printf(p->out, "ANALYZE sqlite_schema;\n");
+ if( strcmp(zTable, "sqlite_sequence")==0 && !noSys ){
+ if( !dataOnly ) raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
+ }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 && !noSys ){
+ if( !dataOnly ) raw_printf(p->out, "ANALYZE sqlite_schema;\n");
}else if( strncmp(zTable, "sqlite_", 7)==0 ){
return 0;
+ }else if( dataOnly ){
+ /* no-op */
}else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
char *zIns;
if( !p->writableSchema ){
@@ -13476,8 +13924,10 @@ static const char *(azHelp[]) = {
".dbinfo ?DB? Show status information about the database",
".dump ?TABLE? Render database content as SQL",
" Options:",
- " --preserve-rowids Include ROWID values in the output",
+ " --data-only Output only INSERT statements",
" --newlines Allow unescaped newline characters in output",
+ " --nosys Omit system tables (ex: \"sqlite_stat1\")",
+ " --preserve-rowids Include ROWID values in the output",
" TABLE is a LIKE pattern for the tables to dump",
" Additional LIKE patterns can be given in subsequent arguments",
".echo on|off Turn command echo on or off",
@@ -13602,8 +14052,9 @@ static const char *(azHelp[]) = {
".save FILE Write in-memory database into FILE",
".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off",
".schema ?PATTERN? Show the CREATE statements matching PATTERN",
- " Options:",
- " --indent Try to pretty-print the schema",
+ " Options:",
+ " --indent Try to pretty-print the schema",
+ " --nosys Omit objects whose names start with \"sqlite_\"",
".selftest ?OPTIONS? Run tests defined in the SELFTEST table",
" Options:",
" --init Create a new SELFTEST table",
@@ -14013,6 +14464,20 @@ static void shellIdQuote(
}
/*
+** Scalar function "usleep(X)" invokes sqlite3_sleep(X) and returns X.
+*/
+static void shellUSleepFunc(
+ sqlite3_context *context,
+ int argcUnused,
+ sqlite3_value **argv
+){
+ int sleep = sqlite3_value_int(argv[0]);
+ (void)argcUnused;
+ sqlite3_sleep(sleep/1000);
+ sqlite3_result_int(context, sleep);
+}
+
+/*
** Scalar function "shell_escape_crnl" used by the .recover command.
** The argument passed to this function is the output of built-in
** function quote(). If the first character of the input is "'",
@@ -14176,6 +14641,7 @@ static void open_db(ShellState *p, int openFlags){
sqlite3_uint_init(p->db, 0, 0);
sqlite3_decimal_init(p->db, 0, 0);
sqlite3_ieee_init(p->db, 0, 0);
+ sqlite3_series_init(p->db, 0, 0);
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
sqlite3_dbdata_init(p->db, 0, 0);
#endif
@@ -14195,6 +14661,8 @@ static void open_db(ShellState *p, int openFlags){
shellInt32, 0, 0);
sqlite3_create_function(p->db, "shell_idquote", 1, SQLITE_UTF8, 0,
shellIdQuote, 0, 0);
+ sqlite3_create_function(p->db, "usleep",1,SQLITE_UTF8,0,
+ shellUSleepFunc, 0, 0);
#ifndef SQLITE_NOHAVE_SYSTEM
sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0,
editFunc, 0, 0);
@@ -17169,21 +17637,41 @@ static int do_meta_command(char *zLine, ShellState *p){
}else
if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
- ShellState data;
- char *zErrMsg = 0;
+ char **azName = 0;
+ int nName = 0;
+ sqlite3_stmt *pStmt;
+ int i;
open_db(p, 0);
- memcpy(&data, p, sizeof(data));
- data.showHeader = 0;
- data.cMode = data.mode = MODE_List;
- sqlite3_snprintf(sizeof(data.colSeparator),data.colSeparator,": ");
- data.cnt = 0;
- sqlite3_exec(p->db, "SELECT name, file FROM pragma_database_list",
- callback, &data, &zErrMsg);
- if( zErrMsg ){
- utf8_printf(stderr,"Error: %s\n", zErrMsg);
- sqlite3_free(zErrMsg);
+ rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
+ if( rc ){
+ utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
rc = 1;
+ }else{
+ while( sqlite3_step(pStmt)==SQLITE_ROW ){
+ const char *zSchema = (const char *)sqlite3_column_text(pStmt,1);
+ const char *zFile = (const char*)sqlite3_column_text(pStmt,2);
+ azName = sqlite3_realloc(azName, (nName+1)*2*sizeof(char*));
+ if( azName==0 ){ shell_out_of_memory(); /* Does not return */ }
+ azName[nName*2] = strdup(zSchema);
+ azName[nName*2+1] = strdup(zFile);
+ nName++;
+ }
}
+ sqlite3_finalize(pStmt);
+ for(i=0; i<nName; i++){
+ int eTxn = sqlite3_txn_state(p->db, azName[i*2]);
+ int bRdonly = sqlite3_db_readonly(p->db, azName[i*2]);
+ const char *z = azName[i*2+1];
+ utf8_printf(p->out, "%s: %s %s%s\n",
+ azName[i*2],
+ z && z[0] ? z : "\"\"",
+ bRdonly ? "r/o" : "r/w",
+ eTxn==SQLITE_TXN_NONE ? "" :
+ eTxn==SQLITE_TXN_READ ? " read-txn" : " write-txn");
+ free(azName[i*2]);
+ free(azName[i*2+1]);
+ }
+ sqlite3_free(azName);
}else
if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){
@@ -17242,7 +17730,9 @@ static int do_meta_command(char *zLine, ShellState *p){
int i;
int savedShowHeader = p->showHeader;
int savedShellFlags = p->shellFlgs;
- ShellClearFlag(p, SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo);
+ ShellClearFlag(p,
+ SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo
+ |SHFLG_DumpDataOnly|SHFLG_DumpNoSys);
for(i=1; i<nArg; i++){
if( azArg[i][0]=='-' ){
const char *z = azArg[i]+1;
@@ -17261,6 +17751,12 @@ static int do_meta_command(char *zLine, ShellState *p){
if( strcmp(z,"newlines")==0 ){
ShellSetFlag(p, SHFLG_Newlines);
}else
+ if( strcmp(z,"data-only")==0 ){
+ ShellSetFlag(p, SHFLG_DumpDataOnly);
+ }else
+ if( strcmp(z,"nosys")==0 ){
+ ShellSetFlag(p, SHFLG_DumpNoSys);
+ }else
{
raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
rc = 1;
@@ -17277,11 +17773,13 @@ static int do_meta_command(char *zLine, ShellState *p){
open_db(p, 0);
- /* When playing back a "dump", the content might appear in an order
- ** which causes immediate foreign key constraints to be violated.
- ** So disable foreign-key constraint enforcement to prevent problems. */
- raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
- raw_printf(p->out, "BEGIN TRANSACTION;\n");
+ if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
+ /* When playing back a "dump", the content might appear in an order
+ ** which causes immediate foreign key constraints to be violated.
+ ** So disable foreign-key constraint enforcement to prevent problems. */
+ raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
+ raw_printf(p->out, "BEGIN TRANSACTION;\n");
+ }
p->writableSchema = 0;
p->showHeader = 0;
/* Set writable_schema=ON since doing so forces SQLite to initialize
@@ -17299,14 +17797,16 @@ static int do_meta_command(char *zLine, ShellState *p){
);
run_schema_dump_query(p,zSql);
sqlite3_free(zSql);
- zSql = sqlite3_mprintf(
- "SELECT sql FROM sqlite_schema "
- "WHERE (%s) AND sql NOT NULL"
- " AND type IN ('index','trigger','view')",
- zLike
- );
- run_table_dump_query(p, zSql);
- sqlite3_free(zSql);
+ if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
+ zSql = sqlite3_mprintf(
+ "SELECT sql FROM sqlite_schema "
+ "WHERE (%s) AND sql NOT NULL"
+ " AND type IN ('index','trigger','view')",
+ zLike
+ );
+ run_table_dump_query(p, zSql);
+ sqlite3_free(zSql);
+ }
sqlite3_free(zLike);
if( p->writableSchema ){
raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
@@ -17314,7 +17814,9 @@ static int do_meta_command(char *zLine, ShellState *p){
}
sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
- raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
+ if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
+ raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
+ }
p->showHeader = savedShowHeader;
p->shellFlgs = savedShellFlags;
}else
@@ -17753,7 +18255,7 @@ static int do_meta_command(char *zLine, ShellState *p){
while( (nSkip--)>0 ){
while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
}
- zSql = sqlite3_mprintf("SELECT * FROM %s", zTable);
+ zSql = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
if( zSql==0 ){
import_cleanup(&sCtx);
shell_out_of_memory();
@@ -17762,7 +18264,7 @@ static int do_meta_command(char *zLine, ShellState *p){
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
- char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable);
+ char *zCreate = sqlite3_mprintf("CREATE TABLE \"%w\"", zTable);
char cSep = '(';
while( xRead(&sCtx) ){
zCreate = sqlite3_mprintf("%z%c\n \"%w\" TEXT", zCreate, cSep, sCtx.z);
@@ -17783,7 +18285,7 @@ static int do_meta_command(char *zLine, ShellState *p){
rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
sqlite3_free(zCreate);
if( rc ){
- utf8_printf(stderr, "CREATE TABLE %s(...) failed: %s\n", zTable,
+ utf8_printf(stderr, "CREATE TABLE \"%s\"(...) failed: %s\n", zTable,
sqlite3_errmsg(p->db));
import_cleanup(&sCtx);
rc = 1;
@@ -18548,9 +19050,16 @@ static int do_meta_command(char *zLine, ShellState *p){
rc = 1;
goto meta_command_exit;
}
- if( notNormalFile(azArg[1])
- || (p->in = fopen(azArg[1], "rb"))==0
- ){
+ if( azArg[1][0]=='|' ){
+ p->in = popen(azArg[1]+1, "r");
+ if( p->in==0 ){
+ utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
+ rc = 1;
+ }else{
+ rc = process_input(p);
+ pclose(p->in);
+ }
+ }else if( notNormalFile(azArg[1]) || (p->in = fopen(azArg[1], "rb"))==0 ){
utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
rc = 1;
}else{
@@ -18632,6 +19141,7 @@ static int do_meta_command(char *zLine, ShellState *p){
const char *zName = 0;
int iSchema = 0;
int bDebug = 0;
+ int bNoSystemTabs = 0;
int ii;
open_db(p, 0);
@@ -18644,10 +19154,16 @@ static int do_meta_command(char *zLine, ShellState *p){
data.cMode = data.mode = MODE_Pretty;
}else if( optionMatch(azArg[ii],"debug") ){
bDebug = 1;
+ }else if( optionMatch(azArg[ii],"nosys") ){
+ bNoSystemTabs = 1;
+ }else if( azArg[ii][0]=='-' ){
+ utf8_printf(stderr, "Unknown option: \"%s\"\n", azArg[ii]);
+ rc = 1;
+ goto meta_command_exit;
}else if( zName==0 ){
zName = azArg[ii];
}else{
- raw_printf(stderr, "Usage: .schema ?--indent? ?LIKE-PATTERN?\n");
+ raw_printf(stderr, "Usage: .schema ?--indent? ?--nosys? ?LIKE-PATTERN?\n");
rc = 1;
goto meta_command_exit;
}
@@ -18733,7 +19249,10 @@ static int do_meta_command(char *zLine, ShellState *p){
appendText(&sSelect, " AND ", 0);
sqlite3_free(zQarg);
}
- appendText(&sSelect, "type!='meta' AND sql IS NOT NULL"
+ if( bNoSystemTabs ){
+ appendText(&sSelect, "name NOT LIKE 'sqlite_%%' AND ", 0);
+ }
+ appendText(&sSelect, "sql IS NOT NULL"
" ORDER BY snum, rowid", 0);
if( bDebug ){
utf8_printf(p->out, "SQL: %s;\n", sSelect.z);
@@ -19430,6 +19949,7 @@ static int do_meta_command(char *zLine, ShellState *p){
{ "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE, "" },
{ "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, "" },
{ "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, "SEED ?db?" },
+ { "seek_count", SQLITE_TESTCTRL_SEEK_COUNT, "" },
};
int testctrl = -1;
int iCtrl = -1;
@@ -19492,7 +20012,6 @@ static int do_meta_command(char *zLine, ShellState *p){
/* sqlite3_test_control(int) */
case SQLITE_TESTCTRL_PRNG_SAVE:
case SQLITE_TESTCTRL_PRNG_RESTORE:
- case SQLITE_TESTCTRL_PRNG_RESET:
case SQLITE_TESTCTRL_BYTEORDER:
if( nArg==2 ){
rc2 = sqlite3_test_control(testctrl);
@@ -19566,6 +20085,14 @@ static int do_meta_command(char *zLine, ShellState *p){
}
break;
+ case SQLITE_TESTCTRL_SEEK_COUNT: {
+ u64 x = 0;
+ rc2 = sqlite3_test_control(testctrl, p->db, &x);
+ utf8_printf(p->out, "%llu\n", x);
+ isOk = 3;
+ break;
+ }
+
#ifdef YYCOVERAGE
case SQLITE_TESTCTRL_PARSER_COVERAGE:
if( nArg==2 ){
@@ -20144,8 +20671,11 @@ static void process_sqliterc(
if( stdin_is_interactive ){
utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc);
}
- process_input(p);
+ if( process_input(p) && bail_on_error ) exit(1);
fclose(p->in);
+ }else if( sqliterc_override!=0 ){
+ utf8_printf(stderr,"cannot open: \"%s\"\n", sqliterc);
+ if( bail_on_error ) exit(1);
}
p->in = inSaved;
p->lineno = savedLineno;
@@ -20204,6 +20734,7 @@ static const char zOptions[] =
#endif
" -stats print memory stats before each finalize\n"
" -table set output mode to 'table'\n"
+ " -tabs set output mode to 'tabs'\n"
" -version show SQLite version\n"
" -vfs NAME use NAME as the default VFS\n"
#ifdef SQLITE_ENABLE_VFSTRACE
@@ -20461,11 +20992,14 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
(void)cmdline_option_value(argc, argv, ++i);
#endif
}else if( strcmp(z,"-pagecache")==0 ){
- int n, sz;
- sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
+ sqlite3_int64 n, sz;
+ sz = integerValue(cmdline_option_value(argc,argv,++i));
if( sz>70000 ) sz = 70000;
if( sz<0 ) sz = 0;
- n = (int)integerValue(cmdline_option_value(argc,argv,++i));
+ n = integerValue(cmdline_option_value(argc,argv,++i));
+ if( sz>0 && n>0 && 0xffffffffffffLL/sz<n ){
+ n = 0xffffffffffffLL/sz;
+ }
sqlite3_config(SQLITE_CONFIG_PAGECACHE,
(n>0 && sz>0) ? malloc(n*sz) : 0, sz, n);
data.shellFlgs |= SHFLG_Pagecache;
@@ -20527,6 +21061,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
#endif
}else if( strcmp(z, "-memtrace")==0 ){
sqlite3MemTraceActivate(stderr);
+ }else if( strcmp(z,"-bail")==0 ){
+ bail_on_error = 1;
}
}
verify_uninitialized();
@@ -20601,6 +21137,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
data.mode = MODE_List;
}else if( strcmp(z,"-quote")==0 ){
data.mode = MODE_Quote;
+ sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Comma);
+ sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
}else if( strcmp(z,"-line")==0 ){
data.mode = MODE_Line;
}else if( strcmp(z,"-column")==0 ){
@@ -20634,10 +21172,12 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
data.openFlags |= SQLITE_OPEN_NOFOLLOW;
}else if( strcmp(z,"-ascii")==0 ){
data.mode = MODE_Ascii;
- sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
- SEP_Unit);
- sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
- SEP_Record);
+ sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Unit);
+ sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Record);
+ }else if( strcmp(z,"-tabs")==0 ){
+ data.mode = MODE_List;
+ sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Tab);
+ sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
}else if( strcmp(z,"-separator")==0 ){
sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
"%s",cmdline_option_value(argc,argv,++i));
@@ -20669,7 +21209,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
*/
ShellSetFlag(&data, SHFLG_Backslash);
}else if( strcmp(z,"-bail")==0 ){
- bail_on_error = 1;
+ /* No-op. The bail_on_error flag should already be set. */
}else if( strcmp(z,"-version")==0 ){
printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid());
return 0;
@@ -20757,20 +21297,25 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
for(i=0; i<nCmd; i++){
if( azCmd[i][0]=='.' ){
rc = do_meta_command(azCmd[i], &data);
- if( rc ) return rc==2 ? 0 : rc;
+ if( rc ){
+ free(azCmd);
+ return rc==2 ? 0 : rc;
+ }
}else{
open_db(&data, 0);
rc = shell_exec(&data, azCmd[i], &zErrMsg);
- if( zErrMsg!=0 ){
- utf8_printf(stderr,"Error: %s\n", zErrMsg);
+ if( zErrMsg || rc ){
+ if( zErrMsg!=0 ){
+ utf8_printf(stderr,"Error: %s\n", zErrMsg);
+ }else{
+ utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]);
+ }
+ sqlite3_free(zErrMsg);
+ free(azCmd);
return rc!=0 ? rc : 1;
- }else if( rc!=0 ){
- utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]);
- return rc;
}
}
}
- free(azCmd);
}else{
/* Run commands received from standard input
*/
@@ -20816,6 +21361,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
rc = process_input(&data);
}
}
+ free(azCmd);
set_table_name(&data, 0);
if( data.db ){
session_close_all(&data);
diff --git a/chromium/third_party/sqlite/src/amalgamation_dev/sqlite3.c b/chromium/third_party/sqlite/src/amalgamation_dev/sqlite3.c
index a82744931c0..d30c9b7dea3 100644
--- a/chromium/third_party/sqlite/src/amalgamation_dev/sqlite3.c
+++ b/chromium/third_party/sqlite/src/amalgamation_dev/sqlite3.c
@@ -1,6 +1,6 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-** version 3.33.0. By combining all the individual C code files into this
+** version 3.34.0. 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
@@ -1171,9 +1171,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.33.0"
-#define SQLITE_VERSION_NUMBER 3033000
-#define SQLITE_SOURCE_ID "2020-08-14 13:23:32 fca8dc8b578f215a969cd899336378966156154710873e68b3d9ac5881b0ff3f"
+#define SQLITE_VERSION "3.34.0"
+#define SQLITE_VERSION_NUMBER 3034000
+#define SQLITE_SOURCE_ID "2020-12-01 16:14:00 b7738010bc8ef02ba84820368e557306390a33c38adaa5c7703154bae3edalt1"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -1552,6 +1552,7 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8))
#define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8))
#define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8))
+#define SQLITE_IOERR_CORRUPTFS (SQLITE_IOERR | (33<<8))
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8))
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
@@ -7235,6 +7236,57 @@ SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName);
/*
+** CAPI3REF: Determine the transaction state of a database
+** METHOD: sqlite3
+**
+** ^The sqlite3_txn_state(D,S) interface returns the current
+** [transaction state] of schema S in database connection D. ^If S is NULL,
+** then the highest transaction state of any schema on database connection D
+** is returned. Transaction states are (in order of lowest to highest):
+** <ol>
+** <li value="0"> SQLITE_TXN_NONE
+** <li value="1"> SQLITE_TXN_READ
+** <li value="2"> SQLITE_TXN_WRITE
+** </ol>
+** ^If the S argument to sqlite3_txn_state(D,S) is not the name of
+** a valid schema, then -1 is returned.
+*/
+SQLITE_API int sqlite3_txn_state(sqlite3*,const char *zSchema);
+
+/*
+** CAPI3REF: Allowed return values from [sqlite3_txn_state()]
+** KEYWORDS: {transaction state}
+**
+** These constants define the current transaction state of a database file.
+** ^The [sqlite3_txn_state(D,S)] interface returns one of these
+** constants in order to describe the transaction state of schema S
+** in [database connection] D.
+**
+** <dl>
+** [[SQLITE_TXN_NONE]] <dt>SQLITE_TXN_NONE</dt>
+** <dd>The SQLITE_TXN_NONE state means that no transaction is currently
+** pending.</dd>
+**
+** [[SQLITE_TXN_READ]] <dt>SQLITE_TXN_READ</dt>
+** <dd>The SQLITE_TXN_READ state means that the database is currently
+** in a read transaction. Content has been read from the database file
+** but nothing in the database file has changed. The transaction state
+** will advanced to SQLITE_TXN_WRITE if any changes occur and there are
+** no other conflicting concurrent write transactions. The transaction
+** state will revert to SQLITE_TXN_NONE following a [ROLLBACK] or
+** [COMMIT].</dd>
+**
+** [[SQLITE_TXN_WRITE]] <dt>SQLITE_TXN_WRITE</dt>
+** <dd>The SQLITE_TXN_WRITE state means that the database is currently
+** in a write transaction. Content has been written to the database file
+** but has not yet committed. The transaction state will change to
+** to SQLITE_TXN_NONE at the next [ROLLBACK] or [COMMIT].</dd>
+*/
+#define SQLITE_TXN_NONE 0
+#define SQLITE_TXN_READ 1
+#define SQLITE_TXN_WRITE 2
+
+/*
** CAPI3REF: Find the next prepared statement
** METHOD: sqlite3
**
@@ -8760,7 +8812,8 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_RESULT_INTREAL 27
#define SQLITE_TESTCTRL_PRNG_SEED 28
#define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29
-#define SQLITE_TESTCTRL_LAST 29 /* Largest TESTCTRL */
+#define SQLITE_TESTCTRL_SEEK_COUNT 30
+#define SQLITE_TESTCTRL_LAST 30 /* Largest TESTCTRL */
/*
** CAPI3REF: SQL Keyword Checking
@@ -10240,10 +10293,11 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
** CAPI3REF: Determine If Virtual Table Column Access Is For UPDATE
**
** If the sqlite3_vtab_nochange(X) routine is called within the [xColumn]
-** method of a [virtual table], then it returns true if and only if the
+** method of a [virtual table], then it might return true if the
** column is being fetched as part of an UPDATE operation during which the
-** column value will not change. Applications might use this to substitute
-** a return value that is less expensive to compute and that the corresponding
+** column value will not change. The virtual table implementation can use
+** this hint as permission to substitute a return value that is less
+** expensive to compute and that the corresponding
** [xUpdate] method understands as a "no-change" value.
**
** If the [xColumn] method calls sqlite3_vtab_nochange() and finds that
@@ -10252,6 +10306,12 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
** any of the [sqlite3_result_int|sqlite3_result_xxxxx() interfaces].
** In that case, [sqlite3_value_nochange(X)] will return true for the
** same column in the [xUpdate] method.
+**
+** The sqlite3_vtab_nochange() routine is an optimization. Virtual table
+** implementations should continue to give a correct answer even if the
+** sqlite3_vtab_nochange() interface were to always return false. In the
+** current implementation, the sqlite3_vtab_nochange() interface does always
+** returns false for the enhanced [UPDATE FROM] statement.
*/
SQLITE_API int sqlite3_vtab_nochange(sqlite3_context*);
@@ -10393,6 +10453,7 @@ SQLITE_API void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
/*
** CAPI3REF: Flush caches to disk mid-transaction
+** METHOD: sqlite3
**
** ^If a write-transaction is open on [database connection] D when the
** [sqlite3_db_cacheflush(D)] interface invoked, any dirty
@@ -10425,6 +10486,7 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*);
/*
** CAPI3REF: The pre-update hook.
+** METHOD: sqlite3
**
** ^These interfaces are only available if SQLite is compiled using the
** [SQLITE_ENABLE_PREUPDATE_HOOK] compile-time option.
@@ -10465,7 +10527,7 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*);
** seventh parameter is the final rowid value of the row being inserted
** or updated. The value of the seventh parameter passed to the callback
** function is not defined for operations on WITHOUT ROWID tables, or for
-** INSERT operations on rowid tables.
+** DELETE operations on rowid tables.
**
** The [sqlite3_preupdate_old()], [sqlite3_preupdate_new()],
** [sqlite3_preupdate_count()], and [sqlite3_preupdate_depth()] interfaces
@@ -10527,6 +10589,7 @@ SQLITE_API int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **);
/*
** CAPI3REF: Low-level system error code
+** METHOD: sqlite3
**
** ^Attempt to return the underlying operating system error code or error
** number that caused the most recent I/O error or failure to open a file.
@@ -13297,11 +13360,7 @@ struct fts5_api {
** The maximum depth of an expression tree. This is limited to
** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might
** want to place more severe limits on the complexity of an
-** expression.
-**
-** A value of 0 used to mean that the limit was not enforced.
-** But that is no longer true. The limit is now strictly enforced
-** at all times.
+** expression. A value of 0 means that there is no limit.
*/
#ifndef SQLITE_MAX_EXPR_DEPTH
# define SQLITE_MAX_EXPR_DEPTH 1000
@@ -15082,16 +15141,24 @@ SQLITE_PRIVATE int sqlite3BtreeCommit(Btree*);
SQLITE_PRIVATE int sqlite3BtreeRollback(Btree*,int,int);
SQLITE_PRIVATE int sqlite3BtreeBeginStmt(Btree*,int);
SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree*, Pgno*, int flags);
-SQLITE_PRIVATE int sqlite3BtreeIsInTrans(Btree*);
-SQLITE_PRIVATE int sqlite3BtreeIsInReadTrans(Btree*);
+SQLITE_PRIVATE int sqlite3BtreeTxnState(Btree*);
SQLITE_PRIVATE int sqlite3BtreeIsInBackup(Btree*);
+
SQLITE_PRIVATE void *sqlite3BtreeSchema(Btree *, int, void(*)(void *));
SQLITE_PRIVATE int sqlite3BtreeSchemaLocked(Btree *pBtree);
#ifndef SQLITE_OMIT_SHARED_CACHE
SQLITE_PRIVATE int sqlite3BtreeLockTable(Btree *pBtree, int iTab, u8 isWriteLock);
#endif
+
+/* Savepoints are named, nestable SQL transactions mostly implemented */
+/* in vdbe.c and pager.c See https://sqlite.org/lang_savepoint.html */
SQLITE_PRIVATE int sqlite3BtreeSavepoint(Btree *, int, int);
+/* "Checkpoint" only refers to WAL. See https://sqlite.org/wal.html#ckpt */
+#ifndef SQLITE_OMIT_WAL
+SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree*, int, int *, int *);
+#endif
+
SQLITE_PRIVATE const char *sqlite3BtreeGetFilename(Btree *);
SQLITE_PRIVATE const char *sqlite3BtreeGetJournalname(Btree *);
SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *, Btree *);
@@ -15328,6 +15395,12 @@ SQLITE_PRIVATE int sqlite3BtreeCursorHasHint(BtCursor*, unsigned int mask);
SQLITE_PRIVATE int sqlite3BtreeIsReadonly(Btree *pBt);
SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void);
+#ifdef SQLITE_DEBUG
+SQLITE_PRIVATE sqlite3_uint64 sqlite3BtreeSeekCount(Btree*);
+#else
+# define sqlite3BtreeSeekCount(X) 0
+#endif
+
#ifndef NDEBUG
SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor*);
#endif
@@ -15681,64 +15754,65 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_String8 115 /* same as TK_STRING, synopsis: r[P2]='P4' */
#define OP_Close 116
#define OP_ColumnsUsed 117
-#define OP_SeekHit 118 /* synopsis: seekHit=P2 */
-#define OP_Sequence 119 /* synopsis: r[P2]=cursor[P1].ctr++ */
-#define OP_NewRowid 120 /* synopsis: r[P2]=rowid */
-#define OP_Insert 121 /* synopsis: intkey=r[P3] data=r[P2] */
-#define OP_Delete 122
-#define OP_ResetCount 123
-#define OP_SorterCompare 124 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
-#define OP_SorterData 125 /* synopsis: r[P2]=data */
-#define OP_RowData 126 /* synopsis: r[P2]=data */
-#define OP_Rowid 127 /* synopsis: r[P2]=rowid */
-#define OP_NullRow 128
-#define OP_SeekEnd 129
-#define OP_IdxInsert 130 /* synopsis: key=r[P2] */
-#define OP_SorterInsert 131 /* synopsis: key=r[P2] */
-#define OP_IdxDelete 132 /* synopsis: key=r[P2@P3] */
-#define OP_DeferredSeek 133 /* synopsis: Move P3 to P1.rowid if needed */
-#define OP_IdxRowid 134 /* synopsis: r[P2]=rowid */
-#define OP_FinishSeek 135
-#define OP_Destroy 136
-#define OP_Clear 137
-#define OP_ResetSorter 138
-#define OP_CreateBtree 139 /* synopsis: r[P2]=root iDb=P1 flags=P3 */
-#define OP_SqlExec 140
-#define OP_ParseSchema 141
-#define OP_LoadAnalysis 142
-#define OP_DropTable 143
-#define OP_DropIndex 144
-#define OP_DropTrigger 145
-#define OP_IntegrityCk 146
-#define OP_RowSetAdd 147 /* synopsis: rowset(P1)=r[P2] */
-#define OP_Param 148
-#define OP_FkCounter 149 /* synopsis: fkctr[P1]+=P2 */
+#define OP_SeekScan 118 /* synopsis: Scan-ahead up to P1 rows */
+#define OP_SeekHit 119 /* synopsis: set P2<=seekHit<=P3 */
+#define OP_Sequence 120 /* synopsis: r[P2]=cursor[P1].ctr++ */
+#define OP_NewRowid 121 /* synopsis: r[P2]=rowid */
+#define OP_Insert 122 /* synopsis: intkey=r[P3] data=r[P2] */
+#define OP_Delete 123
+#define OP_ResetCount 124
+#define OP_SorterCompare 125 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
+#define OP_SorterData 126 /* synopsis: r[P2]=data */
+#define OP_RowData 127 /* synopsis: r[P2]=data */
+#define OP_Rowid 128 /* synopsis: r[P2]=rowid */
+#define OP_NullRow 129
+#define OP_SeekEnd 130
+#define OP_IdxInsert 131 /* synopsis: key=r[P2] */
+#define OP_SorterInsert 132 /* synopsis: key=r[P2] */
+#define OP_IdxDelete 133 /* synopsis: key=r[P2@P3] */
+#define OP_DeferredSeek 134 /* synopsis: Move P3 to P1.rowid if needed */
+#define OP_IdxRowid 135 /* synopsis: r[P2]=rowid */
+#define OP_FinishSeek 136
+#define OP_Destroy 137
+#define OP_Clear 138
+#define OP_ResetSorter 139
+#define OP_CreateBtree 140 /* synopsis: r[P2]=root iDb=P1 flags=P3 */
+#define OP_SqlExec 141
+#define OP_ParseSchema 142
+#define OP_LoadAnalysis 143
+#define OP_DropTable 144
+#define OP_DropIndex 145
+#define OP_DropTrigger 146
+#define OP_IntegrityCk 147
+#define OP_RowSetAdd 148 /* synopsis: rowset(P1)=r[P2] */
+#define OP_Param 149
#define OP_Real 150 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
-#define OP_MemMax 151 /* synopsis: r[P1]=max(r[P1],r[P2]) */
-#define OP_OffsetLimit 152 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */
-#define OP_AggInverse 153 /* synopsis: accum=r[P3] inverse(r[P2@P5]) */
-#define OP_AggStep 154 /* synopsis: accum=r[P3] step(r[P2@P5]) */
-#define OP_AggStep1 155 /* synopsis: accum=r[P3] step(r[P2@P5]) */
-#define OP_AggValue 156 /* synopsis: r[P3]=value N=P2 */
-#define OP_AggFinal 157 /* synopsis: accum=r[P1] N=P2 */
-#define OP_Expire 158
-#define OP_CursorLock 159
-#define OP_CursorUnlock 160
-#define OP_TableLock 161 /* synopsis: iDb=P1 root=P2 write=P3 */
-#define OP_VBegin 162
-#define OP_VCreate 163
-#define OP_VDestroy 164
-#define OP_VOpen 165
-#define OP_VColumn 166 /* synopsis: r[P3]=vcolumn(P2) */
-#define OP_VRename 167
-#define OP_Pagecount 168
-#define OP_MaxPgcnt 169
-#define OP_Trace 170
-#define OP_CursorHint 171
-#define OP_ReleaseReg 172 /* synopsis: release r[P1@P2] mask P3 */
-#define OP_Noop 173
-#define OP_Explain 174
-#define OP_Abortable 175
+#define OP_FkCounter 151 /* synopsis: fkctr[P1]+=P2 */
+#define OP_MemMax 152 /* synopsis: r[P1]=max(r[P1],r[P2]) */
+#define OP_OffsetLimit 153 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */
+#define OP_AggInverse 154 /* synopsis: accum=r[P3] inverse(r[P2@P5]) */
+#define OP_AggStep 155 /* synopsis: accum=r[P3] step(r[P2@P5]) */
+#define OP_AggStep1 156 /* synopsis: accum=r[P3] step(r[P2@P5]) */
+#define OP_AggValue 157 /* synopsis: r[P3]=value N=P2 */
+#define OP_AggFinal 158 /* synopsis: accum=r[P1] N=P2 */
+#define OP_Expire 159
+#define OP_CursorLock 160
+#define OP_CursorUnlock 161
+#define OP_TableLock 162 /* synopsis: iDb=P1 root=P2 write=P3 */
+#define OP_VBegin 163
+#define OP_VCreate 164
+#define OP_VDestroy 165
+#define OP_VOpen 166
+#define OP_VColumn 167 /* synopsis: r[P3]=vcolumn(P2) */
+#define OP_VRename 168
+#define OP_Pagecount 169
+#define OP_MaxPgcnt 170
+#define OP_Trace 171
+#define OP_CursorHint 172
+#define OP_ReleaseReg 173 /* synopsis: release r[P1@P2] mask P3 */
+#define OP_Noop 174
+#define OP_Explain 175
+#define OP_Abortable 176
/* Properties such as "out2" or "jump" that are specified in
** comments following the "case" for each opcode in the vdbe.c
@@ -15765,15 +15839,15 @@ typedef struct VdbeOpList VdbeOpList;
/* 88 */ 0x20, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\
/* 96 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x26, 0x26,\
/* 104 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x00,\
-/* 112 */ 0x12, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10,\
-/* 120 */ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\
-/* 128 */ 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x10, 0x00,\
-/* 136 */ 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,\
-/* 144 */ 0x00, 0x00, 0x00, 0x06, 0x10, 0x00, 0x10, 0x04,\
-/* 152 */ 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 112 */ 0x12, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,\
+/* 120 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 128 */ 0x10, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x10,\
+/* 136 */ 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,\
+/* 144 */ 0x00, 0x00, 0x00, 0x00, 0x06, 0x10, 0x10, 0x00,\
+/* 152 */ 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
/* 160 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 168 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-}
+/* 168 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 176 */ 0x00,}
/* The sqlite3P2Values() routine is able to run faster if it knows
** the value of the largest JUMP opcode. The smaller the maximum
@@ -17550,6 +17624,7 @@ struct Table {
#define TF_OOOHidden 0x0400 /* Out-of-Order hidden columns */
#define TF_HasNotNull 0x0800 /* Contains NOT NULL constraints */
#define TF_Shadow 0x1000 /* True for a shadow table */
+#define TF_HasStat4 0x2000 /* STAT4 info available for this table */
/*
** Test to see whether or not a table is a virtual table. This is
@@ -18078,7 +18153,7 @@ struct Expr {
#define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */
#define EP_Win 0x008000 /* Contains window functions */
#define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */
- /* 0x020000 // available for reuse */
+#define EP_IfNullRow 0x020000 /* The TK_IF_NULL_ROW opcode */
#define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */
#define EP_ConstFunc 0x080000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */
#define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */
@@ -18316,9 +18391,9 @@ struct SrcList {
#define WHERE_DISTINCTBY 0x0080 /* pOrderby is really a DISTINCT clause */
#define WHERE_WANT_DISTINCT 0x0100 /* All output needs to be distinct */
#define WHERE_SORTBYGROUP 0x0200 /* Support sqlite3WhereIsSorted() */
-#define WHERE_SEEK_TABLE 0x0400 /* Do not defer seeks on main table */
+ /* 0x0400 not currently used */
#define WHERE_ORDERBY_LIMIT 0x0800 /* ORDERBY+LIMIT on the inner loop */
-#define WHERE_SEEK_UNIQ_TABLE 0x1000 /* Do not defer seeks if unique */
+ /* 0x1000 not currently used */
/* 0x2000 not currently used */
#define WHERE_USE_LIMIT 0x4000 /* Use the LIMIT in cost estimates */
/* 0x8000 not currently used */
@@ -18515,9 +18590,6 @@ struct Select {
** statements within triggers whose only purpose is
** the side-effects of functions.
**
-** All of the above are free to ignore their ORDER BY clause. Those that
-** follow must honor the ORDER BY clause.
-**
** SRT_Output Generate a row of output (using the OP_ResultRow
** opcode) for each row in the result set.
**
@@ -18574,13 +18646,18 @@ struct Select {
#define SRT_Except 2 /* Remove result from a UNION index */
#define SRT_Exists 3 /* Store 1 if the result is not empty */
#define SRT_Discard 4 /* Do not save the results anywhere */
-#define SRT_Fifo 5 /* Store result as data with an automatic rowid */
-#define SRT_DistFifo 6 /* Like SRT_Fifo, but unique results only */
+#define SRT_DistFifo 5 /* Like SRT_Fifo, but unique results only */
+#define SRT_DistQueue 6 /* Like SRT_Queue, but unique results only */
+
+/* The DISTINCT clause is ignored for all of the above. Not that
+** IgnorableDistinct() implies IgnorableOrderby() */
+#define IgnorableDistinct(X) ((X->eDest)<=SRT_DistQueue)
+
#define SRT_Queue 7 /* Store result in an queue */
-#define SRT_DistQueue 8 /* Like SRT_Queue, but unique results only */
+#define SRT_Fifo 8 /* Store result as data with an automatic rowid */
/* The ORDER BY clause is ignored for all of the above */
-#define IgnorableOrderby(X) ((X->eDest)<=SRT_DistQueue)
+#define IgnorableOrderby(X) ((X->eDest)<=SRT_Fifo)
#define SRT_Output 9 /* Output each row of result */
#define SRT_Mem 10 /* Store result in a memory cell */
@@ -19235,7 +19312,6 @@ SQLITE_PRIVATE int sqlite3WindowCompare(Parse*, Window*, Window*, int);
SQLITE_PRIVATE void sqlite3WindowCodeInit(Parse*, Select*);
SQLITE_PRIVATE void sqlite3WindowCodeStep(Parse*, Select*, WhereInfo*, int, int);
SQLITE_PRIVATE int sqlite3WindowRewrite(Parse*, Select*);
-SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse*, struct SrcList_item*);
SQLITE_PRIVATE void sqlite3WindowUpdate(Parse*, Window*, Window*, FuncDef*);
SQLITE_PRIVATE Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p);
SQLITE_PRIVATE Window *sqlite3WindowListDup(sqlite3 *db, Window *p);
@@ -19547,7 +19623,7 @@ SQLITE_PRIVATE void sqlite3ColumnPropertiesFromName(Table*, Column*);
SQLITE_PRIVATE void sqlite3AddColumn(Parse*,Token*,Token*);
SQLITE_PRIVATE void sqlite3AddNotNull(Parse*, int);
SQLITE_PRIVATE void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int);
-SQLITE_PRIVATE void sqlite3AddCheckConstraint(Parse*, Expr*);
+SQLITE_PRIVATE void sqlite3AddCheckConstraint(Parse*, Expr*, const char*, const char*);
SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,Expr*,const char*,const char*);
SQLITE_PRIVATE void sqlite3AddCollateType(Parse*, Token*);
SQLITE_PRIVATE void sqlite3AddGenerated(Parse*,Expr*,Token*);
@@ -19973,6 +20049,7 @@ SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*, int);
SQLITE_PRIVATE void sqlite3CodeRhsOfIN(Parse*, Expr*, int);
SQLITE_PRIVATE int sqlite3CodeSubselect(Parse*, Expr*);
SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*);
+SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse*, struct SrcList_item*);
SQLITE_PRIVATE void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p);
SQLITE_PRIVATE int sqlite3MatchEName(
const struct ExprList_item*,
@@ -20795,7 +20872,7 @@ struct VdbeCursor {
Bool isEphemeral:1; /* True for an ephemeral table */
Bool useRandomRowid:1; /* Generate new record numbers semi-randomly */
Bool isOrdered:1; /* True if the table is not BTREE_UNORDERED */
- Bool seekHit:1; /* See the OP_SeekHit and OP_IfNoHope opcodes */
+ u16 seekHit; /* See the OP_SeekHit and OP_IfNoHope opcodes */
Btree *pBtx; /* Separate file holding temporary table */
i64 seqCount; /* Sequence counter */
u32 *aAltMap; /* Mapping from table to index column numbers */
@@ -27791,12 +27868,17 @@ SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, u64 nBytes){
if( nOld==nNew ){
pNew = pOld;
}else if( sqlite3GlobalConfig.bMemstat ){
+ sqlite3_int64 nUsed;
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, (int)nBytes);
nDiff = nNew - nOld;
- if( nDiff>0 && sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >=
+ if( nDiff>0 && (nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED)) >=
mem0.alarmThreshold-nDiff ){
sqlite3MallocAlarm(nDiff);
+ if( mem0.hardLimit>0 && nUsed >= mem0.hardLimit - nDiff ){
+ sqlite3_mutex_leave(mem0.mutex);
+ return 0;
+ }
}
pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
@@ -28103,12 +28185,15 @@ SQLITE_PRIVATE void sqlite3OomClear(sqlite3 *db){
}
/*
-** Take actions at the end of an API call to indicate an OOM error
+** Take actions at the end of an API call to deal with error codes.
*/
-static SQLITE_NOINLINE int apiOomError(sqlite3 *db){
- sqlite3OomClear(db);
- sqlite3Error(db, SQLITE_NOMEM);
- return SQLITE_NOMEM_BKPT;
+static SQLITE_NOINLINE int apiHandleError(sqlite3 *db, int rc){
+ if( db->mallocFailed || rc==SQLITE_IOERR_NOMEM ){
+ sqlite3OomClear(db);
+ sqlite3Error(db, SQLITE_NOMEM);
+ return SQLITE_NOMEM_BKPT;
+ }
+ return rc & db->errMask;
}
/*
@@ -28130,8 +28215,8 @@ SQLITE_PRIVATE int sqlite3ApiExit(sqlite3* db, int rc){
*/
assert( db!=0 );
assert( sqlite3_mutex_held(db->mutex) );
- if( db->mallocFailed || rc==SQLITE_IOERR_NOMEM ){
- return apiOomError(db);
+ if( db->mallocFailed || rc ){
+ return apiHandleError(db, rc);
}
return rc & db->errMask;
}
@@ -28567,11 +28652,10 @@ SQLITE_API void sqlite3_str_vappendf(
v = va_arg(ap,int);
}
if( v<0 ){
- if( v==SMALLEST_INT64 ){
- longvalue = ((u64)1)<<63;
- }else{
- longvalue = -v;
- }
+ testcase( v==SMALLEST_INT64 );
+ testcase( v==(-1) );
+ longvalue = ~v;
+ longvalue++;
prefix = '-';
}else{
longvalue = v;
@@ -31867,6 +31951,7 @@ SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc
incr = 1;
}else{
incr = 2;
+ length &= ~1;
assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
for(i=3-enc; i<length && zNum[i]==0; i+=2){}
nonNum = i<length;
@@ -33283,64 +33368,65 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 115 */ "String8" OpHelp("r[P2]='P4'"),
/* 116 */ "Close" OpHelp(""),
/* 117 */ "ColumnsUsed" OpHelp(""),
- /* 118 */ "SeekHit" OpHelp("seekHit=P2"),
- /* 119 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
- /* 120 */ "NewRowid" OpHelp("r[P2]=rowid"),
- /* 121 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
- /* 122 */ "Delete" OpHelp(""),
- /* 123 */ "ResetCount" OpHelp(""),
- /* 124 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
- /* 125 */ "SorterData" OpHelp("r[P2]=data"),
- /* 126 */ "RowData" OpHelp("r[P2]=data"),
- /* 127 */ "Rowid" OpHelp("r[P2]=rowid"),
- /* 128 */ "NullRow" OpHelp(""),
- /* 129 */ "SeekEnd" OpHelp(""),
- /* 130 */ "IdxInsert" OpHelp("key=r[P2]"),
- /* 131 */ "SorterInsert" OpHelp("key=r[P2]"),
- /* 132 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
- /* 133 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"),
- /* 134 */ "IdxRowid" OpHelp("r[P2]=rowid"),
- /* 135 */ "FinishSeek" OpHelp(""),
- /* 136 */ "Destroy" OpHelp(""),
- /* 137 */ "Clear" OpHelp(""),
- /* 138 */ "ResetSorter" OpHelp(""),
- /* 139 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"),
- /* 140 */ "SqlExec" OpHelp(""),
- /* 141 */ "ParseSchema" OpHelp(""),
- /* 142 */ "LoadAnalysis" OpHelp(""),
- /* 143 */ "DropTable" OpHelp(""),
- /* 144 */ "DropIndex" OpHelp(""),
- /* 145 */ "DropTrigger" OpHelp(""),
- /* 146 */ "IntegrityCk" OpHelp(""),
- /* 147 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
- /* 148 */ "Param" OpHelp(""),
- /* 149 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
+ /* 118 */ "SeekScan" OpHelp("Scan-ahead up to P1 rows"),
+ /* 119 */ "SeekHit" OpHelp("set P2<=seekHit<=P3"),
+ /* 120 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
+ /* 121 */ "NewRowid" OpHelp("r[P2]=rowid"),
+ /* 122 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
+ /* 123 */ "Delete" OpHelp(""),
+ /* 124 */ "ResetCount" OpHelp(""),
+ /* 125 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
+ /* 126 */ "SorterData" OpHelp("r[P2]=data"),
+ /* 127 */ "RowData" OpHelp("r[P2]=data"),
+ /* 128 */ "Rowid" OpHelp("r[P2]=rowid"),
+ /* 129 */ "NullRow" OpHelp(""),
+ /* 130 */ "SeekEnd" OpHelp(""),
+ /* 131 */ "IdxInsert" OpHelp("key=r[P2]"),
+ /* 132 */ "SorterInsert" OpHelp("key=r[P2]"),
+ /* 133 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
+ /* 134 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"),
+ /* 135 */ "IdxRowid" OpHelp("r[P2]=rowid"),
+ /* 136 */ "FinishSeek" OpHelp(""),
+ /* 137 */ "Destroy" OpHelp(""),
+ /* 138 */ "Clear" OpHelp(""),
+ /* 139 */ "ResetSorter" OpHelp(""),
+ /* 140 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"),
+ /* 141 */ "SqlExec" OpHelp(""),
+ /* 142 */ "ParseSchema" OpHelp(""),
+ /* 143 */ "LoadAnalysis" OpHelp(""),
+ /* 144 */ "DropTable" OpHelp(""),
+ /* 145 */ "DropIndex" OpHelp(""),
+ /* 146 */ "DropTrigger" OpHelp(""),
+ /* 147 */ "IntegrityCk" OpHelp(""),
+ /* 148 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
+ /* 149 */ "Param" OpHelp(""),
/* 150 */ "Real" OpHelp("r[P2]=P4"),
- /* 151 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
- /* 152 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
- /* 153 */ "AggInverse" OpHelp("accum=r[P3] inverse(r[P2@P5])"),
- /* 154 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"),
- /* 155 */ "AggStep1" OpHelp("accum=r[P3] step(r[P2@P5])"),
- /* 156 */ "AggValue" OpHelp("r[P3]=value N=P2"),
- /* 157 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
- /* 158 */ "Expire" OpHelp(""),
- /* 159 */ "CursorLock" OpHelp(""),
- /* 160 */ "CursorUnlock" OpHelp(""),
- /* 161 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
- /* 162 */ "VBegin" OpHelp(""),
- /* 163 */ "VCreate" OpHelp(""),
- /* 164 */ "VDestroy" OpHelp(""),
- /* 165 */ "VOpen" OpHelp(""),
- /* 166 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
- /* 167 */ "VRename" OpHelp(""),
- /* 168 */ "Pagecount" OpHelp(""),
- /* 169 */ "MaxPgcnt" OpHelp(""),
- /* 170 */ "Trace" OpHelp(""),
- /* 171 */ "CursorHint" OpHelp(""),
- /* 172 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"),
- /* 173 */ "Noop" OpHelp(""),
- /* 174 */ "Explain" OpHelp(""),
- /* 175 */ "Abortable" OpHelp(""),
+ /* 151 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
+ /* 152 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
+ /* 153 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
+ /* 154 */ "AggInverse" OpHelp("accum=r[P3] inverse(r[P2@P5])"),
+ /* 155 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"),
+ /* 156 */ "AggStep1" OpHelp("accum=r[P3] step(r[P2@P5])"),
+ /* 157 */ "AggValue" OpHelp("r[P3]=value N=P2"),
+ /* 158 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
+ /* 159 */ "Expire" OpHelp(""),
+ /* 160 */ "CursorLock" OpHelp(""),
+ /* 161 */ "CursorUnlock" OpHelp(""),
+ /* 162 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
+ /* 163 */ "VBegin" OpHelp(""),
+ /* 164 */ "VCreate" OpHelp(""),
+ /* 165 */ "VDestroy" OpHelp(""),
+ /* 166 */ "VOpen" OpHelp(""),
+ /* 167 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
+ /* 168 */ "VRename" OpHelp(""),
+ /* 169 */ "Pagecount" OpHelp(""),
+ /* 170 */ "MaxPgcnt" OpHelp(""),
+ /* 171 */ "Trace" OpHelp(""),
+ /* 172 */ "CursorHint" OpHelp(""),
+ /* 173 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"),
+ /* 174 */ "Noop" OpHelp(""),
+ /* 175 */ "Explain" OpHelp(""),
+ /* 176 */ "Abortable" OpHelp(""),
};
return azName[i];
}
@@ -33472,7 +33558,8 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
# if defined(__APPLE__) && ((__MAC_OS_X_VERSION_MIN_REQUIRED > 1050) || \
(__IPHONE_OS_VERSION_MIN_REQUIRED > 2000))
# if (!defined(TARGET_OS_EMBEDDED) || (TARGET_OS_EMBEDDED==0)) \
- && (!defined(TARGET_IPHONE_SIMULATOR) || (TARGET_IPHONE_SIMULATOR==0))
+ && (!defined(TARGET_IPHONE_SIMULATOR) || (TARGET_IPHONE_SIMULATOR==0))\
+ && (!defined(TARGET_OS_MACCATALYST) || (TARGET_OS_MACCATALYST==0))
# undef HAVE_GETHOSTUUID
# define HAVE_GETHOSTUUID 1
# else
@@ -35092,6 +35179,9 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
return rc;
}
+/* Forward declaration*/
+static int unixSleep(sqlite3_vfs*,int);
+
/*
** Set a posix-advisory-lock.
**
@@ -35121,7 +35211,7 @@ static int osSetPosixAdvisoryLock(
** 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);
+ unixSleep(0,1000);
rc = osFcntl(h,F_SETLK,pLock);
tm--;
}
@@ -35692,6 +35782,7 @@ static int unixClose(sqlite3_file *id){
}
sqlite3_mutex_leave(pInode->pLockMutex);
releaseInodeInfo(pFile);
+ assert( pFile->pShm==0 );
rc = closeUnixFile(id);
unixLeaveMutex();
return rc;
@@ -36918,7 +37009,24 @@ static int unixRead(
if( got==amt ){
return SQLITE_OK;
}else if( got<0 ){
- /* lastErrno set by seekAndRead */
+ /* pFile->lastErrno has been set by seekAndRead().
+ ** Usually we return SQLITE_IOERR_READ here, though for some
+ ** kinds of errors we return SQLITE_IOERR_CORRUPTFS. The
+ ** SQLITE_IOERR_CORRUPTFS will be converted into SQLITE_CORRUPT
+ ** prior to returning to the application by the sqlite3ApiExit()
+ ** routine.
+ */
+ switch( pFile->lastErrno ){
+ case ERANGE:
+ case EIO:
+#ifdef ENXIO
+ case ENXIO:
+#endif
+#ifdef EDEVERR
+ case EDEVERR:
+#endif
+ return SQLITE_IOERR_CORRUPTFS;
+ }
return SQLITE_IOERR_READ;
}else{
storeLastErrno(pFile, 0); /* not a system error */
@@ -37802,6 +37910,7 @@ struct unixShmNode {
char **apRegion; /* Array of mapped shared-memory regions */
int nRef; /* Number of unixShm objects pointing to this */
unixShm *pFirst; /* All unixShm objects pointing to this */
+ int aLock[SQLITE_SHM_NLOCK]; /* # shared locks on slot, -1==excl lock */
#ifdef SQLITE_DEBUG
u8 exclMask; /* Mask of exclusive locks held */
u8 sharedMask; /* Mask of shared locks held */
@@ -38343,6 +38452,38 @@ shmpage_out:
}
/*
+** Check that the pShmNode->aLock[] array comports with the locking bitmasks
+** held by each client. Return true if it does, or false otherwise. This
+** is to be used in an assert(). e.g.
+**
+** assert( assertLockingArrayOk(pShmNode) );
+*/
+#ifdef SQLITE_DEBUG
+static int assertLockingArrayOk(unixShmNode *pShmNode){
+ unixShm *pX;
+ int aLock[SQLITE_SHM_NLOCK];
+ assert( sqlite3_mutex_held(pShmNode->pShmMutex) );
+
+ memset(aLock, 0, sizeof(aLock));
+ for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
+ int i;
+ for(i=0; i<SQLITE_SHM_NLOCK; i++){
+ if( pX->exclMask & (1<<i) ){
+ assert( aLock[i]==0 );
+ aLock[i] = -1;
+ }else if( pX->sharedMask & (1<<i) ){
+ assert( aLock[i]>=0 );
+ aLock[i]++;
+ }
+ }
+ }
+
+ assert( 0==memcmp(pShmNode->aLock, aLock, sizeof(aLock)) );
+ return (memcmp(pShmNode->aLock, aLock, sizeof(aLock))==0);
+}
+#endif
+
+/*
** Change the lock state for a shared-memory segment.
**
** Note that the relationship between SHAREd and EXCLUSIVE locks is a little
@@ -38358,10 +38499,10 @@ static int unixShmLock(
){
unixFile *pDbFd = (unixFile*)fd; /* Connection holding shared memory */
unixShm *p = pDbFd->pShm; /* The shared memory being locked */
- unixShm *pX; /* For looping over all siblings */
unixShmNode *pShmNode = p->pShmNode; /* The underlying file iNode */
int rc = SQLITE_OK; /* Result code */
u16 mask; /* Mask of locks to take or release */
+ int *aLock = pShmNode->aLock;
assert( pShmNode==pDbFd->pInode->pShmNode );
assert( pShmNode->pInode==pDbFd->pInode );
@@ -38400,78 +38541,76 @@ static int unixShmLock(
mask = (1<<(ofst+n)) - (1<<ofst);
assert( n>1 || mask==(1<<ofst) );
sqlite3_mutex_enter(pShmNode->pShmMutex);
+ assert( assertLockingArrayOk(pShmNode) );
if( flags & SQLITE_SHM_UNLOCK ){
- u16 allMask = 0; /* Mask of locks held by siblings */
+ if( (p->exclMask|p->sharedMask) & mask ){
+ int ii;
+ int bUnlock = 1;
- /* See if any siblings hold this same lock */
- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
- if( pX==p ) continue;
- assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
- allMask |= pX->sharedMask;
- }
+ for(ii=ofst; ii<ofst+n; ii++){
+ if( aLock[ii]>((p->sharedMask & (1<<ii)) ? 1 : 0) ){
+ bUnlock = 0;
+ }
+ }
- /* Unlock the system-level locks */
- if( (mask & allMask)==0 ){
- rc = unixShmSystemLock(pDbFd, F_UNLCK, ofst+UNIX_SHM_BASE, n);
- }else{
- rc = SQLITE_OK;
- }
+ if( bUnlock ){
+ rc = unixShmSystemLock(pDbFd, F_UNLCK, ofst+UNIX_SHM_BASE, n);
+ if( rc==SQLITE_OK ){
+ memset(&aLock[ofst], 0, sizeof(int)*n);
+ }
+ }else if( ALWAYS(p->sharedMask & (1<<ofst)) ){
+ assert( n==1 && aLock[ofst]>1 );
+ aLock[ofst]--;
+ }
- /* Undo the local locks */
- if( rc==SQLITE_OK ){
- p->exclMask &= ~mask;
- p->sharedMask &= ~mask;
+ /* Undo the local locks */
+ if( rc==SQLITE_OK ){
+ p->exclMask &= ~mask;
+ p->sharedMask &= ~mask;
+ }
}
}else if( flags & SQLITE_SHM_SHARED ){
- u16 allShared = 0; /* Union of locks held by connections other than "p" */
-
- /* Find out which shared locks are already held by sibling connections.
- ** If any sibling already holds an exclusive lock, go ahead and return
- ** SQLITE_BUSY.
- */
- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
- if( (pX->exclMask & mask)!=0 ){
+ assert( n==1 );
+ assert( (p->exclMask & (1<<ofst))==0 );
+ if( (p->sharedMask & mask)==0 ){
+ if( aLock[ofst]<0 ){
rc = SQLITE_BUSY;
- break;
- }
- allShared |= pX->sharedMask;
- }
-
- /* Get shared locks at the system level, if necessary */
- if( rc==SQLITE_OK ){
- if( (allShared & mask)==0 ){
+ }else if( aLock[ofst]==0 ){
rc = unixShmSystemLock(pDbFd, F_RDLCK, ofst+UNIX_SHM_BASE, n);
- }else{
- rc = SQLITE_OK;
}
- }
- /* Get the local shared locks */
- if( rc==SQLITE_OK ){
- p->sharedMask |= mask;
+ /* Get the local shared locks */
+ if( rc==SQLITE_OK ){
+ p->sharedMask |= mask;
+ aLock[ofst]++;
+ }
}
}else{
/* Make sure no sibling connections hold locks that will block this
- ** lock. If any do, return SQLITE_BUSY right away.
- */
- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
- if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){
+ ** lock. If any do, return SQLITE_BUSY right away. */
+ int ii;
+ for(ii=ofst; ii<ofst+n; ii++){
+ assert( (p->sharedMask & mask)==0 );
+ if( ALWAYS((p->exclMask & (1<<ii))==0) && aLock[ii] ){
rc = SQLITE_BUSY;
break;
}
}
- /* Get the exclusive locks at the system level. Then if successful
- ** also mark the local connection as being locked.
- */
+ /* Get the exclusive locks at the system level. Then if successful
+ ** also update the in-memory values. */
if( rc==SQLITE_OK ){
rc = unixShmSystemLock(pDbFd, F_WRLCK, ofst+UNIX_SHM_BASE, n);
if( rc==SQLITE_OK ){
assert( (p->sharedMask & mask)==0 );
p->exclMask |= mask;
+ for(ii=ofst; ii<ofst+n; ii++){
+ aLock[ii] = -1;
+ }
}
}
}
+ assert( assertLockingArrayOk(pShmNode) );
sqlite3_mutex_leave(pShmNode->pShmMutex);
OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n",
p->id, osGetpid(0), p->sharedMask, p->exclMask));
@@ -39848,7 +39987,26 @@ static int unixAccess(
}
/*
+** If the last component of the pathname in z[0]..z[j-1] is something
+** other than ".." then back it out and return true. If the last
+** component is empty or if it is ".." then return false.
+*/
+static int unixBackupDir(const char *z, int *pJ){
+ int j = *pJ;
+ int i;
+ if( j<=0 ) return 0;
+ for(i=j-1; ALWAYS(i>0) && z[i-1]!='/'; i--){}
+ if( z[i]=='.' && i==j-2 && z[i+1]=='.' ) return 0;
+ *pJ = i-1;
+ return 1;
+}
+
+/*
+** Convert a relative pathname into a full pathname. Also
+** simplify the pathname as follows:
**
+** Remove all instances of /./
+** Remove all isntances of /X/../ for any X
*/
static int mkFullPathname(
const char *zPath, /* Input path */
@@ -39857,6 +40015,7 @@ static int mkFullPathname(
){
int nPath = sqlite3Strlen30(zPath);
int iOff = 0;
+ int i, j;
if( zPath[0]!='/' ){
if( osGetcwd(zOut, nOut-2)==0 ){
return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath);
@@ -39871,6 +40030,41 @@ static int mkFullPathname(
return SQLITE_CANTOPEN_BKPT;
}
sqlite3_snprintf(nOut-iOff, &zOut[iOff], "%s", zPath);
+
+ /* Remove duplicate '/' characters. Except, two // at the beginning
+ ** of a pathname is allowed since this is important on windows. */
+ for(i=j=1; zOut[i]; i++){
+ zOut[j++] = zOut[i];
+ while( zOut[i]=='/' && zOut[i+1]=='/' ) i++;
+ }
+ zOut[j] = 0;
+
+ assert( zOut[0]=='/' );
+ for(i=j=0; zOut[i]; i++){
+ if( zOut[i]=='/' ){
+ /* Skip over internal "/." directory components */
+ if( zOut[i+1]=='.' && zOut[i+2]=='/' ){
+ i += 1;
+ continue;
+ }
+
+ /* If this is a "/.." directory component then back out the
+ ** previous term of the directory if it is something other than "..".
+ */
+ if( zOut[i+1]=='.'
+ && zOut[i+2]=='.'
+ && zOut[i+3]=='/'
+ && unixBackupDir(zOut, &j)
+ ){
+ i += 2;
+ continue;
+ }
+ }
+ if( ALWAYS(j>=0) ) zOut[j] = zOut[i];
+ j++;
+ }
+ if( NEVER(j==0) ) zOut[j++] = '/';
+ zOut[j] = 0;
return SQLITE_OK;
}
@@ -40091,7 +40285,8 @@ static int unixSleep(sqlite3_vfs *NotUsed, int microseconds){
UNUSED_PARAMETER(NotUsed);
return microseconds;
#elif defined(HAVE_USLEEP) && HAVE_USLEEP
- usleep(microseconds);
+ if( microseconds>=1000000 ) sleep(microseconds/1000000);
+ if( microseconds%1000000 ) usleep(microseconds%1000000);
UNUSED_PARAMETER(NotUsed);
return microseconds;
#else
@@ -40664,7 +40859,7 @@ static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){
if( nTries==1 ){
conchModTime = buf.st_mtimespec;
- usleep(500000); /* wait 0.5 sec and try the lock again*/
+ unixSleep(0,500000); /* wait 0.5 sec and try the lock again*/
continue;
}
@@ -40690,7 +40885,7 @@ static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){
/* don't break the lock on short read or a version mismatch */
return SQLITE_BUSY;
}
- usleep(10000000); /* wait 10 sec and try the lock again */
+ unixSleep(0,10000000); /* wait 10 sec and try the lock again */
continue;
}
@@ -46811,7 +47006,11 @@ static int winOpen(
dwCreationDisposition = OPEN_EXISTING;
}
- dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
+ if( 0==sqlite3_uri_boolean(zName, "exclusive", 0) ){
+ dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
+ }else{
+ dwShareMode = 0;
+ }
if( isDelete ){
#if SQLITE_OS_WINCE
@@ -47964,11 +48163,14 @@ static const sqlite3_io_methods memdb_io_methods = {
** Close an memdb-file.
**
** The pData pointer is owned by the application, so there is nothing
-** to free.
+** to free. Unless the SQLITE_DESERIALIZE_FREEONCLOSE flag is set,
+** in which case we own the pData pointer and need to free it.
*/
static int memdbClose(sqlite3_file *pFile){
MemFile *p = (MemFile *)pFile;
- if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ) sqlite3_free(p->aData);
+ if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ){
+ sqlite3_free(p->aData);
+ }
return SQLITE_OK;
}
@@ -48411,8 +48613,12 @@ SQLITE_API int sqlite3_deserialize(
goto end_deserialize;
}
zSql = sqlite3_mprintf("ATTACH x AS %Q", zSchema);
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
- sqlite3_free(zSql);
+ if( zSql==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ 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;
@@ -48427,6 +48633,7 @@ SQLITE_API int sqlite3_deserialize(
rc = SQLITE_ERROR;
}else{
p->aData = pData;
+ pData = 0;
p->sz = szDb;
p->szAlloc = szBuf;
p->szMax = szBuf;
@@ -48439,6 +48646,9 @@ SQLITE_API int sqlite3_deserialize(
end_deserialize:
sqlite3_finalize(pStmt);
+ if( pData && (mFlags & SQLITE_DESERIALIZE_FREEONCLOSE)!=0 ){
+ sqlite3_free(pData);
+ }
sqlite3_mutex_leave(db->mutex);
return rc;
}
@@ -54194,6 +54404,7 @@ static int pager_delsuper(Pager *pPager, const char *zSuper){
i64 nSuperJournal; /* Size of super-journal file */
char *zJournal; /* Pointer to one journal within MJ file */
char *zSuperPtr; /* Space to hold super-journal filename */
+ char *zFree = 0; /* Free this buffer */
int nSuperPtr; /* Amount of space allocated to zSuperPtr[] */
/* Allocate space for both the pJournal and pSuper file descriptors.
@@ -54218,11 +54429,13 @@ static int pager_delsuper(Pager *pPager, const char *zSuper){
rc = sqlite3OsFileSize(pSuper, &nSuperJournal);
if( rc!=SQLITE_OK ) goto delsuper_out;
nSuperPtr = pVfs->mxPathname+1;
- zSuperJournal = sqlite3Malloc(nSuperJournal + nSuperPtr + 2);
- if( !zSuperJournal ){
+ zFree = sqlite3Malloc(4 + nSuperJournal + nSuperPtr + 2);
+ if( !zFree ){
rc = SQLITE_NOMEM_BKPT;
goto delsuper_out;
}
+ zFree[0] = zFree[1] = zFree[2] = zFree[3] = 0;
+ zSuperJournal = &zFree[4];
zSuperPtr = &zSuperJournal[nSuperJournal+2];
rc = sqlite3OsRead(pSuper, zSuperJournal, (int)nSuperJournal, 0);
if( rc!=SQLITE_OK ) goto delsuper_out;
@@ -54270,7 +54483,7 @@ static int pager_delsuper(Pager *pPager, const char *zSuper){
rc = sqlite3OsDelete(pVfs, zSuper, 0);
delsuper_out:
- sqlite3_free(zSuperJournal);
+ sqlite3_free(zFree);
if( pSuper ){
sqlite3OsClose(pSuper);
assert( !isOpen(pJournal) );
@@ -54608,7 +54821,11 @@ end_playback:
pPager->changeCountDone = pPager->tempFile;
if( rc==SQLITE_OK ){
- zSuper = pPager->pTmpSpace;
+ /* Leave 4 bytes of space before the super-journal filename in memory.
+ ** This is because it may end up being passed to sqlite3OsOpen(), in
+ ** which case it requires 4 0x00 bytes in memory immediately before
+ ** the filename. */
+ zSuper = &pPager->pTmpSpace[4];
rc = readSuperJournal(pPager->jfd, zSuper, pPager->pVfs->mxPathname+1);
testcase( rc!=SQLITE_OK );
}
@@ -54625,6 +54842,8 @@ end_playback:
/* If there was a super-journal and this routine will return success,
** see if it is possible to delete the super-journal.
*/
+ assert( zSuper==&pPager->pTmpSpace[4] );
+ memset(&zSuper[-4], 0, 4);
rc = pager_delsuper(pPager, zSuper);
testcase( rc!=SQLITE_OK );
}
@@ -63828,6 +64047,9 @@ struct Btree {
u32 iDataVersion; /* Combines with pBt->pPager->iDataVersion */
Btree *pNext; /* List of other sharable Btrees from the same db */
Btree *pPrev; /* Back pointer of the same list */
+#ifdef SQLITE_DEBUG
+ u64 nSeek; /* Calls to sqlite3BtreeMovetoUnpacked() */
+#endif
#ifndef SQLITE_OMIT_SHARED_CACHE
BtLock lock; /* Object used to lock page 1 */
#endif
@@ -63839,11 +64061,25 @@ struct Btree {
** If the shared-data extension is enabled, there may be multiple users
** of the Btree structure. At most one of these may open a write transaction,
** but any number may have active read transactions.
+**
+** These values must match SQLITE_TXN_NONE, SQLITE_TXN_READ, and
+** SQLITE_TXN_WRITE
*/
#define TRANS_NONE 0
#define TRANS_READ 1
#define TRANS_WRITE 2
+#if TRANS_NONE!=SQLITE_TXN_NONE
+# error wrong numeric code for no-transaction
+#endif
+#if TRANS_READ!=SQLITE_TXN_READ
+# error wrong numeric code for read-transaction
+#endif
+#if TRANS_WRITE!=SQLITE_TXN_WRITE
+# error wrong numeric code for write-transaction
+#endif
+
+
/*
** An instance of this object represents a single database file.
**
@@ -64595,6 +64831,17 @@ SQLITE_API int sqlite3_enable_shared_cache(int enable){
#define hasReadConflicts(a, b) 0
#endif
+#ifdef SQLITE_DEBUG
+/*
+** Return and reset the seek counter for a Btree object.
+*/
+SQLITE_PRIVATE sqlite3_uint64 sqlite3BtreeSeekCount(Btree *pBt){
+ u64 n = pBt->nSeek;
+ pBt->nSeek = 0;
+ return n;
+}
+#endif
+
/*
** Implementation of the SQLITE_CORRUPT_PAGE() macro. Takes a single
** (MemPage*) as an argument. The (MemPage*) must not be NULL.
@@ -67088,7 +67335,7 @@ btree_open_out:
** do not change the pager-cache size.
*/
if( sqlite3BtreeSchema(p, 0, 0)==0 ){
- sqlite3PagerSetCachesize(p->pBt->pPager, SQLITE_DEFAULT_CACHE_SIZE);
+ sqlite3BtreeSetCacheSize(p, SQLITE_DEFAULT_CACHE_SIZE);
}
pFile = sqlite3PagerFile(pBt->pPager);
@@ -69942,6 +70189,10 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
}
}
+#ifdef SQLITE_DEBUG
+ pCur->pBtree->nSeek++; /* Performance measurement during testing */
+#endif
+
if( pIdxKey ){
xRecordCompare = sqlite3VdbeFindCompare(pIdxKey);
pIdxKey->errCode = 0;
@@ -70218,7 +70469,7 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur){
pPage = pCur->pPage;
idx = ++pCur->ix;
- if( !pPage->isInit ){
+ if( !pPage->isInit || sqlite3FaultSim(412) ){
/* The only known way for this to happen is for there to be a
** recursive SQL function that does a DELETE operation as part of a
** SELECT which deletes content out from under an active cursor
@@ -74793,11 +75044,12 @@ SQLITE_PRIVATE const char *sqlite3BtreeGetJournalname(Btree *p){
}
/*
-** Return non-zero if a transaction is active.
+** Return one of SQLITE_TXN_NONE, SQLITE_TXN_READ, or SQLITE_TXN_WRITE
+** to describe the current transaction state of Btree p.
*/
-SQLITE_PRIVATE int sqlite3BtreeIsInTrans(Btree *p){
+SQLITE_PRIVATE int sqlite3BtreeTxnState(Btree *p){
assert( p==0 || sqlite3_mutex_held(p->db->mutex) );
- return (p && (p->inTrans==TRANS_WRITE));
+ return p ? p->inTrans : 0;
}
#ifndef SQLITE_OMIT_WAL
@@ -74826,14 +75078,8 @@ SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree *p, int eMode, int *pnLog, int *
#endif
/*
-** Return non-zero if a read (or write) transaction is active.
+** Return true if there is currently a backup running on Btree p.
*/
-SQLITE_PRIVATE int sqlite3BtreeIsInReadTrans(Btree *p){
- assert( p );
- assert( sqlite3_mutex_held(p->db->mutex) );
- return p->inTrans!=TRANS_NONE;
-}
-
SQLITE_PRIVATE int sqlite3BtreeIsInBackup(Btree *p){
assert( p );
assert( sqlite3_mutex_held(p->db->mutex) );
@@ -75179,7 +75425,7 @@ static int setDestPgsz(sqlite3_backup *p){
** message in database handle db.
*/
static int checkReadTransaction(sqlite3 *db, Btree *p){
- if( sqlite3BtreeIsInReadTrans(p) ){
+ if( sqlite3BtreeTxnState(p)!=SQLITE_TXN_NONE ){
sqlite3ErrorWithMsg(db, SQLITE_ERROR, "destination database is in use");
return SQLITE_ERROR;
}
@@ -75410,7 +75656,7 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
** one now. If a transaction is opened here, then it will be closed
** before this function exits.
*/
- if( rc==SQLITE_OK && 0==sqlite3BtreeIsInReadTrans(p->pSrc) ){
+ if( rc==SQLITE_OK && SQLITE_TXN_NONE==sqlite3BtreeTxnState(p->pSrc) ){
rc = sqlite3BtreeBeginTrans(p->pSrc, 0, 0);
bCloseTrans = 1;
}
@@ -75782,7 +76028,7 @@ SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
sqlite3BtreeEnter(pTo);
sqlite3BtreeEnter(pFrom);
- assert( sqlite3BtreeIsInTrans(pTo) );
+ assert( sqlite3BtreeTxnState(pTo)==SQLITE_TXN_WRITE );
pFd = sqlite3PagerFile(sqlite3BtreePager(pTo));
if( pFd->pMethods ){
i64 nByte = sqlite3BtreeGetPageSize(pFrom)*(i64)sqlite3BtreeLastPage(pFrom);
@@ -75818,7 +76064,7 @@ SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
sqlite3PagerClearCache(sqlite3BtreePager(b.pDest));
}
- assert( sqlite3BtreeIsInTrans(pTo)==0 );
+ assert( sqlite3BtreeTxnState(pTo)!=SQLITE_TXN_WRITE );
copy_finished:
sqlite3BtreeLeave(pFrom);
sqlite3BtreeLeave(pTo);
@@ -78213,6 +78459,7 @@ SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere){
int j;
sqlite3VdbeAddOp4(p, OP_ParseSchema, iDb, 0, 0, zWhere, P4_DYNAMIC);
for(j=0; j<p->db->nDb; j++) sqlite3VdbeUsesBtree(p, j);
+ sqlite3MayAbort(p->pParse);
}
/*
@@ -78441,7 +78688,7 @@ SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename
|| opcode==OP_VDestroy
|| opcode==OP_VCreate
- || (opcode==OP_ParseSchema && pOp->p4.z==0)
+ || opcode==OP_ParseSchema
|| ((opcode==OP_Halt || opcode==OP_HaltIfNull)
&& ((pOp->p1)!=SQLITE_OK && pOp->p2==OE_Abort))
){
@@ -79259,7 +79506,7 @@ SQLITE_PRIVATE char *sqlite3VdbeDisplayComment(
sqlite3_str_appendf(&x, "%d", v1);
}else if( pCtx->argc>1 ){
sqlite3_str_appendf(&x, "%d..%d", v1, v1+pCtx->argc-1);
- }else{
+ }else if( x.accError==0 ){
assert( x.nChar>2 );
x.nChar -= 2;
ii++;
@@ -80401,7 +80648,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
*/
for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
- if( sqlite3BtreeIsInTrans(pBt) ){
+ if( sqlite3BtreeTxnState(pBt)==SQLITE_TXN_WRITE ){
/* Whether or not a database might need a super-journal depends upon
** its journal mode (among other things). This matrix determines which
** journal modes use a super-journal and which do not */
@@ -80536,7 +80783,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
*/
for(i=0; i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
- if( sqlite3BtreeIsInTrans(pBt) ){
+ if( sqlite3BtreeTxnState(pBt)==SQLITE_TXN_WRITE ){
char const *zFile = sqlite3BtreeGetJournalname(pBt);
if( zFile==0 ){
continue; /* Ignore TEMP and :memory: databases */
@@ -82032,9 +82279,12 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3BlobCompare(const Mem *pB1, const Mem
static int sqlite3IntFloatCompare(i64 i, double r){
if( sizeof(LONGDOUBLE_TYPE)>8 ){
LONGDOUBLE_TYPE x = (LONGDOUBLE_TYPE)i;
+ testcase( x<r );
+ testcase( x>r );
+ testcase( x==r );
if( x<r ) return -1;
- if( x>r ) return +1;
- return 0;
+ if( x>r ) return +1; /*NO_TEST*/ /* work around bugs in gcov */
+ return 0; /*NO_TEST*/ /* work around bugs in gcov */
}else{
i64 y;
double s;
@@ -88814,7 +89064,8 @@ case OP_AutoCommit: {
** active.
** If P2 is non-zero, then a write-transaction is started, or if a
** read-transaction is already active, it is upgraded to a write-transaction.
-** If P2 is zero, then a read-transaction is started.
+** If P2 is zero, then a read-transaction is started. If P2 is 2 or more
+** then an exclusive transaction is started.
**
** P1 is the index of the database file on which the transaction is
** started. Index 0 is the main database file and index 1 is the
@@ -88848,6 +89099,7 @@ case OP_Transaction: {
assert( p->bIsReader );
assert( p->readOnly==0 || pOp->p2==0 );
+ assert( pOp->p2>=0 && pOp->p2<=2 );
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( DbMaskTest(p->btreeMask, pOp->p1) );
if( pOp->p2 && (db->flags & SQLITE_QueryOnly)!=0 ){
@@ -88873,7 +89125,7 @@ case OP_Transaction: {
&& pOp->p2
&& (db->autoCommit==0 || db->nVdbeRead>1)
){
- assert( sqlite3BtreeIsInTrans(pBt) );
+ assert( sqlite3BtreeTxnState(pBt)==SQLITE_TXN_WRITE );
if( p->iStatement==0 ){
assert( db->nStatement>=0 && db->nSavepoint>=0 );
db->nStatement++;
@@ -89226,7 +89478,7 @@ case OP_OpenDup: {
}
-/* Opcode: OpenEphemeral P1 P2 * P4 P5
+/* Opcode: OpenEphemeral P1 P2 P3 P4 P5
** Synopsis: nColumn=P2
**
** Open a new cursor P1 to a transient table.
@@ -89246,6 +89498,10 @@ case OP_OpenDup: {
** in btree.h. These flags control aspects of the operation of
** the btree. The BTREE_OMIT_JOURNAL and BTREE_SINGLE flags are
** added automatically.
+**
+** If P3 is positive, then reg[P3] is modified slightly so that it
+** can be used as zero-length data for OP_Insert. This is an optimization
+** that avoids an extra OP_Blob opcode to initialize that register.
*/
/* Opcode: OpenAutoindex P1 P2 * P4 *
** Synopsis: nColumn=P2
@@ -89268,6 +89524,15 @@ case OP_OpenEphemeral: {
SQLITE_OPEN_TRANSIENT_DB;
assert( pOp->p1>=0 );
assert( pOp->p2>=0 );
+ if( pOp->p3>0 ){
+ /* Make register reg[P3] into a value that can be used as the data
+ ** form sqlite3BtreeInsert() where the length of the data is zero. */
+ assert( pOp->p2==0 ); /* Only used when number of columns is zero */
+ assert( pOp->opcode==OP_OpenEphemeral );
+ assert( aMem[pOp->p3].flags & MEM_Null );
+ aMem[pOp->p3].n = 0;
+ aMem[pOp->p3].z = "";
+ }
pCx = p->apCsr[pOp->p1];
if( pCx && pCx->pBtx ){
/* If the ephermeral table is already open, erase all existing content
@@ -89710,22 +89975,172 @@ seek_not_found:
break;
}
-/* Opcode: SeekHit P1 P2 * * *
-** Synopsis: seekHit=P2
+
+/* Opcode: SeekScan P1 P2 * * *
+** Synopsis: Scan-ahead up to P1 rows
+**
+** This opcode is a prefix opcode to OP_SeekGE. In other words, this
+** opcode must be immediately followed by OP_SeekGE. This constraint is
+** checked by assert() statements.
+**
+** This opcode uses the P1 through P4 operands of the subsequent
+** OP_SeekGE. In the text that follows, the operands of the subsequent
+** OP_SeekGE opcode are denoted as SeekOP.P1 through SeekOP.P4. Only
+** the P1 and P2 operands of this opcode are also used, and are called
+** This.P1 and This.P2.
**
-** Set the seekHit flag on cursor P1 to the value in P2.
-** The seekHit flag is used by the IfNoHope opcode.
+** This opcode helps to optimize IN operators on a multi-column index
+** where the IN operator is on the later terms of the index by avoiding
+** unnecessary seeks on the btree, substituting steps to the next row
+** of the b-tree instead. A correct answer is obtained if this opcode
+** is omitted or is a no-op.
**
-** P1 must be a valid b-tree cursor. P2 must be a boolean value,
-** either 0 or 1.
+** The SeekGE.P3 and SeekGE.P4 operands identify an unpacked key which
+** is the desired entry that we want the cursor SeekGE.P1 to be pointing
+** to. Call this SeekGE.P4/P5 row the "target".
+**
+** If the SeekGE.P1 cursor is not currently pointing to a valid row,
+** then this opcode is a no-op and control passes through into the OP_SeekGE.
+**
+** If the SeekGE.P1 cursor is pointing to a valid row, then that row
+** might be the target row, or it might be near and slightly before the
+** target row. This opcode attempts to position the cursor on the target
+** row by, perhaps by invoking sqlite3BtreeStep() on the cursor
+** between 0 and This.P1 times.
+**
+** There are three possible outcomes from this opcode:<ol>
+**
+** <li> If after This.P1 steps, the cursor is still point to a place that
+** is earlier in the btree than the target row,
+** then fall through into the subsquence OP_SeekGE opcode.
+**
+** <li> If the cursor is successfully moved to the target row by 0 or more
+** sqlite3BtreeNext() calls, then jump to This.P2, which will land just
+** past the OP_IdxGT opcode that follows the OP_SeekGE.
+**
+** <li> If the cursor ends up past the target row (indicating the the target
+** row does not exist in the btree) then jump to SeekOP.P2.
+** </ol>
+*/
+case OP_SeekScan: {
+ VdbeCursor *pC;
+ int res;
+ int nStep;
+ UnpackedRecord r;
+
+ assert( pOp[1].opcode==OP_SeekGE );
+
+ /* pOp->p2 points to the first instruction past the OP_IdxGT that
+ ** follows the OP_SeekGE. */
+ assert( pOp->p2>=(int)(pOp-aOp)+2 );
+ assert( aOp[pOp->p2-1].opcode==OP_IdxGT );
+ assert( pOp[1].p1==aOp[pOp->p2-1].p1 );
+ assert( pOp[1].p2==aOp[pOp->p2-1].p2 );
+ assert( pOp[1].p3==aOp[pOp->p2-1].p3 );
+
+ assert( pOp->p1>0 );
+ pC = p->apCsr[pOp[1].p1];
+ assert( pC!=0 );
+ assert( pC->eCurType==CURTYPE_BTREE );
+ assert( !pC->isTable );
+ if( !sqlite3BtreeCursorIsValidNN(pC->uc.pCursor) ){
+#ifdef SQLITE_DEBUG
+ if( db->flags&SQLITE_VdbeTrace ){
+ printf("... cursor not valid - fall through\n");
+ }
+#endif
+ break;
+ }
+ nStep = pOp->p1;
+ assert( nStep>=1 );
+ r.pKeyInfo = pC->pKeyInfo;
+ r.nField = (u16)pOp[1].p4.i;
+ r.default_rc = 0;
+ r.aMem = &aMem[pOp[1].p3];
+#ifdef SQLITE_DEBUG
+ {
+ int i;
+ for(i=0; i<r.nField; i++){
+ assert( memIsValid(&r.aMem[i]) );
+ REGISTER_TRACE(pOp[1].p3+i, &aMem[pOp[1].p3+i]);
+ }
+ }
+#endif
+ res = 0; /* Not needed. Only used to silence a warning. */
+ while(1){
+ rc = sqlite3VdbeIdxKeyCompare(db, pC, &r, &res);
+ if( rc ) goto abort_due_to_error;
+ if( res>0 ){
+ seekscan_search_fail:
+#ifdef SQLITE_DEBUG
+ if( db->flags&SQLITE_VdbeTrace ){
+ printf("... %d steps and then skip\n", pOp->p1 - nStep);
+ }
+#endif
+ VdbeBranchTaken(1,3);
+ pOp++;
+ goto jump_to_p2;
+ }
+ if( res==0 ){
+#ifdef SQLITE_DEBUG
+ if( db->flags&SQLITE_VdbeTrace ){
+ printf("... %d steps and then success\n", pOp->p1 - nStep);
+ }
+#endif
+ VdbeBranchTaken(2,3);
+ goto jump_to_p2;
+ break;
+ }
+ if( nStep<=0 ){
+#ifdef SQLITE_DEBUG
+ if( db->flags&SQLITE_VdbeTrace ){
+ printf("... fall through after %d steps\n", pOp->p1);
+ }
+#endif
+ VdbeBranchTaken(0,3);
+ break;
+ }
+ nStep--;
+ rc = sqlite3BtreeNext(pC->uc.pCursor, 0);
+ if( rc ){
+ if( rc==SQLITE_DONE ){
+ rc = SQLITE_OK;
+ goto seekscan_search_fail;
+ }else{
+ goto abort_due_to_error;
+ }
+ }
+ }
+
+ break;
+}
+
+
+/* Opcode: SeekHit P1 P2 P3 * *
+** Synopsis: set P2<=seekHit<=P3
+**
+** Increase or decrease the seekHit value for cursor P1, if necessary,
+** so that it is no less than P2 and no greater than P3.
+**
+** The seekHit integer represents the maximum of terms in an index for which
+** there is known to be at least one match. If the seekHit value is smaller
+** than the total number of equality terms in an index lookup, then the
+** OP_IfNoHope opcode might run to see if the IN loop can be abandoned
+** early, thus saving work. This is part of the IN-early-out optimization.
+**
+** P1 must be a valid b-tree cursor.
*/
case OP_SeekHit: {
VdbeCursor *pC;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
- assert( pOp->p2==0 || pOp->p2==1 );
- pC->seekHit = pOp->p2 & 1;
+ assert( pOp->p3>=pOp->p2 );
+ if( pC->seekHit<pOp->p2 ){
+ pC->seekHit = pOp->p2;
+ }else if( pC->seekHit>pOp->p3 ){
+ pC->seekHit = pOp->p3;
+ }
break;
}
@@ -89783,16 +90198,20 @@ case OP_IfNotOpen: { /* jump */
** Synopsis: key=r[P3@P4]
**
** Register P3 is the first of P4 registers that form an unpacked
-** record.
+** record. Cursor P1 is an index btree. P2 is a jump destination.
+** In other words, the operands to this opcode are the same as the
+** operands to OP_NotFound and OP_IdxGT.
**
-** Cursor P1 is on an index btree. If the seekHit flag is set on P1, then
-** this opcode is a no-op. But if the seekHit flag of P1 is clear, then
-** check to see if there is any entry in P1 that matches the
-** prefix identified by P3 and P4. If no entry matches the prefix,
-** jump to P2. Otherwise fall through.
+** This opcode is an optimization attempt only. If this opcode always
+** falls through, the correct answer is still obtained, but extra works
+** is performed.
**
-** This opcode behaves like OP_NotFound if the seekHit
-** flag is clear and it behaves like OP_Noop if the seekHit flag is set.
+** A value of N in the seekHit flag of cursor P1 means that there exists
+** a key P3:N that will match some record in the index. We want to know
+** if it is possible for a record P3:P4 to match some record in the
+** index. If it is not possible, we can skips some work. So if seekHit
+** is less than P4, attempt to find out if a match is possible by running
+** OP_NotFound.
**
** This opcode is used in IN clause processing for a multi-column key.
** If an IN clause is attached to an element of the key other than the
@@ -89834,7 +90253,7 @@ case OP_IfNoHope: { /* jump, in3 */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
- if( pC->seekHit ) break;
+ if( pC->seekHit>=pOp->p4.i ) break;
/* Fall through into OP_NotFound */
/* no break */ deliberate_fall_through
}
@@ -89916,6 +90335,7 @@ case OP_Found: { /* jump, in3 */
}else{
VdbeBranchTaken(takeJump||alreadyExists==0,2);
if( takeJump || !alreadyExists ) goto jump_to_p2;
+ if( pOp->opcode==OP_IfNoHope ) pC->seekHit = pOp->p4.i;
}
break;
}
@@ -90272,7 +90692,7 @@ case OP_Insert: {
if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = x.nKey;
- assert( pData->flags & (MEM_Blob|MEM_Str) );
+ assert( (pData->flags & (MEM_Blob|MEM_Str))!=0 || pData->n==0 );
x.pData = pData->z;
x.nData = pData->n;
seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0);
@@ -91148,7 +91568,7 @@ case OP_FinishSeek: {
break;
}
-/* Opcode: IdxGE P1 P2 P3 P4 P5
+/* Opcode: IdxGE P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
** The P4 register values beginning with P3 form an unpacked index
@@ -91159,7 +91579,7 @@ case OP_FinishSeek: {
** If the P1 index entry is greater than or equal to the key value
** then jump to P2. Otherwise fall through to the next instruction.
*/
-/* Opcode: IdxGT P1 P2 P3 P4 P5
+/* Opcode: IdxGT P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
** The P4 register values beginning with P3 form an unpacked index
@@ -91170,7 +91590,7 @@ case OP_FinishSeek: {
** If the P1 index entry is greater than the key value
** then jump to P2. Otherwise fall through to the next instruction.
*/
-/* Opcode: IdxLT P1 P2 P3 P4 P5
+/* Opcode: IdxLT P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
** The P4 register values beginning with P3 form an unpacked index
@@ -91181,7 +91601,7 @@ case OP_FinishSeek: {
** If the P1 index entry is less than the key value then jump to P2.
** Otherwise fall through to the next instruction.
*/
-/* Opcode: IdxLE P1 P2 P3 P4 P5
+/* Opcode: IdxLE P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
** The P4 register values beginning with P3 form an unpacked index
@@ -91207,7 +91627,6 @@ case OP_IdxGE: { /* jump */
assert( pC->eCurType==CURTYPE_BTREE );
assert( pC->uc.pCursor!=0);
assert( pC->deferredMoveto==0 );
- assert( pOp->p5==0 || pOp->p5==1 );
assert( pOp->p4type==P4_INT32 );
r.pKeyInfo = pC->pKeyInfo;
r.nField = (u16)pOp->p4.i;
@@ -91228,8 +91647,31 @@ case OP_IdxGE: { /* jump */
}
}
#endif
- res = 0; /* Not needed. Only used to silence a warning. */
- rc = sqlite3VdbeIdxKeyCompare(db, pC, &r, &res);
+
+ /* Inlined version of sqlite3VdbeIdxKeyCompare() */
+ {
+ i64 nCellKey = 0;
+ BtCursor *pCur;
+ Mem m;
+
+ assert( pC->eCurType==CURTYPE_BTREE );
+ pCur = pC->uc.pCursor;
+ assert( sqlite3BtreeCursorIsValid(pCur) );
+ nCellKey = sqlite3BtreePayloadSize(pCur);
+ /* nCellKey will always be between 0 and 0xffffffff because of the way
+ ** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */
+ if( nCellKey<=0 || nCellKey>0x7fffffff ){
+ rc = SQLITE_CORRUPT_BKPT;
+ goto abort_due_to_error;
+ }
+ sqlite3VdbeMemInit(&m, db, 0);
+ rc = sqlite3VdbeMemFromBtreeZeroOffset(pCur, (u32)nCellKey, &m);
+ if( rc ) goto abort_due_to_error;
+ res = sqlite3VdbeRecordCompareWithSkip(m.n, m.z, &r, 0);
+ sqlite3VdbeMemRelease(&m);
+ }
+ /* End of inlined sqlite3VdbeIdxKeyCompare() */
+
assert( (OP_IdxLE&1)==(OP_IdxLT&1) && (OP_IdxGE&1)==(OP_IdxGT&1) );
if( (pOp->opcode&1)==(OP_IdxLT&1) ){
assert( pOp->opcode==OP_IdxLE || pOp->opcode==OP_IdxLT );
@@ -91239,7 +91681,7 @@ case OP_IdxGE: { /* jump */
res++;
}
VdbeBranchTaken(res>0,2);
- if( rc ) goto abort_due_to_error;
+ assert( rc==SQLITE_OK );
if( res>0 ) goto jump_to_p2;
break;
}
@@ -92365,7 +92807,7 @@ case OP_JournalMode: { /* out2 */
/* Open a transaction on the database file. Regardless of the journal
** mode, this transaction always uses a rollback journal.
*/
- assert( sqlite3BtreeIsInTrans(pBt)==0 );
+ assert( sqlite3BtreeTxnState(pBt)!=SQLITE_TXN_WRITE );
if( rc==SQLITE_OK ){
rc = sqlite3BtreeSetVersion(pBt, (eNew==PAGER_JOURNALMODE_WAL ? 2 : 1));
}
@@ -93305,7 +93747,11 @@ default: { /* This is really OP_Noop, OP_Explain */
** an error of some kind.
*/
abort_due_to_error:
- if( db->mallocFailed ) rc = SQLITE_NOMEM_BKPT;
+ if( db->mallocFailed ){
+ rc = SQLITE_NOMEM_BKPT;
+ }else if( rc==SQLITE_IOERR_CORRUPTFS ){
+ rc = SQLITE_CORRUPT_BKPT;
+ }
assert( rc );
if( p->zErrMsg==0 && rc!=SQLITE_IOERR_NOMEM ){
sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc));
@@ -94854,13 +95300,16 @@ SQLITE_PRIVATE int sqlite3VdbeSorterInit(
if( pSorter==0 ){
rc = SQLITE_NOMEM_BKPT;
}else{
+ Btree *pBt = db->aDb[0].pBt;
pSorter->pKeyInfo = pKeyInfo = (KeyInfo*)((u8*)pSorter + sz);
memcpy(pKeyInfo, pCsr->pKeyInfo, szKeyInfo);
pKeyInfo->db = 0;
if( nField && nWorker==0 ){
pKeyInfo->nKeyField = nField;
}
- pSorter->pgsz = pgsz = sqlite3BtreeGetPageSize(db->aDb[0].pBt);
+ sqlite3BtreeEnter(pBt);
+ pSorter->pgsz = pgsz = sqlite3BtreeGetPageSize(pBt);
+ sqlite3BtreeLeave(pBt);
pSorter->nTask = nWorker + 1;
pSorter->iPrev = (u8)(nWorker - 1);
pSorter->bUseThreads = (pSorter->nTask>1);
@@ -98830,7 +99279,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
assert( !ExprHasProperty(pExpr, EP_Reduced) );
/* Handle special cases of "x IS TRUE", "x IS FALSE", "x IS NOT TRUE",
** and "x IS NOT FALSE". */
- if( pRight && pRight->op==TK_ID ){
+ if( pRight && (pRight->op==TK_ID || pRight->op==TK_TRUEFALSE) ){
int rc = resolveExprStep(pWalker, pRight);
if( rc==WRC_Abort ) return WRC_Abort;
if( pRight->op==TK_TRUEFALSE ){
@@ -99039,6 +99488,7 @@ static int resolveCompoundOrderBy(
Expr *pE, *pDup;
if( pItem->done ) continue;
pE = sqlite3ExprSkipCollateAndLikely(pItem->pExpr);
+ if( NEVER(pE==0) ) continue;
if( sqlite3ExprIsInteger(pE, &iCol) ){
if( iCol<=0 || iCol>pEList->nExpr ){
resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr);
@@ -99218,6 +99668,7 @@ static int resolveOrderGroupBy(
for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
Expr *pE = pItem->pExpr;
Expr *pE2 = sqlite3ExprSkipCollateAndLikely(pE);
+ if( NEVER(pE2==0) ) continue;
if( zType[0]!='G' ){
iCol = resolveAsName(pParse, pSelect->pEList, pE2);
if( iCol>0 ){
@@ -99758,8 +100209,10 @@ SQLITE_PRIVATE char sqlite3TableColumnAffinity(Table *pTab, int iCol){
*/
SQLITE_PRIVATE char sqlite3ExprAffinity(const Expr *pExpr){
int op;
- while( ExprHasProperty(pExpr, EP_Skip) ){
- assert( pExpr->op==TK_COLLATE || pExpr->op==TK_IF_NULL_ROW );
+ while( ExprHasProperty(pExpr, EP_Skip|EP_IfNullRow) ){
+ assert( pExpr->op==TK_COLLATE
+ || pExpr->op==TK_IF_NULL_ROW
+ || (pExpr->op==TK_REGISTER && pExpr->op2==TK_IF_NULL_ROW) );
pExpr = pExpr->pLeft;
assert( pExpr!=0 );
}
@@ -99829,7 +100282,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, con
*/
SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr *pExpr){
while( pExpr && ExprHasProperty(pExpr, EP_Skip) ){
- assert( pExpr->op==TK_COLLATE || pExpr->op==TK_IF_NULL_ROW );
+ assert( pExpr->op==TK_COLLATE );
pExpr = pExpr->pLeft;
}
return pExpr;
@@ -99848,7 +100301,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprSkipCollateAndLikely(Expr *pExpr){
assert( pExpr->op==TK_FUNCTION );
pExpr = pExpr->x.pList->a[0].pExpr;
}else{
- assert( pExpr->op==TK_COLLATE || pExpr->op==TK_IF_NULL_ROW );
+ assert( pExpr->op==TK_COLLATE );
pExpr = pExpr->pLeft;
}
}
@@ -100482,6 +100935,7 @@ SQLITE_PRIVATE int sqlite3SelectExprHeight(Select *p){
** Expr.flags.
*/
SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){
+ if( pParse->nErr ) return;
if( p && p->x.pList && !ExprHasProperty(p, EP_xIsSelect) ){
p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList);
}
@@ -103334,6 +103788,7 @@ SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int n
*/
static void exprToRegister(Expr *pExpr, int iReg){
Expr *p = sqlite3ExprSkipCollateAndLikely(pExpr);
+ if( NEVER(p==0) ) return;
p->op2 = p->op;
p->op = TK_REGISTER;
p->iTable = iReg;
@@ -104321,6 +104776,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){
int r2;
pExpr = sqlite3ExprSkipCollateAndLikely(pExpr);
if( ConstFactorOk(pParse)
+ && ALWAYS(pExpr!=0)
&& pExpr->op!=TK_REGISTER
&& sqlite3ExprIsConstantNotJoin(pExpr)
){
@@ -106995,13 +107451,21 @@ static int renameResolveTrigger(Parse *pParse){
int i;
for(i=0; i<pSrc->nSrc && rc==SQLITE_OK; i++){
struct SrcList_item *p = &pSrc->a[i];
- p->pTab = sqlite3LocateTableItem(pParse, 0, p);
p->iCursor = pParse->nTab++;
- if( p->pTab==0 ){
- rc = SQLITE_ERROR;
+ if( p->pSelect ){
+ sqlite3SelectPrep(pParse, p->pSelect, 0);
+ sqlite3ExpandSubquery(pParse, p);
+ assert( i>0 );
+ assert( pStep->pFrom->a[i-1].pSelect );
+ sqlite3SelectPrep(pParse, pStep->pFrom->a[i-1].pSelect, 0);
}else{
- p->pTab->nTabRef++;
- rc = sqlite3ViewGetColumnNames(pParse, p->pTab);
+ p->pTab = sqlite3LocateTableItem(pParse, 0, p);
+ if( p->pTab==0 ){
+ rc = SQLITE_ERROR;
+ }else{
+ p->pTab->nTabRef++;
+ rc = sqlite3ViewGetColumnNames(pParse, p->pTab);
+ }
}
}
sNC.pSrcList = pSrc;
@@ -107063,6 +107527,12 @@ static void renameWalkTrigger(Walker *pWalker, Trigger *pTrigger){
sqlite3WalkExpr(pWalker, pUpsert->pUpsertWhere);
sqlite3WalkExpr(pWalker, pUpsert->pUpsertTargetWhere);
}
+ if( pStep->pFrom ){
+ int i;
+ for(i=0; i<pStep->pFrom->nSrc; i++){
+ sqlite3WalkSelect(pWalker, pStep->pFrom->a[i].pSelect);
+ }
+ }
}
}
@@ -109321,6 +109791,7 @@ static int loadStatTbl(
}
pSpace = (tRowcnt*)&pIdx->aSample[nSample];
pIdx->aAvgEq = pSpace; pSpace += nIdxCol;
+ pIdx->pTable->tabFlags |= TF_HasStat4;
for(i=0; i<nSample; i++){
pIdx->aSample[i].anEq = pSpace; pSpace += nIdxCol;
pIdx->aSample[i].anLt = pSpace; pSpace += nIdxCol;
@@ -109787,7 +110258,9 @@ static void detachFunc(
sqlite3_snprintf(sizeof(zErr),zErr, "cannot detach database %s", zName);
goto detach_error;
}
- if( sqlite3BtreeIsInReadTrans(pDb->pBt) || sqlite3BtreeIsInBackup(pDb->pBt) ){
+ if( sqlite3BtreeTxnState(pDb->pBt)!=SQLITE_TXN_NONE
+ || sqlite3BtreeIsInBackup(pDb->pBt)
+ ){
sqlite3_snprintf(sizeof(zErr),zErr, "database %s is locked", zName);
goto detach_error;
}
@@ -110447,7 +110920,7 @@ SQLITE_PRIVATE void sqlite3TableLock(
u8 isWriteLock, /* True for a write lock */
const char *zName /* Name of the table to be locked */
){
- Parse *pToplevel = sqlite3ParseToplevel(pParse);
+ Parse *pToplevel;
int i;
int nBytes;
TableLock *p;
@@ -110455,6 +110928,7 @@ SQLITE_PRIVATE void sqlite3TableLock(
if( iDb==1 ) return;
if( !sqlite3BtreeSharable(pParse->db->aDb[iDb].pBt) ) return;
+ pToplevel = sqlite3ParseToplevel(pParse);
for(i=0; i<pToplevel->nTableLock; i++){
p = &pToplevel->aTableLock[i];
if( p->iDb==iDb && p->iTab==iTab ){
@@ -110484,10 +110958,8 @@ SQLITE_PRIVATE void sqlite3TableLock(
*/
static void codeTableLocks(Parse *pParse){
int i;
- Vdbe *pVdbe;
-
- pVdbe = sqlite3GetVdbe(pParse);
- assert( pVdbe!=0 ); /* sqlite3GetVdbe cannot fail: VDBE already allocated */
+ Vdbe *pVdbe = pParse->pVdbe;
+ assert( pVdbe!=0 );
for(i=0; i<pParse->nTableLock; i++){
TableLock *p = &pParse->aTableLock[i];
@@ -112012,8 +112484,10 @@ primary_key_exit:
** Add a new CHECK constraint to the table currently under construction.
*/
SQLITE_PRIVATE void sqlite3AddCheckConstraint(
- Parse *pParse, /* Parsing context */
- Expr *pCheckExpr /* The check expression */
+ Parse *pParse, /* Parsing context */
+ Expr *pCheckExpr, /* The check expression */
+ const char *zStart, /* Opening "(" */
+ const char *zEnd /* Closing ")" */
){
#ifndef SQLITE_OMIT_CHECK
Table *pTab = pParse->pNewTable;
@@ -112024,6 +112498,13 @@ SQLITE_PRIVATE void sqlite3AddCheckConstraint(
pTab->pCheck = sqlite3ExprListAppend(pParse, pTab->pCheck, pCheckExpr);
if( pParse->constraintName.n ){
sqlite3ExprListSetName(pParse, pTab->pCheck, &pParse->constraintName, 1);
+ }else{
+ Token t;
+ for(zStart++; sqlite3Isspace(zStart[0]); zStart++){}
+ while( sqlite3Isspace(zEnd[-1]) ){ zEnd--; }
+ t.z = zStart;
+ t.n = (int)(zEnd - t.z);
+ sqlite3ExprListSetName(pParse, pTab->pCheck, &t, 1);
}
}else
#endif
@@ -112042,7 +112523,7 @@ SQLITE_PRIVATE void sqlite3AddCollateType(Parse *pParse, Token *pToken){
char *zColl; /* Dequoted name of collation sequence */
sqlite3 *db;
- if( (p = pParse->pNewTable)==0 ) return;
+ if( (p = pParse->pNewTable)==0 || IN_RENAME_OBJECT ) return;
i = p->nCol-1;
db = pParse->db;
zColl = sqlite3NameFromToken(db, pToken);
@@ -112277,12 +112758,15 @@ static int resizeIndexObject(sqlite3 *db, Index *pIdx, int N){
int nByte;
if( pIdx->nColumn>=N ) return SQLITE_OK;
assert( pIdx->isResized==0 );
- nByte = (sizeof(char*) + sizeof(i16) + 1)*N;
+ nByte = (sizeof(char*) + sizeof(LogEst) + sizeof(i16) + 1)*N;
zExtra = sqlite3DbMallocZero(db, nByte);
if( zExtra==0 ) return SQLITE_NOMEM_BKPT;
memcpy(zExtra, pIdx->azColl, sizeof(char*)*pIdx->nColumn);
pIdx->azColl = (const char**)zExtra;
zExtra += sizeof(char*)*N;
+ memcpy(zExtra, pIdx->aiRowLogEst, sizeof(LogEst)*(pIdx->nKeyCol+1));
+ pIdx->aiRowLogEst = (LogEst*)zExtra;
+ zExtra += sizeof(LogEst)*N;
memcpy(zExtra, pIdx->aiColumn, sizeof(i16)*pIdx->nColumn);
pIdx->aiColumn = (i16*)zExtra;
zExtra += sizeof(i16)*N;
@@ -114843,7 +115327,7 @@ SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){
assert(pList || pParse->db->mallocFailed );
if( pList ){
for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
- if( pItem->iCursor>=0 ) break;
+ if( pItem->iCursor>=0 ) continue;
pItem->iCursor = pParse->nTab++;
if( pItem->pSelect ){
sqlite3SrcListAssignCursors(pParse, pItem->pSelect->pSrc);
@@ -114860,15 +115344,15 @@ SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
struct SrcList_item *pItem;
if( pList==0 ) return;
for(pItem=pList->a, i=0; i<pList->nSrc; i++, pItem++){
- sqlite3DbFree(db, pItem->zDatabase);
+ if( pItem->zDatabase ) sqlite3DbFreeNN(db, pItem->zDatabase);
sqlite3DbFree(db, pItem->zName);
- sqlite3DbFree(db, pItem->zAlias);
+ if( pItem->zAlias ) sqlite3DbFreeNN(db, pItem->zAlias);
if( pItem->fg.isIndexedBy ) sqlite3DbFree(db, pItem->u1.zIndexedBy);
if( pItem->fg.isTabFunc ) sqlite3ExprListDelete(db, pItem->u1.pFuncArg);
sqlite3DeleteTable(db, pItem->pTab);
- sqlite3SelectDelete(db, pItem->pSelect);
- sqlite3ExprDelete(db, pItem->pOn);
- sqlite3IdListDelete(db, pItem->pUsing);
+ if( pItem->pSelect ) sqlite3SelectDelete(db, pItem->pSelect);
+ if( pItem->pOn ) sqlite3ExprDelete(db, pItem->pOn);
+ if( pItem->pUsing ) sqlite3IdListDelete(db, pItem->pUsing);
}
sqlite3DbFreeNN(db, pList);
}
@@ -115040,7 +115524,16 @@ SQLITE_PRIVATE void sqlite3BeginTransaction(Parse *pParse, int type){
if( !v ) return;
if( type!=TK_DEFERRED ){
for(i=0; i<db->nDb; i++){
- sqlite3VdbeAddOp2(v, OP_Transaction, i, (type==TK_EXCLUSIVE)+1);
+ int eTxnType;
+ Btree *pBt = db->aDb[i].pBt;
+ if( pBt && sqlite3BtreeIsReadonly(pBt) ){
+ eTxnType = 0; /* Read txn */
+ }else if( type==TK_EXCLUSIVE ){
+ eTxnType = 2; /* Exclusive txn */
+ }else{
+ eTxnType = 1; /* Write txn */
+ }
+ sqlite3VdbeAddOp2(v, OP_Transaction, i, eTxnType);
sqlite3VdbeUsesBtree(v, i);
}
}
@@ -115129,13 +115622,11 @@ SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *pParse){
** will occur at the end of the top-level VDBE and will be generated
** later, by sqlite3FinishCoding().
*/
-SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
- Parse *pToplevel = sqlite3ParseToplevel(pParse);
-
- assert( iDb>=0 && iDb<pParse->db->nDb );
- assert( pParse->db->aDb[iDb].pBt!=0 || iDb==1 );
+static void sqlite3CodeVerifySchemaAtToplevel(Parse *pToplevel, int iDb){
+ assert( iDb>=0 && iDb<pToplevel->db->nDb );
+ assert( pToplevel->db->aDb[iDb].pBt!=0 || iDb==1 );
assert( iDb<SQLITE_MAX_ATTACHED+2 );
- assert( sqlite3SchemaMutexHeld(pParse->db, iDb, 0) );
+ assert( sqlite3SchemaMutexHeld(pToplevel->db, iDb, 0) );
if( DbMaskTest(pToplevel->cookieMask, iDb)==0 ){
DbMaskSet(pToplevel->cookieMask, iDb);
if( !OMIT_TEMPDB && iDb==1 ){
@@ -115143,6 +115634,10 @@ SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
}
}
}
+SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
+ sqlite3CodeVerifySchemaAtToplevel(sqlite3ParseToplevel(pParse), iDb);
+}
+
/*
** If argument zDb is NULL, then call sqlite3CodeVerifySchema() for each
@@ -115174,7 +115669,7 @@ SQLITE_PRIVATE void sqlite3CodeVerifyNamedSchema(Parse *pParse, const char *zDb)
*/
SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){
Parse *pToplevel = sqlite3ParseToplevel(pParse);
- sqlite3CodeVerifySchema(pParse, iDb);
+ sqlite3CodeVerifySchemaAtToplevel(pToplevel, iDb);
DbMaskSet(pToplevel->writeMask, iDb);
pToplevel->isMultiWrite |= setStatement;
}
@@ -115225,7 +115720,9 @@ SQLITE_PRIVATE void sqlite3HaltConstraint(
i8 p4type, /* P4_STATIC or P4_TRANSIENT */
u8 p5Errmsg /* P5_ErrMsg type */
){
- Vdbe *v = sqlite3GetVdbe(pParse);
+ Vdbe *v;
+ assert( pParse->pVdbe!=0 );
+ v = sqlite3GetVdbe(pParse);
assert( (errCode&0xff)==SQLITE_CONSTRAINT || pParse->nested );
if( onError==OE_Abort ){
sqlite3MayAbort(pParse);
@@ -116506,7 +117003,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
}else
#endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */
{
- u16 wcf = WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK|WHERE_SEEK_TABLE;
+ u16 wcf = WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK;
if( sNC.ncFlags & NC_VarSelect ) bComplex = 1;
wcf |= (bComplex ? 0 : WHERE_ONEPASS_MULTIROW);
if( HasRowid(pTab) ){
@@ -116542,6 +117039,9 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
assert( IsVirtual(pTab)==0 || eOnePass!=ONEPASS_MULTI );
assert( IsVirtual(pTab) || bComplex || eOnePass!=ONEPASS_OFF );
if( eOnePass!=ONEPASS_SINGLE ) sqlite3MultiWrite(pParse);
+ if( sqlite3WhereUsesDeferredSeek(pWInfo) ){
+ sqlite3VdbeAddOp1(v, OP_FinishSeek, iTabCur);
+ }
/* Keep track of the number of rows to be deleted */
if( memCnt ){
@@ -116576,6 +117076,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iTabCur] = 0;
if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iTabCur] = 0;
if( addrEphOpen ) sqlite3VdbeChangeToNoop(v, addrEphOpen);
+ addrBypass = sqlite3VdbeMakeLabel(pParse);
}else{
if( pPk ){
/* Add the PK key for this row to the temporary table */
@@ -116589,13 +117090,6 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
nKey = 1; /* OP_DeferredSeek always uses a single rowid */
sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, iKey);
}
- }
-
- /* If this DELETE cannot use the ONEPASS strategy, this is the
- ** end of the WHERE loop */
- if( eOnePass!=ONEPASS_OFF ){
- addrBypass = sqlite3VdbeMakeLabel(pParse);
- }else{
sqlite3WhereEnd(pWInfo);
}
@@ -117026,10 +117520,6 @@ SQLITE_PRIVATE int sqlite3GenerateIndexKey(
}
if( regOut ){
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regOut);
- if( pIdx->pTable->pSelect ){
- const char *zAff = sqlite3IndexAffinityStr(pParse->db, pIdx);
- sqlite3VdbeChangeP4(v, -1, zAff, P4_TRANSIENT);
- }
}
sqlite3ReleaseTempRange(pParse, regBase, nCol);
return regBase;
@@ -119045,6 +119535,8 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void){
FUNCTION(zeroblob, 1, 0, 0, zeroblobFunc ),
FUNCTION(substr, 2, 0, 0, substrFunc ),
FUNCTION(substr, 3, 0, 0, substrFunc ),
+ FUNCTION(substring, 2, 0, 0, substrFunc ),
+ FUNCTION(substring, 3, 0, 0, substrFunc ),
WAGGREGATE(sum, 1,0,0, sumStep, sumFinalize, sumFinalize, sumInverse, 0),
WAGGREGATE(total, 1,0,0, sumStep,totalFinalize,totalFinalize,sumInverse, 0),
WAGGREGATE(avg, 1,0,0, sumStep, avgFinalize, avgFinalize, sumInverse, 0),
@@ -120585,7 +121077,8 @@ SQLITE_PRIVATE void sqlite3OpenTable(
){
Vdbe *v;
assert( !IsVirtual(pTab) );
- v = sqlite3GetVdbe(pParse);
+ assert( pParse->pVdbe!=0 );
+ v = pParse->pVdbe;
assert( opcode==OP_OpenWrite || opcode==OP_OpenRead );
sqlite3TableLock(pParse, iDb, pTab->tnum,
(opcode==OP_OpenWrite)?1:0, pTab->zName);
@@ -122084,7 +122577,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
isUpdate = regOldData!=0;
db = pParse->db;
- v = sqlite3GetVdbe(pParse);
+ v = pParse->pVdbe;
assert( v!=0 );
assert( pTab->pSelect==0 ); /* This table is not a VIEW */
nCol = pTab->nCol;
@@ -122238,7 +122731,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
sqlite3VdbeGoto(v, ignoreDest);
}else{
char *zName = pCheck->a[i].zEName;
- if( zName==0 ) zName = pTab->zName;
+ assert( zName!=0 || pParse->db->mallocFailed );
if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-26383-51744 */
sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_CHECK,
onError, zName, P4_TRANSIENT,
@@ -122857,7 +123350,7 @@ SQLITE_PRIVATE void sqlite3CompleteInsertion(
|| update_flags==(OPFLAG_ISUPDATE|OPFLAG_SAVEPOSITION)
);
- v = sqlite3GetVdbe(pParse);
+ v = pParse->pVdbe;
assert( v!=0 );
assert( pTab->pSelect==0 ); /* This table is not a VIEW */
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
@@ -122958,7 +123451,7 @@ SQLITE_PRIVATE int sqlite3OpenTableAndIndices(
return 0;
}
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
- v = sqlite3GetVdbe(pParse);
+ v = pParse->pVdbe;
assert( v!=0 );
if( iBase<0 ) iBase = pParse->nTab;
iDataCur = iBase++;
@@ -123930,6 +124423,8 @@ struct sqlite3_api_routines {
int,const char**);
void (*free_filename)(char*);
sqlite3_file *(*database_file_object)(const char*);
+ /* Version 3.34.0 and later */
+ int (*txn_state)(sqlite3*,const char*);
};
/*
@@ -124234,6 +124729,8 @@ typedef int (*sqlite3_loadext_entry)(
#define sqlite3_create_filename sqlite3_api->create_filename
#define sqlite3_free_filename sqlite3_api->free_filename
#define sqlite3_database_file_object sqlite3_api->database_file_object
+/* Version 3.34.0 and later */
+#define sqlite3_txn_state sqlite3_api->txn_state
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
@@ -124716,6 +125213,8 @@ static const sqlite3_api_routines sqlite3Apis = {
sqlite3_create_filename,
sqlite3_free_filename,
sqlite3_database_file_object,
+ /* Version 3.34.0 and later */
+ sqlite3_txn_state,
};
/* True if x is the directory separator character
@@ -125876,7 +126375,9 @@ static int getTempStore(const char *z){
static int invalidateTempStorage(Parse *pParse){
sqlite3 *db = pParse->db;
if( db->aDb[1].pBt!=0 ){
- if( !db->autoCommit || sqlite3BtreeIsInReadTrans(db->aDb[1].pBt) ){
+ if( !db->autoCommit
+ || sqlite3BtreeTxnState(db->aDb[1].pBt)!=SQLITE_TXN_NONE
+ ){
sqlite3ErrorMsg(pParse, "temporary storage cannot be changed "
"from within a transaction");
return SQLITE_ERROR;
@@ -127196,7 +127697,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
aiCols = 0;
if( pParent ){
x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols);
- assert( x==0 );
+ assert( x==0 || db->mallocFailed );
}
addrOk = sqlite3VdbeMakeLabel(pParse);
@@ -127221,7 +127722,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
int jmp = sqlite3VdbeCurrentAddr(v)+2;
sqlite3VdbeAddOp3(v, OP_SeekRowid, i, jmp, regRow); VdbeCoverage(v);
sqlite3VdbeGoto(v, addrOk);
- assert( pFK->nCol==1 );
+ assert( pFK->nCol==1 || db->mallocFailed );
}
/* Generate code to report an FK violation to the caller. */
@@ -128579,7 +129080,7 @@ SQLITE_PRIVATE int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFl
** on the b-tree database, open one now. If a transaction is opened, it
** will be closed before this function returns. */
sqlite3BtreeEnter(pDb->pBt);
- if( !sqlite3BtreeIsInReadTrans(pDb->pBt) ){
+ if( sqlite3BtreeTxnState(pDb->pBt)==SQLITE_TXN_NONE ){
rc = sqlite3BtreeBeginTrans(pDb->pBt, 0, 0);
if( rc!=SQLITE_OK ){
sqlite3SetString(pzErrMsg, db, sqlite3ErrStr(rc));
@@ -128822,7 +129323,7 @@ static void schemaIsValid(Parse *pParse){
/* If there is not already a read-only (or read-write) transaction opened
** on the b-tree database, open one now. If a transaction is opened, it
** will be closed immediately after reading the meta-value. */
- if( !sqlite3BtreeIsInReadTrans(pBt) ){
+ if( sqlite3BtreeTxnState(pBt)==SQLITE_TXN_NONE ){
rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
sqlite3OomFault(db);
@@ -129085,6 +129586,7 @@ static int sqlite3LockAndPrepare(
sqlite3BtreeLeaveAll(db);
rc = sqlite3ApiExit(db, rc);
assert( (rc&db->errMask)==rc );
+ db->busyHandler.nBusy = 0;
sqlite3_mutex_leave(db->mutex);
return rc;
}
@@ -131271,6 +131773,7 @@ SQLITE_PRIVATE int sqlite3ColumnsFromExprList(
char *zName; /* Column name */
int nName; /* Size of name in zName[] */
Hash ht; /* Hash table of column names */
+ Table *pTab;
sqlite3HashInit(&ht);
if( pEList ){
@@ -131293,15 +131796,13 @@ SQLITE_PRIVATE int sqlite3ColumnsFromExprList(
/* If the column contains an "AS <name>" phrase, use <name> as the name */
}else{
Expr *pColExpr = sqlite3ExprSkipCollateAndLikely(pEList->a[i].pExpr);
- while( pColExpr->op==TK_DOT ){
+ while( ALWAYS(pColExpr!=0) && pColExpr->op==TK_DOT ){
pColExpr = pColExpr->pRight;
assert( pColExpr!=0 );
}
- if( pColExpr->op==TK_COLUMN ){
+ if( pColExpr->op==TK_COLUMN && (pTab = pColExpr->y.pTab)!=0 ){
/* For columns use the column name name */
int iCol = pColExpr->iColumn;
- Table *pTab = pColExpr->y.pTab;
- assert( pTab!=0 );
if( iCol<0 ) iCol = pTab->iPKey;
zName = iCol>=0 ? pTab->aCol[iCol].zName : "rowid";
}else if( pColExpr->op==TK_ID ){
@@ -131639,6 +132140,7 @@ static void generateWithRecursiveQuery(
int nCol = p->pEList->nExpr; /* Number of columns in the recursive table */
Vdbe *v = pParse->pVdbe; /* The prepared statement under construction */
Select *pSetup = p->pPrior; /* The setup query */
+ Select *pFirstRec; /* Left-most recursive term */
int addrTop; /* Top of the loop */
int addrCont, addrBreak; /* CONTINUE and BREAK addresses */
int iCurrent = 0; /* The Current table */
@@ -131714,7 +132216,25 @@ static void generateWithRecursiveQuery(
/* Detach the ORDER BY clause from the compound SELECT */
p->pOrderBy = 0;
+ /* Figure out how many elements of the compound SELECT are part of the
+ ** recursive query. Make sure no recursive elements use aggregate
+ ** functions. Mark the recursive elements as UNION ALL even if they
+ ** are really UNION because the distinctness will be enforced by the
+ ** iDistinct table. pFirstRec is left pointing to the left-most
+ ** recursive term of the CTE.
+ */
+ pFirstRec = p;
+ for(pFirstRec=p; ALWAYS(pFirstRec!=0); pFirstRec=pFirstRec->pPrior){
+ if( pFirstRec->selFlags & SF_Aggregate ){
+ sqlite3ErrorMsg(pParse, "recursive aggregate queries not supported");
+ goto end_of_recursive_query;
+ }
+ pFirstRec->op = TK_ALL;
+ if( (pFirstRec->pPrior->selFlags & SF_Recursive)==0 ) break;
+ }
+
/* Store the results of the setup-query in Queue. */
+ pSetup = pFirstRec->pPrior;
pSetup->pNext = 0;
ExplainQueryPlan((pParse, 1, "SETUP"));
rc = sqlite3Select(pParse, pSetup, &destQueue);
@@ -131747,15 +132267,11 @@ static void generateWithRecursiveQuery(
/* Execute the recursive SELECT taking the single row in Current as
** the value for the recursive-table. Store the results in the Queue.
*/
- if( p->selFlags & SF_Aggregate ){
- sqlite3ErrorMsg(pParse, "recursive aggregate queries not supported");
- }else{
- p->pPrior = 0;
- ExplainQueryPlan((pParse, 1, "RECURSIVE STEP"));
- sqlite3Select(pParse, p, &destQueue);
- assert( p->pPrior==0 );
- p->pPrior = pSetup;
- }
+ pFirstRec->pPrior = 0;
+ ExplainQueryPlan((pParse, 1, "RECURSIVE STEP"));
+ sqlite3Select(pParse, p, &destQueue);
+ assert( pFirstRec->pPrior==0 );
+ pFirstRec->pPrior = pSetup;
/* Keep running the loop until the Queue is empty */
sqlite3VdbeGoto(v, addrTop);
@@ -131825,6 +132341,16 @@ static int multiSelectValues(
}
/*
+** Return true if the SELECT statement which is known to be the recursive
+** part of a recursive CTE still has its anchor terms attached. If the
+** anchor terms have already been removed, then return false.
+*/
+static int hasAnchor(Select *p){
+ while( p && (p->selFlags & SF_Recursive)!=0 ){ p = p->pPrior; }
+ return p!=0;
+}
+
+/*
** This routine is called to process a compound query form from
** two or more separate queries using UNION, UNION ALL, EXCEPT, or
** INTERSECT
@@ -131909,7 +132435,7 @@ static int multiSelect(
assert( p->pEList->nExpr==pPrior->pEList->nExpr );
#ifndef SQLITE_OMIT_CTE
- if( p->selFlags & SF_Recursive ){
+ if( (p->selFlags & SF_Recursive)!=0 && hasAnchor(p) ){
generateWithRecursiveQuery(pParse, p, &dest);
}else
#endif
@@ -132001,6 +132527,7 @@ static int multiSelect(
assert( p->pEList );
}
+
/* Code the SELECT statements to our left
*/
assert( !pPrior->pOrderBy );
@@ -132805,7 +133332,7 @@ static Expr *substExpr(
ifNullRow.op = TK_IF_NULL_ROW;
ifNullRow.pLeft = pCopy;
ifNullRow.iTable = pSubst->iNewTable;
- ifNullRow.flags = EP_Skip;
+ ifNullRow.flags = EP_IfNullRow;
pCopy = &ifNullRow;
}
testcase( ExprHasProperty(pCopy, EP_Subquery) );
@@ -132814,8 +133341,7 @@ static Expr *substExpr(
ExprSetProperty(pNew, EP_CanBeNull);
}
if( pNew && ExprHasProperty(pExpr,EP_FromJoin) ){
- pNew->iRightJoinTable = pExpr->iRightJoinTable;
- ExprSetProperty(pNew, EP_FromJoin);
+ sqlite3SetJoinExpr(pNew, pExpr->iRightJoinTable);
}
sqlite3ExprDelete(db, pExpr);
pExpr = pNew;
@@ -134094,8 +134620,10 @@ static int withExpand(
ExprList *pEList;
Select *pSel;
Select *pLeft; /* Left-most SELECT statement */
+ Select *pRecTerm; /* Left-most recursive term */
int bMayRecursive; /* True if compound joined by UNION [ALL] */
With *pSavedWith; /* Initial value of pParse->pWith */
+ int iRecTab = -1; /* Cursor for recursive table */
/* If pCte->zCteErr is non-NULL at this point, then this is an illegal
** recursive reference to CTE pCte. Leave an error in pParse and return
@@ -134120,44 +134648,48 @@ static int withExpand(
assert( pFrom->pSelect );
/* Check if this is a recursive CTE. */
- pSel = pFrom->pSelect;
+ pRecTerm = pSel = pFrom->pSelect;
bMayRecursive = ( pSel->op==TK_ALL || pSel->op==TK_UNION );
- if( bMayRecursive ){
+ while( bMayRecursive && pRecTerm->op==pSel->op ){
int i;
- SrcList *pSrc = pFrom->pSelect->pSrc;
+ SrcList *pSrc = pRecTerm->pSrc;
+ assert( pRecTerm->pPrior!=0 );
for(i=0; i<pSrc->nSrc; i++){
struct SrcList_item *pItem = &pSrc->a[i];
if( pItem->zDatabase==0
&& pItem->zName!=0
&& 0==sqlite3StrICmp(pItem->zName, pCte->zName)
- ){
+ ){
pItem->pTab = pTab;
- pItem->fg.isRecursive = 1;
pTab->nTabRef++;
- pSel->selFlags |= SF_Recursive;
+ pItem->fg.isRecursive = 1;
+ if( pRecTerm->selFlags & SF_Recursive ){
+ sqlite3ErrorMsg(pParse,
+ "multiple references to recursive table: %s", pCte->zName
+ );
+ return SQLITE_ERROR;
+ }
+ pRecTerm->selFlags |= SF_Recursive;
+ if( iRecTab<0 ) iRecTab = pParse->nTab++;
+ pItem->iCursor = iRecTab;
}
}
+ if( (pRecTerm->selFlags & SF_Recursive)==0 ) break;
+ pRecTerm = pRecTerm->pPrior;
}
- /* Only one recursive reference is permitted. */
- if( pTab->nTabRef>2 ){
- sqlite3ErrorMsg(
- pParse, "multiple references to recursive table: %s", pCte->zName
- );
- return SQLITE_ERROR;
- }
- assert( pTab->nTabRef==1 ||
- ((pSel->selFlags&SF_Recursive) && pTab->nTabRef==2 ));
-
pCte->zCteErr = "circular reference: %s";
pSavedWith = pParse->pWith;
pParse->pWith = pWith;
- if( bMayRecursive ){
- Select *pPrior = pSel->pPrior;
- assert( pPrior->pWith==0 );
- pPrior->pWith = pSel->pWith;
- sqlite3WalkSelect(pWalker, pPrior);
- pPrior->pWith = 0;
+ if( pSel->selFlags & SF_Recursive ){
+ assert( pRecTerm!=0 );
+ assert( (pRecTerm->selFlags & SF_Recursive)==0 );
+ assert( pRecTerm->pNext!=0 );
+ assert( (pRecTerm->pNext->selFlags & SF_Recursive)!=0 );
+ assert( pRecTerm->pWith==0 );
+ pRecTerm->pWith = pSel->pWith;
+ sqlite3WalkSelect(pWalker, pRecTerm);
+ pRecTerm->pWith = 0;
}else{
sqlite3WalkSelect(pWalker, pSel);
}
@@ -134884,7 +135416,9 @@ static void explainSimpleCount(
static int havingToWhereExprCb(Walker *pWalker, Expr *pExpr){
if( pExpr->op!=TK_AND ){
Select *pS = pWalker->u.pSelect;
- if( sqlite3ExprIsConstantOrGroupBy(pWalker->pParse, pExpr, pS->pGroupBy) ){
+ if( sqlite3ExprIsConstantOrGroupBy(pWalker->pParse, pExpr, pS->pGroupBy)
+ && ExprAlwaysFalse(pExpr)==0
+ ){
sqlite3 *db = pWalker->pParse->db;
Expr *pNew = sqlite3Expr(db, TK_INTEGER, "1");
if( pNew ){
@@ -135107,13 +135641,11 @@ SQLITE_PRIVATE int sqlite3Select(
assert( p->pOrderBy==0 || pDest->eDest!=SRT_Fifo );
assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistQueue );
assert( p->pOrderBy==0 || pDest->eDest!=SRT_Queue );
- if( IgnorableOrderby(pDest) ){
- assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union ||
- pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard ||
- pDest->eDest==SRT_Queue || pDest->eDest==SRT_DistFifo ||
- pDest->eDest==SRT_DistQueue || pDest->eDest==SRT_Fifo);
- /* If ORDER BY makes no difference in the output then neither does
- ** DISTINCT so it can be removed too. */
+ if( IgnorableDistinct(pDest) ){
+ assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union ||
+ pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard ||
+ pDest->eDest==SRT_DistQueue || pDest->eDest==SRT_DistFifo );
+ /* All of these destinations are also able to ignore the ORDER BY clause */
sqlite3ExprListDelete(db, p->pOrderBy);
p->pOrderBy = 0;
p->selFlags &= ~SF_Distinct;
@@ -136547,22 +137079,11 @@ SQLITE_PRIVATE void sqlite3BeginTrigger(
pTab = sqlite3SrcListLookup(pParse, pTableName);
if( !pTab ){
/* The table does not exist. */
- if( db->init.iDb==1 ){
- /* Ticket #3810.
- ** Normally, whenever a table is dropped, all associated triggers are
- ** dropped too. But if a TEMP trigger is created on a non-TEMP table
- ** and the table is dropped by a different database connection, the
- ** trigger is not visible to the database connection that does the
- ** drop so the trigger cannot be dropped. This results in an
- ** "orphaned trigger" - a trigger whose associated table is missing.
- */
- db->init.orphanTrigger = 1;
- }
- goto trigger_cleanup;
+ goto trigger_orphan_error;
}
if( IsVirtual(pTab) ){
sqlite3ErrorMsg(pParse, "cannot create triggers on virtual tables");
- goto trigger_cleanup;
+ goto trigger_orphan_error;
}
/* Check that the trigger name is not reserved and that no trigger of the
@@ -136600,12 +137121,12 @@ SQLITE_PRIVATE void sqlite3BeginTrigger(
if( pTab->pSelect && tr_tm!=TK_INSTEAD ){
sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S",
(tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0);
- goto trigger_cleanup;
+ goto trigger_orphan_error;
}
if( !pTab->pSelect && tr_tm==TK_INSTEAD ){
sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF"
" trigger on table: %S", pTableName, 0);
- goto trigger_cleanup;
+ goto trigger_orphan_error;
}
#ifndef SQLITE_OMIT_AUTHORIZATION
@@ -136665,6 +137186,23 @@ trigger_cleanup:
}else{
assert( pParse->pNewTrigger==pTrigger );
}
+ return;
+
+trigger_orphan_error:
+ if( db->init.iDb==1 ){
+ /* Ticket #3810.
+ ** Normally, whenever a table is dropped, all associated triggers are
+ ** dropped too. But if a TEMP trigger is created on a non-TEMP table
+ ** and the table is dropped by a different database connection, the
+ ** trigger is not visible to the database connection that does the
+ ** drop so the trigger cannot be dropped. This results in an
+ ** "orphaned trigger" - a trigger whose associated table is missing.
+ **
+ ** 2020-11-05 see also https://sqlite.org/forum/forumpost/157dc791df
+ */
+ db->init.orphanTrigger = 1;
+ }
+ goto trigger_cleanup;
}
/*
@@ -137835,7 +138373,7 @@ static void updateFromSelect(
#endif
pList = sqlite3ExprListAppend(pParse, pList, pNew);
}
- eDest = SRT_Upfrom;
+ eDest = IsVirtual(pTab) ? SRT_Table : SRT_Upfrom;
}else if( pTab->pSelect ){
for(i=0; i<pTab->nCol; i++){
pList = sqlite3ExprListAppend(pParse, pList, exprRowColumn(pParse, i));
@@ -138252,6 +138790,8 @@ SQLITE_PRIVATE void sqlite3Update(
if( nChangeFrom==0 && HasRowid(pTab) ){
sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid);
+ iEph = pParse->nTab++;
+ addrOpen = sqlite3VdbeAddOp3(v, OP_OpenEphemeral, iEph, 0, regRowSet);
}else{
assert( pPk!=0 || HasRowid(pTab) );
nPk = pPk ? pPk->nKeyCol : 0;
@@ -138306,7 +138846,7 @@ SQLITE_PRIVATE void sqlite3Update(
** be deleted as a result of REPLACE conflict handling. Any of these
** things might disturb a cursor being used to scan through the table
** or index, causing a single-pass approach to malfunction. */
- flags = WHERE_ONEPASS_DESIRED|WHERE_SEEK_UNIQ_TABLE;
+ flags = WHERE_ONEPASS_DESIRED;
if( !pParse->nested && !pTrigger && !hasFK && !chngKey && !bReplace ){
flags |= WHERE_ONEPASS_MULTIROW;
}
@@ -138343,9 +138883,10 @@ SQLITE_PRIVATE void sqlite3Update(
** leave it in register regOldRowid. */
sqlite3VdbeAddOp2(v, OP_Rowid, iDataCur, regOldRowid);
if( eOnePass==ONEPASS_OFF ){
- /* We need to use regRowSet, so reallocate aRegIdx[nAllIdx] */
aRegIdx[nAllIdx] = ++pParse->nMem;
- sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid);
+ sqlite3VdbeAddOp3(v, OP_Insert, iEph, regRowSet, regOldRowid);
+ }else{
+ if( ALWAYS(addrOpen) ) sqlite3VdbeChangeToNoop(v, addrOpen);
}
}else{
/* Read the PK of the current row into an array of registers. In
@@ -138433,8 +138974,9 @@ SQLITE_PRIVATE void sqlite3Update(
VdbeCoverage(v);
}
}else{
- labelContinue = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet,labelBreak,
- regOldRowid);
+ sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v);
+ labelContinue = sqlite3VdbeMakeLabel(pParse);
+ addrTop = sqlite3VdbeAddOp2(v, OP_Rowid, iEph, regOldRowid);
VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid);
VdbeCoverage(v);
@@ -138684,11 +139226,9 @@ SQLITE_PRIVATE void sqlite3Update(
}else if( eOnePass==ONEPASS_MULTI ){
sqlite3VdbeResolveLabel(v, labelContinue);
sqlite3WhereEnd(pWInfo);
- }else if( pPk || nChangeFrom ){
+ }else{
sqlite3VdbeResolveLabel(v, labelContinue);
sqlite3VdbeAddOp2(v, OP_Next, iEph, addrTop); VdbeCoverage(v);
- }else{
- sqlite3VdbeGoto(v, labelContinue);
}
sqlite3VdbeResolveLabel(v, labelBreak);
@@ -138788,12 +139328,26 @@ static void updateVirtualTable(
regArg = pParse->nMem + 1;
pParse->nMem += nArg;
if( pSrc->nSrc>1 ){
+ Index *pPk = 0;
Expr *pRow;
ExprList *pList;
- if( pRowid ){
- pRow = sqlite3ExprDup(db, pRowid, 0);
+ if( HasRowid(pTab) ){
+ if( pRowid ){
+ pRow = sqlite3ExprDup(db, pRowid, 0);
+ }else{
+ pRow = sqlite3PExpr(pParse, TK_ROW, 0, 0);
+ }
}else{
- pRow = sqlite3PExpr(pParse, TK_ROW, 0, 0);
+ i16 iPk; /* PRIMARY KEY column */
+ pPk = sqlite3PrimaryKeyIndex(pTab);
+ assert( pPk!=0 );
+ assert( pPk->nKeyCol==1 );
+ iPk = pPk->aiColumn[0];
+ if( aXRef[iPk]>=0 ){
+ pRow = sqlite3ExprDup(db, pChanges->a[aXRef[iPk]].pExpr, 0);
+ }else{
+ pRow = exprRowColumn(pParse, iPk);
+ }
}
pList = sqlite3ExprListAppend(pParse, 0, pRow);
@@ -138807,7 +139361,7 @@ static void updateVirtualTable(
}
}
- updateFromSelect(pParse, ephemTab, 0, pList, pSrc, pWhere, 0, 0);
+ updateFromSelect(pParse, ephemTab, pPk, pList, pSrc, pWhere, 0, 0);
sqlite3ExprListDelete(db, pList);
eOnePass = ONEPASS_OFF;
}else{
@@ -139509,8 +140063,8 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3RunVacuum(
BTREE_APPLICATION_ID, 0, /* Preserve the application id */
};
- assert( 1==sqlite3BtreeIsInTrans(pTemp) );
- assert( pOut!=0 || 1==sqlite3BtreeIsInTrans(pMain) );
+ assert( SQLITE_TXN_WRITE==sqlite3BtreeTxnState(pTemp) );
+ assert( pOut!=0 || SQLITE_TXN_WRITE==sqlite3BtreeTxnState(pMain) );
/* Copy Btree meta values */
for(i=0; i<ArraySize(aCopy); i+=2){
@@ -141181,9 +141735,11 @@ struct WhereTerm {
u8 eMatchOp; /* Op for vtab MATCH/LIKE/GLOB/REGEXP terms */
int iParent; /* Disable pWC->a[iParent] when this term disabled */
int leftCursor; /* Cursor number of X in "X <op> <expr>" */
- int iField; /* Field in (?,?,?) IN (SELECT...) vector */
union {
- int leftColumn; /* Column number of X in "X <op> <expr>" */
+ struct {
+ int leftColumn; /* Column number of X in "X <op> <expr>" */
+ int iField; /* Field in (?,?,?) IN (SELECT...) vector */
+ } x; /* Opcode other than OP_OR or OP_AND */
WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */
WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */
} u;
@@ -141408,6 +141964,7 @@ struct WhereInfo {
unsigned sorted :1; /* True if really sorted (not just grouped) */
LogEst nRowOut; /* Estimated number of output rows */
int iTop; /* The very beginning of the WHERE loop */
+ int iEndWhere; /* End of the WHERE clause itself */
WhereLoop *pLoops; /* List of all WhereLoop objects */
WhereExprMod *pExprMods; /* Expression modifications */
Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
@@ -141536,6 +142093,7 @@ SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereC
#define WHERE_PARTIALIDX 0x00020000 /* The automatic index is partial */
#define WHERE_IN_EARLYOUT 0x00040000 /* Perhaps quit IN loops early */
#define WHERE_BIGNULL_SORT 0x00080000 /* Column nEq of index is BIGNULL */
+#define WHERE_IN_SEEKSCAN 0x00100000 /* Seek-scan optimization for IN */
#endif /* !defined(SQLITE_WHEREINT_H) */
@@ -141949,7 +142507,7 @@ static Expr *removeUnindexableInClauseTerms(
for(i=iEq; i<pLoop->nLTerm; i++){
if( pLoop->aLTerm[i]->pExpr==pX ){
- int iField = pLoop->aLTerm[i]->iField - 1;
+ int iField = pLoop->aLTerm[i]->u.x.iField - 1;
if( pOrigRhs->a[iField].pExpr==0 ) continue; /* Duplicate PK column */
pRhs = sqlite3ExprListAppend(pParse, pRhs, pOrigRhs->a[iField].pExpr);
pOrigRhs->a[iField].pExpr = 0;
@@ -142092,6 +142650,9 @@ static int codeEqualityTerm(
if( pLevel->u.in.nIn==0 ){
pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse);
}
+ if( iEq>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0 ){
+ pLoop->wsFlags |= WHERE_IN_EARLYOUT;
+ }
i = pLevel->u.in.nIn;
pLevel->u.in.nIn += nEq;
@@ -142118,7 +142679,6 @@ static int codeEqualityTerm(
if( iEq>0 ){
pIn->iBase = iReg - i;
pIn->nPrefix = i;
- pLoop->wsFlags |= WHERE_IN_EARLYOUT;
}else{
pIn->nPrefix = 0;
}
@@ -142128,6 +142688,14 @@ static int codeEqualityTerm(
pIn++;
}
}
+ testcase( iEq>0
+ && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0
+ && (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 );
+ if( iEq>0
+ && (pLoop->wsFlags & (WHERE_IN_SEEKSCAN|WHERE_VIRTUALTABLE))==0
+ ){
+ sqlite3VdbeAddOp3(v, OP_SeekHit, pLevel->iIdxCur, 0, iEq);
+ }
}else{
pLevel->u.in.nIn = 0;
}
@@ -142914,6 +143482,9 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
pLoop->u.vtab.needFree ? P4_DYNAMIC : P4_STATIC);
VdbeCoverage(v);
pLoop->u.vtab.needFree = 0;
+ /* An OOM inside of AddOp4(OP_VFilter) instruction above might have freed
+ ** the u.vtab.idxStr. NULL it out to prevent a use-after-free */
+ if( db->mallocFailed ) pLoop->u.vtab.idxStr = 0;
pLevel->p1 = iCur;
pLevel->op = pWInfo->eOnePass ? OP_Noop : OP_VNext;
pLevel->p2 = sqlite3VdbeCurrentAddr(v);
@@ -143172,6 +143743,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
u8 bStopAtNull = 0; /* Add condition to terminate at NULLs */
int omitTable; /* True if we use the index only */
int regBignull = 0; /* big-null flag register */
+ int addrSeekScan = 0; /* Opcode of the OP_SeekScan, if any */
pIdx = pLoop->u.btree.pIndex;
iIdxCur = pLevel->iIdxCur;
@@ -143310,9 +143882,6 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
** above has already left the cursor sitting on the correct row,
** so no further seeking is needed */
}else{
- if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){
- sqlite3VdbeAddOp1(v, OP_SeekHit, iIdxCur);
- }
if( regBignull ){
sqlite3VdbeAddOp2(v, OP_Integer, 1, regBignull);
VdbeComment((v, "NULL-scan pass ctr"));
@@ -143320,6 +143889,20 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
assert( op!=0 );
+ if( (pLoop->wsFlags & WHERE_IN_SEEKSCAN)!=0 && op==OP_SeekGE ){
+ assert( regBignull==0 );
+ /* TUNING: The OP_SeekScan opcode seeks to reduce the number
+ ** of expensive seek operations by replacing a single seek with
+ ** 1 or more step operations. The question is, how many steps
+ ** should we try before giving up and going with a seek. The cost
+ ** of a seek is proportional to the logarithm of the of the number
+ ** of entries in the tree, so basing the number of steps to try
+ ** on the estimated number of rows in the btree seems like a good
+ ** guess. */
+ addrSeekScan = sqlite3VdbeAddOp1(v, OP_SeekScan,
+ (pIdx->aiRowLogEst[0]+9)/10);
+ VdbeCoverage(v);
+ }
sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
VdbeCoverage(v);
VdbeCoverageIf(v, op==OP_Rewind); testcase( op==OP_Rewind );
@@ -143402,6 +143985,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
testcase( op==OP_IdxGE ); VdbeCoverageIf(v, op==OP_IdxGE );
testcase( op==OP_IdxLT ); VdbeCoverageIf(v, op==OP_IdxLT );
testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE );
+ if( addrSeekScan ) sqlite3VdbeJumpHere(v, addrSeekScan);
}
if( regBignull ){
/* During a NULL-scan, check to see if we have reached the end of
@@ -143421,8 +144005,8 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE );
}
- if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){
- sqlite3VdbeAddOp2(v, OP_SeekHit, iIdxCur, 1);
+ if( (pLoop->wsFlags & WHERE_IN_EARLYOUT)!=0 ){
+ sqlite3VdbeAddOp3(v, OP_SeekHit, iIdxCur, nEq, nEq);
}
/* Seek the table cursor, if required */
@@ -143431,17 +144015,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
if( omitTable ){
/* pIdx is a covering index. No need to access the main table. */
}else if( HasRowid(pIdx->pTable) ){
- if( (pWInfo->wctrlFlags & WHERE_SEEK_TABLE)
- || ( (pWInfo->wctrlFlags & WHERE_SEEK_UNIQ_TABLE)!=0
- && (pWInfo->eOnePass==ONEPASS_SINGLE || pLoop->nLTerm==0) )
- ){
- iRowidReg = ++pParse->nMem;
- sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg);
- sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowidReg);
- VdbeCoverage(v);
- }else{
- codeDeferredSeek(pWInfo, pIdx, iCur, iIdxCur);
- }
+ codeDeferredSeek(pWInfo, pIdx, iCur, iIdxCur);
}else if( iCur!=iIdxCur ){
Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable);
iRowidReg = sqlite3GetTempRange(pParse, pPk->nKeyCol);
@@ -143568,7 +144142,6 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
int iRetInit; /* Address of regReturn init */
int untestedTerms = 0; /* Some terms not completely tested */
int ii; /* Loop counter */
- u16 wctrlFlags; /* Flags for sub-WHERE clause */
Expr *pAndExpr = 0; /* An ".. AND (...)" expression */
Table *pTab = pTabItem->pTab;
@@ -143669,7 +144242,6 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
** eliminating duplicates from other WHERE clauses, the action for each
** sub-WHERE clause is to to invoke the main loop body as a subroutine.
*/
- wctrlFlags = WHERE_OR_SUBCLAUSE | (pWInfo->wctrlFlags & WHERE_SEEK_TABLE);
ExplainQueryPlan((pParse, 1, "MULTI-INDEX OR"));
for(ii=0; ii<pOrWc->nTerm; ii++){
WhereTerm *pOrTerm = &pOrWc->a[ii];
@@ -143688,7 +144260,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
ExplainQueryPlan((pParse, 1, "INDEX %d", ii+1));
WHERETRACE(0xffff, ("Subplan for OR-clause:\n"));
pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
- wctrlFlags, iCovCur);
+ WHERE_OR_SUBCLAUSE, iCovCur);
assert( pSubWInfo || pParse->nErr || db->mallocFailed );
if( pSubWInfo ){
WhereLoop *pSubLoop;
@@ -143786,6 +144358,9 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
}else{
pCov = 0;
}
+ if( sqlite3WhereUsesDeferredSeek(pSubWInfo) ){
+ pWInfo->bDeferredSeek = 1;
+ }
/* Finish the loop through table entries that match term pOrTerm. */
sqlite3WhereEnd(pSubWInfo);
@@ -143938,7 +144513,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
#endif
assert( !ExprHasProperty(pE, EP_FromJoin) );
assert( (pTerm->prereqRight & pLevel->notReady)!=0 );
- pAlt = sqlite3WhereFindTerm(pWC, iCur, pTerm->u.leftColumn, notReady,
+ pAlt = sqlite3WhereFindTerm(pWC, iCur, pTerm->u.x.leftColumn, notReady,
WO_EQ|WO_IN|WO_IS, 0);
if( pAlt==0 ) continue;
if( pAlt->wtFlags & (TERM_CODED) ) continue;
@@ -144794,7 +145369,7 @@ static void exprAnalyzeOrTerm(
assert( pOrTerm->wtFlags & (TERM_COPIED|TERM_VIRTUAL) );
continue;
}
- iColumn = pOrTerm->u.leftColumn;
+ iColumn = pOrTerm->u.x.leftColumn;
iCursor = pOrTerm->leftCursor;
pLeft = pOrTerm->pExpr->pLeft;
break;
@@ -144816,7 +145391,7 @@ static void exprAnalyzeOrTerm(
assert( pOrTerm->eOperator & WO_EQ );
if( pOrTerm->leftCursor!=iCursor ){
pOrTerm->wtFlags &= ~TERM_OR_OK;
- }else if( pOrTerm->u.leftColumn!=iColumn || (iColumn==XN_EXPR
+ }else if( pOrTerm->u.x.leftColumn!=iColumn || (iColumn==XN_EXPR
&& sqlite3ExprCompare(pParse, pOrTerm->pExpr->pLeft, pLeft, -1)
)){
okToChngToIN = 0;
@@ -144851,7 +145426,7 @@ static void exprAnalyzeOrTerm(
if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue;
assert( pOrTerm->eOperator & WO_EQ );
assert( pOrTerm->leftCursor==iCursor );
- assert( pOrTerm->u.leftColumn==iColumn );
+ assert( pOrTerm->u.x.leftColumn==iColumn );
pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0);
pList = sqlite3ExprListAppend(pWInfo->pParse, pList, pDup);
pLeft = pOrTerm->pExpr->pLeft;
@@ -145087,15 +145662,15 @@ static void exprAnalyze(
Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight);
u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV;
- if( pTerm->iField>0 ){
+ if( pTerm->u.x.iField>0 ){
assert( op==TK_IN );
assert( pLeft->op==TK_VECTOR );
- pLeft = pLeft->x.pList->a[pTerm->iField-1].pExpr;
+ pLeft = pLeft->x.pList->a[pTerm->u.x.iField-1].pExpr;
}
if( exprMightBeIndexed(pSrc, prereqLeft, aiCurCol, pLeft, op) ){
pTerm->leftCursor = aiCurCol[0];
- pTerm->u.leftColumn = aiCurCol[1];
+ pTerm->u.x.leftColumn = aiCurCol[1];
pTerm->eOperator = operatorMask(op) & opMask;
}
if( op==TK_IS ) pTerm->wtFlags |= TERM_IS;
@@ -145105,7 +145680,7 @@ static void exprAnalyze(
WhereTerm *pNew;
Expr *pDup;
u16 eExtraOp = 0; /* Extra bits for pNew->eOperator */
- assert( pTerm->iField==0 );
+ assert( pTerm->u.x.iField==0 );
if( pTerm->leftCursor>=0 ){
int idxNew;
pDup = sqlite3ExprDup(db, pExpr, 0);
@@ -145131,7 +145706,7 @@ static void exprAnalyze(
}
pNew->wtFlags |= exprCommute(pParse, pDup);
pNew->leftCursor = aiCurCol[0];
- pNew->u.leftColumn = aiCurCol[1];
+ pNew->u.x.leftColumn = aiCurCol[1];
testcase( (prereqLeft | extraRight) != prereqLeft );
pNew->prereqRight = prereqLeft | extraRight;
pNew->prereqAll = prereqAll;
@@ -145305,7 +145880,7 @@ static void exprAnalyze(
pNewTerm = &pWC->a[idxNew];
pNewTerm->prereqRight = prereqExpr;
pNewTerm->leftCursor = pLeft->iTable;
- pNewTerm->u.leftColumn = pLeft->iColumn;
+ pNewTerm->u.x.leftColumn = pLeft->iColumn;
pNewTerm->eOperator = WO_AUX;
pNewTerm->eMatchOp = eOp2;
markTermAsChild(pWC, idxNew, idxTerm);
@@ -145352,13 +145927,13 @@ static void exprAnalyze(
/* If there is a vector IN term - e.g. "(a, b) IN (SELECT ...)" - create
** a virtual term for each vector component. The expression object
** used by each such virtual term is pExpr (the full vector IN(...)
- ** expression). The WhereTerm.iField variable identifies the index within
+ ** expression). The WhereTerm.u.x.iField variable identifies the index within
** the vector on the LHS that the virtual term represents.
**
** This only works if the RHS is a simple SELECT (not a compound) that does
** not use window functions.
*/
- if( pWC->op==TK_AND && pExpr->op==TK_IN && pTerm->iField==0
+ if( pWC->op==TK_AND && pExpr->op==TK_IN && pTerm->u.x.iField==0
&& pExpr->pLeft->op==TK_VECTOR
&& pExpr->x.pSelect->pPrior==0
#ifndef SQLITE_OMIT_WINDOWFUNC
@@ -145369,7 +145944,7 @@ static void exprAnalyze(
for(i=0; i<sqlite3ExprVectorSize(pExpr->pLeft); i++){
int idxNew;
idxNew = whereClauseInsert(pWC, pExpr, TERM_VIRTUAL);
- pWC->a[idxNew].iField = i+1;
+ pWC->a[idxNew].u.x.iField = i+1;
exprAnalyze(pSrc, pWC, idxNew);
markTermAsChild(pWC, idxNew, idxTerm);
}
@@ -145404,7 +145979,7 @@ static void exprAnalyze(
pNewTerm = &pWC->a[idxNew];
pNewTerm->prereqRight = 0;
pNewTerm->leftCursor = pLeft->iTable;
- pNewTerm->u.leftColumn = pLeft->iColumn;
+ pNewTerm->u.x.leftColumn = pLeft->iColumn;
pNewTerm->eOperator = WO_GT;
markTermAsChild(pWC, idxNew, idxTerm);
pTerm = &pWC->a[idxTerm];
@@ -145447,6 +146022,7 @@ static void exprAnalyze(
SQLITE_PRIVATE void sqlite3WhereSplit(WhereClause *pWC, Expr *pExpr, u8 op){
Expr *pE2 = sqlite3ExprSkipCollateAndLikely(pExpr);
pWC->op = op;
+ assert( pE2!=0 || pExpr==0 );
if( pE2==0 ) return;
if( pE2->op!=op ){
whereClauseInsert(pWC, pExpr, 0);
@@ -145847,6 +146423,16 @@ static void createMask(WhereMaskSet *pMaskSet, int iCursor){
}
/*
+** If the right-hand branch of the expression is a TK_COLUMN, then return
+** a pointer to the right-hand branch. Otherwise, return NULL.
+*/
+static Expr *whereRightSubexprIsColumn(Expr *p){
+ p = sqlite3ExprSkipCollateAndLikely(p->pRight);
+ if( ALWAYS(p!=0) && p->op==TK_COLUMN ) return p;
+ return 0;
+}
+
+/*
** Advance to the next WhereTerm that matches according to the criteria
** established when the pScan object was initialized by whereScanInit().
** Return NULL if there are no more matching WhereTerms.
@@ -145868,7 +146454,7 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
do{
for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){
if( pTerm->leftCursor==iCur
- && pTerm->u.leftColumn==iColumn
+ && pTerm->u.x.leftColumn==iColumn
&& (iColumn!=XN_EXPR
|| sqlite3ExprCompareSkip(pTerm->pExpr->pLeft,
pScan->pIdxExpr,iCur)==0)
@@ -145876,8 +146462,7 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
){
if( (pTerm->eOperator & WO_EQUIV)!=0
&& pScan->nEquiv<ArraySize(pScan->aiCur)
- && (pX = sqlite3ExprSkipCollateAndLikely(pTerm->pExpr->pRight))->op
- ==TK_COLUMN
+ && (pX = whereRightSubexprIsColumn(pTerm->pExpr))!=0
){
int j;
for(j=0; j<pScan->nEquiv; j++){
@@ -146073,7 +146658,8 @@ static int findIndexCol(
for(i=0; i<pList->nExpr; i++){
Expr *p = sqlite3ExprSkipCollateAndLikely(pList->a[i].pExpr);
- if( p->op==TK_COLUMN
+ if( ALWAYS(p!=0)
+ && p->op==TK_COLUMN
&& p->iColumn==pIdx->aiColumn[iCol]
&& p->iTable==iBase
){
@@ -146137,6 +146723,7 @@ static int isDistinctRedundant(
*/
for(i=0; i<pDistinct->nExpr; i++){
Expr *p = sqlite3ExprSkipCollateAndLikely(pDistinct->a[i].pExpr);
+ if( NEVER(p==0) ) continue;
if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1;
}
@@ -146290,8 +146877,8 @@ static int termCanDriveIndex(
return 0;
}
if( (pTerm->prereqRight & notReady)!=0 ) return 0;
- if( pTerm->u.leftColumn<0 ) return 0;
- aff = pSrc->pTab->aCol[pTerm->u.leftColumn].affinity;
+ if( pTerm->u.x.leftColumn<0 ) return 0;
+ aff = pSrc->pTab->aCol[pTerm->u.x.leftColumn].affinity;
if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0;
testcase( pTerm->pExpr->op==TK_IS );
return 1;
@@ -146362,7 +146949,7 @@ static void constructAutomaticIndex(
sqlite3ExprDup(pParse->db, pExpr, 0));
}
if( termCanDriveIndex(pTerm, pSrc, notReady) ){
- int iCol = pTerm->u.leftColumn;
+ int iCol = pTerm->u.x.leftColumn;
Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol);
testcase( iCol==BMS );
testcase( iCol==BMS-1 );
@@ -146415,14 +147002,14 @@ static void constructAutomaticIndex(
idxCols = 0;
for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
if( termCanDriveIndex(pTerm, pSrc, notReady) ){
- int iCol = pTerm->u.leftColumn;
+ int iCol = pTerm->u.x.leftColumn;
Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol);
testcase( iCol==BMS-1 );
testcase( iCol==BMS );
if( (idxCols & cMask)==0 ){
Expr *pX = pTerm->pExpr;
idxCols |= cMask;
- pIdx->aiColumn[n] = pTerm->u.leftColumn;
+ pIdx->aiColumn[n] = pTerm->u.x.leftColumn;
pColl = sqlite3ExprCompareCollSeq(pParse, pX);
assert( pColl!=0 || pParse->nErr>0 ); /* TH3 collate01.800 */
pIdx->azColl[n] = pColl ? pColl->zName : sqlite3StrBINARY;
@@ -146543,7 +147130,7 @@ static sqlite3_index_info *allocateIndexInfo(
testcase( pTerm->eOperator & WO_ALL );
if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue;
if( pTerm->wtFlags & TERM_VNULL ) continue;
- assert( pTerm->u.leftColumn>=(-1) );
+ assert( pTerm->u.x.leftColumn>=(-1) );
nTerm++;
}
@@ -146603,8 +147190,8 @@ static sqlite3_index_info *allocateIndexInfo(
){
continue;
}
- assert( pTerm->u.leftColumn>=(-1) );
- pIdxCons[j].iColumn = pTerm->u.leftColumn;
+ assert( pTerm->u.x.leftColumn>=(-1) );
+ pIdxCons[j].iColumn = pTerm->u.x.leftColumn;
pIdxCons[j].iTermOffset = i;
op = pTerm->eOperator & WO_ALL;
if( op==WO_IN ) op = WO_EQ;
@@ -147367,9 +147954,9 @@ SQLITE_PRIVATE void sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm){
if( pTerm->wtFlags & TERM_CODED ) zType[3] = 'C';
if( pTerm->eOperator & WO_SINGLE ){
sqlite3_snprintf(sizeof(zLeft),zLeft,"left={%d:%d}",
- pTerm->leftCursor, pTerm->u.leftColumn);
+ pTerm->leftCursor, pTerm->u.x.leftColumn);
}else if( (pTerm->eOperator & WO_OR)!=0 && pTerm->u.pOrInfo!=0 ){
- sqlite3_snprintf(sizeof(zLeft),zLeft,"indexable=0x%lld",
+ sqlite3_snprintf(sizeof(zLeft),zLeft,"indexable=0x%llx",
pTerm->u.pOrInfo->indexable);
}else{
sqlite3_snprintf(sizeof(zLeft),zLeft,"left=%d", pTerm->leftCursor);
@@ -147383,8 +147970,8 @@ SQLITE_PRIVATE void sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm){
sqlite3DebugPrintf(" prob=%-3d prereq=%llx,%llx",
pTerm->truthProb, (u64)pTerm->prereqAll, (u64)pTerm->prereqRight);
}
- if( pTerm->iField ){
- sqlite3DebugPrintf(" iField=%d", pTerm->iField);
+ if( pTerm->u.x.iField ){
+ sqlite3DebugPrintf(" iField=%d", pTerm->u.x.iField);
}
if( pTerm->iParent>=0 ){
sqlite3DebugPrintf(" iParent=%d", pTerm->iParent);
@@ -148051,9 +148638,9 @@ static int whereLoopAddBtreeIndex(
pNew = pBuilder->pNew;
if( db->mallocFailed ) return SQLITE_NOMEM_BKPT;
- WHERETRACE(0x800, ("BEGIN %s.addBtreeIdx(%s), nEq=%d, nSkip=%d\n",
+ WHERETRACE(0x800, ("BEGIN %s.addBtreeIdx(%s), nEq=%d, nSkip=%d, rRun=%d\n",
pProbe->pTable->zName,pProbe->zName,
- pNew->u.btree.nEq, pNew->nSkip));
+ pNew->u.btree.nEq, pNew->nSkip, pNew->rRun));
assert( (pNew->wsFlags & WHERE_VIRTUALTABLE)==0 );
assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 );
@@ -148147,7 +148734,7 @@ static int whereLoopAddBtreeIndex(
/* "x IN (value, value, ...)" */
nIn = sqlite3LogEst(pExpr->x.pList->nExpr);
}
- if( pProbe->hasStat1 ){
+ if( pProbe->hasStat1 && rLogSize>=10 ){
LogEst M, logK, safetyMargin;
/* Let:
** N = the total number of rows in the table
@@ -148166,7 +148753,8 @@ static int whereLoopAddBtreeIndex(
** a safety margin of 2 (LogEst: 10) that favors using the IN operator
** with the index, as using an index has better worst-case behavior.
** If we do not have real sqlite_stat1 data, always prefer to use
- ** the index.
+ ** the index. Do not bother with this optimization on very small
+ ** tables (less than 2 rows) as it is pointless in that case.
*/
M = pProbe->aiRowLogEst[saved_nEq];
logK = estLog(nIn);
@@ -148175,7 +148763,7 @@ static int whereLoopAddBtreeIndex(
WHERETRACE(0x40,
("Scan preferred over IN operator on column %d of \"%s\" (%d<%d)\n",
saved_nEq, pProbe->zName, M+logK+10, nIn+rLogSize));
- continue;
+ pNew->wsFlags |= WHERE_IN_SEEKSCAN;
}else{
WHERETRACE(0x40,
("IN operator preferred on column %d of \"%s\" (%d>=%d)\n",
@@ -148421,6 +149009,7 @@ static int indexMightHelpWithOrderBy(
if( (pOB = pBuilder->pWInfo->pOrderBy)==0 ) return 0;
for(ii=0; ii<pOB->nExpr; ii++){
Expr *pExpr = sqlite3ExprSkipCollateAndLikely(pOB->a[ii].pExpr);
+ if( NEVER(pExpr==0) ) continue;
if( pExpr->op==TK_COLUMN && pExpr->iTable==iCursor ){
if( pExpr->iColumn<0 ) return 1;
for(jj=0; jj<pIndex->nKeyCol; jj++){
@@ -148652,8 +149241,23 @@ static int whereLoopAddBtree(
/* Full table scan */
pNew->iSortIdx = b ? iSortIdx : 0;
- /* TUNING: Cost of full table scan is (N*3.0). */
+ /* TUNING: Cost of full table scan is 3.0*N. The 3.0 factor is an
+ ** extra cost designed to discourage the use of full table scans,
+ ** since index lookups have better worst-case performance if our
+ ** stat guesses are wrong. Reduce the 3.0 penalty slightly
+ ** (to 2.75) if we have valid STAT4 information for the table.
+ ** At 2.75, a full table scan is preferred over using an index on
+ ** a column with just two distinct values where each value has about
+ ** an equal number of appearances. Without STAT4 data, we still want
+ ** to use an index in that case, since the constraint might be for
+ ** the scarcer of the two values, and in that case an index lookup is
+ ** better.
+ */
+#ifdef SQLITE_ENABLE_STAT4
+ pNew->rRun = rSize + 16 - 2*((pTab->tabFlags & TF_HasStat4)!=0);
+#else
pNew->rRun = rSize + 16;
+#endif
ApplyCostMultiplier(pNew->rRun, pTab->costMult);
whereLoopOutputAdjust(pWC, pNew, rSize);
rc = whereLoopInsert(pBuilder, pNew);
@@ -149384,6 +149988,7 @@ static i8 wherePathSatisfiesOrderBy(
for(i=0; i<nOrderBy; i++){
if( MASKBIT(i) & obSat ) continue;
pOBExpr = sqlite3ExprSkipCollateAndLikely(pOrderBy->a[i].pExpr);
+ if( NEVER(pOBExpr==0) ) continue;
if( pOBExpr->op!=TK_COLUMN ) continue;
if( pOBExpr->iTable!=iCur ) continue;
pTerm = sqlite3WhereFindTerm(&pWInfo->sWC, iCur, pOBExpr->iColumn,
@@ -149510,6 +150115,7 @@ static i8 wherePathSatisfiesOrderBy(
pOBExpr = sqlite3ExprSkipCollateAndLikely(pOrderBy->a[i].pExpr);
testcase( wctrlFlags & WHERE_GROUPBY );
testcase( wctrlFlags & WHERE_DISTINCTBY );
+ if( NEVER(pOBExpr==0) ) continue;
if( (wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0 ) bOnce = 0;
if( iColumn>=XN_ROWID ){
if( pOBExpr->op!=TK_COLUMN ) continue;
@@ -149664,16 +150270,24 @@ static LogEst whereSortingCost(
** cost = (3.0 * N * log(N)) * (Y/X)
**
** The (Y/X) term is implemented using stack variable rScale
- ** below. */
+ ** below.
+ */
LogEst rScale, rSortCost;
assert( nOrderBy>0 && 66==sqlite3LogEst(100) );
rScale = sqlite3LogEst((nOrderBy-nSorted)*100/nOrderBy) - 66;
rSortCost = nRow + rScale + 16;
/* Multiple by log(M) where M is the number of output rows.
- ** Use the LIMIT for M if it is smaller */
+ ** Use the LIMIT for M if it is smaller. Or if this sort is for
+ ** a DISTINCT operator, M will be the number of distinct output
+ ** rows, so fudge it downwards a bit.
+ */
if( (pWInfo->wctrlFlags & WHERE_USE_LIMIT)!=0 && pWInfo->iLimit<nRow ){
nRow = pWInfo->iLimit;
+ }else if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT) ){
+ /* TUNING: In the sort for a DISTINCT operator, assume that the DISTINCT
+ ** reduces the number of output rows by a factor of 2 */
+ if( nRow>10 ) nRow -= 10; assert( 10==sqlite3LogEst(2) );
}
rSortCost += estLog(nRow);
return rSortCost;
@@ -150800,6 +151414,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
if( (pLoop->wsFlags & WHERE_CONSTRAINT)!=0
&& (pLoop->wsFlags & (WHERE_COLUMN_RANGE|WHERE_SKIPSCAN))==0
&& (pLoop->wsFlags & WHERE_BIGNULL_SORT)==0
+ && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0
&& (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)==0
&& pWInfo->eDistinct!=WHERE_DISTINCT_ORDERED
){
@@ -150857,6 +151472,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
/* Done. */
VdbeModuleComment((v, "Begin WHERE-core"));
+ pWInfo->iEndWhere = sqlite3VdbeCurrentAddr(v);
return pWInfo;
/* Jump here if malloc fails */
@@ -150900,6 +151516,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
WhereLoop *pLoop;
SrcList *pTabList = pWInfo->pTabList;
sqlite3 *db = pParse->db;
+ int iEnd = sqlite3VdbeCurrentAddr(v);
/* Generate loop termination code.
*/
@@ -150960,7 +151577,9 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
if( pIn->eEndLoopOp!=OP_Noop ){
if( pIn->nPrefix ){
- assert( pLoop->wsFlags & WHERE_IN_EARLYOUT );
+ int bEarlyOut =
+ (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0
+ && (pLoop->wsFlags & WHERE_IN_EARLYOUT)!=0;
if( pLevel->iLeftJoin ){
/* For LEFT JOIN queries, cursor pIn->iCur may not have been
** opened yet. This occurs for WHERE clauses such as
@@ -150971,12 +151590,10 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
** jump over the OP_Next or OP_Prev instruction about to
** be coded. */
sqlite3VdbeAddOp2(v, OP_IfNotOpen, pIn->iCur,
- sqlite3VdbeCurrentAddr(v) + 2 +
- ((pLoop->wsFlags & WHERE_VIRTUALTABLE)==0)
- );
+ sqlite3VdbeCurrentAddr(v) + 2 + bEarlyOut);
VdbeCoverage(v);
}
- if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 ){
+ if( bEarlyOut ){
sqlite3VdbeAddOp4Int(v, OP_IfNoHope, pLevel->iIdxCur,
sqlite3VdbeCurrentAddr(v)+2,
pIn->iBase, pIn->nPrefix);
@@ -151037,7 +151654,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
assert( pWInfo->nLevel<=pTabList->nSrc );
for(i=0, pLevel=pWInfo->a; i<pWInfo->nLevel; i++, pLevel++){
int k, last;
- VdbeOp *pOp;
+ VdbeOp *pOp, *pLastOp;
Index *pIdx = 0;
struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom];
Table *pTab = pTabItem->pTab;
@@ -151095,20 +151712,31 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
pIdx = pLevel->u.pCovidx;
}
if( pIdx
- && (pWInfo->eOnePass==ONEPASS_OFF || !HasRowid(pIdx->pTable))
&& !db->mallocFailed
){
- last = sqlite3VdbeCurrentAddr(v);
- k = pLevel->addrBody;
+ if( pWInfo->eOnePass==ONEPASS_OFF || !HasRowid(pIdx->pTable) ){
+ last = iEnd;
+ }else{
+ last = pWInfo->iEndWhere;
+ }
+ k = pLevel->addrBody + 1;
#ifdef SQLITE_DEBUG
if( db->flags & SQLITE_VdbeAddopTrace ){
printf("TRANSLATE opcodes in range %d..%d\n", k, last-1);
}
+ /* Proof that the "+1" on the k value above is safe */
+ pOp = sqlite3VdbeGetOp(v, k - 1);
+ assert( pOp->opcode!=OP_Column || pOp->p1!=pLevel->iTabCur );
+ assert( pOp->opcode!=OP_Rowid || pOp->p1!=pLevel->iTabCur );
+ assert( pOp->opcode!=OP_IfNullRow || pOp->p1!=pLevel->iTabCur );
#endif
pOp = sqlite3VdbeGetOp(v, k);
- for(; k<last; k++, pOp++){
- if( pOp->p1!=pLevel->iTabCur ) continue;
- if( pOp->opcode==OP_Column
+ pLastOp = pOp + (last - k);
+ assert( pOp<pLastOp );
+ do{
+ if( pOp->p1!=pLevel->iTabCur ){
+ /* no-op */
+ }else if( pOp->opcode==OP_Column
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
|| pOp->opcode==OP_Offset
#endif
@@ -151139,7 +151767,10 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
pOp->p1 = pLevel->iIdxCur;
OpcodeRewriteTrace(db, k, pOp);
}
- }
+#ifdef SQLITE_DEBUG
+ k++;
+#endif
+ }while( (++pOp)<pLastOp );
#ifdef SQLITE_DEBUG
if( db->flags & SQLITE_VdbeAddopTrace ) printf("TRANSLATE complete\n");
#endif
@@ -154208,8 +154839,10 @@ SQLITE_PRIVATE void sqlite3WindowCodeStep(
/************** End of window.c **********************************************/
/************** Begin file parse.c *******************************************/
+/* This file is automatically generated by Lemon from input grammar
+** source file "parse.y". */
/*
-** 2000-05-29
+** 2001-09-15
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
@@ -154219,22 +154852,15 @@ SQLITE_PRIVATE void sqlite3WindowCodeStep(
** May you share freely, never taking more than you give.
**
*************************************************************************
-** Driver template for the LEMON parser generator.
+** This file contains SQLite's SQL parser.
**
-** The "lemon" program processes an LALR(1) input grammar file, then uses
-** this template to construct a parser. The "lemon" program inserts text
-** at each "%%" line. Also, any "P-a-r-s-e" identifer prefix (without the
-** interstitial "-" characters) contained in this template is changed into
-** the value of the %name directive from the grammar. Otherwise, the content
-** of this template is copied straight through into the generate parser
-** source file.
-**
-** The following is the concatenation of all %include directives from the
-** input grammar file:
+** The canonical source code to this file ("parse.y") is a Lemon grammar
+** file that specifies the input grammar and actions to take while parsing.
+** That input file is processed by Lemon to generate a C-language
+** implementation of a parser for the given grammer. You might be reading
+** this comment as part of the translated C-code. Edits should be made
+** to the original parse.y sources.
*/
-/* #include <stdio.h> */
-/* #include <assert.h> */
-/************ Begin %include sections from the grammar ************************/
/* #include "sqliteInt.h" */
@@ -154418,11 +155044,191 @@ static void updateDeleteLimitError(
# error too many tokens in the grammar
#endif
/**************** End of %include directives **********************************/
-/* These constants specify the various numeric values for terminal symbols
-** in a format understandable to "makeheaders". This section is blank unless
-** "lemon" is run with the "-m" command-line option.
-***************** Begin makeheaders token definitions *************************/
-/**************** End makeheaders token definitions ***************************/
+/* These constants specify the various numeric values for terminal symbols.
+***************** Begin token definitions *************************************/
+#ifndef TK_SEMI
+#define TK_SEMI 1
+#define TK_EXPLAIN 2
+#define TK_QUERY 3
+#define TK_PLAN 4
+#define TK_BEGIN 5
+#define TK_TRANSACTION 6
+#define TK_DEFERRED 7
+#define TK_IMMEDIATE 8
+#define TK_EXCLUSIVE 9
+#define TK_COMMIT 10
+#define TK_END 11
+#define TK_ROLLBACK 12
+#define TK_SAVEPOINT 13
+#define TK_RELEASE 14
+#define TK_TO 15
+#define TK_TABLE 16
+#define TK_CREATE 17
+#define TK_IF 18
+#define TK_NOT 19
+#define TK_EXISTS 20
+#define TK_TEMP 21
+#define TK_LP 22
+#define TK_RP 23
+#define TK_AS 24
+#define TK_WITHOUT 25
+#define TK_COMMA 26
+#define TK_ABORT 27
+#define TK_ACTION 28
+#define TK_AFTER 29
+#define TK_ANALYZE 30
+#define TK_ASC 31
+#define TK_ATTACH 32
+#define TK_BEFORE 33
+#define TK_BY 34
+#define TK_CASCADE 35
+#define TK_CAST 36
+#define TK_CONFLICT 37
+#define TK_DATABASE 38
+#define TK_DESC 39
+#define TK_DETACH 40
+#define TK_EACH 41
+#define TK_FAIL 42
+#define TK_OR 43
+#define TK_AND 44
+#define TK_IS 45
+#define TK_MATCH 46
+#define TK_LIKE_KW 47
+#define TK_BETWEEN 48
+#define TK_IN 49
+#define TK_ISNULL 50
+#define TK_NOTNULL 51
+#define TK_NE 52
+#define TK_EQ 53
+#define TK_GT 54
+#define TK_LE 55
+#define TK_LT 56
+#define TK_GE 57
+#define TK_ESCAPE 58
+#define TK_ID 59
+#define TK_COLUMNKW 60
+#define TK_DO 61
+#define TK_FOR 62
+#define TK_IGNORE 63
+#define TK_INITIALLY 64
+#define TK_INSTEAD 65
+#define TK_NO 66
+#define TK_KEY 67
+#define TK_OF 68
+#define TK_OFFSET 69
+#define TK_PRAGMA 70
+#define TK_RAISE 71
+#define TK_RECURSIVE 72
+#define TK_REPLACE 73
+#define TK_RESTRICT 74
+#define TK_ROW 75
+#define TK_ROWS 76
+#define TK_TRIGGER 77
+#define TK_VACUUM 78
+#define TK_VIEW 79
+#define TK_VIRTUAL 80
+#define TK_WITH 81
+#define TK_NULLS 82
+#define TK_FIRST 83
+#define TK_LAST 84
+#define TK_CURRENT 85
+#define TK_FOLLOWING 86
+#define TK_PARTITION 87
+#define TK_PRECEDING 88
+#define TK_RANGE 89
+#define TK_UNBOUNDED 90
+#define TK_EXCLUDE 91
+#define TK_GROUPS 92
+#define TK_OTHERS 93
+#define TK_TIES 94
+#define TK_GENERATED 95
+#define TK_ALWAYS 96
+#define TK_REINDEX 97
+#define TK_RENAME 98
+#define TK_CTIME_KW 99
+#define TK_ANY 100
+#define TK_BITAND 101
+#define TK_BITOR 102
+#define TK_LSHIFT 103
+#define TK_RSHIFT 104
+#define TK_PLUS 105
+#define TK_MINUS 106
+#define TK_STAR 107
+#define TK_SLASH 108
+#define TK_REM 109
+#define TK_CONCAT 110
+#define TK_COLLATE 111
+#define TK_BITNOT 112
+#define TK_ON 113
+#define TK_INDEXED 114
+#define TK_STRING 115
+#define TK_JOIN_KW 116
+#define TK_CONSTRAINT 117
+#define TK_DEFAULT 118
+#define TK_NULL 119
+#define TK_PRIMARY 120
+#define TK_UNIQUE 121
+#define TK_CHECK 122
+#define TK_REFERENCES 123
+#define TK_AUTOINCR 124
+#define TK_INSERT 125
+#define TK_DELETE 126
+#define TK_UPDATE 127
+#define TK_SET 128
+#define TK_DEFERRABLE 129
+#define TK_FOREIGN 130
+#define TK_DROP 131
+#define TK_UNION 132
+#define TK_ALL 133
+#define TK_EXCEPT 134
+#define TK_INTERSECT 135
+#define TK_SELECT 136
+#define TK_VALUES 137
+#define TK_DISTINCT 138
+#define TK_DOT 139
+#define TK_FROM 140
+#define TK_JOIN 141
+#define TK_USING 142
+#define TK_ORDER 143
+#define TK_GROUP 144
+#define TK_HAVING 145
+#define TK_LIMIT 146
+#define TK_WHERE 147
+#define TK_INTO 148
+#define TK_NOTHING 149
+#define TK_FLOAT 150
+#define TK_BLOB 151
+#define TK_INTEGER 152
+#define TK_VARIABLE 153
+#define TK_CASE 154
+#define TK_WHEN 155
+#define TK_THEN 156
+#define TK_ELSE 157
+#define TK_INDEX 158
+#define TK_ALTER 159
+#define TK_ADD 160
+#define TK_WINDOW 161
+#define TK_OVER 162
+#define TK_FILTER 163
+#define TK_COLUMN 164
+#define TK_AGG_FUNCTION 165
+#define TK_AGG_COLUMN 166
+#define TK_TRUEFALSE 167
+#define TK_ISNOT 168
+#define TK_FUNCTION 169
+#define TK_UMINUS 170
+#define TK_UPLUS 171
+#define TK_TRUTH 172
+#define TK_REGISTER 173
+#define TK_VECTOR 174
+#define TK_SELECT_COLUMN 175
+#define TK_IF_NULL_ROW 176
+#define TK_ASTERISK 177
+#define TK_SPAN 178
+#define TK_SPACE 179
+#define TK_ILLEGAL 180
+#endif
+/**************** End token definitions ***************************************/
/* The next sections is a series of control #defines.
** various aspects of the generated parser.
@@ -155428,6 +156234,7 @@ typedef struct yyParser yyParser;
#ifndef NDEBUG
/* #include <stdio.h> */
+/* #include <assert.h> */
static FILE *yyTraceFILE = 0;
static char *yyTracePrompt = 0;
#endif /* NDEBUG */
@@ -156547,7 +157354,7 @@ static YYACTIONTYPE yy_find_shift_action(
#endif /* YYWILDCARD */
return yy_default[stateno];
}else{
- assert( i>=0 && i<sizeof(yy_action)/sizeof(yy_action[0]) );
+ assert( i>=0 && i<(int)(sizeof(yy_action)/sizeof(yy_action[0])) );
return yy_action[i];
}
}while(1);
@@ -157475,8 +158282,9 @@ static YYACTIONTYPE yy_reduce(
(void)yyLookahead;
(void)yyLookaheadToken;
yymsp = yypParser->yytos;
+ assert( yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) );
#ifndef NDEBUG
- if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
+ if( yyTraceFILE ){
yysize = yyRuleInfoNRhs[yyruleno];
if( yysize ){
fprintf(yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n",
@@ -157695,7 +158503,7 @@ static YYACTIONTYPE yy_reduce(
SQLITE_IDXTYPE_UNIQUE);}
break;
case 39: /* ccons ::= CHECK LP expr RP */
-{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy202);}
+{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy202,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy0.z);}
break;
case 40: /* ccons ::= REFERENCES nm eidlist_opt refargs */
{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy242,yymsp[0].minor.yy192);}
@@ -157774,7 +158582,7 @@ static YYACTIONTYPE yy_reduce(
SQLITE_IDXTYPE_UNIQUE);}
break;
case 68: /* tcons ::= CHECK LP expr RP onconf */
-{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy202);}
+{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy202,yymsp[-3].minor.yy0.z,yymsp[-1].minor.yy0.z);}
break;
case 69: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
{
@@ -161896,7 +162704,7 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3 *db){
sqlite3BtreeEnterAll(db);
for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
- if( pBt && sqlite3BtreeIsInTrans(pBt) ){
+ if( pBt && sqlite3BtreeTxnState(pBt)==SQLITE_TXN_WRITE ){
Pager *pPager = sqlite3BtreePager(pBt);
rc = sqlite3PagerFlush(pPager);
if( rc==SQLITE_BUSY ){
@@ -162241,6 +163049,36 @@ static int sqlite3Close(sqlite3 *db, int forceZombie){
}
/*
+** Return the transaction state for a single databse, or the maximum
+** transaction state over all attached databases if zSchema is null.
+*/
+SQLITE_API int sqlite3_txn_state(sqlite3 *db, const char *zSchema){
+ int iDb, nDb;
+ int iTxn = -1;
+#ifdef SQLITE_ENABLE_API_ARMOR
+ if( !sqlite3SafetyCheckOk(db) ){
+ (void)SQLITE_MISUSE_BKPT;
+ return -1;
+ }
+#endif
+ sqlite3_mutex_enter(db->mutex);
+ if( zSchema ){
+ nDb = iDb = sqlite3FindDbName(db, zSchema);
+ if( iDb<0 ) nDb--;
+ }else{
+ iDb = 0;
+ nDb = db->nDb-1;
+ }
+ for(; iDb<=nDb; iDb++){
+ Btree *pBt = db->aDb[iDb].pBt;
+ int x = pBt!=0 ? sqlite3BtreeTxnState(pBt) : SQLITE_TXN_NONE;
+ if( x>iTxn ) iTxn = x;
+ }
+ sqlite3_mutex_leave(db->mutex);
+ return iTxn;
+}
+
+/*
** Two variations on the public interface for closing a database
** connection. The sqlite3_close() version returns SQLITE_BUSY and
** leaves the connection option if there are unfinalized prepared
@@ -162400,7 +163238,7 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){
for(i=0; i<db->nDb; i++){
Btree *p = db->aDb[i].pBt;
if( p ){
- if( sqlite3BtreeIsInTrans(p) ){
+ if( sqlite3BtreeTxnState(p)==SQLITE_TXN_WRITE ){
inTrans = 1;
}
sqlite3BtreeRollback(p, tripCode, !schemaChange);
@@ -164821,7 +165659,9 @@ SQLITE_API int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, vo
}
rc = SQLITE_OK;
}else{
+ int nSave = db->busyHandler.nBusy;
rc = sqlite3OsFileControl(fd, op, pArg);
+ db->busyHandler.nBusy = nSave;
}
sqlite3BtreeLeave(pBtree);
}
@@ -165204,6 +166044,25 @@ SQLITE_API int sqlite3_test_control(int op, ...){
sqlite3ResultIntReal(pCtx);
break;
}
+
+ /* sqlite3_test_control(SQLITE_TESTCTRL_SEEK_COUNT,
+ ** sqlite3 *db, // Database connection
+ ** u64 *pnSeek // Write seek count here
+ ** );
+ **
+ ** This test-control queries the seek-counter on the "main" database
+ ** file. The seek-counter is written into *pnSeek and is then reset.
+ ** The seek-count is only available if compiled with SQLITE_DEBUG.
+ */
+ case SQLITE_TESTCTRL_SEEK_COUNT: {
+ sqlite3 *db = va_arg(ap, sqlite3*);
+ u64 *pn = va_arg(ap, sqlite3_uint64*);
+ *pn = sqlite3BtreeSeekCount(db->aDb->pBt);
+ (void)db; /* Silence harmless unused variable warning */
+ break;
+ }
+
+
}
va_end(ap);
#endif /* SQLITE_UNTESTABLE */
@@ -165439,7 +166298,7 @@ SQLITE_API int sqlite3_snapshot_get(
int iDb = sqlite3FindDbName(db, zDb);
if( iDb==0 || iDb>1 ){
Btree *pBt = db->aDb[iDb].pBt;
- if( 0==sqlite3BtreeIsInTrans(pBt) ){
+ if( SQLITE_TXN_WRITE!=sqlite3BtreeTxnState(pBt) ){
rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
if( rc==SQLITE_OK ){
rc = sqlite3PagerSnapshotGet(sqlite3BtreePager(pBt), ppSnapshot);
@@ -165475,10 +166334,10 @@ SQLITE_API int sqlite3_snapshot_open(
iDb = sqlite3FindDbName(db, zDb);
if( iDb==0 || iDb>1 ){
Btree *pBt = db->aDb[iDb].pBt;
- if( sqlite3BtreeIsInTrans(pBt)==0 ){
+ if( sqlite3BtreeTxnState(pBt)!=SQLITE_TXN_WRITE ){
Pager *pPager = sqlite3BtreePager(pBt);
int bUnlock = 0;
- if( sqlite3BtreeIsInReadTrans(pBt) ){
+ if( sqlite3BtreeTxnState(pBt)!=SQLITE_TXN_NONE ){
if( db->nVdbeActive==0 ){
rc = sqlite3PagerSnapshotCheck(pPager, pSnapshot);
if( rc==SQLITE_OK ){
@@ -165527,7 +166386,7 @@ SQLITE_API int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb){
iDb = sqlite3FindDbName(db, zDb);
if( iDb==0 || iDb>1 ){
Btree *pBt = db->aDb[iDb].pBt;
- if( 0==sqlite3BtreeIsInReadTrans(pBt) ){
+ if( SQLITE_TXN_NONE==sqlite3BtreeTxnState(pBt) ){
rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
if( rc==SQLITE_OK ){
rc = sqlite3PagerSnapshotRecover(sqlite3BtreePager(pBt));
@@ -188818,7 +189677,7 @@ static int nodeAcquire(
** are the leaves, and so on. If the depth as specified on the root node
** is greater than RTREE_MAX_DEPTH, the r-tree structure must be corrupt.
*/
- if( pNode && iNode==1 ){
+ if( pNode && rc==SQLITE_OK && iNode==1 ){
pRtree->iDepth = readInt16(pNode->zData);
if( pRtree->iDepth>RTREE_MAX_DEPTH ){
rc = SQLITE_CORRUPT_VTAB;
@@ -193504,7 +194363,7 @@ static int geopolyOverlap(GeoPoly *p1, GeoPoly *p2){
geopolyAddSegments(p, p1, 1);
geopolyAddSegments(p, p2, 2);
pThisEvent = geopolySortEventsByX(p->aEvent, p->nEvent);
- rX = pThisEvent->x==0.0 ? -1.0 : 0.0;
+ rX = pThisEvent && pThisEvent->x==0.0 ? -1.0 : 0.0;
memset(aOverlap, 0, sizeof(aOverlap));
while( pThisEvent ){
if( pThisEvent->x!=rX ){
@@ -208687,6 +209546,7 @@ struct Fts5Config {
Fts5Tokenizer *pTok;
fts5_tokenizer *pTokApi;
int bLock; /* True when table is preparing statement */
+ int ePattern; /* FTS_PATTERN_XXX constant */
/* Values loaded from the %_config table */
int iCookie; /* Incremented when %_config is modified */
@@ -208707,17 +209567,19 @@ struct Fts5Config {
};
/* Current expected value of %_config table 'version' field */
-#define FTS5_CURRENT_VERSION 4
+#define FTS5_CURRENT_VERSION 4
#define FTS5_CONTENT_NORMAL 0
#define FTS5_CONTENT_NONE 1
#define FTS5_CONTENT_EXTERNAL 2
-#define FTS5_DETAIL_FULL 0
-#define FTS5_DETAIL_NONE 1
-#define FTS5_DETAIL_COLUMNS 2
-
+#define FTS5_DETAIL_FULL 0
+#define FTS5_DETAIL_NONE 1
+#define FTS5_DETAIL_COLUMNS 2
+#define FTS5_PATTERN_NONE 0
+#define FTS5_PATTERN_LIKE 65 /* matches SQLITE_INDEX_CONSTRAINT_LIKE */
+#define FTS5_PATTERN_GLOB 66 /* matches SQLITE_INDEX_CONSTRAINT_GLOB */
static int sqlite3Fts5ConfigParse(
Fts5Global*, sqlite3*, int, const char **, Fts5Config**, char**
@@ -208987,7 +209849,7 @@ static int sqlite3Fts5IndexSetAverages(Fts5Index *p, const u8*, int);
/*
** Functions called by the storage module as part of integrity-check.
*/
-static int sqlite3Fts5IndexIntegrityCheck(Fts5Index*, u64 cksum);
+static int sqlite3Fts5IndexIntegrityCheck(Fts5Index*, u64 cksum, int bUseCksum);
/*
** Called during virtual module initialization to register UDF
@@ -209057,8 +209919,7 @@ static int sqlite3Fts5GetTokenizer(
Fts5Global*,
const char **azArg,
int nArg,
- Fts5Tokenizer**,
- fts5_tokenizer**,
+ Fts5Config*,
char **pzErr
);
@@ -209142,7 +210003,7 @@ static int sqlite3Fts5StorageDelete(Fts5Storage *p, i64, sqlite3_value**);
static int sqlite3Fts5StorageContentInsert(Fts5Storage *p, sqlite3_value**, i64*);
static int sqlite3Fts5StorageIndexInsert(Fts5Storage *p, sqlite3_value**, i64);
-static int sqlite3Fts5StorageIntegrity(Fts5Storage *p);
+static int sqlite3Fts5StorageIntegrity(Fts5Storage *p, int iArg);
static int sqlite3Fts5StorageStmt(Fts5Storage *p, int eStmt, sqlite3_stmt**, char**);
static void sqlite3Fts5StorageStmtRelease(Fts5Storage *p, int eStmt, sqlite3_stmt*);
@@ -209187,11 +210048,19 @@ struct Fts5Token {
/* Parse a MATCH expression. */
static int sqlite3Fts5ExprNew(
Fts5Config *pConfig,
+ int bPhraseToAnd,
int iCol, /* Column on LHS of MATCH operator */
const char *zExpr,
Fts5Expr **ppNew,
char **pzErr
);
+static int sqlite3Fts5ExprPattern(
+ Fts5Config *pConfig,
+ int bGlob,
+ int iCol,
+ const char *zText,
+ Fts5Expr **pp
+);
/*
** for(rc = sqlite3Fts5ExprFirst(pExpr, pIdx, bDesc);
@@ -209300,6 +210169,10 @@ static int sqlite3Fts5AuxInit(fts5_api*);
*/
static int sqlite3Fts5TokenizerInit(fts5_api*);
+static int sqlite3Fts5TokenizerPattern(
+ int (*xCreate)(void*, const char**, int, Fts5Tokenizer**),
+ Fts5Tokenizer *pTok
+);
/*
** End of interface to code in fts5_tokenizer.c.
**************************************************************************/
@@ -209346,6 +210219,8 @@ static void sqlite3Fts5UnicodeAscii(u8*, u8*);
#define FTS5_PLUS 14
#define FTS5_STAR 15
+/* This file is automatically generated by Lemon from input grammar
+** source file "fts5parse.y". */
/*
** 2000-05-29
**
@@ -209370,8 +210245,6 @@ static void sqlite3Fts5UnicodeAscii(u8*, u8*);
** The following is the concatenation of all %include directives from the
** input grammar file:
*/
-/* #include <stdio.h> */
-/* #include <assert.h> */
/************ Begin %include sections from the grammar ************************/
/* #include "fts5Int.h" */
@@ -209401,11 +210274,26 @@ static void sqlite3Fts5UnicodeAscii(u8*, u8*);
#define fts5YYMALLOCARGTYPE u64
/**************** End of %include directives **********************************/
-/* These constants specify the various numeric values for terminal symbols
-** in a format understandable to "makeheaders". This section is blank unless
-** "lemon" is run with the "-m" command-line option.
-***************** Begin makeheaders token definitions *************************/
-/**************** End makeheaders token definitions ***************************/
+/* These constants specify the various numeric values for terminal symbols.
+***************** Begin token definitions *************************************/
+#ifndef FTS5_OR
+#define FTS5_OR 1
+#define FTS5_AND 2
+#define FTS5_NOT 3
+#define FTS5_TERM 4
+#define FTS5_COLON 5
+#define FTS5_MINUS 6
+#define FTS5_LCP 7
+#define FTS5_RCP 8
+#define FTS5_STRING 9
+#define FTS5_LP 10
+#define FTS5_RP 11
+#define FTS5_CARET 12
+#define FTS5_COMMA 13
+#define FTS5_PLUS 14
+#define FTS5_STAR 15
+#endif
+/**************** End token definitions ***************************************/
/* The next sections is a series of control #defines.
** various aspects of the generated parser.
@@ -209688,6 +210576,7 @@ typedef struct fts5yyParser fts5yyParser;
#ifndef NDEBUG
/* #include <stdio.h> */
+/* #include <assert.h> */
static FILE *fts5yyTraceFILE = 0;
static char *fts5yyTracePrompt = 0;
#endif /* NDEBUG */
@@ -210102,7 +210991,7 @@ static fts5YYACTIONTYPE fts5yy_find_shift_action(
#endif /* fts5YYWILDCARD */
return fts5yy_default[stateno];
}else{
- assert( i>=0 && i<sizeof(fts5yy_action)/sizeof(fts5yy_action[0]) );
+ assert( i>=0 && i<(int)(sizeof(fts5yy_action)/sizeof(fts5yy_action[0])) );
return fts5yy_action[i];
}
}while(1);
@@ -210316,8 +211205,9 @@ static fts5YYACTIONTYPE fts5yy_reduce(
(void)fts5yyLookahead;
(void)fts5yyLookaheadToken;
fts5yymsp = fts5yypParser->fts5yytos;
+ assert( fts5yyruleno<(int)(sizeof(fts5yyRuleName)/sizeof(fts5yyRuleName[0])) );
#ifndef NDEBUG
- if( fts5yyTraceFILE && fts5yyruleno<(int)(sizeof(fts5yyRuleName)/sizeof(fts5yyRuleName[0])) ){
+ if( fts5yyTraceFILE ){
fts5yysize = fts5yyRuleInfoNRhs[fts5yyruleno];
if( fts5yysize ){
fprintf(fts5yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n",
@@ -211382,7 +212272,7 @@ static int fts5Bm25GetData(
int rc = SQLITE_OK; /* Return code */
Fts5Bm25Data *p; /* Object to return */
- p = pApi->xGetAuxdata(pFts, 0);
+ p = (Fts5Bm25Data*)pApi->xGetAuxdata(pFts, 0);
if( p==0 ){
int nPhrase; /* Number of phrases in query */
sqlite3_int64 nRow = 0; /* Number of rows in table */
@@ -211456,7 +212346,7 @@ static void fts5Bm25Function(
){
const double k1 = 1.2; /* Constant "k1" from BM25 formula */
const double b = 0.75; /* Constant "b" from BM25 formula */
- int rc = SQLITE_OK; /* Error code */
+ int rc; /* Error code */
double score = 0.0; /* SQL function return value */
Fts5Bm25Data *pData; /* Values allocated/calculated once only */
int i; /* Iterator variable */
@@ -211488,17 +212378,15 @@ static void fts5Bm25Function(
D = (double)nTok;
}
- /* Determine the BM25 score for the current row. */
- for(i=0; rc==SQLITE_OK && i<pData->nPhrase; i++){
- score += pData->aIDF[i] * (
- ( aFreq[i] * (k1 + 1.0) ) /
- ( aFreq[i] + k1 * (1 - b + b * D / pData->avgdl) )
- );
- }
-
- /* If no error has occurred, return the calculated score. Otherwise,
- ** throw an SQL exception. */
+ /* Determine and return the BM25 score for the current row. Or, if an
+ ** error has occurred, throw an exception. */
if( rc==SQLITE_OK ){
+ for(i=0; i<pData->nPhrase; i++){
+ score += pData->aIDF[i] * (
+ ( aFreq[i] * (k1 + 1.0) ) /
+ ( aFreq[i] + k1 * (1 - b + b * D / pData->avgdl) )
+ );
+ }
sqlite3_result_double(pCtx, -1.0 * score);
}else{
sqlite3_result_error_code(pCtx, rc);
@@ -212262,7 +213150,7 @@ static int fts5ConfigParseSpecial(
rc = SQLITE_ERROR;
}else{
rc = sqlite3Fts5GetTokenizer(pGlobal,
- (const char**)azArg, (int)nArg, &pConfig->pTok, &pConfig->pTokApi,
+ (const char**)azArg, (int)nArg, pConfig,
pzErr
);
}
@@ -212334,9 +213222,7 @@ static int fts5ConfigParseSpecial(
*/
static int fts5ConfigDefaultTokenizer(Fts5Global *pGlobal, Fts5Config *pConfig){
assert( pConfig->pTok==0 && pConfig->pTokApi==0 );
- return sqlite3Fts5GetTokenizer(
- pGlobal, 0, 0, &pConfig->pTok, &pConfig->pTokApi, 0
- );
+ return sqlite3Fts5GetTokenizer(pGlobal, 0, 0, pConfig, 0);
}
/*
@@ -213028,6 +213914,7 @@ struct Fts5Parse {
int nPhrase; /* Size of apPhrase array */
Fts5ExprPhrase **apPhrase; /* Array of all phrases */
Fts5ExprNode *pExpr; /* Result of a successful parse */
+ int bPhraseToAnd; /* Convert "a+b" to "a AND b" */
};
static void sqlite3Fts5ParseError(Fts5Parse *pParse, const char *zFmt, ...){
@@ -213116,6 +214003,7 @@ static void fts5ParseFree(void *p){ sqlite3_free(p); }
static int sqlite3Fts5ExprNew(
Fts5Config *pConfig, /* FTS5 Configuration */
+ int bPhraseToAnd,
int iCol,
const char *zExpr, /* Expression text */
Fts5Expr **ppNew,
@@ -213131,6 +214019,7 @@ static int sqlite3Fts5ExprNew(
*ppNew = 0;
*pzErr = 0;
memset(&sParse, 0, sizeof(sParse));
+ sParse.bPhraseToAnd = bPhraseToAnd;
pEngine = sqlite3Fts5ParserAlloc(fts5ParseAlloc);
if( pEngine==0 ){ return SQLITE_NOMEM; }
sParse.pConfig = pConfig;
@@ -213173,6 +214062,7 @@ static int sqlite3Fts5ExprNew(
pNew->pConfig = pConfig;
pNew->apExprPhrase = sParse.apPhrase;
pNew->nPhrase = sParse.nPhrase;
+ pNew->bDesc = 0;
sParse.apPhrase = 0;
}
}else{
@@ -213185,6 +214075,81 @@ static int sqlite3Fts5ExprNew(
}
/*
+** This function is only called when using the special 'trigram' tokenizer.
+** Argument zText contains the text of a LIKE or GLOB pattern matched
+** against column iCol. This function creates and compiles an FTS5 MATCH
+** expression that will match a superset of the rows matched by the LIKE or
+** GLOB. If successful, SQLITE_OK is returned. Otherwise, an SQLite error
+** code.
+*/
+static int sqlite3Fts5ExprPattern(
+ Fts5Config *pConfig, int bGlob, int iCol, const char *zText, Fts5Expr **pp
+){
+ i64 nText = strlen(zText);
+ char *zExpr = (char*)sqlite3_malloc64(nText*4 + 1);
+ int rc = SQLITE_OK;
+
+ if( zExpr==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ char aSpec[3];
+ int iOut = 0;
+ int i = 0;
+ int iFirst = 0;
+
+ if( bGlob==0 ){
+ aSpec[0] = '_';
+ aSpec[1] = '%';
+ aSpec[2] = 0;
+ }else{
+ aSpec[0] = '*';
+ aSpec[1] = '?';
+ aSpec[2] = '[';
+ }
+
+ while( i<=nText ){
+ if( i==nText
+ || zText[i]==aSpec[0] || zText[i]==aSpec[1] || zText[i]==aSpec[2]
+ ){
+ if( i-iFirst>=3 ){
+ int jj;
+ zExpr[iOut++] = '"';
+ for(jj=iFirst; jj<i; jj++){
+ zExpr[iOut++] = zText[jj];
+ if( zText[jj]=='"' ) zExpr[iOut++] = '"';
+ }
+ zExpr[iOut++] = '"';
+ zExpr[iOut++] = ' ';
+ }
+ if( zText[i]==aSpec[2] ){
+ i += 2;
+ if( zText[i-1]=='^' ) i++;
+ while( i<nText && zText[i]!=']' ) i++;
+ }
+ iFirst = i+1;
+ }
+ i++;
+ }
+ if( iOut>0 ){
+ int bAnd = 0;
+ if( pConfig->eDetail!=FTS5_DETAIL_FULL ){
+ bAnd = 1;
+ if( pConfig->eDetail==FTS5_DETAIL_NONE ){
+ iCol = pConfig->nCol;
+ }
+ }
+ zExpr[iOut] = '\0';
+ rc = sqlite3Fts5ExprNew(pConfig, bAnd, iCol, zExpr, pp,pConfig->pzErrmsg);
+ }else{
+ *pp = 0;
+ }
+ sqlite3_free(zExpr);
+ }
+
+ return rc;
+}
+
+/*
** Free the expression node object passed as the only argument.
*/
static void sqlite3Fts5ParseNodeFree(Fts5ExprNode *p){
@@ -214561,6 +215526,20 @@ static void sqlite3Fts5ParseFinished(Fts5Parse *pParse, Fts5ExprNode *p){
pParse->pExpr = p;
}
+static int parseGrowPhraseArray(Fts5Parse *pParse){
+ if( (pParse->nPhrase % 8)==0 ){
+ sqlite3_int64 nByte = sizeof(Fts5ExprPhrase*) * (pParse->nPhrase + 8);
+ Fts5ExprPhrase **apNew;
+ apNew = (Fts5ExprPhrase**)sqlite3_realloc64(pParse->apPhrase, nByte);
+ if( apNew==0 ){
+ pParse->rc = SQLITE_NOMEM;
+ return SQLITE_NOMEM;
+ }
+ pParse->apPhrase = apNew;
+ }
+ return SQLITE_OK;
+}
+
/*
** This function is called by the parser to process a string token. The
** string may or may not be quoted. In any case it is tokenized and a
@@ -214596,16 +215575,9 @@ static Fts5ExprPhrase *sqlite3Fts5ParseTerm(
}else{
if( pAppend==0 ){
- if( (pParse->nPhrase % 8)==0 ){
- sqlite3_int64 nByte = sizeof(Fts5ExprPhrase*) * (pParse->nPhrase + 8);
- Fts5ExprPhrase **apNew;
- apNew = (Fts5ExprPhrase**)sqlite3_realloc64(pParse->apPhrase, nByte);
- if( apNew==0 ){
- pParse->rc = SQLITE_NOMEM;
- fts5ExprPhraseFree(sCtx.pPhrase);
- return 0;
- }
- pParse->apPhrase = apNew;
+ if( parseGrowPhraseArray(pParse) ){
+ fts5ExprPhraseFree(sCtx.pPhrase);
+ return 0;
}
pParse->nPhrase++;
}
@@ -215013,6 +215985,67 @@ static void fts5ExprAddChildren(Fts5ExprNode *p, Fts5ExprNode *pSub){
}
/*
+** This function is used when parsing LIKE or GLOB patterns against
+** trigram indexes that specify either detail=column or detail=none.
+** It converts a phrase:
+**
+** abc + def + ghi
+**
+** into an AND tree:
+**
+** abc AND def AND ghi
+*/
+static Fts5ExprNode *fts5ParsePhraseToAnd(
+ Fts5Parse *pParse,
+ Fts5ExprNearset *pNear
+){
+ int nTerm = pNear->apPhrase[0]->nTerm;
+ int ii;
+ int nByte;
+ Fts5ExprNode *pRet;
+
+ assert( pNear->nPhrase==1 );
+ assert( pParse->bPhraseToAnd );
+
+ nByte = sizeof(Fts5ExprNode) + nTerm*sizeof(Fts5ExprNode*);
+ pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);
+ if( pRet ){
+ pRet->eType = FTS5_AND;
+ pRet->nChild = nTerm;
+ fts5ExprAssignXNext(pRet);
+ pParse->nPhrase--;
+ for(ii=0; ii<nTerm; ii++){
+ Fts5ExprPhrase *pPhrase = (Fts5ExprPhrase*)sqlite3Fts5MallocZero(
+ &pParse->rc, sizeof(Fts5ExprPhrase)
+ );
+ if( pPhrase ){
+ if( parseGrowPhraseArray(pParse) ){
+ fts5ExprPhraseFree(pPhrase);
+ }else{
+ pParse->apPhrase[pParse->nPhrase++] = pPhrase;
+ pPhrase->nTerm = 1;
+ pPhrase->aTerm[0].zTerm = sqlite3Fts5Strndup(
+ &pParse->rc, pNear->apPhrase[0]->aTerm[ii].zTerm, -1
+ );
+ pRet->apChild[ii] = sqlite3Fts5ParseNode(pParse, FTS5_STRING,
+ 0, 0, sqlite3Fts5ParseNearset(pParse, 0, pPhrase)
+ );
+ }
+ }
+ }
+
+ if( pParse->rc ){
+ sqlite3Fts5ParseNodeFree(pRet);
+ pRet = 0;
+ }else{
+ sqlite3Fts5ParseNearsetFree(pNear);
+ }
+ }
+
+ return pRet;
+}
+
+/*
** Allocate and return a new expression object. If anything goes wrong (i.e.
** OOM error), leave an error code in pParse and return NULL.
*/
@@ -215036,51 +216069,58 @@ static Fts5ExprNode *sqlite3Fts5ParseNode(
if( eType!=FTS5_STRING && pLeft==0 ) return pRight;
if( eType!=FTS5_STRING && pRight==0 ) return pLeft;
- if( eType==FTS5_NOT ){
- nChild = 2;
- }else if( eType==FTS5_AND || eType==FTS5_OR ){
- nChild = 2;
- if( pLeft->eType==eType ) nChild += pLeft->nChild-1;
- if( pRight->eType==eType ) nChild += pRight->nChild-1;
- }
+ if( eType==FTS5_STRING
+ && pParse->bPhraseToAnd
+ && pNear->apPhrase[0]->nTerm>1
+ ){
+ pRet = fts5ParsePhraseToAnd(pParse, pNear);
+ }else{
+ if( eType==FTS5_NOT ){
+ nChild = 2;
+ }else if( eType==FTS5_AND || eType==FTS5_OR ){
+ nChild = 2;
+ if( pLeft->eType==eType ) nChild += pLeft->nChild-1;
+ if( pRight->eType==eType ) nChild += pRight->nChild-1;
+ }
- nByte = sizeof(Fts5ExprNode) + sizeof(Fts5ExprNode*)*(nChild-1);
- pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);
+ nByte = sizeof(Fts5ExprNode) + sizeof(Fts5ExprNode*)*(nChild-1);
+ pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);
- if( pRet ){
- pRet->eType = eType;
- pRet->pNear = pNear;
- fts5ExprAssignXNext(pRet);
- if( eType==FTS5_STRING ){
- int iPhrase;
- for(iPhrase=0; iPhrase<pNear->nPhrase; iPhrase++){
- pNear->apPhrase[iPhrase]->pNode = pRet;
- if( pNear->apPhrase[iPhrase]->nTerm==0 ){
- pRet->xNext = 0;
- pRet->eType = FTS5_EOF;
+ if( pRet ){
+ pRet->eType = eType;
+ pRet->pNear = pNear;
+ fts5ExprAssignXNext(pRet);
+ if( eType==FTS5_STRING ){
+ int iPhrase;
+ for(iPhrase=0; iPhrase<pNear->nPhrase; iPhrase++){
+ pNear->apPhrase[iPhrase]->pNode = pRet;
+ if( pNear->apPhrase[iPhrase]->nTerm==0 ){
+ pRet->xNext = 0;
+ pRet->eType = FTS5_EOF;
+ }
}
- }
- if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL ){
- Fts5ExprPhrase *pPhrase = pNear->apPhrase[0];
- if( pNear->nPhrase!=1
- || pPhrase->nTerm>1
- || (pPhrase->nTerm>0 && pPhrase->aTerm[0].bFirst)
- ){
- assert( pParse->rc==SQLITE_OK );
- pParse->rc = SQLITE_ERROR;
- assert( pParse->zErr==0 );
- pParse->zErr = sqlite3_mprintf(
- "fts5: %s queries are not supported (detail!=full)",
- pNear->nPhrase==1 ? "phrase": "NEAR"
- );
- sqlite3_free(pRet);
- pRet = 0;
+ if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL ){
+ Fts5ExprPhrase *pPhrase = pNear->apPhrase[0];
+ if( pNear->nPhrase!=1
+ || pPhrase->nTerm>1
+ || (pPhrase->nTerm>0 && pPhrase->aTerm[0].bFirst)
+ ){
+ assert( pParse->rc==SQLITE_OK );
+ pParse->rc = SQLITE_ERROR;
+ assert( pParse->zErr==0 );
+ pParse->zErr = sqlite3_mprintf(
+ "fts5: %s queries are not supported (detail!=full)",
+ pNear->nPhrase==1 ? "phrase": "NEAR"
+ );
+ sqlite3_free(pRet);
+ pRet = 0;
+ }
}
+ }else{
+ fts5ExprAddChildren(pRet, pLeft);
+ fts5ExprAddChildren(pRet, pRight);
}
- }else{
- fts5ExprAddChildren(pRet, pLeft);
- fts5ExprAddChildren(pRet, pRight);
}
}
}
@@ -215301,8 +216341,17 @@ static char *fts5ExprPrint(Fts5Config *pConfig, Fts5ExprNode *pExpr){
int iTerm;
if( pNear->pColset ){
- int iCol = pNear->pColset->aiCol[0];
- zRet = fts5PrintfAppend(zRet, "%s : ", pConfig->azCol[iCol]);
+ int ii;
+ Fts5Colset *pColset = pNear->pColset;
+ if( pColset->nCol>1 ) zRet = fts5PrintfAppend(zRet, "{");
+ for(ii=0; ii<pColset->nCol; ii++){
+ zRet = fts5PrintfAppend(zRet, "%s%s",
+ pConfig->azCol[pColset->aiCol[ii]], ii==pColset->nCol-1 ? "" : " "
+ );
+ }
+ if( zRet ){
+ zRet = fts5PrintfAppend(zRet, "%s : ", pColset->nCol>1 ? "}" : "");
+ }
if( zRet==0 ) return 0;
}
@@ -215425,7 +216474,7 @@ static void fts5ExprFunction(
rc = sqlite3Fts5ConfigParse(pGlobal, db, nConfig, azConfig, &pConfig, &zErr);
if( rc==SQLITE_OK ){
- rc = sqlite3Fts5ExprNew(pConfig, pConfig->nCol, zExpr, &pExpr, &zErr);
+ rc = sqlite3Fts5ExprNew(pConfig, 0, pConfig->nCol, zExpr, &pExpr, &zErr);
}
if( rc==SQLITE_OK ){
char *zText;
@@ -216098,7 +217147,6 @@ static int sqlite3Fts5HashWrite(
p->iCol = (pHash->eDetail==FTS5_DETAIL_FULL ? 0 : -1);
}
- nIncr += p->nData;
}else{
/* Appending to an existing hash-entry. Check that there is enough
@@ -216131,8 +217179,9 @@ static int sqlite3Fts5HashWrite(
/* If this is a new rowid, append the 4-byte size field for the previous
** entry, and the new rowid for this entry. */
if( iRowid!=p->iRowid ){
+ u64 iDiff = (u64)iRowid - (u64)p->iRowid;
fts5HashAddPoslistSize(pHash, p, 0);
- p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iRowid - p->iRowid);
+ p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iDiff);
p->iRowid = iRowid;
bNew = 1;
p->iSzPoslist = p->nData;
@@ -218107,7 +219156,7 @@ static void fts5SegIterReverseInitPage(Fts5Index *p, Fts5SegIter *pIter){
ASSERT_SZLEAF_OK(pIter->pLeaf);
while( 1 ){
- i64 iDelta = 0;
+ u64 iDelta = 0;
if( eDetail==FTS5_DETAIL_NONE ){
/* todo */
@@ -218122,7 +219171,7 @@ static void fts5SegIterReverseInitPage(Fts5Index *p, Fts5SegIter *pIter){
i += nPos;
}
if( i>=n ) break;
- i += fts5GetVarint(&a[i], (u64*)&iDelta);
+ i += fts5GetVarint(&a[i], &iDelta);
pIter->iRowid += iDelta;
/* If necessary, grow the pIter->aRowidOffset[] array. */
@@ -218221,7 +219270,7 @@ static void fts5SegIterNext_Reverse(
if( pIter->iRowidOffset>0 ){
u8 *a = pIter->pLeaf->p;
int iOff;
- i64 iDelta;
+ u64 iDelta;
pIter->iRowidOffset--;
pIter->iLeafOffset = pIter->aRowidOffset[pIter->iRowidOffset];
@@ -218230,7 +219279,7 @@ static void fts5SegIterNext_Reverse(
if( p->pConfig->eDetail!=FTS5_DETAIL_NONE ){
iOff += pIter->nPos;
}
- fts5GetVarint(&a[iOff], (u64*)&iDelta);
+ fts5GetVarint(&a[iOff], &iDelta);
pIter->iRowid -= iDelta;
}else{
fts5SegIterReverseNewPage(p, pIter);
@@ -221350,7 +222399,9 @@ static void fts5MergePrefixLists(
** at most 20 bytes of unexpected space. */
fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
fts5BufferZero(&tmp);
- sqlite3Fts5BufferSize(&p->rc, &tmp, i1.nPoslist + i2.nPoslist + 10 + 10);
+ sqlite3Fts5BufferSize(&p->rc, &tmp,
+ i1.nPoslist + i2.nPoslist + 10 + 10 + FTS5_DATA_ZERO_PADDING
+ );
if( p->rc ) break;
sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
@@ -221424,9 +222475,10 @@ static void fts5MergePrefixLists(
}
assert_nc( out.n<=(p1->n+p2->n+9) );
- fts5BufferSet(&p->rc, p1, out.n, out.p);
+ fts5BufferFree(p1);
fts5BufferFree(&tmp);
- fts5BufferFree(&out);
+ memset(&out.p[out.n], 0, FTS5_DATA_ZERO_PADDING);
+ *p1 = out;
}
}
@@ -222412,7 +223464,7 @@ static void fts5IndexIntegrityCheckSegment(
** error, or some other SQLite error code if another error (e.g. OOM)
** occurs.
*/
-static int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum){
+static int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum, int bUseCksum){
int eDetail = p->pConfig->eDetail;
u64 cksum2 = 0; /* Checksum based on contents of indexes */
Fts5Buffer poslist = {0,0,0}; /* Buffer used to hold a poslist */
@@ -222473,6 +223525,7 @@ static int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum){
}else{
poslist.n = 0;
fts5SegiterPoslist(p, &pIter->aSeg[pIter->aFirst[1].iFirst], 0, &poslist);
+ fts5BufferAppendBlob(&p->rc, &poslist, 4, (const u8*)"\0\0\0\0");
while( 0==sqlite3Fts5PoslistNext64(poslist.p, poslist.n, &iOff, &iPos) ){
int iCol = FTS5_POS2COLUMN(iPos);
int iTokOff = FTS5_POS2OFFSET(iPos);
@@ -222483,7 +223536,7 @@ static int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum){
fts5TestTerm(p, &term, 0, 0, cksum2, &cksum3);
fts5MultiIterFree(pIter);
- if( p->rc==SQLITE_OK && cksum!=cksum2 ) p->rc = FTS5_CORRUPT;
+ if( p->rc==SQLITE_OK && bUseCksum && cksum!=cksum2 ) p->rc = FTS5_CORRUPT;
fts5StructureRelease(pStruct);
#ifdef SQLITE_DEBUG
@@ -223447,6 +224500,23 @@ static void fts5SetUniqueFlag(sqlite3_index_info *pIdxInfo){
#endif
}
+static int fts5UsePatternMatch(
+ Fts5Config *pConfig,
+ struct sqlite3_index_constraint *p
+){
+ assert( FTS5_PATTERN_GLOB==SQLITE_INDEX_CONSTRAINT_GLOB );
+ assert( FTS5_PATTERN_LIKE==SQLITE_INDEX_CONSTRAINT_LIKE );
+ if( pConfig->ePattern==FTS5_PATTERN_GLOB && p->op==FTS5_PATTERN_GLOB ){
+ return 1;
+ }
+ if( pConfig->ePattern==FTS5_PATTERN_LIKE
+ && (p->op==FTS5_PATTERN_LIKE || p->op==FTS5_PATTERN_GLOB)
+ ){
+ return 1;
+ }
+ return 0;
+}
+
/*
** Implementation of the xBestIndex method for FTS5 tables. Within the
** WHERE constraint, it searches for the following:
@@ -223476,7 +224546,9 @@ static void fts5SetUniqueFlag(sqlite3_index_info *pIdxInfo){
**
** Match against table column: "m"
** Match against rank column: "r"
-** Match against other column: "<column-number>"
+** Match against other column: "M<column-number>"
+** LIKE against other column: "L<column-number>"
+** GLOB against other column: "G<column-number>"
** Equality constraint against the rowid: "="
** A < or <= against the rowid: "<"
** A > or >= against the rowid: ">"
@@ -223537,7 +224609,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
return SQLITE_ERROR;
}
- idxStr = (char*)sqlite3_malloc(pInfo->nConstraint * 6 + 1);
+ idxStr = (char*)sqlite3_malloc(pInfo->nConstraint * 8 + 1);
if( idxStr==0 ) return SQLITE_NOMEM;
pInfo->idxStr = idxStr;
pInfo->needToFreeIdxStr = 1;
@@ -223561,25 +224633,29 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
if( bSeenRank ) continue;
idxStr[iIdxStr++] = 'r';
bSeenRank = 1;
- }else{
+ }else if( iCol>=0 ){
bSeenMatch = 1;
- idxStr[iIdxStr++] = 'm';
- if( iCol<nCol ){
- sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
- idxStr += strlen(&idxStr[iIdxStr]);
- assert( idxStr[iIdxStr]=='\0' );
- }
+ idxStr[iIdxStr++] = 'M';
+ sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
+ idxStr += strlen(&idxStr[iIdxStr]);
+ assert( idxStr[iIdxStr]=='\0' );
}
pInfo->aConstraintUsage[i].argvIndex = ++iCons;
pInfo->aConstraintUsage[i].omit = 1;
}
- }
- else if( p->usable && bSeenEq==0
- && p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol<0
- ){
- idxStr[iIdxStr++] = '=';
- bSeenEq = 1;
- pInfo->aConstraintUsage[i].argvIndex = ++iCons;
+ }else if( p->usable ){
+ if( iCol>=0 && iCol<nCol && fts5UsePatternMatch(pConfig, p) ){
+ assert( p->op==FTS5_PATTERN_LIKE || p->op==FTS5_PATTERN_GLOB );
+ idxStr[iIdxStr++] = p->op==FTS5_PATTERN_LIKE ? 'L' : 'G';
+ sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
+ idxStr += strlen(&idxStr[iIdxStr]);
+ pInfo->aConstraintUsage[i].argvIndex = ++iCons;
+ assert( idxStr[iIdxStr]=='\0' );
+ }else if( bSeenEq==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol<0 ){
+ idxStr[iIdxStr++] = '=';
+ bSeenEq = 1;
+ pInfo->aConstraintUsage[i].argvIndex = ++iCons;
+ }
}
}
@@ -224212,19 +225288,14 @@ static int fts5FilterMethod(
case 'r':
pRank = apVal[i];
break;
- case 'm': {
+ case 'M': {
const char *zText = (const char*)sqlite3_value_text(apVal[i]);
if( zText==0 ) zText = "";
-
- if( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' ){
- iCol = 0;
- do{
- iCol = iCol*10 + (idxStr[iIdxStr]-'0');
- iIdxStr++;
- }while( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' );
- }else{
- iCol = pConfig->nCol;
- }
+ iCol = 0;
+ do{
+ iCol = iCol*10 + (idxStr[iIdxStr]-'0');
+ iIdxStr++;
+ }while( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' );
if( zText[0]=='*' ){
/* The user has issued a query of the form "MATCH '*...'". This
@@ -224234,7 +225305,7 @@ static int fts5FilterMethod(
goto filter_out;
}else{
char **pzErr = &pTab->p.base.zErrMsg;
- rc = sqlite3Fts5ExprNew(pConfig, iCol, zText, &pExpr, pzErr);
+ rc = sqlite3Fts5ExprNew(pConfig, 0, iCol, zText, &pExpr, pzErr);
if( rc==SQLITE_OK ){
rc = sqlite3Fts5ExprAnd(&pCsr->pExpr, pExpr);
pExpr = 0;
@@ -224244,6 +225315,25 @@ static int fts5FilterMethod(
break;
}
+ case 'L':
+ case 'G': {
+ int bGlob = (idxStr[iIdxStr-1]=='G');
+ const char *zText = (const char*)sqlite3_value_text(apVal[i]);
+ iCol = 0;
+ do{
+ iCol = iCol*10 + (idxStr[iIdxStr]-'0');
+ iIdxStr++;
+ }while( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' );
+ if( zText ){
+ rc = sqlite3Fts5ExprPattern(pConfig, bGlob, iCol, zText, &pExpr);
+ }
+ if( rc==SQLITE_OK ){
+ rc = sqlite3Fts5ExprAnd(&pCsr->pExpr, pExpr);
+ pExpr = 0;
+ }
+ if( rc!=SQLITE_OK ) goto filter_out;
+ break;
+ }
case '=':
pRowidEq = apVal[i];
break;
@@ -224491,7 +225581,8 @@ static int fts5SpecialInsert(
int nMerge = sqlite3_value_int(pVal);
rc = sqlite3Fts5StorageMerge(pTab->pStorage, nMerge);
}else if( 0==sqlite3_stricmp("integrity-check", zCmd) ){
- rc = sqlite3Fts5StorageIntegrity(pTab->pStorage);
+ int iArg = sqlite3_value_int(pVal);
+ rc = sqlite3Fts5StorageIntegrity(pTab->pStorage, iArg);
#ifdef SQLITE_DEBUG
}else if( 0==sqlite3_stricmp("prefix-index", zCmd) ){
pConfig->bPrefixIndex = sqlite3_value_int(pVal);
@@ -225654,8 +226745,7 @@ static int sqlite3Fts5GetTokenizer(
Fts5Global *pGlobal,
const char **azArg,
int nArg,
- Fts5Tokenizer **ppTok,
- fts5_tokenizer **ppTokApi,
+ Fts5Config *pConfig,
char **pzErr
){
Fts5TokenizerModule *pMod;
@@ -225667,16 +226757,22 @@ static int sqlite3Fts5GetTokenizer(
rc = SQLITE_ERROR;
*pzErr = sqlite3_mprintf("no such tokenizer: %s", azArg[0]);
}else{
- rc = pMod->x.xCreate(pMod->pUserData, &azArg[1], (nArg?nArg-1:0), ppTok);
- *ppTokApi = &pMod->x;
- if( rc!=SQLITE_OK && pzErr ){
- *pzErr = sqlite3_mprintf("error in tokenizer constructor");
+ rc = pMod->x.xCreate(
+ pMod->pUserData, &azArg[1], (nArg?nArg-1:0), &pConfig->pTok
+ );
+ pConfig->pTokApi = &pMod->x;
+ if( rc!=SQLITE_OK ){
+ if( pzErr ) *pzErr = sqlite3_mprintf("error in tokenizer constructor");
+ }else{
+ pConfig->ePattern = sqlite3Fts5TokenizerPattern(
+ pMod->x.xCreate, pConfig->pTok
+ );
}
}
if( rc!=SQLITE_OK ){
- *ppTokApi = 0;
- *ppTok = 0;
+ pConfig->pTokApi = 0;
+ pConfig->pTok = 0;
}
return rc;
@@ -225725,7 +226821,7 @@ static void fts5SourceIdFunc(
){
assert( nArg==0 );
UNUSED_PARAM2(nArg, apUnused);
- sqlite3_result_text(pCtx, "fts5: 2020-08-14 13:23:32 fca8dc8b578f215a969cd899336378966156154710873e68b3d9ac5881b0ff3f", -1, SQLITE_TRANSIENT);
+ sqlite3_result_text(pCtx, "fts5: 2020-12-01 16:14:00 0000000000000000000000000000000000000000000000000000000000000000", -1, SQLITE_TRANSIENT);
}
/*
@@ -226288,9 +227384,16 @@ static int fts5StorageDeleteFromIndex(
zText, nText, (void*)&ctx, fts5StorageInsertCallback
);
p->aTotalSize[iCol-1] -= (i64)ctx.szCol;
+ if( p->aTotalSize[iCol-1]<0 ){
+ rc = FTS5_CORRUPT;
+ }
}
}
- p->nTotalRow--;
+ if( rc==SQLITE_OK && p->nTotalRow<1 ){
+ rc = FTS5_CORRUPT;
+ }else{
+ p->nTotalRow--;
+ }
rc2 = sqlite3_reset(pSeek);
if( rc==SQLITE_OK ) rc = rc2;
@@ -226733,13 +227836,14 @@ static int fts5StorageIntegrityCallback(
** some other SQLite error code if an error occurs while attempting to
** determine this.
*/
-static int sqlite3Fts5StorageIntegrity(Fts5Storage *p){
+static int sqlite3Fts5StorageIntegrity(Fts5Storage *p, int iArg){
Fts5Config *pConfig = p->pConfig;
- int rc; /* Return code */
+ int rc = SQLITE_OK; /* Return code */
int *aColSize; /* Array of size pConfig->nCol */
i64 *aTotalSize; /* Array of size pConfig->nCol */
Fts5IntegrityCtx ctx;
sqlite3_stmt *pScan;
+ int bUseCksum;
memset(&ctx, 0, sizeof(Fts5IntegrityCtx));
ctx.pConfig = p->pConfig;
@@ -226748,83 +227852,88 @@ static int sqlite3Fts5StorageIntegrity(Fts5Storage *p){
aColSize = (int*)&aTotalSize[pConfig->nCol];
memset(aTotalSize, 0, sizeof(i64) * pConfig->nCol);
- /* Generate the expected index checksum based on the contents of the
- ** %_content table. This block stores the checksum in ctx.cksum. */
- rc = fts5StorageGetStmt(p, FTS5_STMT_SCAN, &pScan, 0);
- if( rc==SQLITE_OK ){
- int rc2;
- while( SQLITE_ROW==sqlite3_step(pScan) ){
- int i;
- ctx.iRowid = sqlite3_column_int64(pScan, 0);
- ctx.szCol = 0;
- if( pConfig->bColumnsize ){
- rc = sqlite3Fts5StorageDocsize(p, ctx.iRowid, aColSize);
- }
- if( rc==SQLITE_OK && pConfig->eDetail==FTS5_DETAIL_NONE ){
- rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
- }
- for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
- if( pConfig->abUnindexed[i] ) continue;
- ctx.iCol = i;
+ bUseCksum = (pConfig->eContent==FTS5_CONTENT_NORMAL
+ || (pConfig->eContent==FTS5_CONTENT_EXTERNAL && iArg)
+ );
+ if( bUseCksum ){
+ /* Generate the expected index checksum based on the contents of the
+ ** %_content table. This block stores the checksum in ctx.cksum. */
+ rc = fts5StorageGetStmt(p, FTS5_STMT_SCAN, &pScan, 0);
+ if( rc==SQLITE_OK ){
+ int rc2;
+ while( SQLITE_ROW==sqlite3_step(pScan) ){
+ int i;
+ ctx.iRowid = sqlite3_column_int64(pScan, 0);
ctx.szCol = 0;
- if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
- rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
- }
- if( rc==SQLITE_OK ){
- const char *zText = (const char*)sqlite3_column_text(pScan, i+1);
- int nText = sqlite3_column_bytes(pScan, i+1);
- rc = sqlite3Fts5Tokenize(pConfig,
- FTS5_TOKENIZE_DOCUMENT,
- zText, nText,
- (void*)&ctx,
- fts5StorageIntegrityCallback
- );
+ if( pConfig->bColumnsize ){
+ rc = sqlite3Fts5StorageDocsize(p, ctx.iRowid, aColSize);
}
- if( rc==SQLITE_OK && pConfig->bColumnsize && ctx.szCol!=aColSize[i] ){
- rc = FTS5_CORRUPT;
+ if( rc==SQLITE_OK && pConfig->eDetail==FTS5_DETAIL_NONE ){
+ rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
}
- aTotalSize[i] += ctx.szCol;
- if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
- sqlite3Fts5TermsetFree(ctx.pTermset);
- ctx.pTermset = 0;
+ for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
+ if( pConfig->abUnindexed[i] ) continue;
+ ctx.iCol = i;
+ ctx.szCol = 0;
+ if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
+ rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
+ }
+ if( rc==SQLITE_OK ){
+ const char *zText = (const char*)sqlite3_column_text(pScan, i+1);
+ int nText = sqlite3_column_bytes(pScan, i+1);
+ rc = sqlite3Fts5Tokenize(pConfig,
+ FTS5_TOKENIZE_DOCUMENT,
+ zText, nText,
+ (void*)&ctx,
+ fts5StorageIntegrityCallback
+ );
+ }
+ if( rc==SQLITE_OK && pConfig->bColumnsize && ctx.szCol!=aColSize[i] ){
+ rc = FTS5_CORRUPT;
+ }
+ aTotalSize[i] += ctx.szCol;
+ if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
+ sqlite3Fts5TermsetFree(ctx.pTermset);
+ ctx.pTermset = 0;
+ }
}
- }
- sqlite3Fts5TermsetFree(ctx.pTermset);
- ctx.pTermset = 0;
+ sqlite3Fts5TermsetFree(ctx.pTermset);
+ ctx.pTermset = 0;
- if( rc!=SQLITE_OK ) break;
+ if( rc!=SQLITE_OK ) break;
+ }
+ rc2 = sqlite3_reset(pScan);
+ if( rc==SQLITE_OK ) rc = rc2;
}
- rc2 = sqlite3_reset(pScan);
- if( rc==SQLITE_OK ) rc = rc2;
- }
- /* Test that the "totals" (sometimes called "averages") record looks Ok */
- if( rc==SQLITE_OK ){
- int i;
- rc = fts5StorageLoadTotals(p, 0);
- for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
- if( p->aTotalSize[i]!=aTotalSize[i] ) rc = FTS5_CORRUPT;
+ /* Test that the "totals" (sometimes called "averages") record looks Ok */
+ if( rc==SQLITE_OK ){
+ int i;
+ rc = fts5StorageLoadTotals(p, 0);
+ for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
+ if( p->aTotalSize[i]!=aTotalSize[i] ) rc = FTS5_CORRUPT;
+ }
}
- }
- /* Check that the %_docsize and %_content tables contain the expected
- ** number of rows. */
- if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){
- i64 nRow = 0;
- rc = fts5StorageCount(p, "content", &nRow);
- if( rc==SQLITE_OK && nRow!=p->nTotalRow ) rc = FTS5_CORRUPT;
- }
- if( rc==SQLITE_OK && pConfig->bColumnsize ){
- i64 nRow = 0;
- rc = fts5StorageCount(p, "docsize", &nRow);
- if( rc==SQLITE_OK && nRow!=p->nTotalRow ) rc = FTS5_CORRUPT;
+ /* Check that the %_docsize and %_content tables contain the expected
+ ** number of rows. */
+ if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){
+ i64 nRow = 0;
+ rc = fts5StorageCount(p, "content", &nRow);
+ if( rc==SQLITE_OK && nRow!=p->nTotalRow ) rc = FTS5_CORRUPT;
+ }
+ if( rc==SQLITE_OK && pConfig->bColumnsize ){
+ i64 nRow = 0;
+ rc = fts5StorageCount(p, "docsize", &nRow);
+ if( rc==SQLITE_OK && nRow!=p->nTotalRow ) rc = FTS5_CORRUPT;
+ }
}
/* Pass the expected checksum down to the FTS index module. It will
** verify, amongst other things, that it matches the checksum generated by
** inspecting the index itself. */
if( rc==SQLITE_OK ){
- rc = sqlite3Fts5IndexIntegrityCheck(p->pIndex, ctx.cksum);
+ rc = sqlite3Fts5IndexIntegrityCheck(p->pIndex, ctx.cksum, bUseCksum);
}
sqlite3_free(aTotalSize);
@@ -228266,6 +229375,133 @@ static int fts5PorterTokenize(
);
}
+/**************************************************************************
+** Start of trigram implementation.
+*/
+typedef struct TrigramTokenizer TrigramTokenizer;
+struct TrigramTokenizer {
+ int bFold; /* True to fold to lower-case */
+};
+
+/*
+** Free a trigram tokenizer.
+*/
+static void fts5TriDelete(Fts5Tokenizer *p){
+ sqlite3_free(p);
+}
+
+/*
+** Allocate a trigram tokenizer.
+*/
+static int fts5TriCreate(
+ void *pUnused,
+ const char **azArg,
+ int nArg,
+ Fts5Tokenizer **ppOut
+){
+ int rc = SQLITE_OK;
+ TrigramTokenizer *pNew = (TrigramTokenizer*)sqlite3_malloc(sizeof(*pNew));
+ UNUSED_PARAM(pUnused);
+ if( pNew==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ int i;
+ pNew->bFold = 1;
+ for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
+ const char *zArg = azArg[i+1];
+ if( 0==sqlite3_stricmp(azArg[i], "case_sensitive") ){
+ if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1] ){
+ rc = SQLITE_ERROR;
+ }else{
+ pNew->bFold = (zArg[0]=='0');
+ }
+ }else{
+ rc = SQLITE_ERROR;
+ }
+ }
+ if( rc!=SQLITE_OK ){
+ fts5TriDelete((Fts5Tokenizer*)pNew);
+ pNew = 0;
+ }
+ }
+ *ppOut = (Fts5Tokenizer*)pNew;
+ return rc;
+}
+
+/*
+** Trigram tokenizer tokenize routine.
+*/
+static int fts5TriTokenize(
+ Fts5Tokenizer *pTok,
+ void *pCtx,
+ int unusedFlags,
+ const char *pText, int nText,
+ int (*xToken)(void*, int, const char*, int, int, int)
+){
+ TrigramTokenizer *p = (TrigramTokenizer*)pTok;
+ int rc = SQLITE_OK;
+ char aBuf[32];
+ const unsigned char *zIn = (const unsigned char*)pText;
+ const unsigned char *zEof = &zIn[nText];
+ u32 iCode;
+
+ UNUSED_PARAM(unusedFlags);
+ while( 1 ){
+ char *zOut = aBuf;
+ int iStart = zIn - (const unsigned char*)pText;
+ const unsigned char *zNext;
+
+ READ_UTF8(zIn, zEof, iCode);
+ if( iCode==0 ) break;
+ zNext = zIn;
+ if( zIn<zEof ){
+ if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, 0);
+ WRITE_UTF8(zOut, iCode);
+ READ_UTF8(zIn, zEof, iCode);
+ if( iCode==0 ) break;
+ }else{
+ break;
+ }
+ if( zIn<zEof ){
+ if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, 0);
+ WRITE_UTF8(zOut, iCode);
+ READ_UTF8(zIn, zEof, iCode);
+ if( iCode==0 ) break;
+ if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, 0);
+ WRITE_UTF8(zOut, iCode);
+ }else{
+ break;
+ }
+ rc = xToken(pCtx, 0, aBuf, zOut-aBuf, iStart, iStart + zOut-aBuf);
+ if( rc!=SQLITE_OK ) break;
+ zIn = zNext;
+ }
+
+ return rc;
+}
+
+/*
+** Argument xCreate is a pointer to a constructor function for a tokenizer.
+** pTok is a tokenizer previously created using the same method. This function
+** returns one of FTS5_PATTERN_NONE, FTS5_PATTERN_LIKE or FTS5_PATTERN_GLOB
+** indicating the style of pattern matching that the tokenizer can support.
+** In practice, this is:
+**
+** "trigram" tokenizer, case_sensitive=1 - FTS5_PATTERN_GLOB
+** "trigram" tokenizer, case_sensitive=0 (the default) - FTS5_PATTERN_LIKE
+** all other tokenizers - FTS5_PATTERN_NONE
+*/
+static int sqlite3Fts5TokenizerPattern(
+ int (*xCreate)(void*, const char**, int, Fts5Tokenizer**),
+ Fts5Tokenizer *pTok
+){
+ if( xCreate==fts5TriCreate ){
+ TrigramTokenizer *p = (TrigramTokenizer*)pTok;
+ return p->bFold ? FTS5_PATTERN_LIKE : FTS5_PATTERN_GLOB;
+ }
+ return FTS5_PATTERN_NONE;
+}
+
/*
** Register all built-in tokenizers with FTS5.
*/
@@ -228277,6 +229513,7 @@ static int sqlite3Fts5TokenizerInit(fts5_api *pApi){
{ "unicode61", {fts5UnicodeCreate, fts5UnicodeDelete, fts5UnicodeTokenize}},
{ "ascii", {fts5AsciiCreate, fts5AsciiDelete, fts5AsciiTokenize }},
{ "porter", {fts5PorterCreate, fts5PorterDelete, fts5PorterTokenize }},
+ { "trigram", {fts5TriCreate, fts5TriDelete, fts5TriTokenize}},
};
int rc = SQLITE_OK; /* Return code */
@@ -229069,8 +230306,10 @@ static void sqlite3Fts5UnicodeAscii(u8 *aArray, u8 *aAscii){
}
iTbl++;
}
+ aAscii[0] = 0; /* 0x00 is never a token character */
}
+
/*
** 2015 May 30
**
@@ -230508,9 +231747,9 @@ SQLITE_API int sqlite3_stmt_init(
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
/************** End of stmt.c ************************************************/
-#if __LINE__!=230511
+#if __LINE__!=231750
#undef SQLITE_SOURCE_ID
-#define SQLITE_SOURCE_ID "2020-08-14 13:23:32 fca8dc8b578f215a969cd899336378966156154710873e68b3d9ac5881b0alt2"
+#define SQLITE_SOURCE_ID "2020-12-01 16:14:00 b7738010bc8ef02ba84820368e557306390a33c38adaa5c7703154bae3edalt2"
#endif
/* Return the source-id for this library */
SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
diff --git a/chromium/third_party/sqlite/src/amalgamation_dev/sqlite3.h b/chromium/third_party/sqlite/src/amalgamation_dev/sqlite3.h
index 910b687aa7d..44be7872663 100644
--- a/chromium/third_party/sqlite/src/amalgamation_dev/sqlite3.h
+++ b/chromium/third_party/sqlite/src/amalgamation_dev/sqlite3.h
@@ -123,9 +123,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.33.0"
-#define SQLITE_VERSION_NUMBER 3033000
-#define SQLITE_SOURCE_ID "2020-08-14 13:23:32 fca8dc8b578f215a969cd899336378966156154710873e68b3d9ac5881b0ff3f"
+#define SQLITE_VERSION "3.34.0"
+#define SQLITE_VERSION_NUMBER 3034000
+#define SQLITE_SOURCE_ID "2020-12-01 16:14:00 b7738010bc8ef02ba84820368e557306390a33c38adaa5c7703154bae3edalt1"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -504,6 +504,7 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8))
#define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8))
#define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8))
+#define SQLITE_IOERR_CORRUPTFS (SQLITE_IOERR | (33<<8))
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8))
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
@@ -6187,6 +6188,57 @@ SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName);
/*
+** CAPI3REF: Determine the transaction state of a database
+** METHOD: sqlite3
+**
+** ^The sqlite3_txn_state(D,S) interface returns the current
+** [transaction state] of schema S in database connection D. ^If S is NULL,
+** then the highest transaction state of any schema on database connection D
+** is returned. Transaction states are (in order of lowest to highest):
+** <ol>
+** <li value="0"> SQLITE_TXN_NONE
+** <li value="1"> SQLITE_TXN_READ
+** <li value="2"> SQLITE_TXN_WRITE
+** </ol>
+** ^If the S argument to sqlite3_txn_state(D,S) is not the name of
+** a valid schema, then -1 is returned.
+*/
+SQLITE_API int sqlite3_txn_state(sqlite3*,const char *zSchema);
+
+/*
+** CAPI3REF: Allowed return values from [sqlite3_txn_state()]
+** KEYWORDS: {transaction state}
+**
+** These constants define the current transaction state of a database file.
+** ^The [sqlite3_txn_state(D,S)] interface returns one of these
+** constants in order to describe the transaction state of schema S
+** in [database connection] D.
+**
+** <dl>
+** [[SQLITE_TXN_NONE]] <dt>SQLITE_TXN_NONE</dt>
+** <dd>The SQLITE_TXN_NONE state means that no transaction is currently
+** pending.</dd>
+**
+** [[SQLITE_TXN_READ]] <dt>SQLITE_TXN_READ</dt>
+** <dd>The SQLITE_TXN_READ state means that the database is currently
+** in a read transaction. Content has been read from the database file
+** but nothing in the database file has changed. The transaction state
+** will advanced to SQLITE_TXN_WRITE if any changes occur and there are
+** no other conflicting concurrent write transactions. The transaction
+** state will revert to SQLITE_TXN_NONE following a [ROLLBACK] or
+** [COMMIT].</dd>
+**
+** [[SQLITE_TXN_WRITE]] <dt>SQLITE_TXN_WRITE</dt>
+** <dd>The SQLITE_TXN_WRITE state means that the database is currently
+** in a write transaction. Content has been written to the database file
+** but has not yet committed. The transaction state will change to
+** to SQLITE_TXN_NONE at the next [ROLLBACK] or [COMMIT].</dd>
+*/
+#define SQLITE_TXN_NONE 0
+#define SQLITE_TXN_READ 1
+#define SQLITE_TXN_WRITE 2
+
+/*
** CAPI3REF: Find the next prepared statement
** METHOD: sqlite3
**
@@ -7712,7 +7764,8 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_RESULT_INTREAL 27
#define SQLITE_TESTCTRL_PRNG_SEED 28
#define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29
-#define SQLITE_TESTCTRL_LAST 29 /* Largest TESTCTRL */
+#define SQLITE_TESTCTRL_SEEK_COUNT 30
+#define SQLITE_TESTCTRL_LAST 30 /* Largest TESTCTRL */
/*
** CAPI3REF: SQL Keyword Checking
@@ -9192,10 +9245,11 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
** CAPI3REF: Determine If Virtual Table Column Access Is For UPDATE
**
** If the sqlite3_vtab_nochange(X) routine is called within the [xColumn]
-** method of a [virtual table], then it returns true if and only if the
+** method of a [virtual table], then it might return true if the
** column is being fetched as part of an UPDATE operation during which the
-** column value will not change. Applications might use this to substitute
-** a return value that is less expensive to compute and that the corresponding
+** column value will not change. The virtual table implementation can use
+** this hint as permission to substitute a return value that is less
+** expensive to compute and that the corresponding
** [xUpdate] method understands as a "no-change" value.
**
** If the [xColumn] method calls sqlite3_vtab_nochange() and finds that
@@ -9204,6 +9258,12 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
** any of the [sqlite3_result_int|sqlite3_result_xxxxx() interfaces].
** In that case, [sqlite3_value_nochange(X)] will return true for the
** same column in the [xUpdate] method.
+**
+** The sqlite3_vtab_nochange() routine is an optimization. Virtual table
+** implementations should continue to give a correct answer even if the
+** sqlite3_vtab_nochange() interface were to always return false. In the
+** current implementation, the sqlite3_vtab_nochange() interface does always
+** returns false for the enhanced [UPDATE FROM] statement.
*/
SQLITE_API int sqlite3_vtab_nochange(sqlite3_context*);
@@ -9345,6 +9405,7 @@ SQLITE_API void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
/*
** CAPI3REF: Flush caches to disk mid-transaction
+** METHOD: sqlite3
**
** ^If a write-transaction is open on [database connection] D when the
** [sqlite3_db_cacheflush(D)] interface invoked, any dirty
@@ -9377,6 +9438,7 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*);
/*
** CAPI3REF: The pre-update hook.
+** METHOD: sqlite3
**
** ^These interfaces are only available if SQLite is compiled using the
** [SQLITE_ENABLE_PREUPDATE_HOOK] compile-time option.
@@ -9417,7 +9479,7 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*);
** seventh parameter is the final rowid value of the row being inserted
** or updated. The value of the seventh parameter passed to the callback
** function is not defined for operations on WITHOUT ROWID tables, or for
-** INSERT operations on rowid tables.
+** DELETE operations on rowid tables.
**
** The [sqlite3_preupdate_old()], [sqlite3_preupdate_new()],
** [sqlite3_preupdate_count()], and [sqlite3_preupdate_depth()] interfaces
@@ -9479,6 +9541,7 @@ SQLITE_API int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **);
/*
** CAPI3REF: Low-level system error code
+** METHOD: sqlite3
**
** ^Attempt to return the underlying operating system error code or error
** number that caused the most recent I/O error or failure to open a file.
diff --git a/chromium/third_party/sqlite/src/art/sqlite370.eps b/chromium/third_party/sqlite/src/art/sqlite370.eps
index c2670a0bc77..770175687ea 100644
--- a/chromium/third_party/sqlite/src/art/sqlite370.eps
+++ b/chromium/third_party/sqlite/src/art/sqlite370.eps
@@ -10,8 +10,8 @@
%%LanguageLevel: 2
%%DocumentData: Clean7Bit
%ADOBeginClientInjection: DocumentHeader "AI11EPS"
-%%AI8_CreatorVersion: 13.0.2 %AI9_PrintingDataBegin %AI3_Cropmarks: 36.0000 36.0000 336.0000 175.3042
-%ADO_BuildNumber: Adobe Illustrator(R) 13.0.2 x434 R agm 4.4379 ct 5.1039 %ADO_ContainsXMP: MainFirst %AI7_Thumbnail: 128 76 8 %%BeginData: 6312 Hex Bytes %0000330000660000990000CC0033000033330033660033990033CC0033FF %0066000066330066660066990066CC0066FF009900009933009966009999 %0099CC0099FF00CC0000CC3300CC6600CC9900CCCC00CCFF00FF3300FF66 %00FF9900FFCC3300003300333300663300993300CC3300FF333300333333 %3333663333993333CC3333FF3366003366333366663366993366CC3366FF %3399003399333399663399993399CC3399FF33CC0033CC3333CC6633CC99 %33CCCC33CCFF33FF0033FF3333FF6633FF9933FFCC33FFFF660000660033 %6600666600996600CC6600FF6633006633336633666633996633CC6633FF %6666006666336666666666996666CC6666FF669900669933669966669999 %6699CC6699FF66CC0066CC3366CC6666CC9966CCCC66CCFF66FF0066FF33 %66FF6666FF9966FFCC66FFFF9900009900339900669900999900CC9900FF %9933009933339933669933999933CC9933FF996600996633996666996699 %9966CC9966FF9999009999339999669999999999CC9999FF99CC0099CC33 %99CC6699CC9999CCCC99CCFF99FF0099FF3399FF6699FF9999FFCC99FFFF %CC0000CC0033CC0066CC0099CC00CCCC00FFCC3300CC3333CC3366CC3399 %CC33CCCC33FFCC6600CC6633CC6666CC6699CC66CCCC66FFCC9900CC9933 %CC9966CC9999CC99CCCC99FFCCCC00CCCC33CCCC66CCCC99CCCCCCCCCCFF %CCFF00CCFF33CCFF66CCFF99CCFFCCCCFFFFFF0033FF0066FF0099FF00CC %FF3300FF3333FF3366FF3399FF33CCFF33FFFF6600FF6633FF6666FF6699 %FF66CCFF66FFFF9900FF9933FF9966FF9999FF99CCFF99FFFFCC00FFCC33 %FFCC66FFCC99FFCCCCFFCCFFFFFF33FFFF66FFFF99FFFFCC110000001100 %000011111111220000002200000022222222440000004400000044444444 %550000005500000055555555770000007700000077777777880000008800 %000088888888AA000000AA000000AAAAAAAABB000000BB000000BBBBBBBB %DD000000DD000000DDDDDDDDEE000000EE000000EEEEEEEE0000000000FF %00FF0000FFFFFF0000FF00FFFFFF00FFFFFF %524C45FDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFD4AFFA90C0D %0C35A8FD79FF3505060506050CA8FD5AFF84360E0E0D140E0E0D140E0E0D %140E0E0D140E0E0D140E0E0D140E0E0D0D0506050C05060535FD59FF7E0E %3685608560856085608560856085608560856085608560856085600D0506 %05060506050605FD59FF365A856085618560856185608561856085618560 %856185608561856035050605060506050605067EFD58FF0D615A615A615A %615A615A615A615A615A615A615A615A615A615A5A050605060506050605 %060584FD58FF146185608561856085618560856185608561856085618560 %856161060C0506050C0606050C05067EFD58FF0D615A615A615A615A615A %615A615A615A615A615A615A615A610D0605060506060C050605060584FD %58FF0E5A855A615A855A615A855A615A855A615A855A615A855A61360605 %060506062F050605060506A8FD58FF0D5A5A615A5A5A615A5A5A615A5A5A %615A5A5A615A5A5A615A0C05060506055905060506050605FD59FF0E5A61 %5A615A615A615A615A615A615A615A615A615A615A5A050C0506052F0C06 %050C05060535FD59FF0D5A365B5A5A365B5A5A365B5A5A365B5A5A365B5A %5A365B0C0605060506590605060506050659FD59FF145A5B5A615A5B5A61 %5A5B5A615A5B5A615A5B5A615A5B360605060506350C05060506050606FD %5AFF0D5A365A365A365A365A365A365A365A365A365A365A360D05060506 %05840506050605060535FD5AFF14365B365B365B365B365B365B365B365B %365B365B365B050C0506055A0C06050C0506050CA8FD5AFF0D5A3636365A %3636365A3636365A3636365A3636365A0D060506050C5906050605060506 %0CFD5BFF0E365A365A365A365A365A365A365A365A365A365A360D050605 %06590C05060506050605A9FD5BFF0D363036303630363036303630363036 %3036303630360506050605A90506050605060535FD5CFF0EFD14360D0C05 %06055A2F06050C0506050CAFFD5CFF0D360E3630360E3630360E3630360E %3630360E36300D0506050684060506050605062FFD5DFF1436360E363636 %0E3636360E3636360E3636360E360C0605060C5905060506050606FD5EFF %0D360E360D360E360D360E360D360E360D360E360D0C0506058406060506 %05060CA9FD5EFF140E360E360E360E360E360E360E360E360E360E0D0506 %050CA806050C062F2FA9FFFF2F0C050C06350C84FD07FF5A0C0C060D050C %2FFD06FF0D0506050C0CFD3AFF0D360E140D360E140D360E140D360E140D %360E14060605062E3505060506050CFFFF0C0659FFFFA806065AFD05FF7E %0C0535A8FFFFFF590C0559FD05FF7E05062EFD3BFF0E0E360E140E360E14 %0E360E140E360E140E360E0C0506058406060506050684FF84062FFD05FF %0584FD04FF590605A9FD06FFA80C052FFD04FF84060584FD3BFF0D0E0D14 %0D0E0D140D0E0D140D0E0D140D0E0D0D050605067E06050605062FFFFF35 %055AFD05FF2F59FFFFFF7E060559FD08FF84060535FD04FF05065AFD09FF %060CFD30FF0E0E140E140E140E140E140E140E140E140E140D06050C0C5A %050C05060CFFFFFF2F0C0CFD05FFA8FD04FF0D050CFD0AFF2F0605AFFFFF %FF0C0584FD09FF0D05AFFD05FFA9FD29FF0D0E0D140D0E0D140D0E0D140D %0E0D140D0E0D0D050605590606050605AFFFFFFF5905062FFD08FF840506 %2FFD0AFFA905062EFFFFFF05065AFD0AFFA9FD05FF5A06FD29FF140E140D %140E140D140E140D140E140D140E140D0C05065906050606A9FD04FFA80C %05060CFD07FF2F060584FD0BFF0C050CFFFFFF060584FD10FF060CFD29FF %0D0E0D0E0D0E0D0E0D0E0D0E0D0E0D0E0D0E0D0E0606055A05062FFD07FF %2F0605060559FD05FF0C0506FD0CFF060605FFFFFF050659FD07FFA85A2E %0C06FFFF350506050C0684FD04FF0C06050C59FD1DFF140E140D140E140D %140E140D140E0E0D140E0E0D0E050C2F0C84FD09FF350C0506050DAFFFFF %FF0C0605FD0CFF0D0506FFFFFF060584FD07FFA92F0C050DFFFF7E5A050C %7E84AFFFFFFF060C2F0C050CA9FD1CFF0D0E0D0E0D0E0D0E0D0E0D0E0D0E %0D0E0D0E0D0E0D060C0C59FD0BFF840C0506050CA8FFFF0C0506FD0CFF06 %0605FFFFA9050659FD09FF840606FFFFFF590606FD05FF060C84FF59060C %FD1DFF0E0D140E0E0D140E0E0D140E0E0D140E0E0D140E0E06590CFD0EFF %5A0606050DFFFF0C060584FD0BFF0C050CFFFF7E060584FD0AFF050CFFFF %FF84050DFD04FF840635FFFF2F05FD1EFF0D0E0D0E0D0E0D0E0D0E0D0E0D %0E0D0E0D0E0D0E0D0C2E84FD0FFF84050605FFFF59050659FD0BFF05060C %FFFF8405065AFD09FF590606FFFFFF5A0606FD04FF59055A590C0584FD1E %FF0E0D140E0E0D140E0E0D140E0E0D140E0E0D140E0E0684FD0AFF59FD06 %FF5A050C7EFFFF0C052FFD0AFF59060584FFFF7E0C0584FD09FF84050DFF %FFFF84050DFD04FF2F0606355AFD20FF0D0E0D0E0D0E0D0E0D0E0D0E0D0E %0D0E0D0E0D0E0D0C59FD0AFF0C59FD05FFA80605A9FFFF59060584FD09FF %0C050CFFFFFF8405065AFD09FF590606FFFFFF5A062EFD04FF350559FD05 %FFA9FD1CFF140E0E0D140E0E0D140E0E0D140E0E0D140E0E0D140684FD0A %FF0C2FFD05FF84050CFD04FF2F0606FD08FF35050CAFFFFFFF7E060584FD %05FF8459FFFF84050DFFFFFF840535FFFF84847E0606FD04FF8406FD1CFF %5A0E0D0E0D0E0D0E0D0E0D0E0D0E0D0E0D0E0D0E0D0C84FD0AFF0C0559FD %04FF060659FD05FF2E0606A8FD04FFA82F050CA8FD04FF5A05062EFD05FF %0559FFFF5A0605FFFFFF590605842F0C7EFF0506065A592F055AFD1DFF5A %0E0D140E0E0D140E0E0D140E0E0D140E0E0D140CA8FD0AFF0C0C060D2F2F %050C59FD07FF7E0D052F2F590C0C065AFD05FF350506050C060D0C0C0506 %7EFF2F0C050C0C5AFFFF0C06050C84FFFFA90C06050C0635FD1FFFA98584 %A9848584A9848584A9848584A9848584355AFD0AFF84A8FF7E5A2F5AA8FD %0AFFA80C0605062EFD07FF7E845A8459845A8459845AAFFD0AFF5A84FD06 %FFA88484FD34FF3584FD1EFF0C06050659FD5BFF842FFD1FFF0C0605067E %FD5AFFA935FD20FF2F06050C59FD5AFF06FD21FF59060506062F2F5AFD7A %FF8435592F5984FDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFC %FFFDD1FFFF %%EndData
+%%AI8_CreatorVersion: 13.0.2 %AI9_PrintingDataBegin %AI3_Cropmarks: 36.0000 36.0000 336.0000 175.3042
+%ADO_BuildNumber: Adobe Illustrator(R) 13.0.2 x434 R agm 4.4379 ct 5.1039 %ADO_ContainsXMP: MainFirst %AI7_Thumbnail: 128 76 8 %%BeginData: 6312 Hex Bytes %0000330000660000990000CC0033000033330033660033990033CC0033FF %0066000066330066660066990066CC0066FF009900009933009966009999 %0099CC0099FF00CC0000CC3300CC6600CC9900CCCC00CCFF00FF3300FF66 %00FF9900FFCC3300003300333300663300993300CC3300FF333300333333 %3333663333993333CC3333FF3366003366333366663366993366CC3366FF %3399003399333399663399993399CC3399FF33CC0033CC3333CC6633CC99 %33CCCC33CCFF33FF0033FF3333FF6633FF9933FFCC33FFFF660000660033 %6600666600996600CC6600FF6633006633336633666633996633CC6633FF %6666006666336666666666996666CC6666FF669900669933669966669999 %6699CC6699FF66CC0066CC3366CC6666CC9966CCCC66CCFF66FF0066FF33 %66FF6666FF9966FFCC66FFFF9900009900339900669900999900CC9900FF %9933009933339933669933999933CC9933FF996600996633996666996699 %9966CC9966FF9999009999339999669999999999CC9999FF99CC0099CC33 %99CC6699CC9999CCCC99CCFF99FF0099FF3399FF6699FF9999FFCC99FFFF %CC0000CC0033CC0066CC0099CC00CCCC00FFCC3300CC3333CC3366CC3399 %CC33CCCC33FFCC6600CC6633CC6666CC6699CC66CCCC66FFCC9900CC9933 %CC9966CC9999CC99CCCC99FFCCCC00CCCC33CCCC66CCCC99CCCCCCCCCCFF %CCFF00CCFF33CCFF66CCFF99CCFFCCCCFFFFFF0033FF0066FF0099FF00CC %FF3300FF3333FF3366FF3399FF33CCFF33FFFF6600FF6633FF6666FF6699 %FF66CCFF66FFFF9900FF9933FF9966FF9999FF99CCFF99FFFFCC00FFCC33 %FFCC66FFCC99FFCCCCFFCCFFFFFF33FFFF66FFFF99FFFFCC110000001100 %000011111111220000002200000022222222440000004400000044444444 %550000005500000055555555770000007700000077777777880000008800 %000088888888AA000000AA000000AAAAAAAABB000000BB000000BBBBBBBB %DD000000DD000000DDDDDDDDEE000000EE000000EEEEEEEE0000000000FF %00FF0000FFFFFF0000FF00FFFFFF00FFFFFF %524C45FDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFD4AFFA90C0D %0C35A8FD79FF3505060506050CA8FD5AFF84360E0E0D140E0E0D140E0E0D %140E0E0D140E0E0D140E0E0D140E0E0D0D0506050C05060535FD59FF7E0E %3685608560856085608560856085608560856085608560856085600D0506 %05060506050605FD59FF365A856085618560856185608561856085618560 %856185608561856035050605060506050605067EFD58FF0D615A615A615A %615A615A615A615A615A615A615A615A615A615A5A050605060506050605 %060584FD58FF146185608561856085618560856185608561856085618560 %856161060C0506050C0606050C05067EFD58FF0D615A615A615A615A615A %615A615A615A615A615A615A615A610D0605060506060C050605060584FD %58FF0E5A855A615A855A615A855A615A855A615A855A615A855A61360605 %060506062F050605060506A8FD58FF0D5A5A615A5A5A615A5A5A615A5A5A %615A5A5A615A5A5A615A0C05060506055905060506050605FD59FF0E5A61 %5A615A615A615A615A615A615A615A615A615A615A5A050C0506052F0C06 %050C05060535FD59FF0D5A365B5A5A365B5A5A365B5A5A365B5A5A365B5A %5A365B0C0605060506590605060506050659FD59FF145A5B5A615A5B5A61 %5A5B5A615A5B5A615A5B5A615A5B360605060506350C05060506050606FD %5AFF0D5A365A365A365A365A365A365A365A365A365A365A360D05060506 %05840506050605060535FD5AFF14365B365B365B365B365B365B365B365B %365B365B365B050C0506055A0C06050C0506050CA8FD5AFF0D5A3636365A %3636365A3636365A3636365A3636365A0D060506050C5906050605060506 %0CFD5BFF0E365A365A365A365A365A365A365A365A365A365A360D050605 %06590C05060506050605A9FD5BFF0D363036303630363036303630363036 %3036303630360506050605A90506050605060535FD5CFF0EFD14360D0C05 %06055A2F06050C0506050CAFFD5CFF0D360E3630360E3630360E3630360E %3630360E36300D0506050684060506050605062FFD5DFF1436360E363636 %0E3636360E3636360E3636360E360C0605060C5905060506050606FD5EFF %0D360E360D360E360D360E360D360E360D360E360D0C0506058406060506 %05060CA9FD5EFF140E360E360E360E360E360E360E360E360E360E0D0506 %050CA806050C062F2FA9FFFF2F0C050C06350C84FD07FF5A0C0C060D050C %2FFD06FF0D0506050C0CFD3AFF0D360E140D360E140D360E140D360E140D %360E14060605062E3505060506050CFFFF0C0659FFFFA806065AFD05FF7E %0C0535A8FFFFFF590C0559FD05FF7E05062EFD3BFF0E0E360E140E360E14 %0E360E140E360E140E360E0C0506058406060506050684FF84062FFD05FF %0584FD04FF590605A9FD06FFA80C052FFD04FF84060584FD3BFF0D0E0D14 %0D0E0D140D0E0D140D0E0D140D0E0D0D050605067E06050605062FFFFF35 %055AFD05FF2F59FFFFFF7E060559FD08FF84060535FD04FF05065AFD09FF %060CFD30FF0E0E140E140E140E140E140E140E140E140E140D06050C0C5A %050C05060CFFFFFF2F0C0CFD05FFA8FD04FF0D050CFD0AFF2F0605AFFFFF %FF0C0584FD09FF0D05AFFD05FFA9FD29FF0D0E0D140D0E0D140D0E0D140D %0E0D140D0E0D0D050605590606050605AFFFFFFF5905062FFD08FF840506 %2FFD0AFFA905062EFFFFFF05065AFD0AFFA9FD05FF5A06FD29FF140E140D %140E140D140E140D140E140D140E140D0C05065906050606A9FD04FFA80C %05060CFD07FF2F060584FD0BFF0C050CFFFFFF060584FD10FF060CFD29FF %0D0E0D0E0D0E0D0E0D0E0D0E0D0E0D0E0D0E0D0E0606055A05062FFD07FF %2F0605060559FD05FF0C0506FD0CFF060605FFFFFF050659FD07FFA85A2E %0C06FFFF350506050C0684FD04FF0C06050C59FD1DFF140E140D140E140D %140E140D140E0E0D140E0E0D0E050C2F0C84FD09FF350C0506050DAFFFFF %FF0C0605FD0CFF0D0506FFFFFF060584FD07FFA92F0C050DFFFF7E5A050C %7E84AFFFFFFF060C2F0C050CA9FD1CFF0D0E0D0E0D0E0D0E0D0E0D0E0D0E %0D0E0D0E0D0E0D060C0C59FD0BFF840C0506050CA8FFFF0C0506FD0CFF06 %0605FFFFA9050659FD09FF840606FFFFFF590606FD05FF060C84FF59060C %FD1DFF0E0D140E0E0D140E0E0D140E0E0D140E0E0D140E0E06590CFD0EFF %5A0606050DFFFF0C060584FD0BFF0C050CFFFF7E060584FD0AFF050CFFFF %FF84050DFD04FF840635FFFF2F05FD1EFF0D0E0D0E0D0E0D0E0D0E0D0E0D %0E0D0E0D0E0D0E0D0C2E84FD0FFF84050605FFFF59050659FD0BFF05060C %FFFF8405065AFD09FF590606FFFFFF5A0606FD04FF59055A590C0584FD1E %FF0E0D140E0E0D140E0E0D140E0E0D140E0E0D140E0E0684FD0AFF59FD06 %FF5A050C7EFFFF0C052FFD0AFF59060584FFFF7E0C0584FD09FF84050DFF %FFFF84050DFD04FF2F0606355AFD20FF0D0E0D0E0D0E0D0E0D0E0D0E0D0E %0D0E0D0E0D0E0D0C59FD0AFF0C59FD05FFA80605A9FFFF59060584FD09FF %0C050CFFFFFF8405065AFD09FF590606FFFFFF5A062EFD04FF350559FD05 %FFA9FD1CFF140E0E0D140E0E0D140E0E0D140E0E0D140E0E0D140684FD0A %FF0C2FFD05FF84050CFD04FF2F0606FD08FF35050CAFFFFFFF7E060584FD %05FF8459FFFF84050DFFFFFF840535FFFF84847E0606FD04FF8406FD1CFF %5A0E0D0E0D0E0D0E0D0E0D0E0D0E0D0E0D0E0D0E0D0C84FD0AFF0C0559FD %04FF060659FD05FF2E0606A8FD04FFA82F050CA8FD04FF5A05062EFD05FF %0559FFFF5A0605FFFFFF590605842F0C7EFF0506065A592F055AFD1DFF5A %0E0D140E0E0D140E0E0D140E0E0D140E0E0D140CA8FD0AFF0C0C060D2F2F %050C59FD07FF7E0D052F2F590C0C065AFD05FF350506050C060D0C0C0506 %7EFF2F0C050C0C5AFFFF0C06050C84FFFFA90C06050C0635FD1FFFA98584 %A9848584A9848584A9848584A9848584355AFD0AFF84A8FF7E5A2F5AA8FD %0AFFA80C0605062EFD07FF7E845A8459845A8459845AAFFD0AFF5A84FD06 %FFA88484FD34FF3584FD1EFF0C06050659FD5BFF842FFD1FFF0C0605067E %FD5AFFA935FD20FF2F06050C59FD5AFF06FD21FF59060506062F2F5AFD7A %FF8435592F5984FDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFCFFFDFC %FFFDD1FFFF %%EndData
%ADOEndClientInjection: DocumentHeader "AI11EPS"
%%Pages: 1
%%DocumentNeededResources:
@@ -4755,7 +4755,7 @@ currentdict Adobe_AGM_Utils eq {end} if
%%EndPageComments
%%BeginPageSetup
%ADOBeginClientInjection: PageSetup Start "AI11EPS"
-%AI12_RMC_Transparency: Balance=75 RasterRes=300 GradRes=150 Text=0 Stroke=1 Clip=1 OP=0
+%AI12_RMC_Transparency: Balance=75 RasterRes=300 GradRes=150 Text=0 Stroke=1 Clip=1 OP=0
%ADOEndClientInjection: PageSetup Start "AI11EPS"
Adobe_AGM_Utils begin
Adobe_AGM_Core/ps gx
@@ -4891,7 +4891,7 @@ Adobe_CoolType_Core/ps get exec Adobe_AGM_Image/ps gx
-<?xpacket end="w"?> % &&end XMP packet marker&& [{ai_metadata_stream_123} <</Type /Metadata /Subtype /XML>> /PUT AI11_PDFMark5 [/Document 1 dict begin /Metadata {ai_metadata_stream_123} def currentdict end /BDC AI11_PDFMark5
+<?xpacket end="w"?> % &&end XMP packet marker&& [{ai_metadata_stream_123} <</Type /Metadata /Subtype /XML>> /PUT AI11_PDFMark5 [/Document 1 dict begin /Metadata {ai_metadata_stream_123} def currentdict end /BDC AI11_PDFMark5
%ADOEndClientInjection: PageSetup End "AI11EPS"
%%EndPageSetup
1 -1 scale 0 -211.304 translate
@@ -5308,14 +5308,14 @@ true sadj
336 211.304 li
@
%ADOBeginClientInjection: EndPageContent "AI11EPS"
-userdict /annotatepage 2 copy known {get exec}{pop pop} ifelse
+userdict /annotatepage 2 copy known {get exec}{pop pop} ifelse
%ADOEndClientInjection: EndPageContent "AI11EPS"
grestore
grestore
pgrs
%%PageTrailer
%ADOBeginClientInjection: PageTrailer Start "AI11EPS"
-[/EMC AI11_PDFMark5 [/NamespacePop AI11_PDFMark5
+[/EMC AI11_PDFMark5 [/NamespacePop AI11_PDFMark5
%ADOEndClientInjection: PageTrailer Start "AI11EPS"
[
[/CSA [/0 ]]
diff --git a/chromium/third_party/sqlite/src/autoconf/tea/win/makefile.vc b/chromium/third_party/sqlite/src/autoconf/tea/win/makefile.vc
index 88b66f173cb..d92a8428bfe 100644
--- a/chromium/third_party/sqlite/src/autoconf/tea/win/makefile.vc
+++ b/chromium/third_party/sqlite/src/autoconf/tea/win/makefile.vc
@@ -153,7 +153,7 @@ Please `cd` to its location first.
#
#-------------------------------------------------------------------------
-PROJECT = tclsqlite3
+PROJECT = sqlite3
!include "rules.vc"
# nmakehelp -V <file> <tag> will search the file for tag, skips until a
diff --git a/chromium/third_party/sqlite/src/configure b/chromium/third_party/sqlite/src/configure
index 9ba67e99ef4..a03d6fdb3ae 100755
--- a/chromium/third_party/sqlite/src/configure
+++ b/chromium/third_party/sqlite/src/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for sqlite 3.33.0.
+# Generated by GNU Autoconf 2.69 for sqlite 3.34.0.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -726,8 +726,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='sqlite'
PACKAGE_TARNAME='sqlite'
-PACKAGE_VERSION='3.33.0'
-PACKAGE_STRING='sqlite 3.33.0'
+PACKAGE_VERSION='3.34.0'
+PACKAGE_STRING='sqlite 3.34.0'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -799,7 +799,6 @@ TEMP_STORE
ALLOWRELEASE
SQLITE_THREADSAFE
BUILD_CC
-VERSION_NUMBER
RELEASE
VERSION
program_prefix
@@ -1467,7 +1466,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures sqlite 3.33.0 to adapt to many kinds of systems.
+\`configure' configures sqlite 3.34.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1532,7 +1531,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of sqlite 3.33.0:";;
+ short | recursive ) echo "Configuration of sqlite 3.34.0:";;
esac
cat <<\_ACEOF
@@ -1659,7 +1658,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-sqlite configure 3.33.0
+sqlite configure 3.34.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2078,7 +2077,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by sqlite $as_me 3.33.0, which was
+It was created by sqlite $as_me 3.34.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -3936,13 +3935,13 @@ if ${lt_cv_nm_interface+:} false; then :
else
lt_cv_nm_interface="BSD nm"
echo "int some_variable = 0;" > conftest.$ac_ext
- (eval echo "\"\$as_me:3939: $ac_compile\"" >&5)
+ (eval echo "\"\$as_me:3938: $ac_compile\"" >&5)
(eval "$ac_compile" 2>conftest.err)
cat conftest.err >&5
- (eval echo "\"\$as_me:3942: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+ (eval echo "\"\$as_me:3941: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
cat conftest.err >&5
- (eval echo "\"\$as_me:3945: output\"" >&5)
+ (eval echo "\"\$as_me:3944: output\"" >&5)
cat conftest.out >&5
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
lt_cv_nm_interface="MS dumpbin"
@@ -5148,7 +5147,7 @@ ia64-*-hpux*)
;;
*-*-irix6*)
# Find out which ABI we are using.
- echo '#line 5151 "configure"' > conftest.$ac_ext
+ echo '#line 5150 "configure"' > conftest.$ac_ext
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -6673,11 +6672,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:6676: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:6675: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:6680: \$? = $ac_status" >&5
+ echo "$as_me:6679: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -7012,11 +7011,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7015: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7014: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:7019: \$? = $ac_status" >&5
+ echo "$as_me:7018: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -7117,11 +7116,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7120: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7119: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:7124: \$? = $ac_status" >&5
+ echo "$as_me:7123: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -7172,11 +7171,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7175: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7174: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:7179: \$? = $ac_status" >&5
+ echo "$as_me:7178: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -9552,7 +9551,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 9555 "configure"
+#line 9554 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -9648,7 +9647,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 9651 "configure"
+#line 9650 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -10388,12 +10387,6 @@ RELEASE=`cat $srcdir/VERSION`
{ $as_echo "$as_me:${as_lineno-$LINENO}: Release set to $RELEASE" >&5
$as_echo "$as_me: Release set to $RELEASE" >&6;}
-VERSION_NUMBER=`cat $srcdir/VERSION \
- | sed 's/[^0-9]/ /g' \
- | awk '{printf "%d%03d%03d",$1,$2,$3}'`
-{ $as_echo "$as_me:${as_lineno-$LINENO}: Version number set to $VERSION_NUMBER" >&5
-$as_echo "$as_me: Version number set to $VERSION_NUMBER" >&6;}
-
#########
# Locate a compiler for the build machine. This compiler should
@@ -12243,7 +12236,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by sqlite $as_me 3.33.0, which was
+This file was extended by sqlite $as_me 3.34.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -12309,7 +12302,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-sqlite config.status 3.33.0
+sqlite config.status 3.34.0
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/chromium/third_party/sqlite/src/configure.ac b/chromium/third_party/sqlite/src/configure.ac
index 6c1fdb6b277..bb8f4bd5637 100644
--- a/chromium/third_party/sqlite/src/configure.ac
+++ b/chromium/third_party/sqlite/src/configure.ac
@@ -155,11 +155,6 @@ AC_SUBST(VERSION)
RELEASE=`cat $srcdir/VERSION`
AC_MSG_NOTICE(Release set to $RELEASE)
AC_SUBST(RELEASE)
-VERSION_NUMBER=[`cat $srcdir/VERSION \
- | sed 's/[^0-9]/ /g' \
- | awk '{printf "%d%03d%03d",$1,$2,$3}'`]
-AC_MSG_NOTICE(Version number set to $VERSION_NUMBER)
-AC_SUBST(VERSION_NUMBER)
#########
# Locate a compiler for the build machine. This compiler should
diff --git a/chromium/third_party/sqlite/src/doc/lemon.html b/chromium/third_party/sqlite/src/doc/lemon.html
index 714cbfa5b2e..bd078c8ec71 100644
--- a/chromium/third_party/sqlite/src/doc/lemon.html
+++ b/chromium/third_party/sqlite/src/doc/lemon.html
@@ -2,7 +2,8 @@
<head>
<title>The Lemon Parser Generator</title>
</head>
-<body bgcolor='white'>
+<body>
+<a id="main"></a>
<h1 align='center'>The Lemon Parser Generator</h1>
<p>Lemon is an LALR(1) parser generator for C.
@@ -23,11 +24,41 @@ or embedded controllers.</p>
<p>This document is an introduction to the Lemon
parser generator.</p>
-<h2>Security Note</h2>
+<a id="toc"></a>
+<h2>1.0 Table of Contents</h2>
+<ul>
+<li><a href="#main">Introduction</a>
+<li><a href="#toc">1.0 Table of Contents</a>
+<li><a href="#secnot">2.0 Security Notes</a><br>
+<li><a href="#optheory">3.0 Theory of Operation</a>
+ <ul>
+ <li><a href="#options">3.1 Command Line Options</a>
+ <li><a href="#interface">3.2 The Parser Interface</a>
+ <ul>
+ <li><a href="#onstack">3.2.1 Allocating The Parse Object On Stack</a>
+ <li><a href="#ifsum">3.2.2 Interface Summary</a>
+ </ul>
+ <li><a href="#yaccdiff">3.3 Differences With YACC and BISON</a>
+ <li><a href="#build">3.4 Building The "lemon" Or "lemon.exe" Executable</a>
+ </ul>
+<li><a href="#syntax">4.0 Input File Syntax</a>
+ <ul>
+ <li><a href="#tnt">4.1 Terminals and Nonterminals</a>
+ <li><a href="#rules">4.2 Grammar Rules</a>
+ <li><a href="#precrules">4.3 Precedence Rules</a>
+ <li><a href="#special">4.4 Special Directives</a>
+ </ul>
+<li><a href="#errors">5.0 Error Processing</a>
+<li><a href="#history">6.0 History of Lemon</a>
+<li><a href="#copyright">7.0 Copyright</a>
+</ul>
+
+<a id="secnot"></a>
+<h2>2.0 Security Note</h2>
<p>The language parser code created by Lemon is very robust and
is well-suited for use in internet-facing applications that need to
-safely process maliciously crafted inputs.
+safely process maliciously crafted inputs.</p>
<p>The "lemon.exe" command-line tool itself works great when given a valid
input grammar file and almost always gives helpful
@@ -43,56 +74,60 @@ To summarize:</p>
<li>The "lemon.exe" command line tool itself &rarr; Not so much
</ul>
-<h2>Theory of Operation</h2>
+<a id="optheory"></a>
+<h2>3.0 Theory of Operation</h2>
-<p>The main goal of Lemon is to translate a context free grammar (CFG)
+<p>Lemon is computer program that translates a context free grammar (CFG)
for a particular language into C code that implements a parser for
that language.
-The program has two inputs:
+The Lemon program has two inputs:</p>
<ul>
<li>The grammar specification.
<li>A parser template file.
</ul>
-Typically, only the grammar specification is supplied by the programmer.
-Lemon comes with a default parser template which works fine for most
-applications. But the user is free to substitute a different parser
-template if desired.</p>
+<p>Typically, only the grammar specification is supplied by the programmer.
+Lemon comes with a default parser template
+("<a href="https://sqlite.org/src/file/tool/lempar.c">lempar.c</a>")
+that works fine for most applications. But the user is free to substitute
+a different parser template if desired.</p>
<p>Depending on command-line options, Lemon will generate up to
-three output files.
+three output files.</p>
<ul>
-<li>C code to implement the parser.
-<li>A header file defining an integer ID for each terminal symbol.
+<li>C code to implement a parser for the input grammar.
+<li>A header file defining an integer ID for each terminal symbol
+ (or "token").
<li>An information file that describes the states of the generated parser
automaton.
</ul>
-By default, all three of these output files are generated.
+<p>By default, all three of these output files are generated.
The header file is suppressed if the "-m" command-line option is
used and the report file is omitted when "-q" is selected.</p>
<p>The grammar specification file uses a ".y" suffix, by convention.
In the examples used in this document, we'll assume the name of the
grammar file is "gram.y". A typical use of Lemon would be the
-following command:
+following command:</p>
<pre>
lemon gram.y
</pre>
-This command will generate three output files named "gram.c",
+<p>This command will generate three output files named "gram.c",
"gram.h" and "gram.out".
The first is C code to implement the parser. The second
is the header file that defines numerical values for all
terminal symbols, and the last is the report that explains
the states used by the parser automaton.</p>
-<h3>Command Line Options</h3>
+<a id="options"></a>
+<h3>3.1 Command Line Options</h3>
<p>The behavior of Lemon can be modified using command-line options.
You can obtain a list of the available command-line options together
-with a brief explanation of what each does by typing
+with a brief explanation of what each does by typing</p>
<pre>
lemon "-?"
</pre>
-As of this writing, the following command-line options are supported:
+<p>As of this writing, the following command-line options are supported:</p>
<ul>
<li><b>-b</b>
Show only the basis for each parser state in the report file.
@@ -134,7 +169,8 @@ Use <i>file</i> as the template for the generated C-code parser implementation.
Print the Lemon version number.
</ul>
-<h3>The Parser Interface</h3>
+<a id="interface"></a>
+<h3>3.2 The Parser Interface</h3>
<p>Lemon doesn't generate a complete, working program. It only generates
a few subroutines that implement a parser. This section describes
@@ -144,11 +180,11 @@ complete system.</p>
<p>Before a program begins using a Lemon-generated parser, the program
must first create the parser.
-A new parser is created as follows:
+A new parser is created as follows:</p>
<pre>
void *pParser = ParseAlloc( malloc );
</pre>
-The ParseAlloc() routine allocates and initializes a new parser and
+<p>The ParseAlloc() routine allocates and initializes a new parser and
returns a pointer to it.
The actual data structure used to represent a parser is opaque &mdash;
its internal structure is not visible or usable by the calling routine.
@@ -158,22 +194,22 @@ The sole argument to the ParseAlloc() routine is a pointer to the
subroutine used to allocate memory. Typically this means malloc().</p>
<p>After a program is finished using a parser, it can reclaim all
-memory allocated by that parser by calling
+memory allocated by that parser by calling</p>
<pre>
ParseFree(pParser, free);
</pre>
-The first argument is the same pointer returned by ParseAlloc(). The
+<p>The first argument is the same pointer returned by ParseAlloc(). The
second argument is a pointer to the function used to release bulk
memory back to the system.</p>
<p>After a parser has been allocated using ParseAlloc(), the programmer
must supply the parser with a sequence of tokens (terminal symbols) to
be parsed. This is accomplished by calling the following function
-once for each token:
+once for each token:<p>
<pre>
Parse(pParser, hTokenID, sTokenData, pArg);
</pre>
-The first argument to the Parse() routine is the pointer returned by
+<p>The first argument to the Parse() routine is the pointer returned by
ParseAlloc().
The second argument is a small positive integer that tells the parser the
type of the next token in the data stream.
@@ -199,7 +235,7 @@ This is a convenient mechanism for passing state information down
to the action routines without having to use global variables.</p>
<p>A typical use of a Lemon parser might look something like the
-following:
+following:</p>
<pre>
1 ParseTree *ParseFile(const char *zFilename){
2 Tokenizer *pTokenizer;
@@ -220,7 +256,7 @@ following:
17 return sState.treeRoot;
18 }
</pre>
-This example shows a user-written routine that parses a file of
+<p>This example shows a user-written routine that parses a file of
text and returns a pointer to the parse tree.
(All error-handling code is omitted from this example to keep it
simple.)
@@ -232,7 +268,7 @@ integer variable hTokenId. The sToken variable is assumed to be
some kind of structure that contains details about each token,
such as its complete text, what line it occurs on, etc.</p>
-<p>This example also assumes the existence of structure of type
+<p>This example also assumes the existence of a structure of type
ParserState that holds state information about a particular parse.
An instance of such a structure is created on line 6 and initialized
on line 10. A pointer to this structure is passed into the Parse()
@@ -243,7 +279,7 @@ appropriate. In the example, we note that the treeRoot field of
the ParserState structure is left pointing to the root of the parse
tree.</p>
-<p>The core of this example as it relates to Lemon is as follows:
+<p>The core of this example as it relates to Lemon is as follows:</p>
<pre>
ParseFile(){
pParser = ParseAlloc( malloc );
@@ -254,7 +290,7 @@ tree.</p>
ParseFree(pParser, free );
}
</pre>
-Basically, what a program has to do to use a Lemon-generated parser
+<p>Basically, what a program has to do to use a Lemon-generated parser
is first create the parser, then send it lots of tokens obtained by
tokenizing an input source. When the end of input is reached, the
Parse() routine should be called one last time with a token type
@@ -265,21 +301,75 @@ parser by calling ParseFree().</p>
<p>There is one other interface routine that should be mentioned
before we move on.
The ParseTrace() function can be used to generate debugging output
-from the parser. A prototype for this routine is as follows:
+from the parser. A prototype for this routine is as follows:</p>
<pre>
ParseTrace(FILE *stream, char *zPrefix);
</pre>
-After this routine is called, a short (one-line) message is written
+<p>After this routine is called, a short (one-line) message is written
to the designated output stream every time the parser changes states
or calls an action routine. Each such message is prefaced using
the text given by zPrefix. This debugging output can be turned off
by calling ParseTrace() again with a first argument of NULL (0).</p>
-<h3>Differences With YACC and BISON</h3>
+<a id="onstack"></a>
+<h4>3.2.1 Allocating The Parse Object On Stack</h4>
+
+<p>If all calls to the Parse() interface are made from within
+<a href="#pcode"><tt>%code</tt> directives</a>, then the parse
+object can be allocated from the stack rather than from the heap.
+These are the steps:
+
+<ul>
+<li> Declare a local variable of type "yyParser"
+<li> Initialize the variable using ParseInit()
+<li> Pass a pointer to the variable in calls ot Parse()
+<li> Deallocate substructure in the parse variable using ParseFinalize().
+</ul>
+
+<p>The following code illustrates how this is done:
+
+<pre>
+ ParseFile(){
+ yyParser x;
+ ParseInit( &x );
+ while( GetNextToken(pTokenizer,&amp;hTokenId, &amp;sToken) ){
+ Parse(&x, hTokenId, sToken);
+ }
+ Parse(&x, 0, sToken);
+ ParseFinalize( &x );
+ }
+</pre>
+
+<a id="ifsum"></a>
+<h4>3.2.2 Interface Summary</h4>
+
+<p>Here is a quick overview of the C-language interface to a
+Lemon-generated parser:</p>
+
+<blockquote><pre>
+void *ParseAlloc( (void*(*malloc)(size_t) );
+void ParseFree(void *pParser, (void(*free)(void*) );
+void Parse(void *pParser, int tokenCode, ParseTOKENTYPE token, ...);
+void ParseTrace(FILE *stream, char *zPrefix);
+</pre></blockquote>
+
+<p>Notes:</p>
+<ul>
+<li> Use the <a href="#pname"><tt>%name</tt> directive</a> to change
+the "Parse" prefix names of the procedures in the interface.
+<li> Use the <a href="#token_type"><tt>%token_type</tt> directive</a>
+to define the "ParseTOKENTYPE" type.
+<li> Use the <a href="#extraarg"><tt>%extra_argument</tt> directive</a>
+to specify the type and name of the 4th parameter to the
+Parse() function.
+</ul>
+
+<a id="yaccdiff"></a>
+<h3>3.3 Differences With YACC and BISON</h3>
<p>Programmers who have previously used the yacc or bison parser
generator will notice several important differences between yacc and/or
-bison and Lemon.
+bison and Lemon.</p>
<ul>
<li>In yacc and bison, the parser calls the tokenizer. In Lemon,
the tokenizer calls the parser.
@@ -288,7 +378,7 @@ bison and Lemon.
<li>Lemon allows multiple parsers to be running simultaneously. Yacc
and bison do not.
</ul>
-These differences may cause some initial confusion for programmers
+<p>These differences may cause some initial confusion for programmers
with prior yacc and bison experience.
But after years of experience using Lemon, I firmly
believe that the Lemon way of doing things is better.</p>
@@ -296,10 +386,39 @@ believe that the Lemon way of doing things is better.</p>
<p><i>Updated as of 2016-02-16:</i>
The text above was written in the 1990s.
We are told that Bison has lately been enhanced to support the
-tokenizer-calls-parser paradigm used by Lemon, and to obviate the
+tokenizer-calls-parser paradigm used by Lemon, eliminating the
need for global variables.</p>
-<h2>Input File Syntax</h2>
+<a id="build"><a>
+<h3>3.4 Building The "lemon" or "lemon.exe" Executable</h3>
+
+<p>The "lemon" or "lemon.exe" program is built from a single file
+of C-code named
+"<a href="https://sqlite.org/src/tool/lemon.c">lemon.c</a>".
+The Lemon source code is generic C89 code that uses
+no unusual or non-standard libraries. Any
+reasonable C compiler should suffice to compile the lemon program.
+A command-line like the following will usually work:</p>
+
+<blockquote><pre>
+cc -o lemon lemon.c
+</pre></blockquote
+
+<p>On Windows machines with Visual C++ installed, bring up a
+"VS20<i>NN</i> x64 Native Tools Command Prompt" window and enter:
+
+<blockquote><pre>
+cl lemon.c
+</pre></blockquote>
+
+<p>Compiling Lemon really is that simple.
+Additional compiler options such as
+"-O2" or "-g" or "-Wall" can be added if desired, but they are not
+necessary.</p>
+
+
+<a id="syntax"></a>
+<h2>4.0 Input File Syntax</h2>
<p>The main purpose of the grammar specification file for Lemon is
to define the grammar for the parser. But the input file also
@@ -307,13 +426,14 @@ specifies additional information Lemon requires to do its job.
Most of the work in using Lemon is in writing an appropriate
grammar file.</p>
-<p>The grammar file for Lemon is, for the most part, free format.
+<p>The grammar file for Lemon is, for the most part, a free format.
It does not have sections or divisions like yacc or bison. Any
-declaration can occur at any point in the file.
-Lemon ignores whitespace (except where it is needed to separate
-tokens), and it honors the same commenting conventions as C and C++.</p>
+declaration can occur at any point in the file. Lemon ignores
+whitespace (except where it is needed to separate tokens), and it
+honors the same commenting conventions as C and C++.</p>
-<h3>Terminals and Nonterminals</h3>
+<a id="tnt"></a>
+<h3>4.1 Terminals and Nonterminals</h3>
<p>A terminal symbol (token) is any string of alphanumeric
and/or underscore characters
@@ -338,7 +458,8 @@ this: ')' or '$'. Lemon does not allow this alternative form for
terminal symbols. With Lemon, all symbols, terminals and nonterminals,
must have alphanumeric names.</p>
-<h3>Grammar Rules</h3>
+<a id="rules"></a>
+<h3>4.2 Grammar Rules</h3>
<p>The main component of a Lemon grammar file is a sequence of grammar
rules.
@@ -351,14 +472,13 @@ Rules can occur in any order, except that the left-hand side of the
first rule is assumed to be the start symbol for the grammar (unless
specified otherwise using the <tt><a href='#start_symbol'>%start_symbol</a></tt>
directive described below.)
-A typical sequence of grammar rules might look something like this:
+A typical sequence of grammar rules might look something like this:</p>
<pre>
expr ::= expr PLUS expr.
expr ::= expr TIMES expr.
expr ::= LPAREN expr RPAREN.
expr ::= VALUE.
</pre>
-</p>
<p>There is one non-terminal in this example, "expr", and five
terminal symbols or tokens: "PLUS", "TIMES", "LPAREN",
@@ -370,11 +490,10 @@ by the parser.
In Lemon, this action is specified by putting the C code (contained
within curly braces <tt>{...}</tt>) immediately after the
period that closes the rule.
-For example:
+For example:</p>
<pre>
expr ::= expr PLUS expr. { printf("Doing an addition...\n"); }
</pre>
-</p>
<p>In order to be useful, grammar actions must normally be linked to
their associated grammar rules.
@@ -391,18 +510,18 @@ rule and say "$7" when you really mean "$8".</p>
<p>Lemon avoids the need to count grammar symbols by assigning symbolic
names to each symbol in a grammar rule and then using those symbolic
names in the action.
-In yacc or bison, one would write this:
+In yacc or bison, one would write this:</p>
<pre>
expr -&gt; expr PLUS expr { $$ = $1 + $3; };
</pre>
-But in Lemon, the same rule becomes the following:
+<p>But in Lemon, the same rule becomes the following:</p>
<pre>
expr(A) ::= expr(B) PLUS expr(C). { A = B+C; }
</pre>
-In the Lemon rule, any symbol in parentheses after a grammar rule
+<p>In the Lemon rule, any symbol in parentheses after a grammar rule
symbol becomes a place holder for that symbol in the grammar rule.
This place holder can then be used in the associated C action to
-stand for the value of that symbol.<p>
+stand for the value of that symbol.</p>
<p>The Lemon notation for linking a grammar rule with its reduce
action is superior to yacc/bison on several counts.
@@ -412,11 +531,11 @@ Secondly, if a terminal or nonterminal in a Lemon grammar rule
includes a linking symbol in parentheses but that linking symbol
is not actually used in the reduce action, then an error message
is generated.
-For example, the rule
+For example, the rule</p>
<pre>
expr(A) ::= expr(B) PLUS expr(C). { A = B; }
</pre>
-will generate an error because the linking symbol "C" is used
+<p>will generate an error because the linking symbol "C" is used
in the grammar rule but not in the reduce action.</p>
<p>The Lemon notation for linking grammar rules to reduce actions
@@ -424,8 +543,8 @@ also facilitates the use of destructors for reclaiming memory
allocated by the values of terminals and nonterminals on the
right-hand side of a rule.</p>
-<a name='precrules'></a>
-<h3>Precedence Rules</h3>
+<a id='precrules'></a>
+<h3>4.3 Precedence Rules</h3>
<p>Lemon resolves parsing ambiguities in exactly the same way as
yacc and bison. A shift-reduce conflict is resolved in favor
@@ -443,50 +562,50 @@ using the
mentioned in earlier directives have a lower precedence than
terminal symbols mentioned in later directives. For example:</p>
-<p><pre>
+<pre>
%left AND.
%left OR.
%nonassoc EQ NE GT GE LT LE.
%left PLUS MINUS.
%left TIMES DIVIDE MOD.
%right EXP NOT.
-</pre></p>
+</pre>
<p>In the preceding sequence of directives, the AND operator is
defined to have the lowest precedence. The OR operator is one
precedence level higher. And so forth. Hence, the grammar would
-attempt to group the ambiguous expression
+attempt to group the ambiguous expression</p>
<pre>
a AND b OR c
</pre>
-like this
+<p>like this</p>
<pre>
a AND (b OR c).
</pre>
-The associativity (left, right or nonassoc) is used to determine
+<p>The associativity (left, right or nonassoc) is used to determine
the grouping when the precedence is the same. AND is left-associative
-in our example, so
+in our example, so</p>
<pre>
a AND b AND c
</pre>
-is parsed like this
+<p>is parsed like this</p>
<pre>
(a AND b) AND c.
</pre>
-The EXP operator is right-associative, though, so
+<p>The EXP operator is right-associative, though, so</p>
<pre>
a EXP b EXP c
</pre>
-is parsed like this
+<p>is parsed like this</p>
<pre>
a EXP (b EXP c).
</pre>
-The nonassoc precedence is used for non-associative operators.
-So
+<p>The nonassoc precedence is used for non-associative operators.
+So</p>
<pre>
a EQ b EQ c
</pre>
-is an error.</p>
+<p>is an error.</p>
<p>The precedence of non-terminals is transferred to rules as follows:
The precedence of a grammar rule is equal to the precedence of the
@@ -497,9 +616,9 @@ you can specify an alternative precedence symbol by putting the
symbol in square braces after the period at the end of the rule and
before any C-code. For example:</p>
-<p><pre>
+<pre>
expr = MINUS expr. [NOT]
-</pre></p>
+</pre>
<p>This rule has a precedence equal to that of the NOT symbol, not the
MINUS symbol as would have been the case by default.</p>
@@ -508,7 +627,7 @@ MINUS symbol as would have been the case by default.</p>
symbols and individual
grammar rules, we can now explain precisely how parsing conflicts
are resolved in Lemon. Shift-reduce conflicts are resolved
-as follows:
+as follows:</p>
<ul>
<li> If either the token to be shifted or the rule to be reduced
lacks precedence information, then resolve in favor of the
@@ -528,7 +647,7 @@ as follows:
<li> Otherwise, resolve the conflict by doing the shift, and
report a parsing conflict.
</ul>
-Reduce-reduce conflicts are resolved this way:
+<p>Reduce-reduce conflicts are resolved this way:</p>
<ul>
<li> If either reduce rule
lacks precedence information, then resolve in favor of the
@@ -541,7 +660,8 @@ Reduce-reduce conflicts are resolved this way:
appears first in the grammar, and report a parsing conflict.
</ul>
-<h3>Special Directives</h3>
+<a id="special"></a>
+<h3>4.4 Special Directives</h3>
<p>The input grammar to Lemon consists of grammar rules and special
directives. We've described all the grammar rules, so now we'll
@@ -553,7 +673,7 @@ grammar rules. It doesn't matter. The relative order of
directives used to assign precedence to terminals is important, but
other than that, the order of directives in Lemon is arbitrary.</p>
-<p>Lemon supports the following special directives:
+<p>Lemon supports the following special directives:</p>
<ul>
<li><tt><a href='#pcode'>%code</a></tt>
<li><tt><a href='#default_destructor'>%default_destructor</a></tt>
@@ -584,11 +704,11 @@ other than that, the order of directives in Lemon is arbitrary.</p>
<li><tt><a href='#ptype'>%type</a></tt>
<li><tt><a href='#pwildcard'>%wildcard</a></tt>
</ul>
-Each of these directives will be described separately in the
+<p>Each of these directives will be described separately in the
following sections:</p>
-<a name='pcode'></a>
-<h4>The <tt>%code</tt> directive</h4>
+<a id='pcode'></a>
+<h4>4.4.1 The <tt>%code</tt> directive</h4>
<p>The <tt>%code</tt> directive is used to specify additional C code that
is added to the end of the main output file. This is similar to
@@ -599,13 +719,16 @@ the <tt><a href='#pinclude'>%include</a></tt> directive except that
a tokenizer or even the "main()" function
as part of the output file.</p>
-<a name='default_destructor'></a>
-<h4>The <tt>%default_destructor</tt> directive</h4>
+<p>There can be multiple <tt>%code</tt> directives. The arguments of
+all <tt>%code</tt> directives are concatenated.</p>
+
+<a id='default_destructor'></a>
+<h4>4.4.2 The <tt>%default_destructor</tt> directive</h4>
<p>The <tt>%default_destructor</tt> directive specifies a destructor to
use for non-terminals that do not have their own destructor
specified by a separate <tt>%destructor</tt> directive. See the documentation
-on the <tt><a name='#destructor'>%destructor</a></tt> directive below for
+on the <tt><a href='#destructor'>%destructor</a></tt> directive below for
additional information.</p>
<p>In some grammars, many different non-terminal symbols have the
@@ -613,15 +736,15 @@ same data type and hence the same destructor. This directive is
a convenient way to specify the same destructor for all those
non-terminals using a single statement.</p>
-<a name='default_type'></a>
-<h4>The <tt>%default_type</tt> directive</h4>
+<a id='default_type'></a>
+<h4>4.4.3 The <tt>%default_type</tt> directive</h4>
<p>The <tt>%default_type</tt> directive specifies the data type of non-terminal
symbols that do not have their own data type defined using a separate
<tt><a href='#ptype'>%type</a></tt> directive.</p>
-<a name='destructor'></a>
-<h4>The <tt>%destructor</tt> directive</h4>
+<a id='destructor'></a>
+<h4>4.4.4 The <tt>%destructor</tt> directive</h4>
<p>The <tt>%destructor</tt> directive is used to specify a destructor for
a non-terminal symbol.
@@ -630,24 +753,24 @@ directive which is used to specify a destructor for terminal symbols.)</p>
<p>A non-terminal's destructor is called to dispose of the
non-terminal's value whenever the non-terminal is popped from
-the stack. This includes all of the following circumstances:
+the stack. This includes all of the following circumstances:</p>
<ul>
<li> When a rule reduces and the value of a non-terminal on
the right-hand side is not linked to C code.
<li> When the stack is popped during error processing.
<li> When the ParseFree() function runs.
</ul>
-The destructor can do whatever it wants with the value of
+<p>The destructor can do whatever it wants with the value of
the non-terminal, but its design is to deallocate memory
or other resources held by that non-terminal.</p>
-<p>Consider an example:
+<p>Consider an example:</p>
<pre>
%type nt {void*}
%destructor nt { free($$); }
nt(A) ::= ID NUM. { A = malloc( 100 ); }
</pre>
-This example is a bit contrived, but it serves to illustrate how
+<p>This example is a bit contrived, but it serves to illustrate how
destructors work. The example shows a non-terminal named
"nt" that holds values of type "void*". When the rule for
an "nt" reduces, it sets the value of the non-terminal to
@@ -670,18 +793,18 @@ the destructor is not called in this circumstance.</p>
allocated objects when they go out of scope.
To do the same using yacc or bison is much more difficult.</p>
-<a name='extraarg'></a>
-<h4>The <tt>%extra_argument</tt> directive</h4>
+<a id='extraarg'></a>
+<h4>4.4.5 The <tt>%extra_argument</tt> directive</h4>
-The <tt>%extra_argument</tt> directive instructs Lemon to add a 4th parameter
+<p>The <tt>%extra_argument</tt> directive instructs Lemon to add a 4th parameter
to the parameter list of the Parse() function it generates. Lemon
doesn't do anything itself with this extra argument, but it does
make the argument available to C-code action routines, destructors,
and so forth. For example, if the grammar file contains:</p>
-<p><pre>
+<pre>
%extra_argument { MyStruct *pAbc }
-</pre></p>
+</pre>
<p>Then the Parse() function generated will have an 4th parameter
of type "MyStruct*" and all action routines will have access to
@@ -690,30 +813,30 @@ in the most recent call to Parse().</p>
<p>The <tt>%extra_context</tt> directive works the same except that it
is passed in on the ParseAlloc() or ParseInit() routines instead of
-on Parse().
+on Parse().</p>
-<a name='extractx'></a>
-<h4>The <tt>%extra_context</tt> directive</h4>
+<a id='extractx'></a>
+<h4>4.4.6 The <tt>%extra_context</tt> directive</h4>
-The <tt>%extra_context</tt> directive instructs Lemon to add a 2nd parameter
-to the parameter list of the ParseAlloc() and ParseInif() functions. Lemon
+<p>The <tt>%extra_context</tt> directive instructs Lemon to add a 2nd parameter
+to the parameter list of the ParseAlloc() and ParseInit() functions. Lemon
doesn't do anything itself with these extra argument, but it does
store the value make it available to C-code action routines, destructors,
and so forth. For example, if the grammar file contains:</p>
-<p><pre>
+<pre>
%extra_context { MyStruct *pAbc }
-</pre></p>
+</pre>
<p>Then the ParseAlloc() and ParseInit() functions will have an 2nd parameter
of type "MyStruct*" and all action routines will have access to
a variable named "pAbc" that is the value of that 2nd parameter.</p>
<p>The <tt>%extra_argument</tt> directive works the same except that it
-is passed in on the Parse() routine instead of on ParseAlloc()/ParseInit().
+is passed in on the Parse() routine instead of on ParseAlloc()/ParseInit().</p>
-<a name='pfallback'></a>
-<h4>The <tt>%fallback</tt> directive</h4>
+<a id='pfallback'></a>
+<h4>4.4.7 The <tt>%fallback</tt> directive</h4>
<p>The <tt>%fallback</tt> directive specifies an alternative meaning for one
or more tokens. The alternative meaning is tried if the original token
@@ -729,7 +852,7 @@ obscure language keyword for an identifier. The <tt>%fallback</tt> directive
provides a mechanism to tell the parser: "If you are unable to parse
this keyword, try treating it as an identifier instead."</p>
-<p>The syntax of <tt>%fallback</tt> is as follows:
+<p>The syntax of <tt>%fallback</tt> is as follows:</p>
<blockquote>
<tt>%fallback</tt> <i>ID</i> <i>TOKEN...</i> <b>.</b>
@@ -742,8 +865,8 @@ token to which all the other tokens fall back to. The second and subsequent
arguments are tokens which fall back to the token identified by the first
argument.</p>
-<a name='pifdef'></a>
-<h4>The <tt>%if</tt> directive and its friends</h4>
+<a id='pifdef'></a>
+<h4>4.4.8 The <tt>%if</tt> directive and its friends</h4>
<p>The <tt>%if</tt>, <tt>%ifdef</tt>, <tt>%ifndef</tt>, <tt>%else</tt>,
and <tt>%endif</tt> directives
@@ -773,8 +896,8 @@ its corresponding <tt>%endif</tt>.</p>
intended to be a single preprocessor symbol name, not a general expression.
Use the "<tt>%if</tt>" directive for general expressions.</p>
-<a name='pinclude'></a>
-<h4>The <tt>%include</tt> directive</h4>
+<a id='pinclude'></a>
+<h4>4.4.9 The <tt>%include</tt> directive</h4>
<p>The <tt>%include</tt> directive specifies C code that is included at the
top of the generated parser. You can include any text you want &mdash;
@@ -787,9 +910,9 @@ generated parser, in the same order as it appeared in the grammar.</p>
preprocessor statements at the beginning of the generated parser.
For example:</p>
-<p><pre>
+<pre>
%include {#include &lt;unistd.h&gt;}
-</pre></p>
+</pre>
<p>This might be needed, for example, if some of the C actions in the
grammar call functions that are prototyped in unistd.h.</p>
@@ -797,8 +920,8 @@ grammar call functions that are prototyped in unistd.h.</p>
<p>Use the <tt><a href="#pcode">%code</a></tt> directive to add code to
the end of the generated parser.</p>
-<a name='pleft'></a>
-<h4>The <tt>%left</tt> directive</h4>
+<a id='pleft'></a>
+<h4>4.4.10 The <tt>%left</tt> directive</h4>
The <tt>%left</tt> directive is used (along with the
<tt><a href='#pright'>%right</a></tt> and
@@ -809,14 +932,14 @@ a <tt>%left</tt> directive but before the next period (".") is
given the same left-associative precedence value. Subsequent
<tt>%left</tt> directives have higher precedence. For example:</p>
-<p><pre>
+<pre>
%left AND.
%left OR.
%nonassoc EQ NE GT GE LT LE.
%left PLUS MINUS.
%left TIMES DIVIDE MOD.
%right EXP NOT.
-</pre></p>
+</pre>
<p>Note the period that terminates each <tt>%left</tt>,
<tt>%right</tt> or <tt>%nonassoc</tt>
@@ -827,30 +950,30 @@ a large amount of stack space if you make heavy use or right-associative
operators. For this reason, it is recommended that you use <tt>%left</tt>
rather than <tt>%right</tt> whenever possible.</p>
-<a name='pname'></a>
-<h4>The <tt>%name</tt> directive</h4>
+<a id='pname'></a>
+<h4>4.4.11 The <tt>%name</tt> directive</h4>
<p>By default, the functions generated by Lemon all begin with the
five-character string "Parse". You can change this string to something
different using the <tt>%name</tt> directive. For instance:</p>
-<p><pre>
+<pre>
%name Abcde
-</pre></p>
+</pre>
<p>Putting this directive in the grammar file will cause Lemon to generate
-functions named
+functions named</p>
<ul>
<li> AbcdeAlloc(),
<li> AbcdeFree(),
<li> AbcdeTrace(), and
<li> Abcde().
</ul>
-The <tt>%name</tt> directive allows you to generate two or more different
+</p>The <tt>%name</tt> directive allows you to generate two or more different
parsers and link them all into the same executable.</p>
-<a name='pnonassoc'></a>
-<h4>The <tt>%nonassoc</tt> directive</h4>
+<a id='pnonassoc'></a>
+<h4>4.4.12 The <tt>%nonassoc</tt> directive</h4>
<p>This directive is used to assign non-associative precedence to
one or more terminal symbols. See the section on
@@ -858,8 +981,8 @@ one or more terminal symbols. See the section on
or on the <tt><a href='#pleft'>%left</a></tt> directive
for additional information.</p>
-<a name='parse_accept'></a>
-<h4>The <tt>%parse_accept</tt> directive</h4>
+<a id='parse_accept'></a>
+<h4>4.4.13 The <tt>%parse_accept</tt> directive</h4>
<p>The <tt>%parse_accept</tt> directive specifies a block of C code that is
executed whenever the parser accepts its input string. To "accept"
@@ -868,14 +991,14 @@ without error.</p>
<p>For example:</p>
-<p><pre>
+<pre>
%parse_accept {
printf("parsing complete!\n");
}
-</pre></p>
+</pre>
-<a name='parse_failure'></a>
-<h4>The <tt>%parse_failure</tt> directive</h4>
+<a id='parse_failure'></a>
+<h4>4.4.14 The <tt>%parse_failure</tt> directive</h4>
<p>The <tt>%parse_failure</tt> directive specifies a block of C code that
is executed whenever the parser fails complete. This code is not
@@ -883,51 +1006,51 @@ executed until the parser has tried and failed to resolve an input
error using is usual error recovery strategy. The routine is
only invoked when parsing is unable to continue.</p>
-<p><pre>
+<pre>
%parse_failure {
fprintf(stderr,"Giving up. Parser is hopelessly lost...\n");
}
-</pre></p>
+</pre>
-<a name='pright'></a>
-<h4>The <tt>%right</tt> directive</h4>
+<a id='pright'></a>
+<h4>4.4.15 The <tt>%right</tt> directive</h4>
<p>This directive is used to assign right-associative precedence to
one or more terminal symbols. See the section on
<a href='#precrules'>precedence rules</a>
or on the <a href='#pleft'>%left</a> directive for additional information.</p>
-<a name='stack_overflow'></a>
-<h4>The <tt>%stack_overflow</tt> directive</h4>
+<a id='stack_overflow'></a>
+<h4>4.4.16 The <tt>%stack_overflow</tt> directive</h4>
<p>The <tt>%stack_overflow</tt> directive specifies a block of C code that
is executed if the parser's internal stack ever overflows. Typically
this just prints an error message. After a stack overflow, the parser
will be unable to continue and must be reset.</p>
-<p><pre>
+<pre>
%stack_overflow {
fprintf(stderr,"Giving up. Parser stack overflow\n");
}
-</pre></p>
+</pre>
<p>You can help prevent parser stack overflows by avoiding the use
of right recursion and right-precedence operators in your grammar.
Use left recursion and and left-precedence operators instead to
encourage rules to reduce sooner and keep the stack size down.
-For example, do rules like this:
+For example, do rules like this:</p>
<pre>
list ::= list element. // left-recursion. Good!
list ::= .
</pre>
-Not like this:
+<p>Not like this:</p>
<pre>
list ::= element list. // right-recursion. Bad!
list ::= .
-</pre></p>
+</pre>
-<a name='stack_size'></a>
-<h4>The <tt>%stack_size</tt> directive</h4>
+<a id='stack_size'></a>
+<h4>4.4.17 The <tt>%stack_size</tt> directive</h4>
<p>If stack overflow is a problem and you can't resolve the trouble
by using left-recursion, then you might want to increase the size
@@ -935,35 +1058,35 @@ of the parser's stack using this directive. Put an positive integer
after the <tt>%stack_size</tt> directive and Lemon will generate a parse
with a stack of the requested size. The default value is 100.</p>
-<p><pre>
+<pre>
%stack_size 2000
-</pre></p>
+</pre>
-<a name='start_symbol'></a>
-<h4>The <tt>%start_symbol</tt> directive</h4>
+<a id='start_symbol'></a>
+<h4>4.4.18 The <tt>%start_symbol</tt> directive</h4>
<p>By default, the start symbol for the grammar that Lemon generates
is the first non-terminal that appears in the grammar file. But you
can choose a different start symbol using the
<tt>%start_symbol</tt> directive.</p>
-<p><pre>
+<pre>
%start_symbol prog
-</pre></p>
+</pre>
-<a name='syntax_error'></a>
-<h4>The <tt>%syntax_error</tt> directive</h4>
+<a id='syntax_error'></a>
+<h4>4.4.19 The <tt>%syntax_error</tt> directive</h4>
<p>See <a href='#error_processing'>Error Processing</a>.</p>
-<a name='token_class'></a>
-<h4>The <tt>%token_class</tt> directive</h4>
+<a id='token_class'></a>
+<h4>4.4.20 The <tt>%token_class</tt> directive</h4>
<p>Undocumented. Appears to be related to the MULTITERMINAL concept.
<a href='http://sqlite.org/src/fdiff?v1=796930d5fc2036c7&v2=624b24c5dc048e09&sbs=0'>Implementation</a>.</p>
-<a name='token_destructor'></a>
-<h4>The <tt>%token_destructor</tt> directive</h4>
+<a id='token_destructor'></a>
+<h4>4.4.21 The <tt>%token_destructor</tt> directive</h4>
<p>The <tt>%destructor</tt> directive assigns a destructor to a non-terminal
symbol. (See the description of the
@@ -971,42 +1094,42 @@ symbol. (See the description of the
The <tt>%token_destructor</tt> directive does the same thing
for all terminal symbols.</p>
-<p>Unlike non-terminal symbols which may each have a different data type
+<p>Unlike non-terminal symbols, which may each have a different data type
for their values, terminals all use the same data type (defined by
the <tt><a href='#token_type'>%token_type</a></tt> directive)
and so they use a common destructor.
Other than that, the token destructor works just like the non-terminal
destructors.</p>
-<a name='token_prefix'></a>
-<h4>The <tt>%token_prefix</tt> directive</h4>
+<a id='token_prefix'></a>
+<h4>4.4.22 The <tt>%token_prefix</tt> directive</h4>
<p>Lemon generates #defines that assign small integer constants
to each terminal symbol in the grammar. If desired, Lemon will
add a prefix specified by this directive
to each of the #defines it generates.</p>
-<p>So if the default output of Lemon looked like this:
+<p>So if the default output of Lemon looked like this:</p>
<pre>
#define AND 1
#define MINUS 2
#define OR 3
#define PLUS 4
</pre>
-You can insert a statement into the grammar like this:
+<p>You can insert a statement into the grammar like this:</p>
<pre>
%token_prefix TOKEN_
</pre>
-to cause Lemon to produce these symbols instead:
+<p>to cause Lemon to produce these symbols instead:</p>
<pre>
#define TOKEN_AND 1
#define TOKEN_MINUS 2
#define TOKEN_OR 3
#define TOKEN_PLUS 4
-</pre></p>
+</pre>
-<a name='token_type'></a><a name='ptype'></a>
-<h4>The <tt>%token_type</tt> and <tt>%type</tt> directives</h4>
+<a id='token_type'></a><a id='ptype'></a>
+<h4>4.4.23 The <tt>%token_type</tt> and <tt>%type</tt> directives</h4>
<p>These directives are used to specify the data types for values
on the parser's stack associated with terminal and non-terminal
@@ -1016,9 +1139,9 @@ to the Parse() function generated by Lemon. Typically, you will
make the value of a terminal symbol be a pointer to some kind of
token structure. Like this:</p>
-<p><pre>
+<pre>
%token_type {Token*}
-</pre></p>
+</pre>
<p>If the data type of terminals is not specified, the default value
is "void*".</p>
@@ -1028,9 +1151,9 @@ the data type of a non-terminal is a pointer to the root of a parse tree
structure that contains all information about that non-terminal.
For example:</p>
-<p><pre>
+<pre>
%type expr {Expr*}
-</pre></p>
+</pre>
<p>Each entry on the parser's stack is actually a union containing
instances of all data types for every non-terminal and terminal symbol.
@@ -1042,8 +1165,8 @@ non-terminal whose data type requires 1K of storage, then your 100
entry parser stack will require 100K of heap space. If you are willing
and able to pay that price, fine. You just need to know.</p>
-<a name='pwildcard'></a>
-<h4>The <tt>%wildcard</tt> directive</h4>
+<a id='pwildcard'></a>
+<h4>4.4.24 The <tt>%wildcard</tt> directive</h4>
<p>The <tt>%wildcard</tt> directive is followed by a single token name and a
period. This directive specifies that the identified token should
@@ -1053,8 +1176,8 @@ match any input token.</p>
the wildcard token and some other token, the other token is always used.
The wildcard token is only matched if there are no alternatives.</p>
-<a name='error_processing'></a>
-<h3>Error Processing</h3>
+<a id='error_processing'></a>
+<h2>5.0 Error Processing</h2>
<p>After extensive experimentation over several years, it has been
discovered that the error recovery strategy used by yacc is about
@@ -1077,5 +1200,41 @@ to begin parsing a new file. This is what will happen at the very
first syntax error, of course, if there are no instances of the
"error" non-terminal in your grammar.</p>
+<a id='history'></a>
+<h2>6.0 History of Lemon</h2>
+
+<p>Lemon was originally written by Richard Hipp sometime in the late
+1980s on a Sun4 Workstation using K&amp;R C.
+There was a companion LL(1) parser generator program named "Lime", the
+source code to which as been lost.</p>
+
+<p>The lemon.c source file was originally many separate files that were
+compiled together to generate the "lemon" executable. Sometime in the
+1990s, the individual source code files were combined together into
+the current single large "lemon.c" source file. You can still see traces
+of original filenames in the code.</p>
+
+<p>Since 2001, Lemon has been part of the
+<a href="https://sqlite.org/">SQLite project</a> and the source code
+to Lemon has been managed as a part of the
+<a href="https://sqlite.org/src">SQLite source tree</a> in the following
+files:</p>
+
+<ul>
+<li> <a href="https://sqlite.org/src/file/tool/lemon.c">tool/lemon.c</a>
+<li> <a href="https://sqlite.org/src/file/tool/lempar.c">tool/lempar.c</a>
+<li> <a href="https://sqlite.org/src/file/doc/lemon.html">doc/lemon.html</a>
+</ul>
+
+<a id="copyright"></a>
+<h2>7.0 Copyright</h2>
+
+<p>All of the source code to Lemon, including the template parser file
+"lempar.c" and this documentation file ("lemon.html") are in the public
+domain. You can use the code for any purpose and without attribution.</p>
+
+<p>The code comes with no warranty. If it breaks, you get to keep both
+pieces.</p>
+
</body>
</html>
diff --git a/chromium/third_party/sqlite/src/ext/expert/expert1.test b/chromium/third_party/sqlite/src/ext/expert/expert1.test
index 3e5d604d52a..f49f1f5e5c0 100644
--- a/chromium/third_party/sqlite/src/ext/expert/expert1.test
+++ b/chromium/third_party/sqlite/src/ext/expert/expert1.test
@@ -326,6 +326,47 @@ do_setup_rec_test $tn.16 {
SCAN TABLE t1
}
+do_setup_rec_test $tn.17.1 {
+ CREATE TABLE example (A INTEGER, B INTEGER, C INTEGER, PRIMARY KEY (A,B));
+} {
+ SELECT * FROM example WHERE a=?
+} {
+ (no new indexes)
+ SEARCH TABLE example USING INDEX sqlite_autoindex_example_1 (A=?)
+}
+do_setup_rec_test $tn.17.2 {
+ CREATE TABLE example (A INTEGER, B INTEGER, C INTEGER, PRIMARY KEY (A,B));
+} {
+ SELECT * FROM example WHERE b=?
+} {
+ CREATE INDEX example_idx_00000042 ON example(B);
+ SEARCH TABLE example USING INDEX example_idx_00000042 (B=?)
+}
+do_setup_rec_test $tn.17.3 {
+ CREATE TABLE example (A INTEGER, B INTEGER, C INTEGER, PRIMARY KEY (A,B));
+} {
+ SELECT * FROM example WHERE a=? AND b=?
+} {
+ (no new indexes)
+ SEARCH TABLE example USING INDEX sqlite_autoindex_example_1 (A=? AND B=?)
+}
+do_setup_rec_test $tn.17.4 {
+ CREATE TABLE example (A INTEGER, B INTEGER, C INTEGER, PRIMARY KEY (A,B));
+} {
+ SELECT * FROM example WHERE a=? AND b>?
+} {
+ (no new indexes)
+ SEARCH TABLE example USING INDEX sqlite_autoindex_example_1 (A=? AND B>?)
+}
+do_setup_rec_test $tn.17.5 {
+ CREATE TABLE example (A INTEGER, B INTEGER, C INTEGER, PRIMARY KEY (A,B));
+} {
+ SELECT * FROM example WHERE a>? AND b=?
+} {
+ CREATE INDEX example_idx_0000cb3f ON example(B, A);
+ SEARCH TABLE example USING INDEX example_idx_0000cb3f (B=? AND A>?)
+}
+
}
proc do_candidates_test {tn sql res} {
diff --git a/chromium/third_party/sqlite/src/ext/expert/sqlite3expert.c b/chromium/third_party/sqlite/src/ext/expert/sqlite3expert.c
index 1dd07008936..c2a6fe3ba9f 100644
--- a/chromium/third_party/sqlite/src/ext/expert/sqlite3expert.c
+++ b/chromium/third_party/sqlite/src/ext/expert/sqlite3expert.c
@@ -685,6 +685,7 @@ static int idxGetTableInfo(
IdxTable *pNew = 0;
int rc, rc2;
char *pCsr = 0;
+ int nPk = 0;
rc = idxPrintfPrepareStmt(db, &p1, pzErrmsg, "PRAGMA table_info=%Q", zTab);
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
@@ -695,6 +696,7 @@ static int idxGetTableInfo(
);
nByte += 1 + STRLEN(zCol);
nCol++;
+ nPk += (sqlite3_column_int(p1, 5)>0);
}
rc2 = sqlite3_reset(p1);
if( rc==SQLITE_OK ) rc = rc2;
@@ -714,7 +716,7 @@ static int idxGetTableInfo(
const char *zCol = (const char*)sqlite3_column_text(p1, 1);
int nCopy = STRLEN(zCol) + 1;
pNew->aCol[nCol].zName = pCsr;
- pNew->aCol[nCol].iPk = sqlite3_column_int(p1, 5);
+ pNew->aCol[nCol].iPk = (sqlite3_column_int(p1, 5)==1 && nPk==1);
memcpy(pCsr, zCol, nCopy);
pCsr += nCopy;
diff --git a/chromium/third_party/sqlite/src/ext/fts3/unicode/mkunicode.tcl b/chromium/third_party/sqlite/src/ext/fts3/unicode/mkunicode.tcl
index a4cc5402827..58d90c68c72 100644
--- a/chromium/third_party/sqlite/src/ext/fts3/unicode/mkunicode.tcl
+++ b/chromium/third_party/sqlite/src/ext/fts3/unicode/mkunicode.tcl
@@ -742,6 +742,7 @@ proc print_categories {lMap} {
}
iTbl++;
}
+ aAscii[0] = 0; /* 0x00 is never a token character */
}
}]
}
diff --git a/chromium/third_party/sqlite/src/ext/fts5/fts5Int.h b/chromium/third_party/sqlite/src/ext/fts5/fts5Int.h
index e0287d1616b..c639f9b57ea 100644
--- a/chromium/third_party/sqlite/src/ext/fts5/fts5Int.h
+++ b/chromium/third_party/sqlite/src/ext/fts5/fts5Int.h
@@ -184,6 +184,7 @@ struct Fts5Config {
Fts5Tokenizer *pTok;
fts5_tokenizer *pTokApi;
int bLock; /* True when table is preparing statement */
+ int ePattern; /* FTS_PATTERN_XXX constant */
/* Values loaded from the %_config table */
int iCookie; /* Incremented when %_config is modified */
@@ -204,17 +205,19 @@ struct Fts5Config {
};
/* Current expected value of %_config table 'version' field */
-#define FTS5_CURRENT_VERSION 4
+#define FTS5_CURRENT_VERSION 4
#define FTS5_CONTENT_NORMAL 0
#define FTS5_CONTENT_NONE 1
#define FTS5_CONTENT_EXTERNAL 2
-#define FTS5_DETAIL_FULL 0
-#define FTS5_DETAIL_NONE 1
-#define FTS5_DETAIL_COLUMNS 2
-
+#define FTS5_DETAIL_FULL 0
+#define FTS5_DETAIL_NONE 1
+#define FTS5_DETAIL_COLUMNS 2
+#define FTS5_PATTERN_NONE 0
+#define FTS5_PATTERN_LIKE 65 /* matches SQLITE_INDEX_CONSTRAINT_LIKE */
+#define FTS5_PATTERN_GLOB 66 /* matches SQLITE_INDEX_CONSTRAINT_GLOB */
int sqlite3Fts5ConfigParse(
Fts5Global*, sqlite3*, int, const char **, Fts5Config**, char**
@@ -484,7 +487,7 @@ int sqlite3Fts5IndexSetAverages(Fts5Index *p, const u8*, int);
/*
** Functions called by the storage module as part of integrity-check.
*/
-int sqlite3Fts5IndexIntegrityCheck(Fts5Index*, u64 cksum);
+int sqlite3Fts5IndexIntegrityCheck(Fts5Index*, u64 cksum, int bUseCksum);
/*
** Called during virtual module initialization to register UDF
@@ -554,8 +557,7 @@ int sqlite3Fts5GetTokenizer(
Fts5Global*,
const char **azArg,
int nArg,
- Fts5Tokenizer**,
- fts5_tokenizer**,
+ Fts5Config*,
char **pzErr
);
@@ -639,7 +641,7 @@ int sqlite3Fts5StorageDelete(Fts5Storage *p, i64, sqlite3_value**);
int sqlite3Fts5StorageContentInsert(Fts5Storage *p, sqlite3_value**, i64*);
int sqlite3Fts5StorageIndexInsert(Fts5Storage *p, sqlite3_value**, i64);
-int sqlite3Fts5StorageIntegrity(Fts5Storage *p);
+int sqlite3Fts5StorageIntegrity(Fts5Storage *p, int iArg);
int sqlite3Fts5StorageStmt(Fts5Storage *p, int eStmt, sqlite3_stmt**, char**);
void sqlite3Fts5StorageStmtRelease(Fts5Storage *p, int eStmt, sqlite3_stmt*);
@@ -684,11 +686,19 @@ struct Fts5Token {
/* Parse a MATCH expression. */
int sqlite3Fts5ExprNew(
Fts5Config *pConfig,
+ int bPhraseToAnd,
int iCol, /* Column on LHS of MATCH operator */
const char *zExpr,
Fts5Expr **ppNew,
char **pzErr
);
+int sqlite3Fts5ExprPattern(
+ Fts5Config *pConfig,
+ int bGlob,
+ int iCol,
+ const char *zText,
+ Fts5Expr **pp
+);
/*
** for(rc = sqlite3Fts5ExprFirst(pExpr, pIdx, bDesc);
@@ -797,6 +807,10 @@ int sqlite3Fts5AuxInit(fts5_api*);
*/
int sqlite3Fts5TokenizerInit(fts5_api*);
+int sqlite3Fts5TokenizerPattern(
+ int (*xCreate)(void*, const char**, int, Fts5Tokenizer**),
+ Fts5Tokenizer *pTok
+);
/*
** End of interface to code in fts5_tokenizer.c.
**************************************************************************/
diff --git a/chromium/third_party/sqlite/src/ext/fts5/fts5_aux.c b/chromium/third_party/sqlite/src/ext/fts5/fts5_aux.c
index 119091574fe..77f6d5babab 100644
--- a/chromium/third_party/sqlite/src/ext/fts5/fts5_aux.c
+++ b/chromium/third_party/sqlite/src/ext/fts5/fts5_aux.c
@@ -566,7 +566,7 @@ static int fts5Bm25GetData(
int rc = SQLITE_OK; /* Return code */
Fts5Bm25Data *p; /* Object to return */
- p = pApi->xGetAuxdata(pFts, 0);
+ p = (Fts5Bm25Data*)pApi->xGetAuxdata(pFts, 0);
if( p==0 ){
int nPhrase; /* Number of phrases in query */
sqlite3_int64 nRow = 0; /* Number of rows in table */
@@ -640,7 +640,7 @@ static void fts5Bm25Function(
){
const double k1 = 1.2; /* Constant "k1" from BM25 formula */
const double b = 0.75; /* Constant "b" from BM25 formula */
- int rc = SQLITE_OK; /* Error code */
+ int rc; /* Error code */
double score = 0.0; /* SQL function return value */
Fts5Bm25Data *pData; /* Values allocated/calculated once only */
int i; /* Iterator variable */
@@ -672,17 +672,15 @@ static void fts5Bm25Function(
D = (double)nTok;
}
- /* Determine the BM25 score for the current row. */
- for(i=0; rc==SQLITE_OK && i<pData->nPhrase; i++){
- score += pData->aIDF[i] * (
- ( aFreq[i] * (k1 + 1.0) ) /
- ( aFreq[i] + k1 * (1 - b + b * D / pData->avgdl) )
- );
- }
-
- /* If no error has occurred, return the calculated score. Otherwise,
- ** throw an SQL exception. */
+ /* Determine and return the BM25 score for the current row. Or, if an
+ ** error has occurred, throw an exception. */
if( rc==SQLITE_OK ){
+ for(i=0; i<pData->nPhrase; i++){
+ score += pData->aIDF[i] * (
+ ( aFreq[i] * (k1 + 1.0) ) /
+ ( aFreq[i] + k1 * (1 - b + b * D / pData->avgdl) )
+ );
+ }
sqlite3_result_double(pCtx, -1.0 * score);
}else{
sqlite3_result_error_code(pCtx, rc);
diff --git a/chromium/third_party/sqlite/src/ext/fts5/fts5_config.c b/chromium/third_party/sqlite/src/ext/fts5/fts5_config.c
index ddd2317974e..6c02d2b35f7 100644
--- a/chromium/third_party/sqlite/src/ext/fts5/fts5_config.c
+++ b/chromium/third_party/sqlite/src/ext/fts5/fts5_config.c
@@ -325,7 +325,7 @@ static int fts5ConfigParseSpecial(
rc = SQLITE_ERROR;
}else{
rc = sqlite3Fts5GetTokenizer(pGlobal,
- (const char**)azArg, (int)nArg, &pConfig->pTok, &pConfig->pTokApi,
+ (const char**)azArg, (int)nArg, pConfig,
pzErr
);
}
@@ -397,9 +397,7 @@ static int fts5ConfigParseSpecial(
*/
static int fts5ConfigDefaultTokenizer(Fts5Global *pGlobal, Fts5Config *pConfig){
assert( pConfig->pTok==0 && pConfig->pTokApi==0 );
- return sqlite3Fts5GetTokenizer(
- pGlobal, 0, 0, &pConfig->pTok, &pConfig->pTokApi, 0
- );
+ return sqlite3Fts5GetTokenizer(pGlobal, 0, 0, pConfig, 0);
}
/*
diff --git a/chromium/third_party/sqlite/src/ext/fts5/fts5_expr.c b/chromium/third_party/sqlite/src/ext/fts5/fts5_expr.c
index d9de1c81780..392dde3ab49 100644
--- a/chromium/third_party/sqlite/src/ext/fts5/fts5_expr.c
+++ b/chromium/third_party/sqlite/src/ext/fts5/fts5_expr.c
@@ -128,6 +128,7 @@ struct Fts5Parse {
int nPhrase; /* Size of apPhrase array */
Fts5ExprPhrase **apPhrase; /* Array of all phrases */
Fts5ExprNode *pExpr; /* Result of a successful parse */
+ int bPhraseToAnd; /* Convert "a+b" to "a AND b" */
};
void sqlite3Fts5ParseError(Fts5Parse *pParse, const char *zFmt, ...){
@@ -216,6 +217,7 @@ static void fts5ParseFree(void *p){ sqlite3_free(p); }
int sqlite3Fts5ExprNew(
Fts5Config *pConfig, /* FTS5 Configuration */
+ int bPhraseToAnd,
int iCol,
const char *zExpr, /* Expression text */
Fts5Expr **ppNew,
@@ -231,6 +233,7 @@ int sqlite3Fts5ExprNew(
*ppNew = 0;
*pzErr = 0;
memset(&sParse, 0, sizeof(sParse));
+ sParse.bPhraseToAnd = bPhraseToAnd;
pEngine = sqlite3Fts5ParserAlloc(fts5ParseAlloc);
if( pEngine==0 ){ return SQLITE_NOMEM; }
sParse.pConfig = pConfig;
@@ -273,6 +276,7 @@ int sqlite3Fts5ExprNew(
pNew->pConfig = pConfig;
pNew->apExprPhrase = sParse.apPhrase;
pNew->nPhrase = sParse.nPhrase;
+ pNew->bDesc = 0;
sParse.apPhrase = 0;
}
}else{
@@ -285,6 +289,81 @@ int sqlite3Fts5ExprNew(
}
/*
+** This function is only called when using the special 'trigram' tokenizer.
+** Argument zText contains the text of a LIKE or GLOB pattern matched
+** against column iCol. This function creates and compiles an FTS5 MATCH
+** expression that will match a superset of the rows matched by the LIKE or
+** GLOB. If successful, SQLITE_OK is returned. Otherwise, an SQLite error
+** code.
+*/
+int sqlite3Fts5ExprPattern(
+ Fts5Config *pConfig, int bGlob, int iCol, const char *zText, Fts5Expr **pp
+){
+ i64 nText = strlen(zText);
+ char *zExpr = (char*)sqlite3_malloc64(nText*4 + 1);
+ int rc = SQLITE_OK;
+
+ if( zExpr==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ char aSpec[3];
+ int iOut = 0;
+ int i = 0;
+ int iFirst = 0;
+
+ if( bGlob==0 ){
+ aSpec[0] = '_';
+ aSpec[1] = '%';
+ aSpec[2] = 0;
+ }else{
+ aSpec[0] = '*';
+ aSpec[1] = '?';
+ aSpec[2] = '[';
+ }
+
+ while( i<=nText ){
+ if( i==nText
+ || zText[i]==aSpec[0] || zText[i]==aSpec[1] || zText[i]==aSpec[2]
+ ){
+ if( i-iFirst>=3 ){
+ int jj;
+ zExpr[iOut++] = '"';
+ for(jj=iFirst; jj<i; jj++){
+ zExpr[iOut++] = zText[jj];
+ if( zText[jj]=='"' ) zExpr[iOut++] = '"';
+ }
+ zExpr[iOut++] = '"';
+ zExpr[iOut++] = ' ';
+ }
+ if( zText[i]==aSpec[2] ){
+ i += 2;
+ if( zText[i-1]=='^' ) i++;
+ while( i<nText && zText[i]!=']' ) i++;
+ }
+ iFirst = i+1;
+ }
+ i++;
+ }
+ if( iOut>0 ){
+ int bAnd = 0;
+ if( pConfig->eDetail!=FTS5_DETAIL_FULL ){
+ bAnd = 1;
+ if( pConfig->eDetail==FTS5_DETAIL_NONE ){
+ iCol = pConfig->nCol;
+ }
+ }
+ zExpr[iOut] = '\0';
+ rc = sqlite3Fts5ExprNew(pConfig, bAnd, iCol, zExpr, pp,pConfig->pzErrmsg);
+ }else{
+ *pp = 0;
+ }
+ sqlite3_free(zExpr);
+ }
+
+ return rc;
+}
+
+/*
** Free the expression node object passed as the only argument.
*/
void sqlite3Fts5ParseNodeFree(Fts5ExprNode *p){
@@ -1661,6 +1740,20 @@ void sqlite3Fts5ParseFinished(Fts5Parse *pParse, Fts5ExprNode *p){
pParse->pExpr = p;
}
+static int parseGrowPhraseArray(Fts5Parse *pParse){
+ if( (pParse->nPhrase % 8)==0 ){
+ sqlite3_int64 nByte = sizeof(Fts5ExprPhrase*) * (pParse->nPhrase + 8);
+ Fts5ExprPhrase **apNew;
+ apNew = (Fts5ExprPhrase**)sqlite3_realloc64(pParse->apPhrase, nByte);
+ if( apNew==0 ){
+ pParse->rc = SQLITE_NOMEM;
+ return SQLITE_NOMEM;
+ }
+ pParse->apPhrase = apNew;
+ }
+ return SQLITE_OK;
+}
+
/*
** This function is called by the parser to process a string token. The
** string may or may not be quoted. In any case it is tokenized and a
@@ -1696,16 +1789,9 @@ Fts5ExprPhrase *sqlite3Fts5ParseTerm(
}else{
if( pAppend==0 ){
- if( (pParse->nPhrase % 8)==0 ){
- sqlite3_int64 nByte = sizeof(Fts5ExprPhrase*) * (pParse->nPhrase + 8);
- Fts5ExprPhrase **apNew;
- apNew = (Fts5ExprPhrase**)sqlite3_realloc64(pParse->apPhrase, nByte);
- if( apNew==0 ){
- pParse->rc = SQLITE_NOMEM;
- fts5ExprPhraseFree(sCtx.pPhrase);
- return 0;
- }
- pParse->apPhrase = apNew;
+ if( parseGrowPhraseArray(pParse) ){
+ fts5ExprPhraseFree(sCtx.pPhrase);
+ return 0;
}
pParse->nPhrase++;
}
@@ -2113,6 +2199,67 @@ static void fts5ExprAddChildren(Fts5ExprNode *p, Fts5ExprNode *pSub){
}
/*
+** This function is used when parsing LIKE or GLOB patterns against
+** trigram indexes that specify either detail=column or detail=none.
+** It converts a phrase:
+**
+** abc + def + ghi
+**
+** into an AND tree:
+**
+** abc AND def AND ghi
+*/
+static Fts5ExprNode *fts5ParsePhraseToAnd(
+ Fts5Parse *pParse,
+ Fts5ExprNearset *pNear
+){
+ int nTerm = pNear->apPhrase[0]->nTerm;
+ int ii;
+ int nByte;
+ Fts5ExprNode *pRet;
+
+ assert( pNear->nPhrase==1 );
+ assert( pParse->bPhraseToAnd );
+
+ nByte = sizeof(Fts5ExprNode) + nTerm*sizeof(Fts5ExprNode*);
+ pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);
+ if( pRet ){
+ pRet->eType = FTS5_AND;
+ pRet->nChild = nTerm;
+ fts5ExprAssignXNext(pRet);
+ pParse->nPhrase--;
+ for(ii=0; ii<nTerm; ii++){
+ Fts5ExprPhrase *pPhrase = (Fts5ExprPhrase*)sqlite3Fts5MallocZero(
+ &pParse->rc, sizeof(Fts5ExprPhrase)
+ );
+ if( pPhrase ){
+ if( parseGrowPhraseArray(pParse) ){
+ fts5ExprPhraseFree(pPhrase);
+ }else{
+ pParse->apPhrase[pParse->nPhrase++] = pPhrase;
+ pPhrase->nTerm = 1;
+ pPhrase->aTerm[0].zTerm = sqlite3Fts5Strndup(
+ &pParse->rc, pNear->apPhrase[0]->aTerm[ii].zTerm, -1
+ );
+ pRet->apChild[ii] = sqlite3Fts5ParseNode(pParse, FTS5_STRING,
+ 0, 0, sqlite3Fts5ParseNearset(pParse, 0, pPhrase)
+ );
+ }
+ }
+ }
+
+ if( pParse->rc ){
+ sqlite3Fts5ParseNodeFree(pRet);
+ pRet = 0;
+ }else{
+ sqlite3Fts5ParseNearsetFree(pNear);
+ }
+ }
+
+ return pRet;
+}
+
+/*
** Allocate and return a new expression object. If anything goes wrong (i.e.
** OOM error), leave an error code in pParse and return NULL.
*/
@@ -2136,51 +2283,58 @@ Fts5ExprNode *sqlite3Fts5ParseNode(
if( eType!=FTS5_STRING && pLeft==0 ) return pRight;
if( eType!=FTS5_STRING && pRight==0 ) return pLeft;
- if( eType==FTS5_NOT ){
- nChild = 2;
- }else if( eType==FTS5_AND || eType==FTS5_OR ){
- nChild = 2;
- if( pLeft->eType==eType ) nChild += pLeft->nChild-1;
- if( pRight->eType==eType ) nChild += pRight->nChild-1;
- }
-
- nByte = sizeof(Fts5ExprNode) + sizeof(Fts5ExprNode*)*(nChild-1);
- pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);
-
- if( pRet ){
- pRet->eType = eType;
- pRet->pNear = pNear;
- fts5ExprAssignXNext(pRet);
- if( eType==FTS5_STRING ){
- int iPhrase;
- for(iPhrase=0; iPhrase<pNear->nPhrase; iPhrase++){
- pNear->apPhrase[iPhrase]->pNode = pRet;
- if( pNear->apPhrase[iPhrase]->nTerm==0 ){
- pRet->xNext = 0;
- pRet->eType = FTS5_EOF;
+ if( eType==FTS5_STRING
+ && pParse->bPhraseToAnd
+ && pNear->apPhrase[0]->nTerm>1
+ ){
+ pRet = fts5ParsePhraseToAnd(pParse, pNear);
+ }else{
+ if( eType==FTS5_NOT ){
+ nChild = 2;
+ }else if( eType==FTS5_AND || eType==FTS5_OR ){
+ nChild = 2;
+ if( pLeft->eType==eType ) nChild += pLeft->nChild-1;
+ if( pRight->eType==eType ) nChild += pRight->nChild-1;
+ }
+
+ nByte = sizeof(Fts5ExprNode) + sizeof(Fts5ExprNode*)*(nChild-1);
+ pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);
+
+ if( pRet ){
+ pRet->eType = eType;
+ pRet->pNear = pNear;
+ fts5ExprAssignXNext(pRet);
+ if( eType==FTS5_STRING ){
+ int iPhrase;
+ for(iPhrase=0; iPhrase<pNear->nPhrase; iPhrase++){
+ pNear->apPhrase[iPhrase]->pNode = pRet;
+ if( pNear->apPhrase[iPhrase]->nTerm==0 ){
+ pRet->xNext = 0;
+ pRet->eType = FTS5_EOF;
+ }
}
- }
- if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL ){
- Fts5ExprPhrase *pPhrase = pNear->apPhrase[0];
- if( pNear->nPhrase!=1
- || pPhrase->nTerm>1
- || (pPhrase->nTerm>0 && pPhrase->aTerm[0].bFirst)
- ){
- assert( pParse->rc==SQLITE_OK );
- pParse->rc = SQLITE_ERROR;
- assert( pParse->zErr==0 );
- pParse->zErr = sqlite3_mprintf(
- "fts5: %s queries are not supported (detail!=full)",
- pNear->nPhrase==1 ? "phrase": "NEAR"
- );
- sqlite3_free(pRet);
- pRet = 0;
+ if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL ){
+ Fts5ExprPhrase *pPhrase = pNear->apPhrase[0];
+ if( pNear->nPhrase!=1
+ || pPhrase->nTerm>1
+ || (pPhrase->nTerm>0 && pPhrase->aTerm[0].bFirst)
+ ){
+ assert( pParse->rc==SQLITE_OK );
+ pParse->rc = SQLITE_ERROR;
+ assert( pParse->zErr==0 );
+ pParse->zErr = sqlite3_mprintf(
+ "fts5: %s queries are not supported (detail!=full)",
+ pNear->nPhrase==1 ? "phrase": "NEAR"
+ );
+ sqlite3_free(pRet);
+ pRet = 0;
+ }
}
+ }else{
+ fts5ExprAddChildren(pRet, pLeft);
+ fts5ExprAddChildren(pRet, pRight);
}
- }else{
- fts5ExprAddChildren(pRet, pLeft);
- fts5ExprAddChildren(pRet, pRight);
}
}
}
@@ -2401,8 +2555,17 @@ static char *fts5ExprPrint(Fts5Config *pConfig, Fts5ExprNode *pExpr){
int iTerm;
if( pNear->pColset ){
- int iCol = pNear->pColset->aiCol[0];
- zRet = fts5PrintfAppend(zRet, "%s : ", pConfig->azCol[iCol]);
+ int ii;
+ Fts5Colset *pColset = pNear->pColset;
+ if( pColset->nCol>1 ) zRet = fts5PrintfAppend(zRet, "{");
+ for(ii=0; ii<pColset->nCol; ii++){
+ zRet = fts5PrintfAppend(zRet, "%s%s",
+ pConfig->azCol[pColset->aiCol[ii]], ii==pColset->nCol-1 ? "" : " "
+ );
+ }
+ if( zRet ){
+ zRet = fts5PrintfAppend(zRet, "%s : ", pColset->nCol>1 ? "}" : "");
+ }
if( zRet==0 ) return 0;
}
@@ -2525,7 +2688,7 @@ static void fts5ExprFunction(
rc = sqlite3Fts5ConfigParse(pGlobal, db, nConfig, azConfig, &pConfig, &zErr);
if( rc==SQLITE_OK ){
- rc = sqlite3Fts5ExprNew(pConfig, pConfig->nCol, zExpr, &pExpr, &zErr);
+ rc = sqlite3Fts5ExprNew(pConfig, 0, pConfig->nCol, zExpr, &pExpr, &zErr);
}
if( rc==SQLITE_OK ){
char *zText;
diff --git a/chromium/third_party/sqlite/src/ext/fts5/fts5_hash.c b/chromium/third_party/sqlite/src/ext/fts5/fts5_hash.c
index 1a32dcdf0f7..0f4651a83f1 100644
--- a/chromium/third_party/sqlite/src/ext/fts5/fts5_hash.c
+++ b/chromium/third_party/sqlite/src/ext/fts5/fts5_hash.c
@@ -306,7 +306,6 @@ int sqlite3Fts5HashWrite(
p->iCol = (pHash->eDetail==FTS5_DETAIL_FULL ? 0 : -1);
}
- nIncr += p->nData;
}else{
/* Appending to an existing hash-entry. Check that there is enough
@@ -339,8 +338,9 @@ int sqlite3Fts5HashWrite(
/* If this is a new rowid, append the 4-byte size field for the previous
** entry, and the new rowid for this entry. */
if( iRowid!=p->iRowid ){
+ u64 iDiff = (u64)iRowid - (u64)p->iRowid;
fts5HashAddPoslistSize(pHash, p, 0);
- p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iRowid - p->iRowid);
+ p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iDiff);
p->iRowid = iRowid;
bNew = 1;
p->iSzPoslist = p->nData;
diff --git a/chromium/third_party/sqlite/src/ext/fts5/fts5_index.c b/chromium/third_party/sqlite/src/ext/fts5/fts5_index.c
index 5e1155c2a96..f83488e2f69 100644
--- a/chromium/third_party/sqlite/src/ext/fts5/fts5_index.c
+++ b/chromium/third_party/sqlite/src/ext/fts5/fts5_index.c
@@ -1754,7 +1754,7 @@ static void fts5SegIterReverseInitPage(Fts5Index *p, Fts5SegIter *pIter){
ASSERT_SZLEAF_OK(pIter->pLeaf);
while( 1 ){
- i64 iDelta = 0;
+ u64 iDelta = 0;
if( eDetail==FTS5_DETAIL_NONE ){
/* todo */
@@ -1769,7 +1769,7 @@ static void fts5SegIterReverseInitPage(Fts5Index *p, Fts5SegIter *pIter){
i += nPos;
}
if( i>=n ) break;
- i += fts5GetVarint(&a[i], (u64*)&iDelta);
+ i += fts5GetVarint(&a[i], &iDelta);
pIter->iRowid += iDelta;
/* If necessary, grow the pIter->aRowidOffset[] array. */
@@ -1868,7 +1868,7 @@ static void fts5SegIterNext_Reverse(
if( pIter->iRowidOffset>0 ){
u8 *a = pIter->pLeaf->p;
int iOff;
- i64 iDelta;
+ u64 iDelta;
pIter->iRowidOffset--;
pIter->iLeafOffset = pIter->aRowidOffset[pIter->iRowidOffset];
@@ -1877,7 +1877,7 @@ static void fts5SegIterNext_Reverse(
if( p->pConfig->eDetail!=FTS5_DETAIL_NONE ){
iOff += pIter->nPos;
}
- fts5GetVarint(&a[iOff], (u64*)&iDelta);
+ fts5GetVarint(&a[iOff], &iDelta);
pIter->iRowid -= iDelta;
}else{
fts5SegIterReverseNewPage(p, pIter);
@@ -4997,7 +4997,9 @@ static void fts5MergePrefixLists(
** at most 20 bytes of unexpected space. */
fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
fts5BufferZero(&tmp);
- sqlite3Fts5BufferSize(&p->rc, &tmp, i1.nPoslist + i2.nPoslist + 10 + 10);
+ sqlite3Fts5BufferSize(&p->rc, &tmp,
+ i1.nPoslist + i2.nPoslist + 10 + 10 + FTS5_DATA_ZERO_PADDING
+ );
if( p->rc ) break;
sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
@@ -5071,9 +5073,10 @@ static void fts5MergePrefixLists(
}
assert_nc( out.n<=(p1->n+p2->n+9) );
- fts5BufferSet(&p->rc, p1, out.n, out.p);
+ fts5BufferFree(p1);
fts5BufferFree(&tmp);
- fts5BufferFree(&out);
+ memset(&out.p[out.n], 0, FTS5_DATA_ZERO_PADDING);
+ *p1 = out;
}
}
@@ -6059,7 +6062,7 @@ static void fts5IndexIntegrityCheckSegment(
** error, or some other SQLite error code if another error (e.g. OOM)
** occurs.
*/
-int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum){
+int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum, int bUseCksum){
int eDetail = p->pConfig->eDetail;
u64 cksum2 = 0; /* Checksum based on contents of indexes */
Fts5Buffer poslist = {0,0,0}; /* Buffer used to hold a poslist */
@@ -6120,6 +6123,7 @@ int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum){
}else{
poslist.n = 0;
fts5SegiterPoslist(p, &pIter->aSeg[pIter->aFirst[1].iFirst], 0, &poslist);
+ fts5BufferAppendBlob(&p->rc, &poslist, 4, (const u8*)"\0\0\0\0");
while( 0==sqlite3Fts5PoslistNext64(poslist.p, poslist.n, &iOff, &iPos) ){
int iCol = FTS5_POS2COLUMN(iPos);
int iTokOff = FTS5_POS2OFFSET(iPos);
@@ -6130,7 +6134,7 @@ int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum){
fts5TestTerm(p, &term, 0, 0, cksum2, &cksum3);
fts5MultiIterFree(pIter);
- if( p->rc==SQLITE_OK && cksum!=cksum2 ) p->rc = FTS5_CORRUPT;
+ if( p->rc==SQLITE_OK && bUseCksum && cksum!=cksum2 ) p->rc = FTS5_CORRUPT;
fts5StructureRelease(pStruct);
#ifdef SQLITE_DEBUG
diff --git a/chromium/third_party/sqlite/src/ext/fts5/fts5_main.c b/chromium/third_party/sqlite/src/ext/fts5/fts5_main.c
index 347bf7f23ea..788821e6b82 100644
--- a/chromium/third_party/sqlite/src/ext/fts5/fts5_main.c
+++ b/chromium/third_party/sqlite/src/ext/fts5/fts5_main.c
@@ -464,6 +464,23 @@ static void fts5SetUniqueFlag(sqlite3_index_info *pIdxInfo){
#endif
}
+static int fts5UsePatternMatch(
+ Fts5Config *pConfig,
+ struct sqlite3_index_constraint *p
+){
+ assert( FTS5_PATTERN_GLOB==SQLITE_INDEX_CONSTRAINT_GLOB );
+ assert( FTS5_PATTERN_LIKE==SQLITE_INDEX_CONSTRAINT_LIKE );
+ if( pConfig->ePattern==FTS5_PATTERN_GLOB && p->op==FTS5_PATTERN_GLOB ){
+ return 1;
+ }
+ if( pConfig->ePattern==FTS5_PATTERN_LIKE
+ && (p->op==FTS5_PATTERN_LIKE || p->op==FTS5_PATTERN_GLOB)
+ ){
+ return 1;
+ }
+ return 0;
+}
+
/*
** Implementation of the xBestIndex method for FTS5 tables. Within the
** WHERE constraint, it searches for the following:
@@ -493,7 +510,9 @@ static void fts5SetUniqueFlag(sqlite3_index_info *pIdxInfo){
**
** Match against table column: "m"
** Match against rank column: "r"
-** Match against other column: "<column-number>"
+** Match against other column: "M<column-number>"
+** LIKE against other column: "L<column-number>"
+** GLOB against other column: "G<column-number>"
** Equality constraint against the rowid: "="
** A < or <= against the rowid: "<"
** A > or >= against the rowid: ">"
@@ -554,7 +573,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
return SQLITE_ERROR;
}
- idxStr = (char*)sqlite3_malloc(pInfo->nConstraint * 6 + 1);
+ idxStr = (char*)sqlite3_malloc(pInfo->nConstraint * 8 + 1);
if( idxStr==0 ) return SQLITE_NOMEM;
pInfo->idxStr = idxStr;
pInfo->needToFreeIdxStr = 1;
@@ -578,25 +597,29 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
if( bSeenRank ) continue;
idxStr[iIdxStr++] = 'r';
bSeenRank = 1;
- }else{
+ }else if( iCol>=0 ){
bSeenMatch = 1;
- idxStr[iIdxStr++] = 'm';
- if( iCol<nCol ){
- sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
- idxStr += strlen(&idxStr[iIdxStr]);
- assert( idxStr[iIdxStr]=='\0' );
- }
+ idxStr[iIdxStr++] = 'M';
+ sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
+ idxStr += strlen(&idxStr[iIdxStr]);
+ assert( idxStr[iIdxStr]=='\0' );
}
pInfo->aConstraintUsage[i].argvIndex = ++iCons;
pInfo->aConstraintUsage[i].omit = 1;
}
- }
- else if( p->usable && bSeenEq==0
- && p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol<0
- ){
- idxStr[iIdxStr++] = '=';
- bSeenEq = 1;
- pInfo->aConstraintUsage[i].argvIndex = ++iCons;
+ }else if( p->usable ){
+ if( iCol>=0 && iCol<nCol && fts5UsePatternMatch(pConfig, p) ){
+ assert( p->op==FTS5_PATTERN_LIKE || p->op==FTS5_PATTERN_GLOB );
+ idxStr[iIdxStr++] = p->op==FTS5_PATTERN_LIKE ? 'L' : 'G';
+ sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
+ idxStr += strlen(&idxStr[iIdxStr]);
+ pInfo->aConstraintUsage[i].argvIndex = ++iCons;
+ assert( idxStr[iIdxStr]=='\0' );
+ }else if( bSeenEq==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol<0 ){
+ idxStr[iIdxStr++] = '=';
+ bSeenEq = 1;
+ pInfo->aConstraintUsage[i].argvIndex = ++iCons;
+ }
}
}
@@ -1229,19 +1252,14 @@ static int fts5FilterMethod(
case 'r':
pRank = apVal[i];
break;
- case 'm': {
+ case 'M': {
const char *zText = (const char*)sqlite3_value_text(apVal[i]);
if( zText==0 ) zText = "";
-
- if( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' ){
- iCol = 0;
- do{
- iCol = iCol*10 + (idxStr[iIdxStr]-'0');
- iIdxStr++;
- }while( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' );
- }else{
- iCol = pConfig->nCol;
- }
+ iCol = 0;
+ do{
+ iCol = iCol*10 + (idxStr[iIdxStr]-'0');
+ iIdxStr++;
+ }while( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' );
if( zText[0]=='*' ){
/* The user has issued a query of the form "MATCH '*...'". This
@@ -1251,7 +1269,7 @@ static int fts5FilterMethod(
goto filter_out;
}else{
char **pzErr = &pTab->p.base.zErrMsg;
- rc = sqlite3Fts5ExprNew(pConfig, iCol, zText, &pExpr, pzErr);
+ rc = sqlite3Fts5ExprNew(pConfig, 0, iCol, zText, &pExpr, pzErr);
if( rc==SQLITE_OK ){
rc = sqlite3Fts5ExprAnd(&pCsr->pExpr, pExpr);
pExpr = 0;
@@ -1261,6 +1279,25 @@ static int fts5FilterMethod(
break;
}
+ case 'L':
+ case 'G': {
+ int bGlob = (idxStr[iIdxStr-1]=='G');
+ const char *zText = (const char*)sqlite3_value_text(apVal[i]);
+ iCol = 0;
+ do{
+ iCol = iCol*10 + (idxStr[iIdxStr]-'0');
+ iIdxStr++;
+ }while( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' );
+ if( zText ){
+ rc = sqlite3Fts5ExprPattern(pConfig, bGlob, iCol, zText, &pExpr);
+ }
+ if( rc==SQLITE_OK ){
+ rc = sqlite3Fts5ExprAnd(&pCsr->pExpr, pExpr);
+ pExpr = 0;
+ }
+ if( rc!=SQLITE_OK ) goto filter_out;
+ break;
+ }
case '=':
pRowidEq = apVal[i];
break;
@@ -1508,7 +1545,8 @@ static int fts5SpecialInsert(
int nMerge = sqlite3_value_int(pVal);
rc = sqlite3Fts5StorageMerge(pTab->pStorage, nMerge);
}else if( 0==sqlite3_stricmp("integrity-check", zCmd) ){
- rc = sqlite3Fts5StorageIntegrity(pTab->pStorage);
+ int iArg = sqlite3_value_int(pVal);
+ rc = sqlite3Fts5StorageIntegrity(pTab->pStorage, iArg);
#ifdef SQLITE_DEBUG
}else if( 0==sqlite3_stricmp("prefix-index", zCmd) ){
pConfig->bPrefixIndex = sqlite3_value_int(pVal);
@@ -2671,8 +2709,7 @@ int sqlite3Fts5GetTokenizer(
Fts5Global *pGlobal,
const char **azArg,
int nArg,
- Fts5Tokenizer **ppTok,
- fts5_tokenizer **ppTokApi,
+ Fts5Config *pConfig,
char **pzErr
){
Fts5TokenizerModule *pMod;
@@ -2684,16 +2721,22 @@ int sqlite3Fts5GetTokenizer(
rc = SQLITE_ERROR;
*pzErr = sqlite3_mprintf("no such tokenizer: %s", azArg[0]);
}else{
- rc = pMod->x.xCreate(pMod->pUserData, &azArg[1], (nArg?nArg-1:0), ppTok);
- *ppTokApi = &pMod->x;
- if( rc!=SQLITE_OK && pzErr ){
- *pzErr = sqlite3_mprintf("error in tokenizer constructor");
+ rc = pMod->x.xCreate(
+ pMod->pUserData, &azArg[1], (nArg?nArg-1:0), &pConfig->pTok
+ );
+ pConfig->pTokApi = &pMod->x;
+ if( rc!=SQLITE_OK ){
+ if( pzErr ) *pzErr = sqlite3_mprintf("error in tokenizer constructor");
+ }else{
+ pConfig->ePattern = sqlite3Fts5TokenizerPattern(
+ pMod->x.xCreate, pConfig->pTok
+ );
}
}
if( rc!=SQLITE_OK ){
- *ppTokApi = 0;
- *ppTok = 0;
+ pConfig->pTokApi = 0;
+ pConfig->pTok = 0;
}
return rc;
diff --git a/chromium/third_party/sqlite/src/ext/fts5/fts5_storage.c b/chromium/third_party/sqlite/src/ext/fts5/fts5_storage.c
index 22f90c0ef86..c5052b04786 100644
--- a/chromium/third_party/sqlite/src/ext/fts5/fts5_storage.c
+++ b/chromium/third_party/sqlite/src/ext/fts5/fts5_storage.c
@@ -429,9 +429,16 @@ static int fts5StorageDeleteFromIndex(
zText, nText, (void*)&ctx, fts5StorageInsertCallback
);
p->aTotalSize[iCol-1] -= (i64)ctx.szCol;
+ if( p->aTotalSize[iCol-1]<0 ){
+ rc = FTS5_CORRUPT;
+ }
}
}
- p->nTotalRow--;
+ if( rc==SQLITE_OK && p->nTotalRow<1 ){
+ rc = FTS5_CORRUPT;
+ }else{
+ p->nTotalRow--;
+ }
rc2 = sqlite3_reset(pSeek);
if( rc==SQLITE_OK ) rc = rc2;
@@ -874,13 +881,14 @@ static int fts5StorageIntegrityCallback(
** some other SQLite error code if an error occurs while attempting to
** determine this.
*/
-int sqlite3Fts5StorageIntegrity(Fts5Storage *p){
+int sqlite3Fts5StorageIntegrity(Fts5Storage *p, int iArg){
Fts5Config *pConfig = p->pConfig;
- int rc; /* Return code */
+ int rc = SQLITE_OK; /* Return code */
int *aColSize; /* Array of size pConfig->nCol */
i64 *aTotalSize; /* Array of size pConfig->nCol */
Fts5IntegrityCtx ctx;
sqlite3_stmt *pScan;
+ int bUseCksum;
memset(&ctx, 0, sizeof(Fts5IntegrityCtx));
ctx.pConfig = p->pConfig;
@@ -889,83 +897,88 @@ int sqlite3Fts5StorageIntegrity(Fts5Storage *p){
aColSize = (int*)&aTotalSize[pConfig->nCol];
memset(aTotalSize, 0, sizeof(i64) * pConfig->nCol);
- /* Generate the expected index checksum based on the contents of the
- ** %_content table. This block stores the checksum in ctx.cksum. */
- rc = fts5StorageGetStmt(p, FTS5_STMT_SCAN, &pScan, 0);
- if( rc==SQLITE_OK ){
- int rc2;
- while( SQLITE_ROW==sqlite3_step(pScan) ){
- int i;
- ctx.iRowid = sqlite3_column_int64(pScan, 0);
- ctx.szCol = 0;
- if( pConfig->bColumnsize ){
- rc = sqlite3Fts5StorageDocsize(p, ctx.iRowid, aColSize);
- }
- if( rc==SQLITE_OK && pConfig->eDetail==FTS5_DETAIL_NONE ){
- rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
- }
- for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
- if( pConfig->abUnindexed[i] ) continue;
- ctx.iCol = i;
+ bUseCksum = (pConfig->eContent==FTS5_CONTENT_NORMAL
+ || (pConfig->eContent==FTS5_CONTENT_EXTERNAL && iArg)
+ );
+ if( bUseCksum ){
+ /* Generate the expected index checksum based on the contents of the
+ ** %_content table. This block stores the checksum in ctx.cksum. */
+ rc = fts5StorageGetStmt(p, FTS5_STMT_SCAN, &pScan, 0);
+ if( rc==SQLITE_OK ){
+ int rc2;
+ while( SQLITE_ROW==sqlite3_step(pScan) ){
+ int i;
+ ctx.iRowid = sqlite3_column_int64(pScan, 0);
ctx.szCol = 0;
- if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
- rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
- }
- if( rc==SQLITE_OK ){
- const char *zText = (const char*)sqlite3_column_text(pScan, i+1);
- int nText = sqlite3_column_bytes(pScan, i+1);
- rc = sqlite3Fts5Tokenize(pConfig,
- FTS5_TOKENIZE_DOCUMENT,
- zText, nText,
- (void*)&ctx,
- fts5StorageIntegrityCallback
- );
+ if( pConfig->bColumnsize ){
+ rc = sqlite3Fts5StorageDocsize(p, ctx.iRowid, aColSize);
}
- if( rc==SQLITE_OK && pConfig->bColumnsize && ctx.szCol!=aColSize[i] ){
- rc = FTS5_CORRUPT;
+ if( rc==SQLITE_OK && pConfig->eDetail==FTS5_DETAIL_NONE ){
+ rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
}
- aTotalSize[i] += ctx.szCol;
- if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
- sqlite3Fts5TermsetFree(ctx.pTermset);
- ctx.pTermset = 0;
+ for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
+ if( pConfig->abUnindexed[i] ) continue;
+ ctx.iCol = i;
+ ctx.szCol = 0;
+ if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
+ rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
+ }
+ if( rc==SQLITE_OK ){
+ const char *zText = (const char*)sqlite3_column_text(pScan, i+1);
+ int nText = sqlite3_column_bytes(pScan, i+1);
+ rc = sqlite3Fts5Tokenize(pConfig,
+ FTS5_TOKENIZE_DOCUMENT,
+ zText, nText,
+ (void*)&ctx,
+ fts5StorageIntegrityCallback
+ );
+ }
+ if( rc==SQLITE_OK && pConfig->bColumnsize && ctx.szCol!=aColSize[i] ){
+ rc = FTS5_CORRUPT;
+ }
+ aTotalSize[i] += ctx.szCol;
+ if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
+ sqlite3Fts5TermsetFree(ctx.pTermset);
+ ctx.pTermset = 0;
+ }
}
+ sqlite3Fts5TermsetFree(ctx.pTermset);
+ ctx.pTermset = 0;
+
+ if( rc!=SQLITE_OK ) break;
}
- sqlite3Fts5TermsetFree(ctx.pTermset);
- ctx.pTermset = 0;
-
- if( rc!=SQLITE_OK ) break;
+ rc2 = sqlite3_reset(pScan);
+ if( rc==SQLITE_OK ) rc = rc2;
}
- rc2 = sqlite3_reset(pScan);
- if( rc==SQLITE_OK ) rc = rc2;
- }
- /* Test that the "totals" (sometimes called "averages") record looks Ok */
- if( rc==SQLITE_OK ){
- int i;
- rc = fts5StorageLoadTotals(p, 0);
- for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
- if( p->aTotalSize[i]!=aTotalSize[i] ) rc = FTS5_CORRUPT;
+ /* Test that the "totals" (sometimes called "averages") record looks Ok */
+ if( rc==SQLITE_OK ){
+ int i;
+ rc = fts5StorageLoadTotals(p, 0);
+ for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
+ if( p->aTotalSize[i]!=aTotalSize[i] ) rc = FTS5_CORRUPT;
+ }
}
- }
- /* Check that the %_docsize and %_content tables contain the expected
- ** number of rows. */
- if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){
- i64 nRow = 0;
- rc = fts5StorageCount(p, "content", &nRow);
- if( rc==SQLITE_OK && nRow!=p->nTotalRow ) rc = FTS5_CORRUPT;
- }
- if( rc==SQLITE_OK && pConfig->bColumnsize ){
- i64 nRow = 0;
- rc = fts5StorageCount(p, "docsize", &nRow);
- if( rc==SQLITE_OK && nRow!=p->nTotalRow ) rc = FTS5_CORRUPT;
+ /* Check that the %_docsize and %_content tables contain the expected
+ ** number of rows. */
+ if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){
+ i64 nRow = 0;
+ rc = fts5StorageCount(p, "content", &nRow);
+ if( rc==SQLITE_OK && nRow!=p->nTotalRow ) rc = FTS5_CORRUPT;
+ }
+ if( rc==SQLITE_OK && pConfig->bColumnsize ){
+ i64 nRow = 0;
+ rc = fts5StorageCount(p, "docsize", &nRow);
+ if( rc==SQLITE_OK && nRow!=p->nTotalRow ) rc = FTS5_CORRUPT;
+ }
}
/* Pass the expected checksum down to the FTS index module. It will
** verify, amongst other things, that it matches the checksum generated by
** inspecting the index itself. */
if( rc==SQLITE_OK ){
- rc = sqlite3Fts5IndexIntegrityCheck(p->pIndex, ctx.cksum);
+ rc = sqlite3Fts5IndexIntegrityCheck(p->pIndex, ctx.cksum, bUseCksum);
}
sqlite3_free(aTotalSize);
diff --git a/chromium/third_party/sqlite/src/ext/fts5/fts5_tokenize.c b/chromium/third_party/sqlite/src/ext/fts5/fts5_tokenize.c
index 93edcee133e..e61d6b1eddc 100644
--- a/chromium/third_party/sqlite/src/ext/fts5/fts5_tokenize.c
+++ b/chromium/third_party/sqlite/src/ext/fts5/fts5_tokenize.c
@@ -1258,6 +1258,133 @@ static int fts5PorterTokenize(
);
}
+/**************************************************************************
+** Start of trigram implementation.
+*/
+typedef struct TrigramTokenizer TrigramTokenizer;
+struct TrigramTokenizer {
+ int bFold; /* True to fold to lower-case */
+};
+
+/*
+** Free a trigram tokenizer.
+*/
+static void fts5TriDelete(Fts5Tokenizer *p){
+ sqlite3_free(p);
+}
+
+/*
+** Allocate a trigram tokenizer.
+*/
+static int fts5TriCreate(
+ void *pUnused,
+ const char **azArg,
+ int nArg,
+ Fts5Tokenizer **ppOut
+){
+ int rc = SQLITE_OK;
+ TrigramTokenizer *pNew = (TrigramTokenizer*)sqlite3_malloc(sizeof(*pNew));
+ UNUSED_PARAM(pUnused);
+ if( pNew==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ int i;
+ pNew->bFold = 1;
+ for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
+ const char *zArg = azArg[i+1];
+ if( 0==sqlite3_stricmp(azArg[i], "case_sensitive") ){
+ if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1] ){
+ rc = SQLITE_ERROR;
+ }else{
+ pNew->bFold = (zArg[0]=='0');
+ }
+ }else{
+ rc = SQLITE_ERROR;
+ }
+ }
+ if( rc!=SQLITE_OK ){
+ fts5TriDelete((Fts5Tokenizer*)pNew);
+ pNew = 0;
+ }
+ }
+ *ppOut = (Fts5Tokenizer*)pNew;
+ return rc;
+}
+
+/*
+** Trigram tokenizer tokenize routine.
+*/
+static int fts5TriTokenize(
+ Fts5Tokenizer *pTok,
+ void *pCtx,
+ int unusedFlags,
+ const char *pText, int nText,
+ int (*xToken)(void*, int, const char*, int, int, int)
+){
+ TrigramTokenizer *p = (TrigramTokenizer*)pTok;
+ int rc = SQLITE_OK;
+ char aBuf[32];
+ const unsigned char *zIn = (const unsigned char*)pText;
+ const unsigned char *zEof = &zIn[nText];
+ u32 iCode;
+
+ UNUSED_PARAM(unusedFlags);
+ while( 1 ){
+ char *zOut = aBuf;
+ int iStart = zIn - (const unsigned char*)pText;
+ const unsigned char *zNext;
+
+ READ_UTF8(zIn, zEof, iCode);
+ if( iCode==0 ) break;
+ zNext = zIn;
+ if( zIn<zEof ){
+ if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, 0);
+ WRITE_UTF8(zOut, iCode);
+ READ_UTF8(zIn, zEof, iCode);
+ if( iCode==0 ) break;
+ }else{
+ break;
+ }
+ if( zIn<zEof ){
+ if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, 0);
+ WRITE_UTF8(zOut, iCode);
+ READ_UTF8(zIn, zEof, iCode);
+ if( iCode==0 ) break;
+ if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, 0);
+ WRITE_UTF8(zOut, iCode);
+ }else{
+ break;
+ }
+ rc = xToken(pCtx, 0, aBuf, zOut-aBuf, iStart, iStart + zOut-aBuf);
+ if( rc!=SQLITE_OK ) break;
+ zIn = zNext;
+ }
+
+ return rc;
+}
+
+/*
+** Argument xCreate is a pointer to a constructor function for a tokenizer.
+** pTok is a tokenizer previously created using the same method. This function
+** returns one of FTS5_PATTERN_NONE, FTS5_PATTERN_LIKE or FTS5_PATTERN_GLOB
+** indicating the style of pattern matching that the tokenizer can support.
+** In practice, this is:
+**
+** "trigram" tokenizer, case_sensitive=1 - FTS5_PATTERN_GLOB
+** "trigram" tokenizer, case_sensitive=0 (the default) - FTS5_PATTERN_LIKE
+** all other tokenizers - FTS5_PATTERN_NONE
+*/
+int sqlite3Fts5TokenizerPattern(
+ int (*xCreate)(void*, const char**, int, Fts5Tokenizer**),
+ Fts5Tokenizer *pTok
+){
+ if( xCreate==fts5TriCreate ){
+ TrigramTokenizer *p = (TrigramTokenizer*)pTok;
+ return p->bFold ? FTS5_PATTERN_LIKE : FTS5_PATTERN_GLOB;
+ }
+ return FTS5_PATTERN_NONE;
+}
+
/*
** Register all built-in tokenizers with FTS5.
*/
@@ -1269,6 +1396,7 @@ int sqlite3Fts5TokenizerInit(fts5_api *pApi){
{ "unicode61", {fts5UnicodeCreate, fts5UnicodeDelete, fts5UnicodeTokenize}},
{ "ascii", {fts5AsciiCreate, fts5AsciiDelete, fts5AsciiTokenize }},
{ "porter", {fts5PorterCreate, fts5PorterDelete, fts5PorterTokenize }},
+ { "trigram", {fts5TriCreate, fts5TriDelete, fts5TriTokenize}},
};
int rc = SQLITE_OK; /* Return code */
diff --git a/chromium/third_party/sqlite/src/ext/fts5/fts5_unicode2.c b/chromium/third_party/sqlite/src/ext/fts5/fts5_unicode2.c
index 161e8d880f7..3e97264fa80 100644
--- a/chromium/third_party/sqlite/src/ext/fts5/fts5_unicode2.c
+++ b/chromium/third_party/sqlite/src/ext/fts5/fts5_unicode2.c
@@ -773,4 +773,6 @@ void sqlite3Fts5UnicodeAscii(u8 *aArray, u8 *aAscii){
}
iTbl++;
}
+ aAscii[0] = 0; /* 0x00 is never a token character */
}
+
diff --git a/chromium/third_party/sqlite/src/ext/fts5/tool/fts5txt2db.tcl b/chromium/third_party/sqlite/src/ext/fts5/tool/fts5txt2db.tcl
index 4766b00b06b..1996b2c3136 100644
--- a/chromium/third_party/sqlite/src/ext/fts5/tool/fts5txt2db.tcl
+++ b/chromium/third_party/sqlite/src/ext/fts5/tool/fts5txt2db.tcl
@@ -12,6 +12,7 @@ proc process_cmdline {} {
cmdline::process ::A $::argv {
{fts5 "use fts5 (this is the default)"}
{fts4 "use fts4"}
+ {trigram "Use tokenize=trigram"}
{colsize "10 10 10" "list of column sizes"}
{tblname "t1" "table name to create"}
{detail "full" "Fts5 detail mode to use"}
@@ -175,6 +176,7 @@ proc create_table {} {
set sql "CREATE VIRTUAL TABLE IF NOT EXISTS $A(tblname) USING $A(fts) ("
append sql [join $cols ,]
if {$A(fts)=="fts5"} { append sql ",detail=$A(detail)" }
+ if {$A(trigram)} { append sql ",tokenize=trigram" }
append sql ", prefix='$A(prefix)');"
db eval $sql
diff --git a/chromium/third_party/sqlite/src/ext/misc/carray.c b/chromium/third_party/sqlite/src/ext/misc/carray.c
index 32fec3406ea..b8cda21bc73 100644
--- a/chromium/third_party/sqlite/src/ext/misc/carray.c
+++ b/chromium/third_party/sqlite/src/ext/misc/carray.c
@@ -57,20 +57,31 @@ SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>
+/* Allowed values for the mFlags parameter to sqlite3_carray_bind().
+** Must exactly match the definitions in carray.h.
+*/
+#define CARRAY_INT32 0 /* Data is 32-bit signed integers */
+#define CARRAY_INT64 1 /* Data is 64-bit signed integers */
+#define CARRAY_DOUBLE 2 /* Data is doubles */
+#define CARRAY_TEXT 3 /* Data is char* */
+
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
-** Allowed datatypes
+** Names of allowed datatypes
*/
-#define CARRAY_INT32 0
-#define CARRAY_INT64 1
-#define CARRAY_DOUBLE 2
-#define CARRAY_TEXT 3
+static const char *azType[] = { "int32", "int64", "double", "char*" };
/*
-** Names of types
+** Structure used to hold the sqlite3_carray_bind() information
*/
-static const char *azType[] = { "int32", "int64", "double", "char*" };
+typedef struct carray_bind carray_bind;
+struct carray_bind {
+ void *aData; /* The data */
+ int nData; /* Number of elements */
+ int mFlags; /* Control flags */
+ void (*xDel)(void*); /* Destructor for aData */
+};
/* carray_cursor is a subclass of sqlite3_vtab_cursor which will
@@ -239,28 +250,39 @@ static int carrayFilter(
int argc, sqlite3_value **argv
){
carray_cursor *pCur = (carray_cursor *)pVtabCursor;
- if( idxNum ){
- pCur->pPtr = sqlite3_value_pointer(argv[0], "carray");
- pCur->iCnt = pCur->pPtr ? sqlite3_value_int64(argv[1]) : 0;
- if( idxNum<3 ){
- pCur->eType = CARRAY_INT32;
- }else{
- unsigned char i;
- const char *zType = (const char*)sqlite3_value_text(argv[2]);
- for(i=0; i<sizeof(azType)/sizeof(azType[0]); i++){
- if( sqlite3_stricmp(zType, azType[i])==0 ) break;
- }
- if( i>=sizeof(azType)/sizeof(azType[0]) ){
- pVtabCursor->pVtab->zErrMsg = sqlite3_mprintf(
- "unknown datatype: %Q", zType);
- return SQLITE_ERROR;
+ pCur->pPtr = 0;
+ pCur->iCnt = 0;
+ switch( idxNum ){
+ case 1: {
+ carray_bind *pBind = sqlite3_value_pointer(argv[0], "carray-bind");
+ if( pBind==0 ) break;
+ pCur->pPtr = pBind->aData;
+ pCur->iCnt = pBind->nData;
+ pCur->eType = pBind->mFlags & 0x03;
+ break;
+ }
+ case 2:
+ case 3: {
+ pCur->pPtr = sqlite3_value_pointer(argv[0], "carray");
+ pCur->iCnt = pCur->pPtr ? sqlite3_value_int64(argv[1]) : 0;
+ if( idxNum<3 ){
+ pCur->eType = CARRAY_INT32;
}else{
- pCur->eType = i;
+ unsigned char i;
+ const char *zType = (const char*)sqlite3_value_text(argv[2]);
+ for(i=0; i<sizeof(azType)/sizeof(azType[0]); i++){
+ if( sqlite3_stricmp(zType, azType[i])==0 ) break;
+ }
+ if( i>=sizeof(azType)/sizeof(azType[0]) ){
+ pVtabCursor->pVtab->zErrMsg = sqlite3_mprintf(
+ "unknown datatype: %Q", zType);
+ return SQLITE_ERROR;
+ }else{
+ pCur->eType = i;
+ }
}
+ break;
}
- }else{
- pCur->pPtr = 0;
- pCur->iCnt = 0;
}
pCur->iRowid = 1;
return SQLITE_OK;
@@ -275,9 +297,16 @@ static int carrayFilter(
** In this implementation idxNum is used to represent the
** query plan. idxStr is unused.
**
-** idxNum is 2 if the pointer= and count= constraints exist,
-** 3 if the ctype= constraint also exists, and is 0 otherwise.
-** If idxNum is 0, then carray becomes an empty table.
+** idxNum is:
+**
+** 1 If only the pointer= constraint exists. In this case, the
+** parameter must be bound using sqlite3_carray_bind().
+**
+** 2 if the pointer= and count= constraints exist.
+**
+** 3 if the ctype= constraint also exists.
+**
+** idxNum is 0 otherwise and carray becomes an empty table.
*/
static int carrayBestIndex(
sqlite3_vtab *tab,
@@ -305,18 +334,21 @@ static int carrayBestIndex(
break;
}
}
- if( ptrIdx>=0 && cntIdx>=0 ){
+ if( ptrIdx>=0 ){
pIdxInfo->aConstraintUsage[ptrIdx].argvIndex = 1;
pIdxInfo->aConstraintUsage[ptrIdx].omit = 1;
- pIdxInfo->aConstraintUsage[cntIdx].argvIndex = 2;
- pIdxInfo->aConstraintUsage[cntIdx].omit = 1;
pIdxInfo->estimatedCost = (double)1;
pIdxInfo->estimatedRows = 100;
- pIdxInfo->idxNum = 2;
- if( ctypeIdx>=0 ){
- pIdxInfo->aConstraintUsage[ctypeIdx].argvIndex = 3;
- pIdxInfo->aConstraintUsage[ctypeIdx].omit = 1;
- pIdxInfo->idxNum = 3;
+ pIdxInfo->idxNum = 1;
+ if( cntIdx>=0 ){
+ pIdxInfo->aConstraintUsage[cntIdx].argvIndex = 2;
+ pIdxInfo->aConstraintUsage[cntIdx].omit = 1;
+ pIdxInfo->idxNum = 2;
+ if( ctypeIdx>=0 ){
+ pIdxInfo->aConstraintUsage[ctypeIdx].argvIndex = 3;
+ pIdxInfo->aConstraintUsage[ctypeIdx].omit = 1;
+ pIdxInfo->idxNum = 3;
+ }
}
}else{
pIdxInfo->estimatedCost = (double)2147483647;
@@ -354,6 +386,89 @@ static sqlite3_module carrayModule = {
};
/*
+** Destructor for the carray_bind object
+*/
+static void carrayBindDel(void *pPtr){
+ carray_bind *p = (carray_bind*)pPtr;
+ if( p->xDel!=SQLITE_STATIC ){
+ p->xDel(p->aData);
+ }
+ sqlite3_free(p);
+}
+
+/*
+** Invoke this interface in order to bind to the single-argument
+** version of CARRAY().
+*/
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int sqlite3_carray_bind(
+ sqlite3_stmt *pStmt,
+ int idx,
+ void *aData,
+ int nData,
+ int mFlags,
+ void (*xDestroy)(void*)
+){
+ carray_bind *pNew;
+ int i;
+ pNew = sqlite3_malloc64(sizeof(*pNew));
+ if( pNew==0 ){
+ if( xDestroy!=SQLITE_STATIC && xDestroy!=SQLITE_TRANSIENT ){
+ xDestroy(aData);
+ }
+ return SQLITE_NOMEM;
+ }
+ pNew->nData = nData;
+ pNew->mFlags = mFlags;
+ if( xDestroy==SQLITE_TRANSIENT ){
+ sqlite3_int64 sz = nData;
+ switch( mFlags & 0x03 ){
+ case CARRAY_INT32: sz *= 4; break;
+ case CARRAY_INT64: sz *= 8; break;
+ case CARRAY_DOUBLE: sz *= 8; break;
+ case CARRAY_TEXT: sz *= sizeof(char*); break;
+ }
+ if( (mFlags & 0x03)==CARRAY_TEXT ){
+ for(i=0; i<nData; i++){
+ const char *z = ((char**)aData)[i];
+ if( z ) sz += strlen(z) + 1;
+ }
+ }
+ pNew->aData = sqlite3_malloc64( sz );
+ if( pNew->aData==0 ){
+ sqlite3_free(pNew);
+ return SQLITE_NOMEM;
+ }
+ if( (mFlags & 0x03)==CARRAY_TEXT ){
+ char **az = (char**)pNew->aData;
+ char *z = (char*)&az[nData];
+ for(i=0; i<nData; i++){
+ const char *zData = ((char**)aData)[i];
+ sqlite3_int64 n;
+ if( zData==0 ){
+ az[i] = 0;
+ continue;
+ }
+ az[i] = z;
+ n = strlen(zData);
+ memcpy(z, zData, n+1);
+ z += n+1;
+ }
+ }else{
+ memcpy(pNew->aData, aData, sz*nData);
+ }
+ pNew->xDel = sqlite3_free;
+ }else{
+ pNew->aData = aData;
+ pNew->xDel = xDestroy;
+ }
+ return sqlite3_bind_pointer(pStmt, idx, pNew, "carray-bind", carrayBindDel);
+}
+
+
+/*
** For testing purpose in the TCL test harness, we need a method for
** setting the pointer value. The inttoptr(X) SQL function accomplishes
** this. Tcl script will bind an integer to X and the inttoptr() SQL
diff --git a/chromium/third_party/sqlite/src/ext/misc/cksumvfs.c b/chromium/third_party/sqlite/src/ext/misc/cksumvfs.c
index 64cd37f251f..a0888c0024d 100644
--- a/chromium/third_party/sqlite/src/ext/misc/cksumvfs.c
+++ b/chromium/third_party/sqlite/src/ext/misc/cksumvfs.c
@@ -54,11 +54,11 @@
** statically linked against the application, initialize it using
** a single API call as follows:
**
-** sqlite3_cksumvfs_init();
+** sqlite3_register_cksumvfs();
**
** Cksumvfs is a VFS Shim. When loaded, "cksmvfs" becomes the new
** default VFS and it uses the prior default VFS as the next VFS
-** down in the stack. This is normally what you want. However, it
+** down in the stack. This is normally what you want. However, in
** complex situations where multiple VFS shims are being loaded,
** it might be important to ensure that cksumvfs is loaded in the
** correct order so that it sequences itself into the default VFS
@@ -79,7 +79,7 @@
** the reserve-bytes value to 8 by runing:
**
** int n = 8;
-** sqlite3_file_control(db, 0, SQLITE_FCNTL_RESERVED_BYTES, &n);
+** sqlite3_file_control(db, 0, SQLITE_FCNTL_RESERVE_BYTES, &n);
**
** If you do this immediately after creating a new database file,
** before anything else has been written into the file, then that
@@ -157,6 +157,9 @@
** value at offset 20 the SQLite database header is exactly 8. If
** the reserved-space value is not 8, this module is a no-op.
*/
+#if defined(SQLITE_AMALGAMATION) && !defined(SQLITE_CKSUMVFS_STATIC)
+# define SQLITE_CKSUMVFS_STATIC
+#endif
#ifdef SQLITE_CKSUMVFS_STATIC
# include "sqlite3.h"
#else
@@ -176,7 +179,7 @@ typedef struct CksmFile CksmFile;
/*
** Useful datatype abbreviations
*/
-#if !defined(SQLITE_CORE)
+#if !defined(SQLITE_AMALGAMATION)
typedef unsigned char u8;
typedef unsigned int u32;
#endif
@@ -395,7 +398,9 @@ static int cksmRead(
pFile = ORIGFILE(pFile);
rc = pFile->pMethods->xRead(pFile, zBuf, iAmt, iOfst);
if( rc==SQLITE_OK ){
- if( iOfst==0 && iAmt>=100 && memcmp(zBuf,"SQLite format 3",16)==0 ){
+ if( iOfst==0 && iAmt>=100 && (
+ memcmp(zBuf,"SQLite format 3",16)==0 || memcmp(zBuf,"ZV-",3)==0
+ )){
u8 *d = (u8*)zBuf;
char hasCorrectReserveSize = (d[20]==8);
cksmSetFlags(p, hasCorrectReserveSize);
@@ -434,7 +439,9 @@ static int cksmWrite(
){
CksmFile *p = (CksmFile *)pFile;
pFile = ORIGFILE(pFile);
- if( iOfst==0 && iAmt>=100 && memcmp(zBuf,"SQLite format 3",16)==0 ){
+ if( iOfst==0 && iAmt>=100 && (
+ memcmp(zBuf,"SQLite format 3",16)==0 || memcmp(zBuf,"ZV-",3)==0
+ )){
u8 *d = (u8*)zBuf;
char hasCorrectReserveSize = (d[20]==8);
cksmSetFlags(p, hasCorrectReserveSize);
@@ -604,13 +611,20 @@ static int cksmFetch(
return SQLITE_OK;
}
pFile = ORIGFILE(pFile);
- return pFile->pMethods->xFetch(pFile, iOfst, iAmt, pp);
+ if( pFile->pMethods->iVersion>2 && pFile->pMethods->xFetch ){
+ return pFile->pMethods->xFetch(pFile, iOfst, iAmt, pp);
+ }
+ *pp = 0;
+ return SQLITE_OK;
}
/* Release a memory-mapped page */
static int cksmUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
pFile = ORIGFILE(pFile);
- return pFile->pMethods->xUnfetch(pFile, iOfst, pPage);
+ if( pFile->pMethods->iVersion>2 && pFile->pMethods->xUnfetch ){
+ return pFile->pMethods->xUnfetch(pFile, iOfst, pPage);
+ }
+ return SQLITE_OK;
}
/*
@@ -763,6 +777,13 @@ int sqlite3_register_cksumvfs(const char *NotUsed){
(void)NotUsed;
return cksmRegisterVfs();
}
+int sqlite3_unregister_cksumvfs(void){
+ if( sqlite3_vfs_find("cksmvfs") ){
+ sqlite3_vfs_unregister(&cksm_vfs);
+ sqlite3_cancel_auto_extension((void(*)(void))cksmRegisterFunc);
+ }
+ return SQLITE_OK;
+}
#endif /* defined(SQLITE_CKSUMVFS_STATIC */
#if !defined(SQLITE_CKSUMVFS_STATIC)
diff --git a/chromium/third_party/sqlite/src/ext/misc/csv.c b/chromium/third_party/sqlite/src/ext/misc/csv.c
index 71e3828c77b..d08ddd6b3a1 100644
--- a/chromium/third_party/sqlite/src/ext/misc/csv.c
+++ b/chromium/third_party/sqlite/src/ext/misc/csv.c
@@ -776,7 +776,7 @@ static int csvtabColumn(
CsvCursor *pCur = (CsvCursor*)cur;
CsvTable *pTab = (CsvTable*)cur->pVtab;
if( i>=0 && i<pTab->nCol && pCur->azVal[i]!=0 ){
- sqlite3_result_text(ctx, pCur->azVal[i], -1, SQLITE_STATIC);
+ sqlite3_result_text(ctx, pCur->azVal[i], -1, SQLITE_TRANSIENT);
}
return SQLITE_OK;
}
diff --git a/chromium/third_party/sqlite/src/ext/misc/series.c b/chromium/third_party/sqlite/src/ext/misc/series.c
index ac93f1fc4c2..092383e57e7 100644
--- a/chromium/third_party/sqlite/src/ext/misc/series.c
+++ b/chromium/third_party/sqlite/src/ext/misc/series.c
@@ -106,10 +106,10 @@ struct series_cursor {
*/
static int seriesConnect(
sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
+ void *pUnused,
+ int argcUnused, const char *const*argvUnused,
sqlite3_vtab **ppVtab,
- char **pzErr
+ char **pzErrUnused
){
sqlite3_vtab *pNew;
int rc;
@@ -120,6 +120,10 @@ static int seriesConnect(
#define SERIES_COLUMN_STOP 2
#define SERIES_COLUMN_STEP 3
+ (void)pUnused;
+ (void)argcUnused;
+ (void)argvUnused;
+ (void)pzErrUnused;
rc = sqlite3_declare_vtab(db,
"CREATE TABLE x(value,start hidden,stop hidden,step hidden)");
if( rc==SQLITE_OK ){
@@ -142,8 +146,9 @@ static int seriesDisconnect(sqlite3_vtab *pVtab){
/*
** Constructor for a new series_cursor object.
*/
-static int seriesOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
+static int seriesOpen(sqlite3_vtab *pUnused, sqlite3_vtab_cursor **ppCursor){
series_cursor *pCur;
+ (void)pUnused;
pCur = sqlite3_malloc( sizeof(*pCur) );
if( pCur==0 ) return SQLITE_NOMEM;
memset(pCur, 0, sizeof(*pCur));
@@ -250,11 +255,12 @@ static int seriesEof(sqlite3_vtab_cursor *cur){
*/
static int seriesFilter(
sqlite3_vtab_cursor *pVtabCursor,
- int idxNum, const char *idxStr,
+ int idxNum, const char *idxStrUnused,
int argc, sqlite3_value **argv
){
series_cursor *pCur = (series_cursor *)pVtabCursor;
int i = 0;
+ (void)idxStrUnused;
if( idxNum & 1 ){
pCur->mnValue = sqlite3_value_int64(argv[i++]);
}else{
@@ -311,7 +317,7 @@ static int seriesFilter(
** (8) output in descending order
*/
static int seriesBestIndex(
- sqlite3_vtab *tab,
+ sqlite3_vtab *tabUnused,
sqlite3_index_info *pIdxInfo
){
int i, j; /* Loop over constraints */
@@ -325,6 +331,7 @@ static int seriesBestIndex(
** are the last three columns in the virtual table. */
assert( SERIES_COLUMN_STOP == SERIES_COLUMN_START+1 );
assert( SERIES_COLUMN_STEP == SERIES_COLUMN_START+2 );
+ (void)tabUnused;
aIdx[0] = aIdx[1] = aIdx[2] = -1;
pConstraint = pIdxInfo->aConstraint;
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
@@ -398,6 +405,10 @@ static sqlite3_module seriesModule = {
0, /* xRollback */
0, /* xFindMethod */
0, /* xRename */
+ 0, /* xSavepoint */
+ 0, /* xRelease */
+ 0, /* xRollbackTo */
+ 0 /* xShadowName */
};
#endif /* SQLITE_OMIT_VIRTUALTABLE */
diff --git a/chromium/third_party/sqlite/src/ext/misc/zipfile.c b/chromium/third_party/sqlite/src/ext/misc/zipfile.c
index a35a26f4d8e..f9fbcfc0bd7 100644
--- a/chromium/third_party/sqlite/src/ext/misc/zipfile.c
+++ b/chromium/third_party/sqlite/src/ext/misc/zipfile.c
@@ -523,14 +523,16 @@ static int zipfileAppendData(
const u8 *aWrite,
int nWrite
){
- size_t n;
- fseek(pTab->pWriteFd, (long)pTab->szCurrent, SEEK_SET);
- n = fwrite(aWrite, 1, nWrite, pTab->pWriteFd);
- if( (int)n!=nWrite ){
- pTab->base.zErrMsg = sqlite3_mprintf("error in fwrite()");
- return SQLITE_ERROR;
+ if( nWrite>0 ){
+ size_t n = nWrite;
+ fseek(pTab->pWriteFd, (long)pTab->szCurrent, SEEK_SET);
+ n = fwrite(aWrite, 1, nWrite, pTab->pWriteFd);
+ if( (int)n!=nWrite ){
+ pTab->base.zErrMsg = sqlite3_mprintf("error in fwrite()");
+ return SQLITE_ERROR;
+ }
+ pTab->szCurrent += nWrite;
}
- pTab->szCurrent += nWrite;
return SQLITE_OK;
}
diff --git a/chromium/third_party/sqlite/src/ext/rtree/geopoly.c b/chromium/third_party/sqlite/src/ext/rtree/geopoly.c
index 35294c8d858..b1cff38edfd 100644
--- a/chromium/third_party/sqlite/src/ext/rtree/geopoly.c
+++ b/chromium/third_party/sqlite/src/ext/rtree/geopoly.c
@@ -1075,7 +1075,7 @@ static int geopolyOverlap(GeoPoly *p1, GeoPoly *p2){
geopolyAddSegments(p, p1, 1);
geopolyAddSegments(p, p2, 2);
pThisEvent = geopolySortEventsByX(p->aEvent, p->nEvent);
- rX = pThisEvent->x==0.0 ? -1.0 : 0.0;
+ rX = pThisEvent && pThisEvent->x==0.0 ? -1.0 : 0.0;
memset(aOverlap, 0, sizeof(aOverlap));
while( pThisEvent ){
if( pThisEvent->x!=rX ){
diff --git a/chromium/third_party/sqlite/src/ext/rtree/rtree.c b/chromium/third_party/sqlite/src/ext/rtree/rtree.c
index df0f6c2e272..f5b57a5e231 100644
--- a/chromium/third_party/sqlite/src/ext/rtree/rtree.c
+++ b/chromium/third_party/sqlite/src/ext/rtree/rtree.c
@@ -759,7 +759,7 @@ static int nodeAcquire(
** are the leaves, and so on. If the depth as specified on the root node
** is greater than RTREE_MAX_DEPTH, the r-tree structure must be corrupt.
*/
- if( pNode && iNode==1 ){
+ if( pNode && rc==SQLITE_OK && iNode==1 ){
pRtree->iDepth = readInt16(pNode->zData);
if( pRtree->iDepth>RTREE_MAX_DEPTH ){
rc = SQLITE_CORRUPT_VTAB;
diff --git a/chromium/third_party/sqlite/src/ext/session/test_session.c b/chromium/third_party/sqlite/src/ext/session/test_session.c
index 1e76616cbbb..82f30979f51 100644
--- a/chromium/third_party/sqlite/src/ext/session/test_session.c
+++ b/chromium/third_party/sqlite/src/ext/session/test_session.c
@@ -227,7 +227,7 @@ static int SQLITE_TCLAPI test_session_cmd(
){
TestSession *p = (TestSession*)clientData;
sqlite3_session *pSession = p->pSession;
- struct SessionSubcmd {
+ static struct SessionSubcmd {
const char *zSub;
int nArg;
const char *zMsg;
@@ -1131,7 +1131,7 @@ static int SQLITE_TCLAPI test_rebaser_cmd(
int objc,
Tcl_Obj *CONST objv[]
){
- struct RebaseSubcmd {
+ static struct RebaseSubcmd {
const char *zSub;
int nArg;
const char *zMsg;
@@ -1248,7 +1248,7 @@ static int SQLITE_TCLAPI test_sqlite3session_config(
int objc,
Tcl_Obj *CONST objv[]
){
- struct ConfigOpt {
+ static struct ConfigOpt {
const char *zSub;
int op;
} aSub[] = {
diff --git a/chromium/third_party/sqlite/src/main.mk b/chromium/third_party/sqlite/src/main.mk
index 693887bd664..e47e85fdfbf 100644
--- a/chromium/third_party/sqlite/src/main.mk
+++ b/chromium/third_party/sqlite/src/main.mk
@@ -361,6 +361,7 @@ TESTSRC = \
TESTSRC += \
$(TOP)/ext/misc/amatch.c \
$(TOP)/ext/misc/carray.c \
+ $(TOP)/ext/misc/cksumvfs.c \
$(TOP)/ext/misc/closure.c \
$(TOP)/ext/misc/csv.c \
$(TOP)/ext/misc/decimal.c \
@@ -912,6 +913,7 @@ TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_STMTVTAB
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_DBPAGE_VTAB
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_BYTECODE_VTAB
TESTFIXTURE_FLAGS += -DTCLSH_INIT_PROC=sqlite3TestInit
+TESTFIXTURE_FLAGS += -DSQLITE_CKSUMVFS_STATIC
testfixture$(EXE): $(TESTSRC2) libsqlite3.a $(TESTSRC) $(TOP)/src/tclsqlite.c
$(TCCX) $(TCL_FLAGS) $(TESTFIXTURE_FLAGS) \
diff --git a/chromium/third_party/sqlite/src/manifest b/chromium/third_party/sqlite/src/manifest
index 9122e4aaf4e..6c9cbb5ed81 100644
--- a/chromium/third_party/sqlite/src/manifest
+++ b/chromium/third_party/sqlite/src/manifest
@@ -1,13 +1,13 @@
-C Version\s3.33.0
-D 2020-08-14T13:23:32.827
+C Version\s3.34.0
+D 2020-12-01T16:14:00.051
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
-F Makefile.in 19374a5db06c3199ec1bab71ab74a103d8abf21053c05e9389255dc58083f806
+F Makefile.in 0e88f5d095213a9ccd45c5bbd871c8ead498f886dff4493471fbf48b1f867f9d
F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241
-F Makefile.msc 48f5a3fc32672c09ad73795749f6253e406a31526935fbbffd8f021108d54574
+F Makefile.msc dd10dbf63b2f8ac3e2f0542963a21bc69058976ac4355165f212a31c83d17f44
F README.md 1514a365ffca3c138e00c5cc839906108a01011a6b082bad19b09781e3aa498a
-F VERSION 5db2ee2cfcc790af73775fa485c13b2e8ccaa5936c6e1f47aedeba7056041ca5
+F VERSION 4027b9aea92d64385570778ebd14388c0b23e92aafda15e7b89c45886c9b920a
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
@@ -28,19 +28,20 @@ F autoconf/tea/license.terms 13bd403c9610fd2b76ece0ab50c4c5eda933d523
F autoconf/tea/pkgIndex.tcl.in 3ef61715cf1c7bdcff56947ffadb26bc991ca39d
F autoconf/tea/tclconfig/install-sh bdd5e293591621ae60d9824d86a4b1c5f22c3d00
F autoconf/tea/tclconfig/tcl.m4 66ddf0a5d5e4b1d29bff472c0985fd7fa89d0fb5
-F autoconf/tea/win/makefile.vc 71915591c07cd5137711dc40ba3e127deb3f4531b9aad220b724cf5b451362bd
+F autoconf/tea/win/makefile.vc a5ff708245260c2794c6aaa0151efe5403d5896566eaf096747be0d9075284e4
F autoconf/tea/win/nmakehlp.c 247538ad8e8c508f33c03ec1fbd67d3a07ef6291
F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
F config.guess 883205ddf25b46f10c181818bf42c09da9888884af96f79e1719264345053bd6
F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc
F config.sub c2d0260f17f3e4bc0b6808fccf1b291cb5e9126c14fc5890efc77b9fd0175559
-F configure a97f98dfff699495aef66ae3d9c424345778a663f583e0d6e7522670518f87c1 x
-F configure.ac 40d01e89cb325c28b33f5957e61fede0bd17da2b5e37d9b223a90c8a318e88d4
+F configure e7df2824b6e60d482d919fb3e7d823faf08467093b096ad47a4fe2eec3f0ba99 x
+F configure.ac 73545c21eebcef9398d85c982c7be260f07708256778221b541f83ae8c6f61eb
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
-F doc/lemon.html 1edc0f916e771212792d4d077aedc05168bf13fd65d64d41b2c13e46ac0063a8
+F doc/lemon.html c5d8ba85ac1daef7be8c2d389899480eb62451ff5c09b0c28ff8157bb8770746
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
F doc/trusted-schema.md 33625008620e879c7bcfbbfa079587612c434fa094d338b08242288d358c3e8a
+F doc/vdbesort-memory.md 4da2639c14cd24a31e0af694b1a8dd37eaf277aff3867e9a8cc14046bc49df56
F doc/vfs-shm.txt e101f27ea02a8387ce46a05be2b1a902a021d37a
F doc/wal-lock.md 781726aaba20bafeceb7ba9f91d5c98c6731691b30c954e37cf0b49a053d461d
F ext/README.md fd5f78013b0a2bc6f0067afb19e6ad040e89a10179b4f6f03eee58fac5f169bd
@@ -49,8 +50,8 @@ F ext/async/sqlite3async.c 6f247666b495c477628dd19364d279c78ea48cd90c72d9f9b98ad
F ext/async/sqlite3async.h 46b47c79357b97ad85d20d2795942c0020dc20c532114a49808287f04aa5309a
F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3
F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4
-F ext/expert/expert1.test 2e10ff875c31c9e6fc5e324767624181273859771fe34c5daeeadf3f2974a4f7
-F ext/expert/sqlite3expert.c b5eae75862d34a204d16c45dcb813888b5f86bdc156c6136b0f79094c0da4f79
+F ext/expert/expert1.test dba6e752cc701621771f925f3872b183fa688f7b4a9f4822631fc02bdbffc45a
+F ext/expert/sqlite3expert.c 2778d9f06b3a8bfa859cb6b75b82f004477bf5dd78edd17d954319750ca963f3
F ext/expert/sqlite3expert.h ca81efc2679a92373a13a3e76a6138d0310e32be53d6c3bfaedabd158ea8969b
F ext/expert/test_expert.c d56c194b769bdc90cf829a14c9ecbc1edca9c850b837a4d0b13be14095c32a72
F ext/fts1/README.txt 20ac73b006a70bcfd80069bdaf59214b6cf1db5e
@@ -108,24 +109,24 @@ F ext/fts3/tool/fts3cov.sh c331d006359456cf6f8f953e37f2b9c7d568f3863f00bb5f7eb87
F ext/fts3/tool/fts3view.c 413c346399159df81f86c4928b7c4a455caab73bfbc8cd68f950f632e5751674
F ext/fts3/unicode/CaseFolding.txt 8c678ca52ecc95e16bc7afc2dbf6fc9ffa05db8c
F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7
-F ext/fts3/unicode/mkunicode.tcl bf7fcaa6d68e6d38223467983785d054f1cff4d9e3905dd51f6ed8801bb590d5
+F ext/fts3/unicode/mkunicode.tcl d5aebf022fa4577ee8cdf27468f0d847879993959101f6dbd6348ef0cfc324a7
F ext/fts3/unicode/parseunicode.tcl a981bd6466d12dd17967515801c3ff23f74a281be1a03cf1e6f52a6959fc77eb
F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0
F ext/fts5/fts5.h c132a9323f22a972c4c93a8d5a3d901113a6e612faf30ca8e695788438c5ca2a
-F ext/fts5/fts5Int.h d7cbc214ee167496f70905667e18f73ea0402f7ef09236ce305e117e0efc866a
-F ext/fts5/fts5_aux.c dcc627d8b6e3fc773db528ff67b39955dab7b51628f9dba8e15849e5bedfd7fa
+F ext/fts5/fts5Int.h 26c74dd5776f798436fbf604a0bf0e8de263b35b5060b05c15f9085845d9fda2
+F ext/fts5/fts5_aux.c f558e1fb9f0f86a4f7489e258c162e1f947de5ff2709087fbb465fddb7092f98
F ext/fts5/fts5_buffer.c 5a5fe0159752c0fb0a5a93c722e9db2662822709490769d482b76a6dc8aaca70
-F ext/fts5/fts5_config.c b447948f35ad3354e8fe5e242e0a7e7b5b941555400b9404259944e3aa570037
-F ext/fts5/fts5_expr.c 2be456484786333d559dc2987a00f2750981fab91d52db8452a8046278c5f22e
-F ext/fts5/fts5_hash.c 1cc0095646f5f3b46721aa112fb4f9bf29ae175cb5338f89dcec66ed97acfe75
-F ext/fts5/fts5_index.c de14c9a30f45e2b847ff9284b14776d9d07961e545e8f1546a6aa3f915af721f
-F ext/fts5/fts5_main.c e881a2ea0bf01b3a3ff0bc1b31373c58fd54b6c9f3c43ea3d431bea4e5d4025e
-F ext/fts5/fts5_storage.c 3ecda8edadc1f62a355d6789776be0da609f8658c50d72e422674093ab7e1528
+F ext/fts5/fts5_config.c be54f44fca491e96c6923a4b9a736f2da2b13811600eb6e38d1bcc91c4ea2e61
+F ext/fts5/fts5_expr.c e527e3a7410393075598cec544e3831798a8c88b3e8878e2cfb7cb147113e925
+F ext/fts5/fts5_hash.c 1aa93c9b5f461afba66701ee226297dc78402b3bdde81e90a10de5fe3df14959
+F ext/fts5/fts5_index.c 9f152a596df3a2227ddd59adb82549c2b6858ab36bc1d26fd8933f43d3d63d36
+F ext/fts5/fts5_main.c b4e4931c7fcc9acfa0c3b8b5e5e80b5b424b8d9207aae3a22b674bd35ccf149d
+F ext/fts5/fts5_storage.c 58ba71e6cd3d43a5735815e7956ee167babb4d2cbfe206905174792af4d09d75
F ext/fts5/fts5_tcl.c 39bcbae507f594aad778172fa914cad0f585bf92fd3b078c686e249282db0d95
F ext/fts5/fts5_test_mi.c 08c11ec968148d4cb4119d96d819f8c1f329812c568bac3684f5464be177d3ee
F ext/fts5/fts5_test_tok.c f96c6e193c466711d6d7828d5f190407fe7ab897062d371426dd3036f01258e7
-F ext/fts5/fts5_tokenize.c 2e508c6a3bd8ee56c48e98a38052e1a650e49b32a484cce9b189984114bc3b88
-F ext/fts5/fts5_unicode2.c 8bd0cd07396b74c1a05590e4070d635bccfc849812c305619f109e6c0485e250
+F ext/fts5/fts5_tokenize.c 5e251efb0f1af99a25ed50010ba6b1ad1250aca5921af1988fdcabe5ebc3cb43
+F ext/fts5/fts5_unicode2.c eca63dbc797f8ff0572e97caf4631389c0ab900d6364861b915bdd4735973f00
F ext/fts5/fts5_varint.c e64d2113f6e1bfee0032972cffc1207b77af63319746951bf1d09885d1dadf80
F ext/fts5/fts5_vocab.c 7a071833064dc8bca236c3c323e56aac36f583aa2c46ce916d52e31ce87462c9
F ext/fts5/fts5parse.y eb526940f892ade5693f22ffd6c4f2702543a9059942772526eac1fde256bb05
@@ -151,7 +152,7 @@ F ext/fts5/test/fts5bigpl.test 6466c89b38439f0aba26ac09e232a6b963f29b1cbe1304f6a
F ext/fts5/test/fts5bigtok.test 541119e616c637caea925a8c028c37c2c29e94383e00aa2f9198d530724b6e36
F ext/fts5/test/fts5cat.test daba0b80659460b0cb60bd1f40b402478a761fe7ea414c3c94c2be25568cc33a
F ext/fts5/test/fts5circref.test f880dfd0d99f6fb73b88ccacb0927d18e833672fd906cc47d6b4e529419eaa62
-F ext/fts5/test/fts5colset.test a30473451321bbf0b6218af62e96b4ae5fa99931cfdb210b5ecc804623b30f75
+F ext/fts5/test/fts5colset.test 7031ce84fb4d312df5a99fc4e7b324e660ccb513c97eccdef469bfd52d3d0f8f
F ext/fts5/test/fts5columnsize.test 45459ce4dd9fd853b6044cdc9674921bff89e3d840f348ca8c1630f9edbf5482
F ext/fts5/test/fts5config.test 60094712debc59286c59aef0e6cf511c37d866802776a825ce437d26afe0817f
F ext/fts5/test/fts5conflict.test 655925678e630d3cdf145d18725a558971806416f453ac8410ca8c04d934238d
@@ -159,9 +160,9 @@ F ext/fts5/test/fts5connect.test 08030168fc96fc278fa81f28654fb7e90566f33aff269c0
F ext/fts5/test/fts5content.test 213506436fb2c87567b8e31f6d43ab30aab99354cec74ed679f22aad0cdbf283
F ext/fts5/test/fts5corrupt.test 77ae6f41a7eba10620efb921cf7dbe218b0ef232b04519deb43581cb17a57ebe
F ext/fts5/test/fts5corrupt2.test 7453752ba12ce91690c469a6449d412561cc604b1dec994e16ab132952e7805f
-F ext/fts5/test/fts5corrupt3.test 7afe0fea5b2160798fdc3306395048768c6fc13acefc0e7129d4075b6e1bb224
+F ext/fts5/test/fts5corrupt3.test dd5435659d5363fc3b3ac32175e2fc793fdc17980b47e3d598695d867eaa77a2
F ext/fts5/test/fts5corrupt4.test ea805c4d7c68b5f185b9db5d2060a7ae5875339738dd48203c92162f41e7ca91
-F ext/fts5/test/fts5delete.test cbf87e3b8867c4d5cfcaed975c7475fd3f99d072bce2075fcedf43d1f82af775
+F ext/fts5/test/fts5delete.test 4a15fb03b6c7eac62ac807a3a32b7f0dc74f0d479c410e3e3568ae96b9469290
F ext/fts5/test/fts5detail.test 31b240dbf6d44ac3507e2f8b65f29fdc12465ffd531212378c7ce1066766f54e
F ext/fts5/test/fts5determin.test 1b77879b2ae818b5b71c859e534ee334dac088b7cf3ff3bf76a2c82b1c788d11
F ext/fts5/test/fts5dlidx.test b90852c55881b29dbac6380b274de27beae623ac4b6d567c6c8fb9cdc315a86e
@@ -179,12 +180,13 @@ F ext/fts5/test/fts5fault8.test 318238659d35f82ad215ecb57ca4c87486ea85d45dbeedae
F ext/fts5/test/fts5fault9.test 098e6b894bbdf9b2192f994a30f4043673fb3f338b6b8ab1624c704422f39119
F ext/fts5/test/fts5faultA.test be4487576bff8c22cee6597d1893b312f306504a8c6ccd3c53ca85af12290c8c
F ext/fts5/test/fts5faultB.test d606bdb8e81aaeb6f41de3fc9fc7ae315733f0903fbff05cf54f5b045b729ab5
-F ext/fts5/test/fts5faultD.test cc5d1225556e356615e719c612e845d41bff7d5a
+F ext/fts5/test/fts5faultD.test e7ed7895abfe6bc98a5e853826f6b74956e7ba7f594f1860bbf9e504b9647996
+F ext/fts5/test/fts5faultE.test 844586ce71dab4be85bb86880e87b624d089f851654cd22e4710c77eb8ce7075
F ext/fts5/test/fts5first.test 3fcf2365c00a15fc9704233674789a3b95131d12de18a9b996159f6909dc8079
F ext/fts5/test/fts5full.test e1701a112354e0ff9a1fdffb0c940c576530c33732ee20ac5e8361777070d717
F ext/fts5/test/fts5fuzz1.test 238d8c45f3b81342aa384de3e581ff2fa330bf922a7b69e484bbc06051a1080e
-F ext/fts5/test/fts5hash.test a4cf51acad99bfc43c16fb74f9d22495dc221ae0701fc5e908ca963a9b26a02b
-F ext/fts5/test/fts5integrity.test 8ffabcd91b058d812aba3e3e0a06f76ce165ba402a18cca20e34204a7feec92e
+F ext/fts5/test/fts5hash.test dc7bc7e0cdeb42cfce31294ad2f8fcf43192bfd0145bb7f3ecc5465d8c72696f
+F ext/fts5/test/fts5integrity.test e387b2bd1c83e50f4a12f58a5fd399111bbab36be2f1c9fd5bb974be08a32de6
F ext/fts5/test/fts5interrupt.test 09613247b273a99889808ef852898177e671406fe71fdde7ea00e78ea283d227
F ext/fts5/test/fts5lastrowid.test be98fe3e03235296585b72daad7aed5717ba0062bae5e5c18dd6e04e194c6b28
F ext/fts5/test/fts5leftjoin.test c0b4cafb9661379e576dc4405c0891d8fcc2782680740513c4d1fc114b43d4ad
@@ -198,7 +200,7 @@ F ext/fts5/test/fts5near.test 211477940142d733ac04fad97cb24095513ab2507073a99c27
F ext/fts5/test/fts5onepass.test f9b7d9b2c334900c6542a869760290e2ab5382af8fbd618834bf1fcc3e7b84da
F ext/fts5/test/fts5optimize.test 36a752d24c818792032e4ff502936fc9cc5ef938721696396fdc79214b2717f1
F ext/fts5/test/fts5phrase.test 13e5d8e9083077b3d9c74315b3c92ec723cc6eb37c8155e0bfe1bba00559f07b
-F ext/fts5/test/fts5plan.test 771b999d161e24fd803ce0290adb7c6e7c9b9cc2c6a0adb344813fb89473aa32
+F ext/fts5/test/fts5plan.test 79d35b5e83bbdcba48d946a7f008df161f6b0ede1a966892d0aa6c8dd0b6e773
F ext/fts5/test/fts5porter.test 8d08010c28527db66bc3feebd2b8767504aaeb9b101a986342fa7833d49d0d15
F ext/fts5/test/fts5porter2.test 0d251a673f02fa13ca7f011654873b3add20745f7402f108600a23e52d8c7457
F ext/fts5/test/fts5prefix.test a0fa67b06650f2deaa7bf27745899d94e0fb547ad9ecbd08bfad98c04912c056
@@ -213,9 +215,10 @@ F ext/fts5/test/fts5simple2.test 258a1b0c590409bfa5271e872c79572b319d2a56554d058
F ext/fts5/test/fts5simple3.test d5c74a9d3ca71bd5dd5cacb7c55b86ea12cdddfc8b1910e3de2995206898380f
F ext/fts5/test/fts5synonym.test 1651815b8008de170e8e600dcacc17521d765482ea8f074ae82cfa870d8bb7fb
F ext/fts5/test/fts5synonym2.test b54cce5c34ec08ed616f646635538ae82e34a0e28f947ec60b6fadbc4b3fb17a
-F ext/fts5/test/fts5tok1.test ce6551e41ff56f30b69963577324624733bed0d1753589f06120d664d9cd45c9
+F ext/fts5/test/fts5tok1.test 1f7817499f5971450d8c4a652114b3d833393c8134e32422d0af27884ffe9cef
F ext/fts5/test/fts5tok2.test dcacb32d4a2a3f0dd3215d4a3987f78ae4be21a2
F ext/fts5/test/fts5tokenizer.test ac3c9112b263a639fb0508ae73a3ee886bf4866d2153771a8e8a20c721305a43
+F ext/fts5/test/fts5trigram.test e2ce256fd0ccd6707e740aa3596206aedb0d5834b100c0cb49e344dcd1d8463c
F ext/fts5/test/fts5umlaut.test a42fe2fe6387c40c49ab27ccbd070e1ae38e07f38d05926482cc0bccac9ad602
F ext/fts5/test/fts5unicode.test 17056f4efe6b0a5d4f41fdf7a7dc9af2873004562eaa899d40633b93dc95f5a9
F ext/fts5/test/fts5unicode2.test 9b3df486de05fb4bde4aa7ee8de2e6dae1df6eb90e3f2e242c9383b95d314e3e
@@ -227,7 +230,7 @@ F ext/fts5/test/fts5version.test c8f2cc105f0abf0224965f93e584633dee3e06c91478bc6
F ext/fts5/test/fts5vocab.test 7ed80d9af1ddaaa1637da05e406327b5aac250848bc604c1c1cc667908b87760
F ext/fts5/test/fts5vocab2.test e0fdc3a3095f6eda68ac9bf9a443ff929a124d46f00af19933604085712e9d47
F ext/fts5/tool/fts5speed.tcl b0056f91a55b2d1a3684ec05729de92b042e2f85
-F ext/fts5/tool/fts5txt2db.tcl 526a9979c963f1c54fd50976a05a502e533a4c59
+F ext/fts5/tool/fts5txt2db.tcl c0d43c8590656f8240e622b00957b3a0facc49482411a9fdc2870b45c0c82f9f
F ext/fts5/tool/loadfts5.tcl 95b03429ee6b138645703c6ca192c3ac96eaf093
F ext/fts5/tool/mkfts5c.tcl d1c2a9ab8e0ec690a52316f33dd9b1d379942f45
F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c
@@ -285,12 +288,13 @@ F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a2
F ext/misc/appendvfs.c 55121d311d408ba9c62c3cfa367408887638f02f9522dd9859891d0ee69a7eba
F ext/misc/blobio.c a867c4c4617f6ec223a307ebfe0eabb45e0992f74dd47722b96f3e631c0edb2a
F ext/misc/btreeinfo.c d28ce349b40054eaa9473e835837bad7a71deec33ba13e39f963d50933bfa0f9
-F ext/misc/carray.c 91e9a7f512fda934894bed30464552fffa7d3073b5be04189ae0bd0c59f26bfd
-F ext/misc/cksumvfs.c 0f022867786b615d7f68fb3ab3a16627fe6a730442abf804735e18a73f835a83
+F ext/misc/carray.c b75a0f207391038bf1540d3372f482a95c3613511c7c474db51ede1196321c7c
+F ext/misc/carray.h de74ac70b2338f416723f7d538026e8ec0b7f1d388319f8f140c9a4d7677f02e
+F ext/misc/cksumvfs.c c4e7ebeae5aa578df98f23bddb63ecbcbe913ee3c32b8b769525af100d752061
F ext/misc/closure.c dbfd8543b2a017ae6b1a5843986b22ddf99ff126ec9634a2f4047cd14c85c243
F ext/misc/completion.c 6dafd7f4348eecc7be9e920d4b419d1fb2af75d938cd9c59a20cfe8beb2f22b9
F ext/misc/compress.c 3354c77a7c8e86e07d849916000cdac451ed96500bfb5bd83b20eb61eee012c9
-F ext/misc/csv.c 3ed979c1eb35e35a98b30ef545a2facf62994594217681d9138b4b75faf6b0d7
+F ext/misc/csv.c 53b3338d4fa812eda51a2637df30233a4dae16b964ee5666e2051b9672ed8bb4
F ext/misc/dbdata.c e316fba936571584e55abd5b974a32a191727a6b746053a0c9d439bd2cf93940
F ext/misc/dbdump.c b8592f6f2da292c62991a13864a60d6c573c47a9cc58362131b9e6a64f823e01
F ext/misc/decimal.c 3ddbf8162015be4d5ec2395dee4538f1e638bb517174bb148274b132df6e1d08
@@ -314,7 +318,7 @@ F ext/misc/regexp.c 246244c714267f303df76acf73dcf110cf2eaf076896aaaba8db6d6d21a1
F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c
F ext/misc/scrub.c 2a44b0d44c69584c0580ad2553f6290a307a49df4668941d2812135bfb96a946
-F ext/misc/series.c 4057dda3579b38ff88b2d3b13b4dd92dbd9d6f90dac2b55c19b0a8ed87ee4959
+F ext/misc/series.c fbb8e6be97b54d10d2f235e163fa2f53a8f4421c66ebd532a233fd1c69c3f522
F ext/misc/sha1.c c8f2253c8792ffab9517695ea7d88c079f0395a5505eefef5c8198fe184ed5ac
F ext/misc/shathree.c 135b7c145db4a09b1650c3e7aff9cb538763a9a361e834c015dd1aaf8d5c9a00
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
@@ -332,7 +336,7 @@ F ext/misc/vfsstat.c 389ea13983d3af926504c314f06a83cc858d5adc24b40af74aaed1fece0
F ext/misc/vtablog.c 5538acd0c8ddaae372331bee11608d76973436b77d6a91e8635cfc9432fba5ae
F ext/misc/vtshim.c 1976e6dd68dd0d64508c91a6dfab8e75f8aaf6cd
F ext/misc/wholenumber.c 520f34c3099e5b7d546f13708607dc2fa173c46b68952eecf0d19cd675fec85e
-F ext/misc/zipfile.c d1be54ea83ac9ad71b8b6ffc4b60db8946ce2ceacdf6bff063fcd9489f41bb49
+F ext/misc/zipfile.c e35e035bc2765b1ccdcb15f9815c2112843fcbc8f36aa071f0e5935df7072228
F ext/misc/zorder.c b0ff58fa643afa1d846786d51ea8d5c4b6b35aa0254ab5a82617db92f3adda64
F ext/rbu/rbu.c 8681f6157db6adc82c34af24b14ea8a3be0146ad2a3b6c1d5da6cb8a5796c8ce
F ext/rbu/rbu1.test 221d9c18a5e600ac9ac6b1810d99d9f99163a7909ba61597876ab6e4d4beb3d6
@@ -387,8 +391,8 @@ F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc782
F ext/repair/test/checkindex01.test b530f141413b587c9eb78ff734de6bb79bc3515c335096108c12c01bddbadcec
F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
-F ext/rtree/geopoly.c f15cc6845d64a629035627d863cbe3eadc9cb30f9ca77bd823b0ca8a5a3f8b00
-F ext/rtree/rtree.c f87ffcc91f49272862119cfdd256b02514351893786a710d88f85933790608d4
+F ext/rtree/geopoly.c 1b1ddecb79877b12331d35de9f393b80bbb731e0bf6db6c572f23191987ea803
+F ext/rtree/rtree.c 60f6f1675134201974be4189dbd219494c13e1ed30e80bd92ae0dcc86df1b035
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
F ext/rtree/rtree1.test 00792b030a4e188ff1b22e8530e8aa0452bb5dd81c2b18cb004afc7dc63e040e
F ext/rtree/rtree2.test 9d9deddbb16fd0c30c36e6b4fdc3ee3132d765567f0f9432ee71e1303d32603d
@@ -450,14 +454,14 @@ F ext/session/sessionstat1.test 218d351cf9fcd6648f125a26b607b140310160184723c266
F ext/session/sessionwor.test 67b5ab91d4f93ce65ff1f58240ac5ddf73f8670facc1ffa49cef56293d52818d
F ext/session/sqlite3session.c 2c76b8c3a5d6dab736686f8a48833b8bdac0871ecc6f447f9839d28bd4a63d6c
F ext/session/sqlite3session.h a2db5b72b938d12c727b4b4ec632254ca493670a9c0de597af3271a7f774fc57
-F ext/session/test_session.c 98797aba475a799376c9a42214f2d1debf2d0c3cb657d9c8bbf4f70bf3fb4aec
+F ext/session/test_session.c 24286d958dc6f4ca4d7e710f09bc0fa9d50956a40dd99fd8223e7488024c71fe
F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
-F main.mk b1cd0bc6aedad7ebb667b7f74f835f932f60ee33be2a5c3051fd93eb465f5c75
+F main.mk 57451ea5b3d5cd86e9c5324b10c9de184b12e8dcccc31c65d24fbcb55ccd9c53
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -469,44 +473,44 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
-F src/alter.c 805de23ddca536181f8f0439df989fdd4a2f76c40bc305ec9fe2f211f68c89e8
-F src/analyze.c 5cffff3d355858cd22bfc6e20ac7203510d2e1cc935086eb06f4abb2f579f628
-F src/attach.c 0b11e00c166b622c84ec176773b1d691c61ad07d247809e3e1635d4e99e71d30
+F src/alter.c b6de60d59419e34f5b48ff2b21fe0f9bb66fc714e5545a6ac790ac7a0c46548c
+F src/analyze.c 01c6c6765cb4d40b473b71d85535093730770bb186f2f473abac25f07fcdee5c
+F src/attach.c 0f497c15c4cfe3bdcb214f0dbdbbb6c5ed7e8a9308ac445c7959f5e5780437a9
F src/auth.c a3d5bfdba83d25abed1013a8c7a5f204e2e29b0c25242a56bc02bb0c07bf1e06
-F src/backup.c b1c90cd4110248c8e1273ff4578d3a84c0c34725e1b96dacd4a6294a908702de
+F src/backup.c 3014889fa06e20e6adfa0d07b60097eec1f6e5b06671625f476a714d2356513d
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
-F src/btree.c 1439fd9b45d4d1883c53752daef42af489adaa1a1508fa39dedbc9c80ea21a2f
-F src/btree.h 7af72bbb4863c331c8f6753277ab40ee67d2a2125a63256d5c25489722ec162b
-F src/btreeInt.h 83166f6daeb91062b6ae9ee6247b3ad07e40eba58f3c05ba9e8dedad4ab1ea38
-F src/build.c dbdaee54ffef924a070eb6202017e10d6be56baab953ef0a8e714a6def683198
+F src/btree.c ee14224322b9e4172d01e691e2f289f6c630ae39b7906f84b72dc780b9e42a76
+F src/btree.h dcdff4037d75b3f032a5de0d922fcfaf35d48589417f634fa8627362709315f9
+F src/btreeInt.h ffd66480520d9d70222171b3a026d78b80833b5cea49c89867949f3e023d5f43
+F src/build.c f6449d4e85e998e14d3f537e8ea898dca2fcb83c277db3e60945af9b9177db81
F src/callback.c d0b853dd413255d2e337b34545e54d888ea02f20da5ad0e63585b389624c4a6c
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c e98518d2d3d4029a13c805e07313fb60c877be56db76e90dd5f3af73085d0ce6
F src/date.c dace306a10d9b02ee553d454c8e1cf8d3c9b932e137738a6b15b90253a9bfc10
F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a
F src/dbstat.c 3aa79fc3aed7ce906e4ea6c10e85d657299e304f6049861fe300053ac57de36c
-F src/delete.c 410c771c25afc113c273d9efad6ab6881bda28c75a1838b9d2c52ba20d1dc704
-F src/expr.c 58c06940d964c2cf455b979cf66a648499d294a5ee6dadcaeaed447257c1dc75
+F src/delete.c 927cf8f900583e79aca8f1a321979e0a8f053babd9a690b44b38f79de2cc09fe
+F src/expr.c 0d196ed5a2ebf96be7e8df88add4fabfad0dce16c0fed81a4b8f6a26e259797f
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 83372403298e6a7dd989a47aaacdbaa5b4307b5199dbd56e07d4896066b3de72
-F src/func.c 2333eb4277f55a5efdc12ef754e7d7ec9105d257b2fd00301d23ce1e8fa67dc0
+F src/func.c 574f7e5a67e4b7a7855cf3478037717c8f44686c0cd727e1d7f7773414165c03
F src/global.c 943256ac44f333039d35a9830c18d075a81fa6b6bf2af05771494a9acfb9a40b
F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19
F src/hash.h 9d56a9079d523b648774c1784b74b89bd93fac7b365210157482e4319a468f38
F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
-F src/insert.c 957254a2d0542597455d0d4c640e4e3f3eea8c6d78f04582df03dfc626f07925
+F src/insert.c 7e081d33aab4a9d761c39dccf3c3872c35501565d2ed9db66301918d23bc7901
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
-F src/loadext.c 436af4968c6954d304fce9efa12719367bd8f37b19b93b71d6ad607e85adbb47
-F src/main.c 09580279145f27f3db206ef44dcb3a8875a42644230f79c7e54aff35e71668f0
-F src/malloc.c 22d5bdd9fe88ae4fad1b91a1b9735104b82853ffef868f1f05517d60dc1875f5
+F src/loadext.c 8c9c8cd2bd8eecdb06d9b6e89de7e9e65bae45cc8fc33609cc74023a5c296067
+F src/main.c 54d61d1e94f225636053c862c930d7dd7b29162b93d3f3ecb00439910ccba02a
+F src/malloc.c c1af4ac5a463648cd2953fd4ac679b3ba9022ce5ec794a60806150ad69dfd33a
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
F src/mem2.c b93b8762ab999a29ae7751532dadf0a1ac78040308a5fb1d17fcc365171d67eb
F src/mem3.c 30301196cace2a085cbedee1326a49f4b26deff0af68774ca82c1f7c06fda4f6
F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944
-F src/memdb.c d58e398e315e88f95f8d07d17e80ab11259ebd6d1a10397434329eeabd1985e3
+F src/memdb.c ab0632d42407e866d2b616bd19d4211ac0ad1b430f04c4e187d60005b8700b98
F src/memjournal.c 90b2ca7e2f465d57c16b69d15a9f3e3294af61088eb4938f2f7664d5ac50f813
F src/msvc.h 3a15918220367a8876be3fa4f2abe423a861491e84b864fb2b7426bf022a28f8
F src/mutex.c 5e3409715552348732e97b9194abe92fdfcd934cfb681df4ba0ab87ac6c18d25
@@ -519,38 +523,38 @@ F src/os.c 80e4cf3e5da06be03ca641661e331ce60eeeeabf0d7354dbb1c0e166d0eedbbe
F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
-F src/os_unix.c 9b1b860163fd2d4d7679b5260d384d1a9f88ef917a90f28963eca8acd472d8c8
-F src/os_win.c a2149ff0a85c1c3f9cc102a46c673ce87e992396ba3411bfb53db66813b32f1d
+F src/os_unix.c adbbcea4c63d3b400d405f60a5da4c01433753ec4a12e2dc695beb2bbd671fe9
+F src/os_win.c 77d39873836f1831a9b0b91894fec45ab0e9ca8e067dc8c549e1d1eca1566fe9
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
-F src/pager.c 3700a1c55427a3d4168ad1f1b8a8b0cb9ace1d107e4506e30a8f1e66d8a1195e
+F src/pager.c c49952ac5e9cc536778eff528091d79d38b3e45cbeeed4695dc05e207dc6547d
F src/pager.h 4bf9b3213a4b2bebbced5eaa8b219cf25d4a82f385d093cd64b7e93e5285f66f
-F src/parse.y 5bdb760a29c0b25caf7e80e82210b81cd2ea3066d5199ca29e6eac40b34bc184
+F src/parse.y 9ce4dfb772608ed5bd3c32f33e943e021e3b06cfd2c01932d4280888fdd2ebed
F src/pcache.c 385ff064bca69789d199a98e2169445dc16e4291fa807babd61d4890c3b34177
F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
F src/pcache1.c 6596e10baf3d8f84cc1585d226cf1ab26564a5f5caf85a15757a281ff977d51a
-F src/pragma.c bdb600be936f66b9fe69d26dfbba4528beaaf4f95c479c85b328a92484e0bf71
+F src/pragma.c 6daaaecc26a4b09481d21722525b079ce756751a43a79cc1d8f122d686806193
F src/pragma.h 8dc78ab7e9ec6ce3ded8332810a2066f1ef6267e2e03cd7356ee00276125c6cf
-F src/prepare.c 3d5a761d026052bc888d1b803a06dd2bfe245e8e836d4689f927003549148b0f
-F src/printf.c 9efcd4e984f22bcccb1ded37a1178cac98f6e3a0534e1e0629f64899971f8838
+F src/prepare.c 270170a239c0f66bd3c228f373afe24447c2614a6829ae22080babc64f241931
+F src/printf.c 30e92b638fac71dcd85cdea1d12ecfae354c9adee2c71e8e1ae4727cde7c91ed
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
-F src/resolve.c d74715aceed2a8f493ba244d535646fa93132042a4400a29dfd26ec841514048
+F src/resolve.c 1948a92ca9eab776632816b97e57c61d933474a78aad4f4ef835c916a83dbb1c
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
-F src/select.c 510fdf819f218be3dac2683d3eaaf64e5080f548061a4dd12205590beda976bb
-F src/shell.c.in b9b819feede7b85585ab0826490a352e04e2ee46e8132c92597d29972b2be1d7
-F src/sqlite.h.in d2c03414a8ee5d4a6855c04dd7cd5998e45139b0fe66b65bae86d4223edd091f
+F src/select.c 847062694ac9a6add162d39182584b7ca53948ad821c52512a125cd845904e71
+F src/shell.c.in 55113760ae91a05c6ce4558714a1c8fc7a44bf266f735de6e71ea40f79e69830
+F src/sqlite.h.in 1dbae67057d999161c30b21c3c7fa45d51f665b510d397dd1b7d671287d772b0
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
-F src/sqlite3ext.h 2d1af80082edffd71c6f96f70ad1ce6a4fb46615ad10291fc77fe0dea9ff0197
-F src/sqliteInt.h a1aa5457ca881cbf5adb55933bf81d7d4889375afb9a0a5df382a451c058087d
-F src/sqliteLimit.h 95cb8479ca459496d9c1c6a9f76b38aee12203a56ce1092fe13e50ae2454c032
+F src/sqlite3ext.h 61b38c073d5e1e96a3d45271b257aef27d0d13da2bea5347692ae579475cd95e
+F src/sqliteInt.h c01115c8dd967f7d334a98ba37ac821eafb04144c8085a795daaf2185743d27a
+F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
F src/tclsqlite.c 986b6391f02cd9b53c1d688be55899f6ffddeb8e8014cd83c1b73ff912579a71
-F src/test1.c 24b9cd0863ecc4d3920f4999c40e876c2bd92f3cc5879c48b99abe02c546ed18
+F src/test1.c 465b7a35b7e231bf2833e47c1371b5dfc99bd803ebe73783862399d479d696a5
F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
F src/test4.c 7c4420e01c577b5c4add2cb03119743b1a357543d347773b9e717195ea967159
F src/test5.c 328aae2c010c57a9829d255dc099d6899311672d
-F src/test6.c e8d839fbc552ce044bec8234561a2d5b8819b48e29548ad0ba400471697946a8
+F src/test6.c ae73a3a42bbc982fb9e301b84d30bda65a307be48c6dff20aba1461e17a9b0ce
F src/test7.c 5612e9aecf934d6df7bba6ce861fdf5ba5456010
F src/test8.c 7fb971777c2c79c734bb52757191d68d4af659b8de9b4a071be3f527a9d19a02
F src/test9.c 12e5ba554d2d1cbe0158f6ab3f7ffcd7a86ee4e5
@@ -563,10 +567,10 @@ F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274
F src/test_config.c 5ea19bf0972a9d91728518b4d30e91477acce80496003ecbef3a7fb18d0bd081
F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f
F src/test_demovfs.c 86142ba864d4297d54c5b2e972e74f3141ae4b30f05b3a95824184ed2d3d7f91
-F src/test_devsym.c 6109b45c3db3ef7b002320947ed448c027356ab8b885156ff535fd8684d4a571
+F src/test_devsym.c aff2255ea290d7718da08af30cdf18e470ff7325a5eff63e0057b1496ed66593
F src/test_fs.c ba1e1dc18fd3159fdba0b9c4256f14032159785320dfbd6776eb9973cb75d480
F src/test_func.c 181f992e5495644434c4f0e3cc72362a78c295eb2cf3ff4d02498b8bde7aa276
-F src/test_hexio.c d170d0e1a6431afdeac086a250d2595078288c2257615d37949355361399bcaa
+F src/test_hexio.c 9478e56a0f08e07841a014a93b20e4ba2709ab56d039d1ca8020e26846aa19bd
F src/test_init.c 4413c211a94b62157ca4c145b3f27c497f03c664
F src/test_intarray.c 39b4181662a0f33a427748d87218e7578d913e683dc27eab7098bb41617cac71
F src/test_intarray.h d57ae92f420cda25e22790dac474d60961bd0c500cbaa3338a05152d4a669ef7
@@ -592,7 +596,7 @@ F src/test_tclsh.c eeafce33ad2136d57e5dec10f1e9a4347447eb72ffd504a1c7b9c6bfe2e71
F src/test_tclvar.c 33ff42149494a39c5fbb0df3d25d6fafb2f668888e41c0688d07273dcb268dfc
F src/test_thread.c 269ea9e1fa5828dba550eb26f619aa18aedbc29fd92f8a5f6b93521fbb74a61c
F src/test_vdbecov.c f60c6f135ec42c0de013a1d5136777aa328a776d33277f92abac648930453d43
-F src/test_vfs.c 36822d696789535bdd0260f07d2c9a46546082fea8bb1d0a7354c7f9366e37ea
+F src/test_vfs.c 2cc38a79892017702d13da79ad5152c196eec19bbd67fbde4d88065aac894a84
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
F src/test_windirent.c a895e2c068a06644eef91a7f0a32182445a893b9a0f33d0cdb4283dca2486ac1
F src/test_windirent.h 90dfbe95442c9762357fe128dc7ae3dc199d006de93eb33ba3972e0a90484215
@@ -601,20 +605,20 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c 4dc01b267593537e2a0d0efe9f80dabe24c5b6f7627bc6971c487fa6a1dacbbf
F src/treeview.c 4b92992176fb2caefbe06ba5bd06e0e0ebcde3d5564758da672631f17aa51cda
-F src/trigger.c ef67bde309a831515dc3c2173d792574309f2f42d45f8c078743fae9f7f98c75
-F src/update.c fb15bec5b54fd098f4b84f6abc83c7103b45ba8484011fff8edf5ae31656eab6
+F src/trigger.c 515e79206d40d1d4149129318582e79a6e9db590a7b74e226fdb5b2a6c7e1b10
+F src/update.c 9f126204a6acb96bbe47391ae48e0fc579105d8e76a6d9c4fab3271367476580
F src/upsert.c 2920de71b20f04fe25eb00b655d086f0ba60ea133c59d7fa3325c49838818e78
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
-F src/util.c c8bf30c4356b091bcc3b624d0e24b2b4d11b8be4d6c90d8e0705971e15cc819b
-F src/vacuum.c 1c4f8e2f39d950037f4cf946b6858c993d3a54c3101f78e05c76460a073afcf0
-F src/vdbe.c e9f7f818f128c8600058c0eabb6b3975974c95153a104d340f419adabbc15b9f
+F src/util.c c0c7977de7ef9b8cb10f6c85f2d0557889a658f817b0455909a49179ba4c8002
+F src/vacuum.c 492422c1463c076473bae1858799c7a0a5fe87a133d1223239447c422cd26286
+F src/vdbe.c d24a43b6b1ed2dba893636a14f5e56001444ab3fd5465e3bca8ab01799840acd
F src/vdbe.h 83603854bfa5851af601fc0947671eb260f4363e62e960e8a994fb9bbcd2aaa1
-F src/vdbeInt.h 762abffb7709f19c2cb74af1bba73a900f762e64f80d69c31c9ae89ed1066b60
+F src/vdbeInt.h 3ca5e9fd6e095a8b6cf6bc3587a46fc93499503b2fe48951e1034ba9e2ce2f6e
F src/vdbeapi.c c5e7cb2ab89a24d7f723e87b508f21bfb1359a04db5277d8a99fd1e015c12eb9
-F src/vdbeaux.c 73854da7a9a4f12db72a855758214173c82f46a14be6cb19e63677ba02c97cae
+F src/vdbeaux.c c76b7e96e189f5056d1de914d33d07bd03d3b88741f75375c8e18c9b11ffd379
F src/vdbeblob.c 253ed82894924c362a7fa3079551d3554cd1cdace39aa833da77d3bc67e7c1b1
F src/vdbemem.c 947f2a65910edb4014dc981d33e414a68c51f169f9df8c4c493a0ba840b6eb1f
-F src/vdbesort.c 2be76d26998ce2b3324cdcc9f6443728e54b6c7677c553ad909c7d7cfab587df
+F src/vdbesort.c f5b5e473a7cee44e47a94817b042fd7172cf3aa2c0a7928a8339d612bcfdec5a
F src/vdbetrace.c fa3bf238002f0bbbdfb66cc8afb0cea284ff9f148d6439bc1f6f2b4c3b7143f0
F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c
F src/vtab.c 5f5fc793092f53bbdfde296c50f563fb7bda58cf48e9cf6a8bdfbc5abd409845
@@ -622,14 +626,14 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c 69e770e96fd56cc21608992bf2c6f1f3dc5cf2572d0495c6a643b06c3a679f14
F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
F src/walker.c 3df26a33dc4f54e8771600fb7fdebe1ece0896c2ad68c30ab40b017aa4395049
-F src/where.c 2ea911238674e9baaeddf105dddabed92692a01996073c4d4983f9a7efe481f9
-F src/whereInt.h 6b874aa15f94e43a2cec1080be64d955b04deeafeac90ffb5d6975c0d511be3c
-F src/wherecode.c 8064fe5c042824853a9b1fda670054a51a49033a6c79059988c97751ccf8088e
-F src/whereexpr.c 264d58971eaf8256eb5b0917bcd7fc7a1f1109fdda183a8382308a1b18a2dce7
+F src/where.c ad738741bf45999188a3047f6277063e3f6843304d581e3ad5875419afdeb6b2
+F src/whereInt.h 59077fbd0b3d01bc8715e746c86a99ebf4c85bde8a57077ec04d2a23e59666ec
+F src/wherecode.c a3a1aff30fe99a818d8e7c607980f033f40c68d890e03ed25838b9dbb7908bee
+F src/whereexpr.c 3a463e156ea388083c501502229c2c7f4f5c6b5330ea59bdf40d6eb6e155a25f
F src/window.c edd6f5e25a1e8f2b6f5305b7f5f7da7bb35f07f0d432b255b1d4c2fcab4205aa
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
-F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
+F test/affinity3.test eecb0dabee4b7765a8465439d5e99429279ffba23ca74a7eae270a452799f9e7
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/aggnested.test 2f65ec8132e0ca896de550b9908094d49ad65a99116a9d79deeb6017604ad4f6
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
@@ -644,12 +648,12 @@ F test/altercol.test 1d6a6fe698b81e626baea4881f5717f9bc53d7d07f1cd23ee7ad1b931f1
F test/alterlegacy.test 82022721ce0de29cedc9a7af63bc9fcc078b0ee000f8283b4b6ea9c3eab2f44b
F test/altermalloc.test 167a47de41b5c638f5f5c6efb59784002b196fff70f98d9b4ed3cd74a3fb80c9
F test/altermalloc2.test fa7b1c1139ea39b8dec407cf1feb032ca8e0076bd429574969b619175ad0174b
-F test/altertab.test b8b2104212e8ea87c75c3cbe3cb78ed7236a6c828ee2e59ed09d3dbe9812d002
+F test/altertab.test 6d7bbac2c4a6ef71b775094a3298fa3a92274d95034ee23157ffba92768e47e6
F test/altertab2.test b0d62f323ca5dab42b0bc028c52e310ebdd13e655e8fac070fe622bad7852c2b
-F test/altertab3.test d0d51e652aaa11e37de1f1215181d88334fefcb185f3b9bd91e06e98260c4694
+F test/altertab3.test 1db384eb85b4a30b0b332842f5c596b0dc0126f7c61959be3f85ae8b1c271d9a
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
F test/analyze.test 547bb700f903107b38611b014ca645d6b5bb819f5210d7bf39c40802aafeb7d7
-F test/analyze3.test 01f0b122e3e54ad2544f14f7cc7dcb4c2cb8753cad5e88c6b8d49615b3fd6a2b
+F test/analyze3.test fca2a9de0017becfdcc201647f03b1cfd5ba0e7b5b5c852936e4ec62780cde49
F test/analyze4.test cdf88f3f72b0f0643a1ff6c730fc5af1e42464d47478d9fbac84c333f72c014e
F test/analyze5.test fa5131952303ac4146aba101b116b9c8cb89e2637531c334a6df7f7d19dddc0d
F test/analyze6.test 6c3f7df2996cb6872f355a6ac1eb6d5de00a5a9288214bad7ef25c97d9cc72dc
@@ -667,7 +671,7 @@ F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b
F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7
F test/async4.test 1787e3952128aa10238bf39945126de7ca23685a
F test/async5.test 383ab533fdb9f7ad228cc99ee66e1acb34cc0dc0
-F test/atof1.test 1ccfc96a6888566597b83d882c81b3c04258dc39317e8c1cec89ba481eaa2fba
+F test/atof1.test 10049623e77006691c4c2978c1dc8a3f75276377a53417811aa85bda7493f963
F test/atomic.test 065a453dde33c77ff586d91ccaa6ed419829d492dbb1a5694b8a09f3f9d7d061
F test/atomic2.test b6863b4aa552543874f80b42fb3063f1c8c2e3d8e56b6562f00a3cc347b5c1da
F test/atrc.c c388fac43dbba05c804432a7135ae688b32e8f25818e9994ffba4b64cf60c27c
@@ -709,7 +713,7 @@ F test/bestindex7.test f36ada201973d3022cf7afffffe08de9e58341996020e7a2df9a1d2f2
F test/between.test 68137a6e941c221417c15b6fe2d55f27bb1b6ab48bdf9e2aa51efdd85bc53802
F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59
F test/bigfile2.test 1b489a3a39ae90c7f027b79110d6b4e1dbc71bfc
-F test/bigmmap.test 31dad31573638bd32de866cdefd11843f75685be4ba6aec1a47918f098f1899b
+F test/bigmmap.test e906cf9729d7c362270ffe9fa6471f4c39c28ba83f0f77fb795e1b4d38a22ba0
F test/bigrow.test f0aeb7573dcb8caaafea76454be3ade29b7fc747
F test/bigsort.test 8299fa9298f4f1e02fc7d2712e8b77d6cd60e5a2
F test/bind.test 1e136709b306f7ed3192d349c2930d89df6ab621654ad6f1a72381d3fe76f483
@@ -728,7 +732,7 @@ F test/btree01.test e08b3613540145b353f20c81cb18ead54ff12e0f
F test/btree02.test 7555a5440453d900410160a52554fe6478af4faf53098f7235f1f443d5a1d6cc
F test/btreefault.test c2bcb542685eea44621275cfedbd8a13f65201e3
F test/busy.test 510dc6daaad18bcbbc085bcc6217d6dc418def5e73f72ce1475eea0cb7834727
-F test/busy2.test 2499cb62c9e58e18335892602c158cb35639c411803adca6423401b31e46c503
+F test/busy2.test 0a1633fef7987fc8ea25ed5838f7eef2f08fc6d2a3dcc77d23e6402e53946a7a
F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de
F test/cacheflush.test af25bb1509df04c1da10e38d8f322d66eceedf61
F test/cachespill.test 895997f84a25b323b166aecb69baab2d6380ea98f9e0bcc688c4493c535cfab9
@@ -738,9 +742,10 @@ F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4
F test/capi3c.test 54e2dc0c8fd7c34ad1590d1be6864397da2438c95a9f5aee2f8fbc60c112e44b
F test/capi3d.test aba917805573a03deed961a21f07a5a84505ad0a616f7e3fc1508844a15bccc4
F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe
-F test/cast.test 2906ccab6a3ebd147ffa63304b635be903ce58264110d0a0eb4fd9939422bb53
+F test/carray01.test 3f2658bbddd75a013735a296ae2178ff441aca3f00ba623cfbae00b732ede792
+F test/cast.test 336fa21989b5170ebcaf90c24266be22dd97b3e23d1fad5ecf6ad4efb04c4423
F test/cffault.test 9d6b20606afe712374952eec4f8fd74b1a8097ef
-F test/check.test 9776af795bb5d0f197b7f8fe248052e3ca2ed35304d863efcdbf8b1316e11f65
+F test/check.test 4a2a91ed67eee84a6be16057c48d5198b6fb24849cd6da6cd855981de3fbb416
F test/checkfault.test da6cb3d50247169efcb20bdf57863a3ccfa1d27d9e55cd324f0680096970f014
F test/chunksize.test 427d87791743486cbf0c3b8c625002f3255cb3a89c6eba655a98923b1387b760
F test/close.test eccbad8ecd611d974cbf47278c3d4e5874faf02d811338d5d348af42d56d647c
@@ -759,8 +764,8 @@ F test/collateA.test b8218ab90d1fa5c59dcf156efabb1b2599c580d6
F test/collateB.test 1e68906951b846570f29f20102ed91d29e634854ee47454d725f2151ecac0b95
F test/colmeta.test 2c765ea61ee37bc43bbe6d6047f89004e6508eb1
F test/colname.test 87ad5458bb8709312dac0d6755fd30e8e4ca83298d0a9ef6e5c24277a3c3390e
-F test/conflict.test 58857e2533fb9f2e0358ea7cb191215657846be1dd9da3b3d6df3e750c02ae03
-F test/conflict2.test bb0b94cf7196c64a3cbd815c66d3ee98c2fecd9c
+F test/conflict.test ac0667090f66130ac77d5fb764655558ca6600dd6d88f670ca9123b61c448337
+F test/conflict2.test 5557909ce683b1073982f5d1b61dfb1d41e369533bfdaf003180c5bc87282dd1
F test/conflict3.test 81865d9599609aca394fb3b9cd5f561d4729ea5b176bece3644f6ecb540f88ac
F test/contrib01.test 2a1cbc0f2f48955d7d073f725765da6fbceda6b4
F test/corrupt.test d7cb0300e4a297147b6a05e92a1684bc8973635c3bcaa3d66e983c9cbdbf47a3
@@ -807,7 +812,7 @@ F test/cursorhint.test 0175e4404181ace3ceca8b114eb0a98eae600d565aa4e2705abbe6614
F test/cursorhint2.test 6f3aa9cb19e7418967a10ec6905209bcbb5968054da855fc36c8beee9ae9c42f
F test/dataversion1.test 6e5e86ac681f0782e766ebcb56c019ae001522d114e0e111e5ebf68ccf2a7bb8
F test/date.test 9b73bbeb1b82d9c1f44dec5cf563bf7da58d2373
-F test/date2.test 5ef8265c71460cda6b1698bf18f4bb0ffb40ac08c5092f6afe84d398c2feb5be
+F test/date2.test 520a1708e4e14c682cf514560f3e9f2e5affa9d66560fbc2a6941ae291260daf
F test/dbdata.test 042f49acff3438f940eeba5868d3af080ae64ddf26ae78f80c92bec3ca7d8603
F test/dbfuzz.c 73047c920d6210e5912c87cdffd9a1c281d4252e
F test/dbfuzz001.test 55e1a3504f8dea84155e09912fe3b1c3ad77e0b1a938ec42ca03b8e51b321e30
@@ -828,18 +833,18 @@ F test/descidx2.test a0ba347037ff3b811f4c6ceca5fd0f9d5d72e74e59f2d9de346a9d2f6ad
F test/descidx3.test 953c831df7ea219c73826dfbf2f6ee02d95040725aa88ccb4fa43d1a1999b926
F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e
F test/distinct.test e7d0cf371944dd0cbedff86420744e2f1ea2b528156451c97eb6ff41a99b9236
-F test/distinct2.test 11b0594c932098e969d084ba45ab81d5040f4d4e766db65d49146705a305ed98
+F test/distinct2.test cd1d15a4a2abf579298f7161e821ed50c0119136fe0424db85c52cf0adc230d1
F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376
F test/e_blobbytes.test 439a945953b35cb6948a552edaec4dc31fd70a05
F test/e_blobclose.test 4b3c8c60c2171164d472059c73e9f3c1844bb66d
F test/e_blobopen.test e95e1d40f995056f6f322cd5e1a1b83a27e1a145
F test/e_blobwrite.test f87ff598b67af5b3ec002a8d83e804dc8d23808e88cf0080c176612fc9ffce14
F test/e_changes.test fd66105385153dbf21fdb35eb8ef6c3e1eade579
-F test/e_createtable.test ea27082d6f84df61e1d9e383f3fd79220418856a4a8afc41af75d458b8e7ac33
+F test/e_createtable.test 7107f5deda2324ea12dbf105044dc9265195401e9dbb3eead6a2c1a3da4bb5b7
F test/e_delete.test ab39084f26ae1f033c940b70ebdbbd523dc4962e
F test/e_droptrigger.test 235c610f8bf8ec44513e222b9085c7e49fad65ad0c1975ac2577109dd06fd8fa
F test/e_dropview.test 74e405df7fa0f762e0c9445b166fe03955856532e2bb234c372f7c51228d75e7
-F test/e_expr.test 62000e6675d5bcf4b09276fe011a27779629ff8f6678ba5937fb6f1b78d645ff
+F test/e_expr.test 6ba7a51ece7b3e7fc145f14f924eed25ebb5a24e7b8596c78f3838d372cf0385
F test/e_fkey.test 0b458b85f192cdb9e9933d5891848bb19bcc44d3f49faf111a375f2844a164d3
F test/e_fts3.test 17ba7c373aba4d4f5696ba147ee23fd1a1ef70782af050e03e262ca187c5ee07
F test/e_insert.test f02f7f17852b2163732c6611d193f84fc67bc641fb4882c77a464076e5eba80e
@@ -879,7 +884,7 @@ F test/filter2.tcl 44e525497ce07382915f01bd29ffd0fa49dab3adb87253b5e5103ba8f9339
F test/filter2.test 485cf95d1f6d6ceee5632201ca52a71868599836f430cdee42e5f7f14666e30a
F test/filterfault.test c08fb491d698e8df6c122c98f7db1c65ffcfcad2c1ab0e07fa8a5be1b34eaa8b
F test/fkey1.test d11dbb8a93ead9b5c46ae5d02da016d61245d47662fb2d844c99214f6163f768
-F test/fkey2.test b1b6a8c5556dc0ccf31291b1fed8aa57e404b38f3236110e19ab4dc6aa93edf2
+F test/fkey2.test 1063d65e5923c054cfb8f0555a92a3ae0fa8c067275a33ee1715bd856cdb304c
F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49
F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d
F test/fkey5.test 6727452e163a427147e84e739da18713da553d79f9783559b04fdcd36d5c7421
@@ -1017,7 +1022,7 @@ F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
F test/func.test f673822636fb8ed618dd2b80230d16e495d19c8f2e2e7d6c22e93e2b3de097ad
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
F test/func3.test 2bb0f31ab7baaed690b962a88544d7be6b34fa389364bc36a44e441ed3e3f1e6
-F test/func4.test a94858a8c1f10a408b0b3db439c990b59dbb2349411d503de011ac4e2b5f27a6
+F test/func4.test 2285fb5792d593fef442358763f0fd9de806eda47dbc7a5934df57ffdc484c31
F test/func5.test 863e6d1bd0013d09c17236f8a13ea34008dd857d87d85a13a673960e4c25d82a
F test/func6.test 90e42b64c4f9fb6f04f44cb8a1da586c8542502e926b19c76504fe74ff2a9b7c
F test/fuzz-oss1.test e58330d01cbbd8215ee636b17a03fe220b37dbfa
@@ -1027,7 +1032,7 @@ F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c
F test/fuzz4.test c229bcdb45518a89e1d208a21343e061503460ac69fae1539320a89f572eb634
F test/fuzz_common.tcl b7197de6ed1ee8250a4f82d67876f4561b42ee8cbbfc6160dcb66331bad3f830
F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2
-F test/fuzzcheck.c 656ee850f331872a784e7d6a10649efe2af123bdaacb728b5a03e4faee8b959c
+F test/fuzzcheck.c 5f81f2cc65f13068620245f2e2c6059657d3b26be476df379ae2da539f17676d
F test/fuzzdata1.db d36e88741b4f23bcbaaf55b006290669d03c6c891cf13c7b3a53bc1b097b693f
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
@@ -1035,14 +1040,14 @@ F test/fuzzdata4.db b502c7d5498261715812dd8b3c2005bad08b3a26e6489414bd13926cd3e4
F test/fuzzdata5.db e35f64af17ec48926481cfaf3b3855e436bd40d1cfe2d59a9474cb4b748a52a5
F test/fuzzdata6.db 92a80e4afc172c24f662a10a612d188fb272de4a9bd19e017927c95f737de6d7
F test/fuzzdata7.db 0166b56fd7a6b9636a1d60ef0a060f86ddaecf99400a666bb6e5bbd7199ad1f2
-F test/fuzzdata8.db 99f99201280962430f3287e879e050ba88fe458d05cbf28e37ecab369ffe2e86
+F test/fuzzdata8.db f8451a1fd38efbea8c1a7cdf5d02259c4702446a9fabf566becd306b64a50236
F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8
F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14
F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
F test/gcfault.test dd28c228a38976d6336a3fc42d7e5f1ad060cb8c
F test/gencol1.test b05e6c5edb9b10d48efb634ed07342441bddc89d225043e17095c36e567521a0
F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
-F test/having.test e4098a4b8962f9596035c3b87a8928a10648acc509f1bb8d6f96413bbf79a1b3
+F test/having.test ea5cb01cdf3d90fd1b516ef36b1fbde518dbbd61c50141f5eb830d8101844040
F test/hexlit.test 4a6a5f46e3c65c4bf1fa06f5dd5a9507a5627751
F test/hidden.test 23c1393a79e846d68fd902d72c85d5e5dcf98711
F test/hook.test e97382e68e4379838e888756d653afd159f5f14780315ff97b70360d3d8485bc
@@ -1050,7 +1055,7 @@ F test/hook2.test b9ff3b8c6519fb67f33192f1afe86e7782ee4ac8
F test/icu.test 716a6b89fbabe5cc63e0cd4c260befb08fd7b9d761f04d43669233292f0753b1
F test/ieee754.test b0945d12be7d255f3dfa18e2511b17ca37e0edd2b803231c52d05b86c04ab26e
F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8
-F test/in.test ae4ba0fe3232fdd84ef1090a68c5cd6ccd93f1f8774d5c967dd0c1b301492eed
+F test/in.test 688ed2011d922d83141a45af431601738674a4c0bdde34b6351f688b82a169b3
F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
F test/in4.test 65460600d48933adba4283c6ebd089aae173d16136ab9d01f74c89089090c5a5
@@ -1084,7 +1089,7 @@ F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
F test/insert.test 4e3f0de67aac3c5be1f4aaedbcea11638f1b5cdc9a3115be14d19aa9db7623c6
F test/insert2.test 4d14b8f1b810a41995f6286b64a6943215d52208
F test/insert3.test 1b7db95a03ad9c5013fdf7d6722b6cd66ee55e30
-F test/insert4.test fb9e0f752c75f453555990250b449f6d123ae6a3ebf054d14e4470de4498dce3
+F test/insert4.test 59cb99521be01a5aefc9be8e8b5a51ee7f3944781d4d7f6201b9f774fcd51662
F test/insert5.test 394f96728d1258f406fe5f5aeb0aaf29487c39a6
F test/insertfault.test ac63d14ea3b49c573673a572f4014b9117383a03e497c58f308b5c776e4a7f74
F test/instr.test 107df2b9b74a4b59315916b575590a08f2a714de0754abe541f10a0971d0a2a4
@@ -1101,13 +1106,13 @@ F test/ioerr3.test d3cec5e1a11ad6d27527d0d38573fbff14c71bdd
F test/ioerr4.test f130fe9e71008577b342b8874d52984bd04ede2c
F test/ioerr5.test 2edfa4fb0f896f733071303b42224df8bedd9da4
F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b
-F test/istrue.test 06f92ea38750fa74df7dbbe6920205251c2310861fbbe23a3adfa918a2e2ba74
-F test/join.test bca044589e94bb466e4c1e91fb6fecdc3f3326ca6b3f590f555f1958156eb321
-F test/join2.test 7d24d095ab88d3910228d53a3b548b7baf2e0e7d8aac6731a273e300e1b34b61
+F test/istrue.test 9619a2d77580f676048aaff7a16a0bcfea2b96c6c660dfaded2e53c873418899
+F test/join.test 25da4f53523a4aa17c893134b47fba6aa4799bb33350517b157785878290e238
+F test/join2.test 21fc30e54ab35ed66bf51b89cec18729205497f5cc43c83bc042f96a73721593
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
F test/join5.test 3a96dc62f0b45402d7207e22d1993fe0c2fce1c57644a11439891dd62b990eb7
-F test/join6.test cfe6503791ceb0cbb509966740286ec423cbf10b
+F test/join6.test f809c025fa253f9e150c0e9afd4cef8813257bceeb6f46e04041228c9403cc2c
F test/journal1.test c7b768041b7f494471531e17abc2f4f5ebf9e5096984f43ed17c4eb80ba34497
F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4
F test/journal3.test 7c3cf23ffc77db06601c1fcfc9743de8441cb77db9d1aa931863d94f5ffa140e
@@ -1207,7 +1212,7 @@ F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf
F test/notify2.test 2ecabaa1305083856b7c39cf32816b612740c161
F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934
F test/notnull.test a37b663d5bb728d66fc182016613fb8e4a0a4bbf3d75b8876a7527f7d4ed3f18
-F test/null.test 0dcce4f04284ec66108c503327ad6d224c0752b3
+F test/null.test b7ff206a1c60fe01aa2abd33ef9ea83c93727d993ca8a613de86e925c9f2bc6f
F test/nulls1.test 82c5bc33148405f21205865abf13c786084438d573a4ac4e87e11b6091cde526
F test/numcast.test 5d126f7f581432e86a90d1e35cac625164aec4a1
F test/numindex1.test 20a5450d4b056e48cd5db30e659f13347a099823
@@ -1230,7 +1235,7 @@ F test/oserror.test 1fc9746b83d778e70d115049747ba19c7fba154afce7cc165b09feb6ca6a
F test/ossfuzz.c 9636dad2092a05a32110df0ca06713038dd0c43dd89a77dabe4b8b0d71096715
F test/ossshell.c f125c5bd16e537a2549aa579b328dd1c59905e7ab1338dfc210e755bb7b69f17
F test/ovfl.test 199c482696defceacee8c8e0e0ef36da62726b2f
-F test/pager1.test 4fba160bf450cea19f6bf1d6483ef467545bac6405570e176c83c2c4b5d6d0d5
+F test/pager1.test 293c7ad1f19a07e548179b97534c6588249d4e40058b378ea26e75cc84d936f5
F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71
F test/pager3.test 4e9a83d6ca0838d7c602c9eb93d1357562d9059c1e02ffb138a8271020838370
F test/pager4.test a122e9e6925d5b23b31e3dfef8c6a44bbf19590e
@@ -1262,7 +1267,7 @@ F test/quick.test 1681febc928d686362d50057c642f77a02c62e57
F test/quota-glob.test 32901e9eed6705d68ca3faee2a06b73b57cb3c26
F test/quota.test bfb269ce81ea52f593f9648316cd5013d766dd2a
F test/quota2.test 7dc12e08b11cbc4c16c9ba2aa2e040ea8d8ab4b8
-F test/quote.test 626149eda89ee64d81a3790de370f9f0211921b11568a49c28c861f394330508
+F test/quote.test 3f9238ab0e1db70dea89af9afa5859dbd759b0ce0a63da67d547553e2c316475
F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459
F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df
F test/rbu.test 168573d353cd0fd10196b87b0caa322c144ef736
@@ -1272,7 +1277,7 @@ F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
F test/regexp2.test 40e894223b3d6672655481493f1be12012f2b33c
F test/reindex.test cd9d6021729910ece82267b4f5e1b5ac2911a7566c43b43c176a6a4732e2118d
F test/releasetest.tcl fb76d8fcc95ac29d6356cd9e52b726ab9e43a24082897618dfbcb7c2b0049153 x
-F test/releasetest_data.tcl 9919fc6ac5bc92f8878fecfd1840db15999f660a6c9f609240b41aa62b885c88
+F test/releasetest_data.tcl b9cb30360759b80d92d4ea86b84ebfd8035b97f9078a482deb3cf9d0b2442655
F test/resetdb.test 8062cf10a09d8c048f8de7711e94571c38b38168db0e5877ba7561789e5eeb2b
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa
@@ -1312,7 +1317,7 @@ F test/schema6.test e4bd1f23d368695eb9e7b51ef6e02ca0642ea2ab4a52579959826b5e7dce
F test/schemafault.test 1936bceca55ac82c5efbcc9fc91a1933e45c8d1e1d106b9a7e56c972a5a2a51e
F test/securedel.test 2f70b2449186a1921bd01ec9da407fbfa98c3a7a5521854c300c194b2ff09384
F test/securedel2.test 2d54c28e46eb1fd6902089958b20b1b056c6f1c5
-F test/select1.test 009a6d8eacd9684d046302b8d13b50846a87e39d6f08e92178aa13e95ea29a2d
+F test/select1.test 0ed936740777f52858b6607f39ffac4b2b63b8fc7edf3ab2ebad3c3553ceecee
F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56
F test/select3.test c49fbb758903f3718e2de5aa4655eda4838131cbea24a86db908f8b6889aa68c
F test/select4.test e8a2502e3623f3058871030599a48abb35789d2244d5b380ecf3696873fdd4a4
@@ -1332,9 +1337,9 @@ F test/server1.test c2b00864514a68a0e6fd518659dc95d0050307a357a08969872bef027d78
F test/session.test 78fa2365e93d3663a6e933f86e7afc395adf18be
F test/sessionfuzz-data1.db 1f8d5def831f19b1c74571037f0d53a588ea49a6c4ca2a028fc0c27ef896dbcb
F test/sessionfuzz.c f74c4e806bab5a093fb9c11b6123d17a6e0cf73fb7a0f49b12f5a75bf0b7b1a8
-F test/shared.test 1826673eb5eb745fb91a3bdac99a7737057742ae38dcb0fe076a384d6727578b
+F test/shared.test f022874d9d299fe913529dc10f52ad5a386e4e7ff709270b9b1111b3a0f3420a
F test/shared2.test 03eb4a8d372e290107d34b6ce1809919a698e879
-F test/shared3.test ab693f9b6e156b8bfb2a0ad94f29fe69602a5d38
+F test/shared3.test f8cd07c1a2b7cdb315c01671a0b2f8e3830b11ef31da6baa9a9cd8da88965403
F test/shared4.test c75f476804e76e26bf6fa0e7b421fb0ca7d07558
F test/shared6.test 866bb4982c45ce216c61ded5e8fde4e7e2f3ffa9
F test/shared7.test a81e99f83e6c51b02ac99c96fb3a2a7b5978c956
@@ -1344,7 +1349,7 @@ F test/sharedA.test 49d87ec54ab640fbbc3786ee3c01de94aaa482a3a9f834ad3fe92770eb69
F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
-F test/shell1.test 1305efc92f132a1fcf97c00ac02b1b192865b4d33d44cab499e0bdcff71ce045
+F test/shell1.test 0ba53c72545de142e1b76fa793ee33293134aa02abb9b50b35398670481ea661
F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b
F test/shell3.test ac8c2b744014c3e9a0e26bfd829ab65f00923dc1a91ffd044863e9423cc91494
F test/shell4.test 1c6aef11daaa2d6830acaba3ac9cbec93fbc1c3d5530743a637f39b3987d08ce
@@ -1360,7 +1365,7 @@ F test/sidedelete.test f0ad71abe6233e3b153100f3b8d679b19a488329
F test/skipscan1.test ed524bc86f27646b3a297f45d6557b55db338977b6838f8064b196b35848b31b
F test/skipscan2.test 3eb703ce794f139e7b83567911046298bcde29606116727f9b700ce34f559d2d
F test/skipscan3.test ec5bab3f81c7038b43450e7b3062e04a198bdbb5
-F test/skipscan5.test 67817a4b6857c47e0e33ba3e506da6f23ef68de2
+F test/skipscan5.test 980875ad45d8aacfe7bdec7c288343520cd1d14e84befdcfe50c785f9e6c8709
F test/skipscan6.test 0b4cd1b4ac9f84d91454df513c99a4932fa07e8f27b8049bea605068b3e34ac7
F test/snapshot.test a504f2e7009f512ef66c719f0ea1c55a556bdaf1e1312c80a04d46fc1a3e9632
F test/snapshot2.test 8d6ff5dd9cc503f6e12d408a30409c3f9c653507b24408d9cd7195931c89bc54
@@ -1385,7 +1390,7 @@ F test/speed3.test 694affeb9100526007436334cf7d08f3d74b85ef
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
F test/speed4p.test 377a0c48e5a92e0b11c1c5ebb1bc9d83a7312c922bc0cb05970ef5d6a96d1f0c
-F test/speedtest1.c ac0e6ebadb97b54b7ac45288d1beea633a219d5fb98aa3395cb8364c31c985cb
+F test/speedtest1.c 849dbcb0bded9f966e43f28e8ce824b2915cb5dd0031a2e85996f7e3de36c2b1
F test/spellfix.test 951a6405d49d1a23d6b78027d3877b4a33eeb8221dcab5704b499755bb4f552e
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
@@ -1401,7 +1406,7 @@ F test/subjournal.test 8d4e2572c0ee9a15549f0d8e40863161295107e52f07a3e8012a2e1fd
F test/subquery.test d7268d193dd33d5505df965399d3a594e76ae13f
F test/subquery2.test 90cf944b9de8204569cf656028391e4af1ccc8c0cc02d4ef38ee3be8de1ffb12
F test/subselect.test 0966aa8e720224dbd6a5e769a3ec2a723e332303
-F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a
+F test/substr.test a673e3763e247e9b5e497a6cacbaf3da2bd8ec8921c0677145c109f2e633f36b
F test/subtype1.test 7fe09496352f97053af1437150751be2d0a0cae8
F test/superlock.test ec94f0556b6488d97f71c79f9061ae08d9ab8f12
F test/swarmvtab.test 9a3fd5ab3e9b3c976ad1b3d7646aab725114f2ac26b59395d0778b33bab6cdaf
@@ -1426,7 +1431,7 @@ F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
F test/temptable2.test d2940417496e2b9548e01d09990763fbe88c316504033256d51493e1f1a5ce6a
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
-F test/tester.tcl 6417cbb60c4169804e2e1b36ce1a840c9f33d0b0d97956e058f3cc49ed3904f0
+F test/tester.tcl 754521f0db534d51ab504b2d14fe0bdca1f1c15de731ceb8ee5bfd78372a2a5f
F test/thread001.test b61a29dd87cf669f5f6ac96124a7c97d71b0c80d9012746072055877055cf9ef
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@ -1437,7 +1442,7 @@ F test/thread2.test f35d2106452b77523b3a2b7d1dcde2e5ee8f9e46
F test/thread_common.tcl 334639cadcb9f912bf82aa73f49efd5282e6cadd
F test/threadtest1.c 6029d9c5567db28e6dc908a0c63099c3ba6c383b
F test/threadtest2.c a70a8e94bef23339d34226eb9521015ef99f4df8
-F test/threadtest3.c 38a612ea62854349ed66372f330a40d73c5cf956
+F test/threadtest3.c e63013af10cf236c7610eb06d33bde08c861806dc64be811940ff4d9ddd34a4f
F test/threadtest4.c c1e67136ceb6c7ec8184e56ac61db28f96bd2925
F test/time-wordcount.sh 8e0b0f8109367827ad5d58f5cc849705731e4b90
F test/tkt-02a8e81d44.test 6c80d9c7514e2a42d4918bf87bf6bc54f379110c
@@ -1533,7 +1538,7 @@ F test/tkt2817.test f31839e01f4243cff7399ef654d3af3558cb8d8d
F test/tkt2820.test 39940276b3436d125deb7d8ebeee053e4cf13213
F test/tkt2822.test f391776423a7c0d0949edfce375708bfb0f3141e
F test/tkt2832.test a9b0b74a02dca166a04d9e37739c414b10929caa
-F test/tkt2854.test e432965db29e27e16f539b2ba7f502eb2ccc49af
+F test/tkt2854.test 47a2ae03bf36812f675ec06806a7b958e0de75312261dd8280c187f4a4a8281a
F test/tkt2920.test a8737380e4ae6424e00c0273dc12775704efbebf
F test/tkt2927.test 4752868b9eeeb07a217f7f19f4cbaac98d6d086d
F test/tkt2942.test c5c87d179799ca6d1fbe83c815510b87cd5ec7ce
@@ -1567,8 +1572,8 @@ F test/tkt3761.test b95ea9c98f21cf91325f18a984887e62caceab33
F test/tkt3762.test 4d439ff7abdc8d9323150269d182c37c2d514576
F test/tkt3773.test 7bca904d2a647a6a4a291bd86d7fd7c73855b789
F test/tkt3791.test a6624b9a80b216a26cf473607f42f3e51898c267
-F test/tkt3793.test d90ffd75c52413908d15e1c44fc2ea9c80fcc449
-F test/tkt3810.test 09608d81c63a6ff3aaf7bc70717909c51f5f4048
+F test/tkt3793.test 9ee9c6f300adce634e8990a131ad5e20e22241643a1240c6b372b351205ef7cb
+F test/tkt3810.test 3a3be9965d1861bd84019875851ad5ea90fd8d76b638361514a36a48ea53191b
F test/tkt3824.test 150aa00bb6220672e5f0eb14dc8eaa36750425f0
F test/tkt3832.test 2300d10d57562b89875b72148338ac3e14f8847d
F test/tkt3838.test 292e72489101cd1320d7278dc111c173ebf334d4
@@ -1588,7 +1593,7 @@ F test/tpch01.test 7c4eb8cdd79c568f46d344b3e789c9fdb8a766d112871352704861f3fca32
F test/trace.test a659a9862957f4789e37a92b3bf6d2caf5c86b02cdeefc41e850ae53acf6992a
F test/trace2.test f5cb67ad3bc09e0c58e8cca78dfd0b5639259983
F test/trace3.test 1dff966888773ff1bfea01c080caf15417892b3f998408fe920c4791f7337144
-F test/trans.test 6e1b4c6a42dba31bd65f8fa5e61a2708e08ddde6
+F test/trans.test 45f6f9ab6f66a7b5744f1caac06b558f95da62501916906cf55586a896f9f439
F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76
F test/trans3.test 91a100e5412b488e22a655fe423a14c26403ab94
F test/transitive1.test 293300f46916569f08875cdb2fe2134be2c27677
@@ -1613,6 +1618,7 @@ F test/trustschema1.test 4e970aef0bfe0cee139703cc7209d0e0f07725d999b180ba50770f4
F test/tt3_checkpoint.c 9e75cf7c1c364f52e1c47fd0f14c4340a9db0fe1
F test/tt3_index.c 39eec10a35f57672225be4d182862152896dee4a
F test/tt3_lookaside1.c 0377e202c3c2a50d688cb65ba203afeda6fafeb9
+F test/tt3_shared.c b37d22defc944a2ac4c91c927fd06c1d48cd51e2ce9d004fe868625bd2399f93
F test/tt3_stress.c f9a769ca8b026ecc76ee93ca8c9700a5619f8e51c581107c4053ba6ac97f616f
F test/tt3_vacuum.c 1753f45917699c9c1f66b64c717a717c9379f776
F test/types.test bf816ce73c7dfcfe26b700c19f97ef4050d194ff
@@ -1649,7 +1655,7 @@ F test/vacuum5.test 263b144d537e92ad8e9ca8a73cc6e1583f41cfd0dda9432b87f7806174a2
F test/vacuummem.test 7b42abb3208bd82dd23a7536588396f295a314f2
F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
-F test/view.test 10ea54300a097d7c0337fd104abffe4a4786d1598b94017a37efe0e0d3e04dd5
+F test/view.test fd48eddb32a35a98c3de70062ebac66ebf4a2bbfc75a1cc1109159ef8bfc47a9
F test/vtab1.test c5d9e90ed02bcacd776dcbb7360199d290f7f53c26b484ddece543060c54319f
F test/vtab2.test 14d4ab26cee13ba6cf5c5601b158e4f57552d3b055cdd9406cf7f711e9c84082
F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e
@@ -1667,7 +1673,7 @@ F test/vtabE.test 2a143fe75a11275781d1fd1988d86b66a3f69cb98f4add62e3da8fd0f637b4
F test/vtabF.test 1918844c7c902f6a16c8dacf1ec8f84886d6e78b
F test/vtabH.test 2efb5a24b0bb50796b21eca23032cfb77abfa4b0c03938e38ce5897abac404ca
F test/vtabI.test 751b07636700dbdea328e4265b6077ccd6811a3f
-F test/vtabJ.test d7b73675708cf63cfcb9d443bb451fc01a028347275b7311e51f9fdf3ca6757f
+F test/vtabJ.test a6aef49d558af90fae10565b29501f82a95781cb4f797f2d13e2d19f9b6bc77b
F test/vtab_alter.test 736e66fb5ec7b4fee58229aa3ada2f27ec58bc58c00edae4836890c3784c6783
F test/vtab_err.test dcc8b7b9cb67522b3fe7a272c73856829dae4ab7fdb30399aea1b6981bda2b65
F test/vtab_shared.test 5253bff2355a9a3f014c15337da7e177ab0ef8ad
@@ -1710,7 +1716,7 @@ F test/walthread.test 14b20fcfa6ae152f5d8e12f5dc8a8a724b7ef189f5d8ef1e2ceab79f2a
F test/walvfs.test a2913001a83b19c1d20220e556cee14d87d47ecb6949b5e0a2e9e2590abecf1e
F test/wapp.tcl b440cd8cf57953d3a49e7ee81e6a18f18efdaf113b69f7d8482b0710a64566ec
F test/wapptest.tcl 899594e25684861d5b0c0880fb012364def50ef8097041b8ddf74be5ba7fa270 x
-F test/where.test f5e62453537e5b335b69f3b09f8a02ce3328289fad5d866e25371284b837d78d
+F test/where.test e713c0c64e3e6b062235e39a2f7e5508c517df16b63d69fd786e26bc7330b1c6
F test/where2.test 478d2170637b9211f593120648858593bf2445a1
F test/where3.test 2341a294e17193a6b1699ea7f192124a5286ca6acfcc3f4b06d16c931fbcda2c
F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8
@@ -1719,13 +1725,13 @@ F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b
F test/where7.test 75722434c486ac9e74718caa6cce234f45ba34c0b6c0f9555b29eb8bb5f6ade1
F test/where8.test 461ca40265ed996a6305da99bb024b0e41602bb586acf544c08f95922358e49f
F test/where9.test 8e3e0ff42cc17156f52361a1c012281550d0d632912fec92d1d6df74db7a8e6d
-F test/whereA.test 6c6a420ca7d313242f9b1bd471dc80e4d0f8323700ba9c78df0bb843d4daa3b4
+F test/whereA.test 9d1077b117f1b68d5f739d94f36956c36cf995eb87bb19b77b2e81af020edd20
F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5
F test/whereC.test cae295158703cb3fc23bf1a108a9ab730efff0f6
F test/whereD.test c1c335e914e28b122e000e9310f02d2be83e1c9dbca2e29f46bd732703944d1b
F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f
F test/whereF.test 3d9412b1199d3e2bed34fcb76b4c48d0bf4df95d27e3f8dd27b6f8b4716d0d89
-F test/whereG.test 9363b2a97d914cb1b81aff5069ef0cf2a071a67e2b604eac6fe9c0114017d9aa
+F test/whereG.test 77127a4d214bb21da3b5c695cf4106cd9e418c60d9c24471ba55d3772067cd35
F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2
F test/whereI.test a2874062140ed4aba9ffae76e6190a3df6fc73d1373fdfa8fd632945082a5364
F test/whereJ.test 88287550f6ee604422403b053455b1ad894eeaa5c35d348532dfa1439286cb9a
@@ -1758,14 +1764,15 @@ F test/windowB.test 7a983ea1cc1cf72be7f378e4b32f6cb2d73014c5cd8b25aaee825164cd42
F test/windowerr.tcl f5acd6fbc210d7b5546c0e879d157888455cd4a17a1d3f28f07c1c8a387019e0
F test/windowerr.test a8b752402109c15aa1c5efe1b93ccb0ce1ef84fa964ae1cd6684dd0b3cc1819b
F test/windowfault.test 72375ae71031eabf96bc88d0af128c8628a091ddc99b5a394e848b3df5fc17ad
-F test/with1.test 584580a5ae79868a91873863f8cb2d00040006dc1e4c332ef1d8642f2815dc6e
+F test/with1.test 780be387f01e290e768bdfd1827280f9e37ba37223eb4736aba386864fac5a94
F test/with2.test e0030e2f0267a910d6c0e4f46f2dfe941c1cc0d4f659ba69b3597728e7e8f1ab
-F test/with3.test 13b3336739da648a9e4dfa11bb04e73a920c97620041007c5f75d5d14084c346
+F test/with3.test a261f0ea225c4af0ce6447f1157bb603959b2a665f14a03951c2883d2ef1c0f0
F test/with4.test 257be66c0c67fee1defbbac0f685c3465e2cad037f21ce65f23f86084f198205
+F test/with5.test 6248213c41fab36290b5b73aa3f937309dfba337004d9d8434c3fabc8c7d4be8
F test/withM.test 693b61765f2b387b5e3e24a4536e2e82de15ff64
-F test/without_rowid1.test 9cfb83705c506e3849fa7efc88a3c9a15f9a50bf9b1516b41757a7cef9bba8c3
+F test/without_rowid1.test e4034c0849ccc2e8bb749c69f15bd69bb9fcf8fe77e8d17ce02369604242fe83
F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
-F test/without_rowid3.test 96426a6c9a2a5cf62bbe55ea1ad038eaaf4bf743f40a1ad517233b8e5a3d4339
+F test/without_rowid3.test 39ab0dd773eaa62e59b17093f875327630f54c4145458f6d2b053d68d4b2f67b
F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a
F test/without_rowid5.test 89b1c587bd92a0590e440da33e7666bf4891572a
F test/without_rowid6.test 8463b20098e9f75a501a9f17dfb42fffc79068eac0b2775fe56ef2281d2df45e
@@ -1778,7 +1785,7 @@ F test/zipfile.test 429cb81c518487fa1b644b6b04b6e9af704a4fa767bd1a110204c5f03b2e
F test/zipfile2.test 9903388a602a3834189857a985106ff95c3bba6a3969e0134127df991889db5d
F test/zipfilefault.test 44d4d7a7f7cca7521d569d7f71026b241d65a6b1757aa409c1a168827edbbc2c
F tool/GetFile.cs 47852aa0d806fe47ed1ac5138bdce7f000fe87aaa7f28107d0cb1e26682aeb44
-F tool/GetTclKit.bat 8995df40c4209808b31f24de0b58f90930239a234f7591e3675d45bfbb990c5d
+F tool/GetTclKit.bat e95747c0f7a9fe279a9979178b71f6431a21f945b390fc3120244897ff3f5135
F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91
F tool/build-all-msvc.bat c12328d06c45fec8baada5949e3d5af54bf8c887 x
F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367
@@ -1798,8 +1805,8 @@ F tool/genfkey.test b6afd7b825d797a1e1274f519ab5695373552ecad5cd373530c63533638a
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
F tool/index_usage.c f62a0c701b2c7ff2f3e21d206f093c123f222dbf07136a10ffd1ca15a5c706c5
F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f
-F tool/lemon.c 600a58b9d1b8ec5419373982428e927ca208826edacb91ca42ab94514d006039
-F tool/lempar.c e8899b28488f060d0ff931539ea6311b16b22dce068c086c788a06d5e8d01ab7
+F tool/lemon.c 70eedc31614a58fe31a71025c17ebd1502a6ce9cfef0ed5e33acb0b5b737b291
+F tool/lempar.c 0e1d5eeb9736108d3dba782a9dd56f4e7cb69006b6ee181308b7ebfb15313a12
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca
@@ -1817,7 +1824,7 @@ F tool/mkshellc.tcl 70a9978e363b0f3280ca9ce1c46d72563ff479c1930a12a7375e3881b732
F tool/mksourceid.c 36aa8020014aed0836fd13c51d6dc9219b0df1761d6b5f58ff5b616211b079b9
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
F tool/mksqlite3c-noext.tcl 4f7cfef5152b0c91920355cbfc1d608a4ad242cb819f1aea07f6d0274f584a7f
-F tool/mksqlite3c.tcl f4ef476510eca4124c874a72029f1e01bc54a896b1724e8f9eef0d8bfae0e84c
+F tool/mksqlite3c.tcl 00c4c0382eb000153182da2bee2547ca05554eeeed10177efe5894c54e4e6d4d
F tool/mksqlite3h.tcl 1f5e4a1dbbbc43c83cc6e74fe32c6c620502240b66c7c0f33a51378e78fc4edf
F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b
F tool/mkvsix.tcl b9e0777a213c23156b6542842c238479e496ebf5
@@ -1844,7 +1851,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd
F tool/split-sqlite3c.tcl 3efcd4240b738f6bb2b5af0aea7e1e0ef9bc1c61654f645076cec883030b710c
-F tool/sqldiff.c 5046b8e227213ad016b336eb5a933e252e1f0fd1e07060c5755e259a30891287
+F tool/sqldiff.c 4151108387cb56c08906e5ac8d6a353dcfe8fc6014eeded0f0910e2230ea0f5b
F tool/sqlite3_analyzer.c.in 7eeaae8b0d7577662acaabbb11107af0659d1b41bc1dfdd4d91422de27127968
F tool/sqltclsh.c.in 1bcc2e9da58fadf17b0bf6a50e68c1159e602ce057210b655d50bad5aaaef898
F tool/sqltclsh.tcl 862f4cf1418df5e1315b5db3b5ebe88969e2a784525af5fbf9596592f14ed848
@@ -1879,10 +1886,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P b050976079ba4a22d4dfeadb81f40cf71da6588c95bf2b634d88b416de5accd7
-R 799818c17104aa7af945cf9f5cad3762
+P 23212b1a054f05773a9f69f9802035eea6a9d759a2a09e22f46d1046c058b417
+R 02db8b9bcb7f3c64353edbc1fa9fbf5b
T +bgcolor * #d0c0ff
T +sym-release *
-T +sym-version-3.33.0 *
+T +sym-version-3.34.0 *
U drh
-Z 652aa26f564c1138ae3a9226a8f034b3
+Z b7b093d44b407c1b4e832f8c913357ae
diff --git a/chromium/third_party/sqlite/src/manifest.uuid b/chromium/third_party/sqlite/src/manifest.uuid
index 4231aa8eafe..cd09bbf164e 100644
--- a/chromium/third_party/sqlite/src/manifest.uuid
+++ b/chromium/third_party/sqlite/src/manifest.uuid
@@ -1 +1 @@
-fca8dc8b578f215a969cd899336378966156154710873e68b3d9ac5881b0ff3f \ No newline at end of file
+0000000000000000000000000000000000000000000000000000000000000000
diff --git a/chromium/third_party/sqlite/src/src/alter.c b/chromium/third_party/sqlite/src/src/alter.c
index c146c2ff913..f4098863dda 100644
--- a/chromium/third_party/sqlite/src/src/alter.c
+++ b/chromium/third_party/sqlite/src/src/alter.c
@@ -1196,13 +1196,21 @@ static int renameResolveTrigger(Parse *pParse){
int i;
for(i=0; i<pSrc->nSrc && rc==SQLITE_OK; i++){
struct SrcList_item *p = &pSrc->a[i];
- p->pTab = sqlite3LocateTableItem(pParse, 0, p);
p->iCursor = pParse->nTab++;
- if( p->pTab==0 ){
- rc = SQLITE_ERROR;
+ if( p->pSelect ){
+ sqlite3SelectPrep(pParse, p->pSelect, 0);
+ sqlite3ExpandSubquery(pParse, p);
+ assert( i>0 );
+ assert( pStep->pFrom->a[i-1].pSelect );
+ sqlite3SelectPrep(pParse, pStep->pFrom->a[i-1].pSelect, 0);
}else{
- p->pTab->nTabRef++;
- rc = sqlite3ViewGetColumnNames(pParse, p->pTab);
+ p->pTab = sqlite3LocateTableItem(pParse, 0, p);
+ if( p->pTab==0 ){
+ rc = SQLITE_ERROR;
+ }else{
+ p->pTab->nTabRef++;
+ rc = sqlite3ViewGetColumnNames(pParse, p->pTab);
+ }
}
}
sNC.pSrcList = pSrc;
@@ -1264,6 +1272,12 @@ static void renameWalkTrigger(Walker *pWalker, Trigger *pTrigger){
sqlite3WalkExpr(pWalker, pUpsert->pUpsertWhere);
sqlite3WalkExpr(pWalker, pUpsert->pUpsertTargetWhere);
}
+ if( pStep->pFrom ){
+ int i;
+ for(i=0; i<pStep->pFrom->nSrc; i++){
+ sqlite3WalkSelect(pWalker, pStep->pFrom->a[i].pSelect);
+ }
+ }
}
}
diff --git a/chromium/third_party/sqlite/src/src/analyze.c b/chromium/third_party/sqlite/src/src/analyze.c
index 9a9de991deb..dc77220a53c 100644
--- a/chromium/third_party/sqlite/src/src/analyze.c
+++ b/chromium/third_party/sqlite/src/src/analyze.c
@@ -1772,6 +1772,7 @@ static int loadStatTbl(
}
pSpace = (tRowcnt*)&pIdx->aSample[nSample];
pIdx->aAvgEq = pSpace; pSpace += nIdxCol;
+ pIdx->pTable->tabFlags |= TF_HasStat4;
for(i=0; i<nSample; i++){
pIdx->aSample[i].anEq = pSpace; pSpace += nIdxCol;
pIdx->aSample[i].anLt = pSpace; pSpace += nIdxCol;
diff --git a/chromium/third_party/sqlite/src/src/attach.c b/chromium/third_party/sqlite/src/src/attach.c
index 545159d3ea7..3b5c57f0ccd 100644
--- a/chromium/third_party/sqlite/src/src/attach.c
+++ b/chromium/third_party/sqlite/src/src/attach.c
@@ -293,7 +293,9 @@ static void detachFunc(
sqlite3_snprintf(sizeof(zErr),zErr, "cannot detach database %s", zName);
goto detach_error;
}
- if( sqlite3BtreeIsInReadTrans(pDb->pBt) || sqlite3BtreeIsInBackup(pDb->pBt) ){
+ if( sqlite3BtreeTxnState(pDb->pBt)!=SQLITE_TXN_NONE
+ || sqlite3BtreeIsInBackup(pDb->pBt)
+ ){
sqlite3_snprintf(sizeof(zErr),zErr, "database %s is locked", zName);
goto detach_error;
}
diff --git a/chromium/third_party/sqlite/src/src/backup.c b/chromium/third_party/sqlite/src/src/backup.c
index 77e7ed950fd..2b286de6bda 100644
--- a/chromium/third_party/sqlite/src/src/backup.c
+++ b/chromium/third_party/sqlite/src/src/backup.c
@@ -123,7 +123,7 @@ static int setDestPgsz(sqlite3_backup *p){
** message in database handle db.
*/
static int checkReadTransaction(sqlite3 *db, Btree *p){
- if( sqlite3BtreeIsInReadTrans(p) ){
+ if( sqlite3BtreeTxnState(p)!=SQLITE_TXN_NONE ){
sqlite3ErrorWithMsg(db, SQLITE_ERROR, "destination database is in use");
return SQLITE_ERROR;
}
@@ -354,7 +354,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
** one now. If a transaction is opened here, then it will be closed
** before this function exits.
*/
- if( rc==SQLITE_OK && 0==sqlite3BtreeIsInReadTrans(p->pSrc) ){
+ if( rc==SQLITE_OK && SQLITE_TXN_NONE==sqlite3BtreeTxnState(p->pSrc) ){
rc = sqlite3BtreeBeginTrans(p->pSrc, 0, 0);
bCloseTrans = 1;
}
@@ -726,7 +726,7 @@ int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
sqlite3BtreeEnter(pTo);
sqlite3BtreeEnter(pFrom);
- assert( sqlite3BtreeIsInTrans(pTo) );
+ assert( sqlite3BtreeTxnState(pTo)==SQLITE_TXN_WRITE );
pFd = sqlite3PagerFile(sqlite3BtreePager(pTo));
if( pFd->pMethods ){
i64 nByte = sqlite3BtreeGetPageSize(pFrom)*(i64)sqlite3BtreeLastPage(pFrom);
@@ -762,7 +762,7 @@ int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
sqlite3PagerClearCache(sqlite3BtreePager(b.pDest));
}
- assert( sqlite3BtreeIsInTrans(pTo)==0 );
+ assert( sqlite3BtreeTxnState(pTo)!=SQLITE_TXN_WRITE );
copy_finished:
sqlite3BtreeLeave(pFrom);
sqlite3BtreeLeave(pTo);
diff --git a/chromium/third_party/sqlite/src/src/btree.c b/chromium/third_party/sqlite/src/src/btree.c
index 919d3b87cd8..4ac283101a2 100644
--- a/chromium/third_party/sqlite/src/src/btree.c
+++ b/chromium/third_party/sqlite/src/src/btree.c
@@ -112,6 +112,17 @@ int sqlite3_enable_shared_cache(int enable){
#define hasReadConflicts(a, b) 0
#endif
+#ifdef SQLITE_DEBUG
+/*
+** Return and reset the seek counter for a Btree object.
+*/
+sqlite3_uint64 sqlite3BtreeSeekCount(Btree *pBt){
+ u64 n = pBt->nSeek;
+ pBt->nSeek = 0;
+ return n;
+}
+#endif
+
/*
** Implementation of the SQLITE_CORRUPT_PAGE() macro. Takes a single
** (MemPage*) as an argument. The (MemPage*) must not be NULL.
@@ -2605,7 +2616,7 @@ btree_open_out:
** do not change the pager-cache size.
*/
if( sqlite3BtreeSchema(p, 0, 0)==0 ){
- sqlite3PagerSetCachesize(p->pBt->pPager, SQLITE_DEFAULT_CACHE_SIZE);
+ sqlite3BtreeSetCacheSize(p, SQLITE_DEFAULT_CACHE_SIZE);
}
pFile = sqlite3PagerFile(pBt->pPager);
@@ -5459,6 +5470,10 @@ int sqlite3BtreeMovetoUnpacked(
}
}
+#ifdef SQLITE_DEBUG
+ pCur->pBtree->nSeek++; /* Performance measurement during testing */
+#endif
+
if( pIdxKey ){
xRecordCompare = sqlite3VdbeFindCompare(pIdxKey);
pIdxKey->errCode = 0;
@@ -5735,7 +5750,7 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur){
pPage = pCur->pPage;
idx = ++pCur->ix;
- if( !pPage->isInit ){
+ if( !pPage->isInit || sqlite3FaultSim(412) ){
/* The only known way for this to happen is for there to be a
** recursive SQL function that does a DELETE operation as part of a
** SELECT which deletes content out from under an active cursor
@@ -10310,11 +10325,12 @@ const char *sqlite3BtreeGetJournalname(Btree *p){
}
/*
-** Return non-zero if a transaction is active.
+** Return one of SQLITE_TXN_NONE, SQLITE_TXN_READ, or SQLITE_TXN_WRITE
+** to describe the current transaction state of Btree p.
*/
-int sqlite3BtreeIsInTrans(Btree *p){
+int sqlite3BtreeTxnState(Btree *p){
assert( p==0 || sqlite3_mutex_held(p->db->mutex) );
- return (p && (p->inTrans==TRANS_WRITE));
+ return p ? p->inTrans : 0;
}
#ifndef SQLITE_OMIT_WAL
@@ -10343,14 +10359,8 @@ int sqlite3BtreeCheckpoint(Btree *p, int eMode, int *pnLog, int *pnCkpt){
#endif
/*
-** Return non-zero if a read (or write) transaction is active.
+** Return true if there is currently a backup running on Btree p.
*/
-int sqlite3BtreeIsInReadTrans(Btree *p){
- assert( p );
- assert( sqlite3_mutex_held(p->db->mutex) );
- return p->inTrans!=TRANS_NONE;
-}
-
int sqlite3BtreeIsInBackup(Btree *p){
assert( p );
assert( sqlite3_mutex_held(p->db->mutex) );
diff --git a/chromium/third_party/sqlite/src/src/btree.h b/chromium/third_party/sqlite/src/src/btree.h
index 5dd5287d18c..7a9ed2e3c61 100644
--- a/chromium/third_party/sqlite/src/src/btree.h
+++ b/chromium/third_party/sqlite/src/src/btree.h
@@ -85,16 +85,24 @@ int sqlite3BtreeCommit(Btree*);
int sqlite3BtreeRollback(Btree*,int,int);
int sqlite3BtreeBeginStmt(Btree*,int);
int sqlite3BtreeCreateTable(Btree*, Pgno*, int flags);
-int sqlite3BtreeIsInTrans(Btree*);
-int sqlite3BtreeIsInReadTrans(Btree*);
+int sqlite3BtreeTxnState(Btree*);
int sqlite3BtreeIsInBackup(Btree*);
+
void *sqlite3BtreeSchema(Btree *, int, void(*)(void *));
int sqlite3BtreeSchemaLocked(Btree *pBtree);
#ifndef SQLITE_OMIT_SHARED_CACHE
int sqlite3BtreeLockTable(Btree *pBtree, int iTab, u8 isWriteLock);
#endif
+
+/* Savepoints are named, nestable SQL transactions mostly implemented */
+/* in vdbe.c and pager.c See https://sqlite.org/lang_savepoint.html */
int sqlite3BtreeSavepoint(Btree *, int, int);
+/* "Checkpoint" only refers to WAL. See https://sqlite.org/wal.html#ckpt */
+#ifndef SQLITE_OMIT_WAL
+ int sqlite3BtreeCheckpoint(Btree*, int, int *, int *);
+#endif
+
const char *sqlite3BtreeGetFilename(Btree *);
const char *sqlite3BtreeGetJournalname(Btree *);
int sqlite3BtreeCopyFile(Btree *, Btree *);
@@ -331,6 +339,12 @@ int sqlite3BtreeCursorHasHint(BtCursor*, unsigned int mask);
int sqlite3BtreeIsReadonly(Btree *pBt);
int sqlite3HeaderSizeBtree(void);
+#ifdef SQLITE_DEBUG
+sqlite3_uint64 sqlite3BtreeSeekCount(Btree*);
+#else
+# define sqlite3BtreeSeekCount(X) 0
+#endif
+
#ifndef NDEBUG
int sqlite3BtreeCursorIsValid(BtCursor*);
#endif
diff --git a/chromium/third_party/sqlite/src/src/btreeInt.h b/chromium/third_party/sqlite/src/src/btreeInt.h
index c6dfa27ef56..c09699fbb56 100644
--- a/chromium/third_party/sqlite/src/src/btreeInt.h
+++ b/chromium/third_party/sqlite/src/src/btreeInt.h
@@ -353,6 +353,9 @@ struct Btree {
u32 iDataVersion; /* Combines with pBt->pPager->iDataVersion */
Btree *pNext; /* List of other sharable Btrees from the same db */
Btree *pPrev; /* Back pointer of the same list */
+#ifdef SQLITE_DEBUG
+ u64 nSeek; /* Calls to sqlite3BtreeMovetoUnpacked() */
+#endif
#ifndef SQLITE_OMIT_SHARED_CACHE
BtLock lock; /* Object used to lock page 1 */
#endif
@@ -364,11 +367,25 @@ struct Btree {
** If the shared-data extension is enabled, there may be multiple users
** of the Btree structure. At most one of these may open a write transaction,
** but any number may have active read transactions.
+**
+** These values must match SQLITE_TXN_NONE, SQLITE_TXN_READ, and
+** SQLITE_TXN_WRITE
*/
#define TRANS_NONE 0
#define TRANS_READ 1
#define TRANS_WRITE 2
+#if TRANS_NONE!=SQLITE_TXN_NONE
+# error wrong numeric code for no-transaction
+#endif
+#if TRANS_READ!=SQLITE_TXN_READ
+# error wrong numeric code for read-transaction
+#endif
+#if TRANS_WRITE!=SQLITE_TXN_WRITE
+# error wrong numeric code for write-transaction
+#endif
+
+
/*
** An instance of this object represents a single database file.
**
diff --git a/chromium/third_party/sqlite/src/src/build.c b/chromium/third_party/sqlite/src/src/build.c
index aa0f919bc6f..9779e93732b 100644
--- a/chromium/third_party/sqlite/src/src/build.c
+++ b/chromium/third_party/sqlite/src/src/build.c
@@ -53,7 +53,7 @@ void sqlite3TableLock(
u8 isWriteLock, /* True for a write lock */
const char *zName /* Name of the table to be locked */
){
- Parse *pToplevel = sqlite3ParseToplevel(pParse);
+ Parse *pToplevel;
int i;
int nBytes;
TableLock *p;
@@ -61,6 +61,7 @@ void sqlite3TableLock(
if( iDb==1 ) return;
if( !sqlite3BtreeSharable(pParse->db->aDb[iDb].pBt) ) return;
+ pToplevel = sqlite3ParseToplevel(pParse);
for(i=0; i<pToplevel->nTableLock; i++){
p = &pToplevel->aTableLock[i];
if( p->iDb==iDb && p->iTab==iTab ){
@@ -90,10 +91,8 @@ void sqlite3TableLock(
*/
static void codeTableLocks(Parse *pParse){
int i;
- Vdbe *pVdbe;
-
- pVdbe = sqlite3GetVdbe(pParse);
- assert( pVdbe!=0 ); /* sqlite3GetVdbe cannot fail: VDBE already allocated */
+ Vdbe *pVdbe = pParse->pVdbe;
+ assert( pVdbe!=0 );
for(i=0; i<pParse->nTableLock; i++){
TableLock *p = &pParse->aTableLock[i];
@@ -1618,8 +1617,10 @@ primary_key_exit:
** Add a new CHECK constraint to the table currently under construction.
*/
void sqlite3AddCheckConstraint(
- Parse *pParse, /* Parsing context */
- Expr *pCheckExpr /* The check expression */
+ Parse *pParse, /* Parsing context */
+ Expr *pCheckExpr, /* The check expression */
+ const char *zStart, /* Opening "(" */
+ const char *zEnd /* Closing ")" */
){
#ifndef SQLITE_OMIT_CHECK
Table *pTab = pParse->pNewTable;
@@ -1630,6 +1631,13 @@ void sqlite3AddCheckConstraint(
pTab->pCheck = sqlite3ExprListAppend(pParse, pTab->pCheck, pCheckExpr);
if( pParse->constraintName.n ){
sqlite3ExprListSetName(pParse, pTab->pCheck, &pParse->constraintName, 1);
+ }else{
+ Token t;
+ for(zStart++; sqlite3Isspace(zStart[0]); zStart++){}
+ while( sqlite3Isspace(zEnd[-1]) ){ zEnd--; }
+ t.z = zStart;
+ t.n = (int)(zEnd - t.z);
+ sqlite3ExprListSetName(pParse, pTab->pCheck, &t, 1);
}
}else
#endif
@@ -1648,7 +1656,7 @@ void sqlite3AddCollateType(Parse *pParse, Token *pToken){
char *zColl; /* Dequoted name of collation sequence */
sqlite3 *db;
- if( (p = pParse->pNewTable)==0 ) return;
+ if( (p = pParse->pNewTable)==0 || IN_RENAME_OBJECT ) return;
i = p->nCol-1;
db = pParse->db;
zColl = sqlite3NameFromToken(db, pToken);
@@ -1883,12 +1891,15 @@ static int resizeIndexObject(sqlite3 *db, Index *pIdx, int N){
int nByte;
if( pIdx->nColumn>=N ) return SQLITE_OK;
assert( pIdx->isResized==0 );
- nByte = (sizeof(char*) + sizeof(i16) + 1)*N;
+ nByte = (sizeof(char*) + sizeof(LogEst) + sizeof(i16) + 1)*N;
zExtra = sqlite3DbMallocZero(db, nByte);
if( zExtra==0 ) return SQLITE_NOMEM_BKPT;
memcpy(zExtra, pIdx->azColl, sizeof(char*)*pIdx->nColumn);
pIdx->azColl = (const char**)zExtra;
zExtra += sizeof(char*)*N;
+ memcpy(zExtra, pIdx->aiRowLogEst, sizeof(LogEst)*(pIdx->nKeyCol+1));
+ pIdx->aiRowLogEst = (LogEst*)zExtra;
+ zExtra += sizeof(LogEst)*N;
memcpy(zExtra, pIdx->aiColumn, sizeof(i16)*pIdx->nColumn);
pIdx->aiColumn = (i16*)zExtra;
zExtra += sizeof(i16)*N;
@@ -4449,7 +4460,7 @@ void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){
assert(pList || pParse->db->mallocFailed );
if( pList ){
for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
- if( pItem->iCursor>=0 ) break;
+ if( pItem->iCursor>=0 ) continue;
pItem->iCursor = pParse->nTab++;
if( pItem->pSelect ){
sqlite3SrcListAssignCursors(pParse, pItem->pSelect->pSrc);
@@ -4466,15 +4477,15 @@ void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
struct SrcList_item *pItem;
if( pList==0 ) return;
for(pItem=pList->a, i=0; i<pList->nSrc; i++, pItem++){
- sqlite3DbFree(db, pItem->zDatabase);
+ if( pItem->zDatabase ) sqlite3DbFreeNN(db, pItem->zDatabase);
sqlite3DbFree(db, pItem->zName);
- sqlite3DbFree(db, pItem->zAlias);
+ if( pItem->zAlias ) sqlite3DbFreeNN(db, pItem->zAlias);
if( pItem->fg.isIndexedBy ) sqlite3DbFree(db, pItem->u1.zIndexedBy);
if( pItem->fg.isTabFunc ) sqlite3ExprListDelete(db, pItem->u1.pFuncArg);
sqlite3DeleteTable(db, pItem->pTab);
- sqlite3SelectDelete(db, pItem->pSelect);
- sqlite3ExprDelete(db, pItem->pOn);
- sqlite3IdListDelete(db, pItem->pUsing);
+ if( pItem->pSelect ) sqlite3SelectDelete(db, pItem->pSelect);
+ if( pItem->pOn ) sqlite3ExprDelete(db, pItem->pOn);
+ if( pItem->pUsing ) sqlite3IdListDelete(db, pItem->pUsing);
}
sqlite3DbFreeNN(db, pList);
}
@@ -4646,7 +4657,16 @@ void sqlite3BeginTransaction(Parse *pParse, int type){
if( !v ) return;
if( type!=TK_DEFERRED ){
for(i=0; i<db->nDb; i++){
- sqlite3VdbeAddOp2(v, OP_Transaction, i, (type==TK_EXCLUSIVE)+1);
+ int eTxnType;
+ Btree *pBt = db->aDb[i].pBt;
+ if( pBt && sqlite3BtreeIsReadonly(pBt) ){
+ eTxnType = 0; /* Read txn */
+ }else if( type==TK_EXCLUSIVE ){
+ eTxnType = 2; /* Exclusive txn */
+ }else{
+ eTxnType = 1; /* Write txn */
+ }
+ sqlite3VdbeAddOp2(v, OP_Transaction, i, eTxnType);
sqlite3VdbeUsesBtree(v, i);
}
}
@@ -4735,13 +4755,11 @@ int sqlite3OpenTempDatabase(Parse *pParse){
** will occur at the end of the top-level VDBE and will be generated
** later, by sqlite3FinishCoding().
*/
-void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
- Parse *pToplevel = sqlite3ParseToplevel(pParse);
-
- assert( iDb>=0 && iDb<pParse->db->nDb );
- assert( pParse->db->aDb[iDb].pBt!=0 || iDb==1 );
+static void sqlite3CodeVerifySchemaAtToplevel(Parse *pToplevel, int iDb){
+ assert( iDb>=0 && iDb<pToplevel->db->nDb );
+ assert( pToplevel->db->aDb[iDb].pBt!=0 || iDb==1 );
assert( iDb<SQLITE_MAX_ATTACHED+2 );
- assert( sqlite3SchemaMutexHeld(pParse->db, iDb, 0) );
+ assert( sqlite3SchemaMutexHeld(pToplevel->db, iDb, 0) );
if( DbMaskTest(pToplevel->cookieMask, iDb)==0 ){
DbMaskSet(pToplevel->cookieMask, iDb);
if( !OMIT_TEMPDB && iDb==1 ){
@@ -4749,6 +4767,10 @@ void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
}
}
}
+void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
+ sqlite3CodeVerifySchemaAtToplevel(sqlite3ParseToplevel(pParse), iDb);
+}
+
/*
** If argument zDb is NULL, then call sqlite3CodeVerifySchema() for each
@@ -4780,7 +4802,7 @@ void sqlite3CodeVerifyNamedSchema(Parse *pParse, const char *zDb){
*/
void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){
Parse *pToplevel = sqlite3ParseToplevel(pParse);
- sqlite3CodeVerifySchema(pParse, iDb);
+ sqlite3CodeVerifySchemaAtToplevel(pToplevel, iDb);
DbMaskSet(pToplevel->writeMask, iDb);
pToplevel->isMultiWrite |= setStatement;
}
@@ -4831,7 +4853,9 @@ void sqlite3HaltConstraint(
i8 p4type, /* P4_STATIC or P4_TRANSIENT */
u8 p5Errmsg /* P5_ErrMsg type */
){
- Vdbe *v = sqlite3GetVdbe(pParse);
+ Vdbe *v;
+ assert( pParse->pVdbe!=0 );
+ v = sqlite3GetVdbe(pParse);
assert( (errCode&0xff)==SQLITE_CONSTRAINT || pParse->nested );
if( onError==OE_Abort ){
sqlite3MayAbort(pParse);
diff --git a/chromium/third_party/sqlite/src/src/delete.c b/chromium/third_party/sqlite/src/src/delete.c
index ae2f85b3a9f..064ae7325a2 100644
--- a/chromium/third_party/sqlite/src/src/delete.c
+++ b/chromium/third_party/sqlite/src/src/delete.c
@@ -425,7 +425,7 @@ void sqlite3DeleteFrom(
}else
#endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */
{
- u16 wcf = WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK|WHERE_SEEK_TABLE;
+ u16 wcf = WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK;
if( sNC.ncFlags & NC_VarSelect ) bComplex = 1;
wcf |= (bComplex ? 0 : WHERE_ONEPASS_MULTIROW);
if( HasRowid(pTab) ){
@@ -461,6 +461,9 @@ void sqlite3DeleteFrom(
assert( IsVirtual(pTab)==0 || eOnePass!=ONEPASS_MULTI );
assert( IsVirtual(pTab) || bComplex || eOnePass!=ONEPASS_OFF );
if( eOnePass!=ONEPASS_SINGLE ) sqlite3MultiWrite(pParse);
+ if( sqlite3WhereUsesDeferredSeek(pWInfo) ){
+ sqlite3VdbeAddOp1(v, OP_FinishSeek, iTabCur);
+ }
/* Keep track of the number of rows to be deleted */
if( memCnt ){
@@ -495,6 +498,7 @@ void sqlite3DeleteFrom(
if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iTabCur] = 0;
if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iTabCur] = 0;
if( addrEphOpen ) sqlite3VdbeChangeToNoop(v, addrEphOpen);
+ addrBypass = sqlite3VdbeMakeLabel(pParse);
}else{
if( pPk ){
/* Add the PK key for this row to the temporary table */
@@ -508,13 +512,6 @@ void sqlite3DeleteFrom(
nKey = 1; /* OP_DeferredSeek always uses a single rowid */
sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, iKey);
}
- }
-
- /* If this DELETE cannot use the ONEPASS strategy, this is the
- ** end of the WHERE loop */
- if( eOnePass!=ONEPASS_OFF ){
- addrBypass = sqlite3VdbeMakeLabel(pParse);
- }else{
sqlite3WhereEnd(pWInfo);
}
@@ -945,10 +942,6 @@ int sqlite3GenerateIndexKey(
}
if( regOut ){
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regOut);
- if( pIdx->pTable->pSelect ){
- const char *zAff = sqlite3IndexAffinityStr(pParse->db, pIdx);
- sqlite3VdbeChangeP4(v, -1, zAff, P4_TRANSIENT);
- }
}
sqlite3ReleaseTempRange(pParse, regBase, nCol);
return regBase;
diff --git a/chromium/third_party/sqlite/src/src/expr.c b/chromium/third_party/sqlite/src/src/expr.c
index b64ea28bf5e..685f041752f 100644
--- a/chromium/third_party/sqlite/src/src/expr.c
+++ b/chromium/third_party/sqlite/src/src/expr.c
@@ -44,8 +44,10 @@ char sqlite3TableColumnAffinity(Table *pTab, int iCol){
*/
char sqlite3ExprAffinity(const Expr *pExpr){
int op;
- while( ExprHasProperty(pExpr, EP_Skip) ){
- assert( pExpr->op==TK_COLLATE || pExpr->op==TK_IF_NULL_ROW );
+ while( ExprHasProperty(pExpr, EP_Skip|EP_IfNullRow) ){
+ assert( pExpr->op==TK_COLLATE
+ || pExpr->op==TK_IF_NULL_ROW
+ || (pExpr->op==TK_REGISTER && pExpr->op2==TK_IF_NULL_ROW) );
pExpr = pExpr->pLeft;
assert( pExpr!=0 );
}
@@ -115,7 +117,7 @@ Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){
*/
Expr *sqlite3ExprSkipCollate(Expr *pExpr){
while( pExpr && ExprHasProperty(pExpr, EP_Skip) ){
- assert( pExpr->op==TK_COLLATE || pExpr->op==TK_IF_NULL_ROW );
+ assert( pExpr->op==TK_COLLATE );
pExpr = pExpr->pLeft;
}
return pExpr;
@@ -134,7 +136,7 @@ Expr *sqlite3ExprSkipCollateAndLikely(Expr *pExpr){
assert( pExpr->op==TK_FUNCTION );
pExpr = pExpr->x.pList->a[0].pExpr;
}else{
- assert( pExpr->op==TK_COLLATE || pExpr->op==TK_IF_NULL_ROW );
+ assert( pExpr->op==TK_COLLATE );
pExpr = pExpr->pLeft;
}
}
@@ -768,6 +770,7 @@ int sqlite3SelectExprHeight(Select *p){
** Expr.flags.
*/
void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){
+ if( pParse->nErr ) return;
if( p && p->x.pList && !ExprHasProperty(p, EP_xIsSelect) ){
p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList);
}
@@ -3620,6 +3623,7 @@ void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){
*/
static void exprToRegister(Expr *pExpr, int iReg){
Expr *p = sqlite3ExprSkipCollateAndLikely(pExpr);
+ if( NEVER(p==0) ) return;
p->op2 = p->op;
p->op = TK_REGISTER;
p->iTable = iReg;
@@ -4607,6 +4611,7 @@ int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){
int r2;
pExpr = sqlite3ExprSkipCollateAndLikely(pExpr);
if( ConstFactorOk(pParse)
+ && ALWAYS(pExpr!=0)
&& pExpr->op!=TK_REGISTER
&& sqlite3ExprIsConstantNotJoin(pExpr)
){
diff --git a/chromium/third_party/sqlite/src/src/func.c b/chromium/third_party/sqlite/src/src/func.c
index 48b5f5f1984..5d00c94a920 100644
--- a/chromium/third_party/sqlite/src/src/func.c
+++ b/chromium/third_party/sqlite/src/src/func.c
@@ -1995,6 +1995,8 @@ void sqlite3RegisterBuiltinFunctions(void){
FUNCTION(zeroblob, 1, 0, 0, zeroblobFunc ),
FUNCTION(substr, 2, 0, 0, substrFunc ),
FUNCTION(substr, 3, 0, 0, substrFunc ),
+ FUNCTION(substring, 2, 0, 0, substrFunc ),
+ FUNCTION(substring, 3, 0, 0, substrFunc ),
WAGGREGATE(sum, 1,0,0, sumStep, sumFinalize, sumFinalize, sumInverse, 0),
WAGGREGATE(total, 1,0,0, sumStep,totalFinalize,totalFinalize,sumInverse, 0),
WAGGREGATE(avg, 1,0,0, sumStep, avgFinalize, avgFinalize, sumInverse, 0),
diff --git a/chromium/third_party/sqlite/src/src/insert.c b/chromium/third_party/sqlite/src/src/insert.c
index 789b3b66345..393cd528f1f 100644
--- a/chromium/third_party/sqlite/src/src/insert.c
+++ b/chromium/third_party/sqlite/src/src/insert.c
@@ -32,7 +32,8 @@ void sqlite3OpenTable(
){
Vdbe *v;
assert( !IsVirtual(pTab) );
- v = sqlite3GetVdbe(pParse);
+ assert( pParse->pVdbe!=0 );
+ v = pParse->pVdbe;
assert( opcode==OP_OpenWrite || opcode==OP_OpenRead );
sqlite3TableLock(pParse, iDb, pTab->tnum,
(opcode==OP_OpenWrite)?1:0, pTab->zName);
@@ -1531,7 +1532,7 @@ void sqlite3GenerateConstraintChecks(
isUpdate = regOldData!=0;
db = pParse->db;
- v = sqlite3GetVdbe(pParse);
+ v = pParse->pVdbe;
assert( v!=0 );
assert( pTab->pSelect==0 ); /* This table is not a VIEW */
nCol = pTab->nCol;
@@ -1685,7 +1686,7 @@ void sqlite3GenerateConstraintChecks(
sqlite3VdbeGoto(v, ignoreDest);
}else{
char *zName = pCheck->a[i].zEName;
- if( zName==0 ) zName = pTab->zName;
+ assert( zName!=0 || pParse->db->mallocFailed );
if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-26383-51744 */
sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_CHECK,
onError, zName, P4_TRANSIENT,
@@ -2304,7 +2305,7 @@ void sqlite3CompleteInsertion(
|| update_flags==(OPFLAG_ISUPDATE|OPFLAG_SAVEPOSITION)
);
- v = sqlite3GetVdbe(pParse);
+ v = pParse->pVdbe;
assert( v!=0 );
assert( pTab->pSelect==0 ); /* This table is not a VIEW */
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
@@ -2405,7 +2406,7 @@ int sqlite3OpenTableAndIndices(
return 0;
}
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
- v = sqlite3GetVdbe(pParse);
+ v = pParse->pVdbe;
assert( v!=0 );
if( iBase<0 ) iBase = pParse->nTab;
iDataCur = iBase++;
diff --git a/chromium/third_party/sqlite/src/src/loadext.c b/chromium/third_party/sqlite/src/src/loadext.c
index 7007e3137dc..60cffdaed3a 100644
--- a/chromium/third_party/sqlite/src/src/loadext.c
+++ b/chromium/third_party/sqlite/src/src/loadext.c
@@ -478,6 +478,8 @@ static const sqlite3_api_routines sqlite3Apis = {
sqlite3_create_filename,
sqlite3_free_filename,
sqlite3_database_file_object,
+ /* Version 3.34.0 and later */
+ sqlite3_txn_state,
};
/* True if x is the directory separator character
diff --git a/chromium/third_party/sqlite/src/src/main.c b/chromium/third_party/sqlite/src/src/main.c
index 831e06e9333..cc1464f136c 100644
--- a/chromium/third_party/sqlite/src/src/main.c
+++ b/chromium/third_party/sqlite/src/src/main.c
@@ -897,7 +897,7 @@ int sqlite3_db_cacheflush(sqlite3 *db){
sqlite3BtreeEnterAll(db);
for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
- if( pBt && sqlite3BtreeIsInTrans(pBt) ){
+ if( pBt && sqlite3BtreeTxnState(pBt)==SQLITE_TXN_WRITE ){
Pager *pPager = sqlite3BtreePager(pBt);
rc = sqlite3PagerFlush(pPager);
if( rc==SQLITE_BUSY ){
@@ -1242,6 +1242,36 @@ static int sqlite3Close(sqlite3 *db, int forceZombie){
}
/*
+** Return the transaction state for a single databse, or the maximum
+** transaction state over all attached databases if zSchema is null.
+*/
+int sqlite3_txn_state(sqlite3 *db, const char *zSchema){
+ int iDb, nDb;
+ int iTxn = -1;
+#ifdef SQLITE_ENABLE_API_ARMOR
+ if( !sqlite3SafetyCheckOk(db) ){
+ (void)SQLITE_MISUSE_BKPT;
+ return -1;
+ }
+#endif
+ sqlite3_mutex_enter(db->mutex);
+ if( zSchema ){
+ nDb = iDb = sqlite3FindDbName(db, zSchema);
+ if( iDb<0 ) nDb--;
+ }else{
+ iDb = 0;
+ nDb = db->nDb-1;
+ }
+ for(; iDb<=nDb; iDb++){
+ Btree *pBt = db->aDb[iDb].pBt;
+ int x = pBt!=0 ? sqlite3BtreeTxnState(pBt) : SQLITE_TXN_NONE;
+ if( x>iTxn ) iTxn = x;
+ }
+ sqlite3_mutex_leave(db->mutex);
+ return iTxn;
+}
+
+/*
** Two variations on the public interface for closing a database
** connection. The sqlite3_close() version returns SQLITE_BUSY and
** leaves the connection option if there are unfinalized prepared
@@ -1401,7 +1431,7 @@ void sqlite3RollbackAll(sqlite3 *db, int tripCode){
for(i=0; i<db->nDb; i++){
Btree *p = db->aDb[i].pBt;
if( p ){
- if( sqlite3BtreeIsInTrans(p) ){
+ if( sqlite3BtreeTxnState(p)==SQLITE_TXN_WRITE ){
inTrans = 1;
}
sqlite3BtreeRollback(p, tripCode, !schemaChange);
@@ -3822,7 +3852,9 @@ int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){
}
rc = SQLITE_OK;
}else{
+ int nSave = db->busyHandler.nBusy;
rc = sqlite3OsFileControl(fd, op, pArg);
+ db->busyHandler.nBusy = nSave;
}
sqlite3BtreeLeave(pBtree);
}
@@ -4205,6 +4237,25 @@ int sqlite3_test_control(int op, ...){
sqlite3ResultIntReal(pCtx);
break;
}
+
+ /* sqlite3_test_control(SQLITE_TESTCTRL_SEEK_COUNT,
+ ** sqlite3 *db, // Database connection
+ ** u64 *pnSeek // Write seek count here
+ ** );
+ **
+ ** This test-control queries the seek-counter on the "main" database
+ ** file. The seek-counter is written into *pnSeek and is then reset.
+ ** The seek-count is only available if compiled with SQLITE_DEBUG.
+ */
+ case SQLITE_TESTCTRL_SEEK_COUNT: {
+ sqlite3 *db = va_arg(ap, sqlite3*);
+ u64 *pn = va_arg(ap, sqlite3_uint64*);
+ *pn = sqlite3BtreeSeekCount(db->aDb->pBt);
+ (void)db; /* Silence harmless unused variable warning */
+ break;
+ }
+
+
}
va_end(ap);
#endif /* SQLITE_UNTESTABLE */
@@ -4440,7 +4491,7 @@ int sqlite3_snapshot_get(
int iDb = sqlite3FindDbName(db, zDb);
if( iDb==0 || iDb>1 ){
Btree *pBt = db->aDb[iDb].pBt;
- if( 0==sqlite3BtreeIsInTrans(pBt) ){
+ if( SQLITE_TXN_WRITE!=sqlite3BtreeTxnState(pBt) ){
rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
if( rc==SQLITE_OK ){
rc = sqlite3PagerSnapshotGet(sqlite3BtreePager(pBt), ppSnapshot);
@@ -4476,10 +4527,10 @@ int sqlite3_snapshot_open(
iDb = sqlite3FindDbName(db, zDb);
if( iDb==0 || iDb>1 ){
Btree *pBt = db->aDb[iDb].pBt;
- if( sqlite3BtreeIsInTrans(pBt)==0 ){
+ if( sqlite3BtreeTxnState(pBt)!=SQLITE_TXN_WRITE ){
Pager *pPager = sqlite3BtreePager(pBt);
int bUnlock = 0;
- if( sqlite3BtreeIsInReadTrans(pBt) ){
+ if( sqlite3BtreeTxnState(pBt)!=SQLITE_TXN_NONE ){
if( db->nVdbeActive==0 ){
rc = sqlite3PagerSnapshotCheck(pPager, pSnapshot);
if( rc==SQLITE_OK ){
@@ -4528,7 +4579,7 @@ int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb){
iDb = sqlite3FindDbName(db, zDb);
if( iDb==0 || iDb>1 ){
Btree *pBt = db->aDb[iDb].pBt;
- if( 0==sqlite3BtreeIsInReadTrans(pBt) ){
+ if( SQLITE_TXN_NONE==sqlite3BtreeTxnState(pBt) ){
rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
if( rc==SQLITE_OK ){
rc = sqlite3PagerSnapshotRecover(sqlite3BtreePager(pBt));
diff --git a/chromium/third_party/sqlite/src/src/malloc.c b/chromium/third_party/sqlite/src/src/malloc.c
index 70e6ff94e5a..a0f7a739c0a 100644
--- a/chromium/third_party/sqlite/src/src/malloc.c
+++ b/chromium/third_party/sqlite/src/src/malloc.c
@@ -474,12 +474,17 @@ void *sqlite3Realloc(void *pOld, u64 nBytes){
if( nOld==nNew ){
pNew = pOld;
}else if( sqlite3GlobalConfig.bMemstat ){
+ sqlite3_int64 nUsed;
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, (int)nBytes);
nDiff = nNew - nOld;
- if( nDiff>0 && sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >=
+ if( nDiff>0 && (nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED)) >=
mem0.alarmThreshold-nDiff ){
sqlite3MallocAlarm(nDiff);
+ if( mem0.hardLimit>0 && nUsed >= mem0.hardLimit - nDiff ){
+ sqlite3_mutex_leave(mem0.mutex);
+ return 0;
+ }
}
pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
@@ -786,12 +791,15 @@ void sqlite3OomClear(sqlite3 *db){
}
/*
-** Take actions at the end of an API call to indicate an OOM error
+** Take actions at the end of an API call to deal with error codes.
*/
-static SQLITE_NOINLINE int apiOomError(sqlite3 *db){
- sqlite3OomClear(db);
- sqlite3Error(db, SQLITE_NOMEM);
- return SQLITE_NOMEM_BKPT;
+static SQLITE_NOINLINE int apiHandleError(sqlite3 *db, int rc){
+ if( db->mallocFailed || rc==SQLITE_IOERR_NOMEM ){
+ sqlite3OomClear(db);
+ sqlite3Error(db, SQLITE_NOMEM);
+ return SQLITE_NOMEM_BKPT;
+ }
+ return rc & db->errMask;
}
/*
@@ -813,8 +821,8 @@ int sqlite3ApiExit(sqlite3* db, int rc){
*/
assert( db!=0 );
assert( sqlite3_mutex_held(db->mutex) );
- if( db->mallocFailed || rc==SQLITE_IOERR_NOMEM ){
- return apiOomError(db);
+ if( db->mallocFailed || rc ){
+ return apiHandleError(db, rc);
}
return rc & db->errMask;
}
diff --git a/chromium/third_party/sqlite/src/src/memdb.c b/chromium/third_party/sqlite/src/src/memdb.c
index dc969a47e85..a48980aa341 100644
--- a/chromium/third_party/sqlite/src/src/memdb.c
+++ b/chromium/third_party/sqlite/src/src/memdb.c
@@ -126,11 +126,14 @@ static const sqlite3_io_methods memdb_io_methods = {
** Close an memdb-file.
**
** The pData pointer is owned by the application, so there is nothing
-** to free.
+** to free. Unless the SQLITE_DESERIALIZE_FREEONCLOSE flag is set,
+** in which case we own the pData pointer and need to free it.
*/
static int memdbClose(sqlite3_file *pFile){
MemFile *p = (MemFile *)pFile;
- if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ) sqlite3_free(p->aData);
+ if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ){
+ sqlite3_free(p->aData);
+ }
return SQLITE_OK;
}
@@ -573,8 +576,12 @@ int sqlite3_deserialize(
goto end_deserialize;
}
zSql = sqlite3_mprintf("ATTACH x AS %Q", zSchema);
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
- sqlite3_free(zSql);
+ if( zSql==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ 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;
@@ -589,6 +596,7 @@ int sqlite3_deserialize(
rc = SQLITE_ERROR;
}else{
p->aData = pData;
+ pData = 0;
p->sz = szDb;
p->szAlloc = szBuf;
p->szMax = szBuf;
@@ -601,6 +609,9 @@ int sqlite3_deserialize(
end_deserialize:
sqlite3_finalize(pStmt);
+ if( pData && (mFlags & SQLITE_DESERIALIZE_FREEONCLOSE)!=0 ){
+ sqlite3_free(pData);
+ }
sqlite3_mutex_leave(db->mutex);
return rc;
}
diff --git a/chromium/third_party/sqlite/src/src/os_unix.c b/chromium/third_party/sqlite/src/src/os_unix.c
index fc54153333c..a688ed2706e 100644
--- a/chromium/third_party/sqlite/src/src/os_unix.c
+++ b/chromium/third_party/sqlite/src/src/os_unix.c
@@ -122,7 +122,8 @@
# if defined(__APPLE__) && ((__MAC_OS_X_VERSION_MIN_REQUIRED > 1050) || \
(__IPHONE_OS_VERSION_MIN_REQUIRED > 2000))
# if (!defined(TARGET_OS_EMBEDDED) || (TARGET_OS_EMBEDDED==0)) \
- && (!defined(TARGET_IPHONE_SIMULATOR) || (TARGET_IPHONE_SIMULATOR==0))
+ && (!defined(TARGET_IPHONE_SIMULATOR) || (TARGET_IPHONE_SIMULATOR==0))\
+ && (!defined(TARGET_OS_MACCATALYST) || (TARGET_OS_MACCATALYST==0))
# undef HAVE_GETHOSTUUID
# define HAVE_GETHOSTUUID 1
# else
@@ -1544,6 +1545,9 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
return rc;
}
+/* Forward declaration*/
+static int unixSleep(sqlite3_vfs*,int);
+
/*
** Set a posix-advisory-lock.
**
@@ -1573,7 +1577,7 @@ static int osSetPosixAdvisoryLock(
** 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);
+ unixSleep(0,1000);
rc = osFcntl(h,F_SETLK,pLock);
tm--;
}
@@ -2144,6 +2148,7 @@ static int unixClose(sqlite3_file *id){
}
sqlite3_mutex_leave(pInode->pLockMutex);
releaseInodeInfo(pFile);
+ assert( pFile->pShm==0 );
rc = closeUnixFile(id);
unixLeaveMutex();
return rc;
@@ -3370,7 +3375,24 @@ static int unixRead(
if( got==amt ){
return SQLITE_OK;
}else if( got<0 ){
- /* lastErrno set by seekAndRead */
+ /* pFile->lastErrno has been set by seekAndRead().
+ ** Usually we return SQLITE_IOERR_READ here, though for some
+ ** kinds of errors we return SQLITE_IOERR_CORRUPTFS. The
+ ** SQLITE_IOERR_CORRUPTFS will be converted into SQLITE_CORRUPT
+ ** prior to returning to the application by the sqlite3ApiExit()
+ ** routine.
+ */
+ switch( pFile->lastErrno ){
+ case ERANGE:
+ case EIO:
+#ifdef ENXIO
+ case ENXIO:
+#endif
+#ifdef EDEVERR
+ case EDEVERR:
+#endif
+ return SQLITE_IOERR_CORRUPTFS;
+ }
return SQLITE_IOERR_READ;
}else{
storeLastErrno(pFile, 0); /* not a system error */
@@ -4254,6 +4276,7 @@ struct unixShmNode {
char **apRegion; /* Array of mapped shared-memory regions */
int nRef; /* Number of unixShm objects pointing to this */
unixShm *pFirst; /* All unixShm objects pointing to this */
+ int aLock[SQLITE_SHM_NLOCK]; /* # shared locks on slot, -1==excl lock */
#ifdef SQLITE_DEBUG
u8 exclMask; /* Mask of exclusive locks held */
u8 sharedMask; /* Mask of shared locks held */
@@ -4795,6 +4818,38 @@ shmpage_out:
}
/*
+** Check that the pShmNode->aLock[] array comports with the locking bitmasks
+** held by each client. Return true if it does, or false otherwise. This
+** is to be used in an assert(). e.g.
+**
+** assert( assertLockingArrayOk(pShmNode) );
+*/
+#ifdef SQLITE_DEBUG
+static int assertLockingArrayOk(unixShmNode *pShmNode){
+ unixShm *pX;
+ int aLock[SQLITE_SHM_NLOCK];
+ assert( sqlite3_mutex_held(pShmNode->pShmMutex) );
+
+ memset(aLock, 0, sizeof(aLock));
+ for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
+ int i;
+ for(i=0; i<SQLITE_SHM_NLOCK; i++){
+ if( pX->exclMask & (1<<i) ){
+ assert( aLock[i]==0 );
+ aLock[i] = -1;
+ }else if( pX->sharedMask & (1<<i) ){
+ assert( aLock[i]>=0 );
+ aLock[i]++;
+ }
+ }
+ }
+
+ assert( 0==memcmp(pShmNode->aLock, aLock, sizeof(aLock)) );
+ return (memcmp(pShmNode->aLock, aLock, sizeof(aLock))==0);
+}
+#endif
+
+/*
** Change the lock state for a shared-memory segment.
**
** Note that the relationship between SHAREd and EXCLUSIVE locks is a little
@@ -4810,10 +4865,10 @@ static int unixShmLock(
){
unixFile *pDbFd = (unixFile*)fd; /* Connection holding shared memory */
unixShm *p = pDbFd->pShm; /* The shared memory being locked */
- unixShm *pX; /* For looping over all siblings */
unixShmNode *pShmNode = p->pShmNode; /* The underlying file iNode */
int rc = SQLITE_OK; /* Result code */
u16 mask; /* Mask of locks to take or release */
+ int *aLock = pShmNode->aLock;
assert( pShmNode==pDbFd->pInode->pShmNode );
assert( pShmNode->pInode==pDbFd->pInode );
@@ -4852,78 +4907,76 @@ static int unixShmLock(
mask = (1<<(ofst+n)) - (1<<ofst);
assert( n>1 || mask==(1<<ofst) );
sqlite3_mutex_enter(pShmNode->pShmMutex);
+ assert( assertLockingArrayOk(pShmNode) );
if( flags & SQLITE_SHM_UNLOCK ){
- u16 allMask = 0; /* Mask of locks held by siblings */
+ if( (p->exclMask|p->sharedMask) & mask ){
+ int ii;
+ int bUnlock = 1;
- /* See if any siblings hold this same lock */
- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
- if( pX==p ) continue;
- assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
- allMask |= pX->sharedMask;
- }
+ for(ii=ofst; ii<ofst+n; ii++){
+ if( aLock[ii]>((p->sharedMask & (1<<ii)) ? 1 : 0) ){
+ bUnlock = 0;
+ }
+ }
- /* Unlock the system-level locks */
- if( (mask & allMask)==0 ){
- rc = unixShmSystemLock(pDbFd, F_UNLCK, ofst+UNIX_SHM_BASE, n);
- }else{
- rc = SQLITE_OK;
- }
+ if( bUnlock ){
+ rc = unixShmSystemLock(pDbFd, F_UNLCK, ofst+UNIX_SHM_BASE, n);
+ if( rc==SQLITE_OK ){
+ memset(&aLock[ofst], 0, sizeof(int)*n);
+ }
+ }else if( ALWAYS(p->sharedMask & (1<<ofst)) ){
+ assert( n==1 && aLock[ofst]>1 );
+ aLock[ofst]--;
+ }
- /* Undo the local locks */
- if( rc==SQLITE_OK ){
- p->exclMask &= ~mask;
- p->sharedMask &= ~mask;
- }
+ /* Undo the local locks */
+ if( rc==SQLITE_OK ){
+ p->exclMask &= ~mask;
+ p->sharedMask &= ~mask;
+ }
+ }
}else if( flags & SQLITE_SHM_SHARED ){
- u16 allShared = 0; /* Union of locks held by connections other than "p" */
-
- /* Find out which shared locks are already held by sibling connections.
- ** If any sibling already holds an exclusive lock, go ahead and return
- ** SQLITE_BUSY.
- */
- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
- if( (pX->exclMask & mask)!=0 ){
+ assert( n==1 );
+ assert( (p->exclMask & (1<<ofst))==0 );
+ if( (p->sharedMask & mask)==0 ){
+ if( aLock[ofst]<0 ){
rc = SQLITE_BUSY;
- break;
- }
- allShared |= pX->sharedMask;
- }
-
- /* Get shared locks at the system level, if necessary */
- if( rc==SQLITE_OK ){
- if( (allShared & mask)==0 ){
+ }else if( aLock[ofst]==0 ){
rc = unixShmSystemLock(pDbFd, F_RDLCK, ofst+UNIX_SHM_BASE, n);
- }else{
- rc = SQLITE_OK;
}
- }
- /* Get the local shared locks */
- if( rc==SQLITE_OK ){
- p->sharedMask |= mask;
+ /* Get the local shared locks */
+ if( rc==SQLITE_OK ){
+ p->sharedMask |= mask;
+ aLock[ofst]++;
+ }
}
}else{
/* Make sure no sibling connections hold locks that will block this
- ** lock. If any do, return SQLITE_BUSY right away.
- */
- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
- if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){
+ ** lock. If any do, return SQLITE_BUSY right away. */
+ int ii;
+ for(ii=ofst; ii<ofst+n; ii++){
+ assert( (p->sharedMask & mask)==0 );
+ if( ALWAYS((p->exclMask & (1<<ii))==0) && aLock[ii] ){
rc = SQLITE_BUSY;
break;
}
}
-
- /* Get the exclusive locks at the system level. Then if successful
- ** also mark the local connection as being locked.
- */
+
+ /* Get the exclusive locks at the system level. Then if successful
+ ** also update the in-memory values. */
if( rc==SQLITE_OK ){
rc = unixShmSystemLock(pDbFd, F_WRLCK, ofst+UNIX_SHM_BASE, n);
if( rc==SQLITE_OK ){
assert( (p->sharedMask & mask)==0 );
p->exclMask |= mask;
+ for(ii=ofst; ii<ofst+n; ii++){
+ aLock[ii] = -1;
+ }
}
}
}
+ assert( assertLockingArrayOk(pShmNode) );
sqlite3_mutex_leave(pShmNode->pShmMutex);
OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n",
p->id, osGetpid(0), p->sharedMask, p->exclMask));
@@ -6300,7 +6353,26 @@ static int unixAccess(
}
/*
+** If the last component of the pathname in z[0]..z[j-1] is something
+** other than ".." then back it out and return true. If the last
+** component is empty or if it is ".." then return false.
+*/
+static int unixBackupDir(const char *z, int *pJ){
+ int j = *pJ;
+ int i;
+ if( j<=0 ) return 0;
+ for(i=j-1; ALWAYS(i>0) && z[i-1]!='/'; i--){}
+ if( z[i]=='.' && i==j-2 && z[i+1]=='.' ) return 0;
+ *pJ = i-1;
+ return 1;
+}
+
+/*
+** Convert a relative pathname into a full pathname. Also
+** simplify the pathname as follows:
**
+** Remove all instances of /./
+** Remove all isntances of /X/../ for any X
*/
static int mkFullPathname(
const char *zPath, /* Input path */
@@ -6309,6 +6381,7 @@ static int mkFullPathname(
){
int nPath = sqlite3Strlen30(zPath);
int iOff = 0;
+ int i, j;
if( zPath[0]!='/' ){
if( osGetcwd(zOut, nOut-2)==0 ){
return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath);
@@ -6323,6 +6396,41 @@ static int mkFullPathname(
return SQLITE_CANTOPEN_BKPT;
}
sqlite3_snprintf(nOut-iOff, &zOut[iOff], "%s", zPath);
+
+ /* Remove duplicate '/' characters. Except, two // at the beginning
+ ** of a pathname is allowed since this is important on windows. */
+ for(i=j=1; zOut[i]; i++){
+ zOut[j++] = zOut[i];
+ while( zOut[i]=='/' && zOut[i+1]=='/' ) i++;
+ }
+ zOut[j] = 0;
+
+ assert( zOut[0]=='/' );
+ for(i=j=0; zOut[i]; i++){
+ if( zOut[i]=='/' ){
+ /* Skip over internal "/." directory components */
+ if( zOut[i+1]=='.' && zOut[i+2]=='/' ){
+ i += 1;
+ continue;
+ }
+
+ /* If this is a "/.." directory component then back out the
+ ** previous term of the directory if it is something other than "..".
+ */
+ if( zOut[i+1]=='.'
+ && zOut[i+2]=='.'
+ && zOut[i+3]=='/'
+ && unixBackupDir(zOut, &j)
+ ){
+ i += 2;
+ continue;
+ }
+ }
+ if( ALWAYS(j>=0) ) zOut[j] = zOut[i];
+ j++;
+ }
+ if( NEVER(j==0) ) zOut[j++] = '/';
+ zOut[j] = 0;
return SQLITE_OK;
}
@@ -6543,7 +6651,8 @@ static int unixSleep(sqlite3_vfs *NotUsed, int microseconds){
UNUSED_PARAMETER(NotUsed);
return microseconds;
#elif defined(HAVE_USLEEP) && HAVE_USLEEP
- usleep(microseconds);
+ if( microseconds>=1000000 ) sleep(microseconds/1000000);
+ if( microseconds%1000000 ) usleep(microseconds%1000000);
UNUSED_PARAMETER(NotUsed);
return microseconds;
#else
@@ -7116,7 +7225,7 @@ static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){
if( nTries==1 ){
conchModTime = buf.st_mtimespec;
- usleep(500000); /* wait 0.5 sec and try the lock again*/
+ unixSleep(0,500000); /* wait 0.5 sec and try the lock again*/
continue;
}
@@ -7142,7 +7251,7 @@ static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){
/* don't break the lock on short read or a version mismatch */
return SQLITE_BUSY;
}
- usleep(10000000); /* wait 10 sec and try the lock again */
+ unixSleep(0,10000000); /* wait 10 sec and try the lock again */
continue;
}
diff --git a/chromium/third_party/sqlite/src/src/os_win.c b/chromium/third_party/sqlite/src/src/os_win.c
index 1f22fd992ab..d7c436eff91 100644
--- a/chromium/third_party/sqlite/src/src/os_win.c
+++ b/chromium/third_party/sqlite/src/src/os_win.c
@@ -5126,7 +5126,11 @@ static int winOpen(
dwCreationDisposition = OPEN_EXISTING;
}
- dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
+ if( 0==sqlite3_uri_boolean(zName, "exclusive", 0) ){
+ dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
+ }else{
+ dwShareMode = 0;
+ }
if( isDelete ){
#if SQLITE_OS_WINCE
diff --git a/chromium/third_party/sqlite/src/src/pager.c b/chromium/third_party/sqlite/src/src/pager.c
index 005d678f942..a5510e7eb8d 100644
--- a/chromium/third_party/sqlite/src/src/pager.c
+++ b/chromium/third_party/sqlite/src/src/pager.c
@@ -2486,6 +2486,7 @@ static int pager_delsuper(Pager *pPager, const char *zSuper){
i64 nSuperJournal; /* Size of super-journal file */
char *zJournal; /* Pointer to one journal within MJ file */
char *zSuperPtr; /* Space to hold super-journal filename */
+ char *zFree = 0; /* Free this buffer */
int nSuperPtr; /* Amount of space allocated to zSuperPtr[] */
/* Allocate space for both the pJournal and pSuper file descriptors.
@@ -2510,11 +2511,13 @@ static int pager_delsuper(Pager *pPager, const char *zSuper){
rc = sqlite3OsFileSize(pSuper, &nSuperJournal);
if( rc!=SQLITE_OK ) goto delsuper_out;
nSuperPtr = pVfs->mxPathname+1;
- zSuperJournal = sqlite3Malloc(nSuperJournal + nSuperPtr + 2);
- if( !zSuperJournal ){
+ zFree = sqlite3Malloc(4 + nSuperJournal + nSuperPtr + 2);
+ if( !zFree ){
rc = SQLITE_NOMEM_BKPT;
goto delsuper_out;
}
+ zFree[0] = zFree[1] = zFree[2] = zFree[3] = 0;
+ zSuperJournal = &zFree[4];
zSuperPtr = &zSuperJournal[nSuperJournal+2];
rc = sqlite3OsRead(pSuper, zSuperJournal, (int)nSuperJournal, 0);
if( rc!=SQLITE_OK ) goto delsuper_out;
@@ -2562,7 +2565,7 @@ static int pager_delsuper(Pager *pPager, const char *zSuper){
rc = sqlite3OsDelete(pVfs, zSuper, 0);
delsuper_out:
- sqlite3_free(zSuperJournal);
+ sqlite3_free(zFree);
if( pSuper ){
sqlite3OsClose(pSuper);
assert( !isOpen(pJournal) );
@@ -2900,7 +2903,11 @@ end_playback:
pPager->changeCountDone = pPager->tempFile;
if( rc==SQLITE_OK ){
- zSuper = pPager->pTmpSpace;
+ /* Leave 4 bytes of space before the super-journal filename in memory.
+ ** This is because it may end up being passed to sqlite3OsOpen(), in
+ ** which case it requires 4 0x00 bytes in memory immediately before
+ ** the filename. */
+ zSuper = &pPager->pTmpSpace[4];
rc = readSuperJournal(pPager->jfd, zSuper, pPager->pVfs->mxPathname+1);
testcase( rc!=SQLITE_OK );
}
@@ -2917,6 +2924,8 @@ end_playback:
/* If there was a super-journal and this routine will return success,
** see if it is possible to delete the super-journal.
*/
+ assert( zSuper==&pPager->pTmpSpace[4] );
+ memset(&zSuper[-4], 0, 4);
rc = pager_delsuper(pPager, zSuper);
testcase( rc!=SQLITE_OK );
}
diff --git a/chromium/third_party/sqlite/src/src/parse.y b/chromium/third_party/sqlite/src/src/parse.y
index 44e0b4f343a..d3ec2b3da65 100644
--- a/chromium/third_party/sqlite/src/src/parse.y
+++ b/chromium/third_party/sqlite/src/src/parse.y
@@ -1,5 +1,6 @@
+%include {
/*
-** 2001 September 15
+** 2001-09-15
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
@@ -9,11 +10,16 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
-** This file contains SQLite's grammar for SQL. Process this file
-** using the lemon parser generator to generate C code that runs
-** the parser. Lemon will also generate a header file containing
-** numeric codes for all of the tokens.
+** This file contains SQLite's SQL parser.
+**
+** The canonical source code to this file ("parse.y") is a Lemon grammar
+** file that specifies the input grammar and actions to take while parsing.
+** That input file is processed by Lemon to generate a C-language
+** implementation of a parser for the given grammer. You might be reading
+** this comment as part of the translated C-code. Edits should be made
+** to the original parse.y sources.
*/
+}
// All token codes are small integers with #defines that begin with "TK_"
%token_prefix TK_
@@ -366,7 +372,7 @@ ccons ::= PRIMARY KEY sortorder(Z) onconf(R) autoinc(I).
{sqlite3AddPrimaryKey(pParse,0,R,I,Z);}
ccons ::= UNIQUE onconf(R). {sqlite3CreateIndex(pParse,0,0,0,0,R,0,0,0,0,
SQLITE_IDXTYPE_UNIQUE);}
-ccons ::= CHECK LP expr(X) RP. {sqlite3AddCheckConstraint(pParse,X);}
+ccons ::= CHECK LP(A) expr(X) RP(B). {sqlite3AddCheckConstraint(pParse,X,A.z,B.z);}
ccons ::= REFERENCES nm(T) eidlist_opt(TA) refargs(R).
{sqlite3CreateForeignKey(pParse,0,&T,TA,R);}
ccons ::= defer_subclause(D). {sqlite3DeferForeignKey(pParse,D);}
@@ -420,8 +426,8 @@ tcons ::= PRIMARY KEY LP sortlist(X) autoinc(I) RP onconf(R).
tcons ::= UNIQUE LP sortlist(X) RP onconf(R).
{sqlite3CreateIndex(pParse,0,0,0,X,R,0,0,0,0,
SQLITE_IDXTYPE_UNIQUE);}
-tcons ::= CHECK LP expr(E) RP onconf.
- {sqlite3AddCheckConstraint(pParse,E);}
+tcons ::= CHECK LP(A) expr(E) RP(B) onconf.
+ {sqlite3AddCheckConstraint(pParse,E,A.z,B.z);}
tcons ::= FOREIGN KEY LP eidlist(FA) RP
REFERENCES nm(T) eidlist_opt(TA) refargs(R) defer_subclause_opt(D). {
sqlite3CreateForeignKey(pParse, FA, &T, TA, R);
diff --git a/chromium/third_party/sqlite/src/src/pragma.c b/chromium/third_party/sqlite/src/src/pragma.c
index 97ad5ac90b7..7be0f7f2563 100644
--- a/chromium/third_party/sqlite/src/src/pragma.c
+++ b/chromium/third_party/sqlite/src/src/pragma.c
@@ -131,7 +131,9 @@ static int getTempStore(const char *z){
static int invalidateTempStorage(Parse *pParse){
sqlite3 *db = pParse->db;
if( db->aDb[1].pBt!=0 ){
- if( !db->autoCommit || sqlite3BtreeIsInReadTrans(db->aDb[1].pBt) ){
+ if( !db->autoCommit
+ || sqlite3BtreeTxnState(db->aDb[1].pBt)!=SQLITE_TXN_NONE
+ ){
sqlite3ErrorMsg(pParse, "temporary storage cannot be changed "
"from within a transaction");
return SQLITE_ERROR;
@@ -1451,7 +1453,7 @@ void sqlite3Pragma(
aiCols = 0;
if( pParent ){
x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols);
- assert( x==0 );
+ assert( x==0 || db->mallocFailed );
}
addrOk = sqlite3VdbeMakeLabel(pParse);
@@ -1476,7 +1478,7 @@ void sqlite3Pragma(
int jmp = sqlite3VdbeCurrentAddr(v)+2;
sqlite3VdbeAddOp3(v, OP_SeekRowid, i, jmp, regRow); VdbeCoverage(v);
sqlite3VdbeGoto(v, addrOk);
- assert( pFK->nCol==1 );
+ assert( pFK->nCol==1 || db->mallocFailed );
}
/* Generate code to report an FK violation to the caller. */
diff --git a/chromium/third_party/sqlite/src/src/prepare.c b/chromium/third_party/sqlite/src/src/prepare.c
index 8e2186b1026..13fd1d33b22 100644
--- a/chromium/third_party/sqlite/src/src/prepare.c
+++ b/chromium/third_party/sqlite/src/src/prepare.c
@@ -240,7 +240,7 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
** on the b-tree database, open one now. If a transaction is opened, it
** will be closed before this function returns. */
sqlite3BtreeEnter(pDb->pBt);
- if( !sqlite3BtreeIsInReadTrans(pDb->pBt) ){
+ if( sqlite3BtreeTxnState(pDb->pBt)==SQLITE_TXN_NONE ){
rc = sqlite3BtreeBeginTrans(pDb->pBt, 0, 0);
if( rc!=SQLITE_OK ){
sqlite3SetString(pzErrMsg, db, sqlite3ErrStr(rc));
@@ -483,7 +483,7 @@ static void schemaIsValid(Parse *pParse){
/* If there is not already a read-only (or read-write) transaction opened
** on the b-tree database, open one now. If a transaction is opened, it
** will be closed immediately after reading the meta-value. */
- if( !sqlite3BtreeIsInReadTrans(pBt) ){
+ if( sqlite3BtreeTxnState(pBt)==SQLITE_TXN_NONE ){
rc = sqlite3BtreeBeginTrans(pBt, 0, 0);
if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
sqlite3OomFault(db);
@@ -746,6 +746,7 @@ static int sqlite3LockAndPrepare(
sqlite3BtreeLeaveAll(db);
rc = sqlite3ApiExit(db, rc);
assert( (rc&db->errMask)==rc );
+ db->busyHandler.nBusy = 0;
sqlite3_mutex_leave(db->mutex);
return rc;
}
diff --git a/chromium/third_party/sqlite/src/src/printf.c b/chromium/third_party/sqlite/src/src/printf.c
index 2f99208bf30..f78d3bbb178 100644
--- a/chromium/third_party/sqlite/src/src/printf.c
+++ b/chromium/third_party/sqlite/src/src/printf.c
@@ -427,11 +427,10 @@ void sqlite3_str_vappendf(
v = va_arg(ap,int);
}
if( v<0 ){
- if( v==SMALLEST_INT64 ){
- longvalue = ((u64)1)<<63;
- }else{
- longvalue = -v;
- }
+ testcase( v==SMALLEST_INT64 );
+ testcase( v==(-1) );
+ longvalue = ~v;
+ longvalue++;
prefix = '-';
}else{
longvalue = v;
diff --git a/chromium/third_party/sqlite/src/src/resolve.c b/chromium/third_party/sqlite/src/src/resolve.c
index fcb6f152245..b55bdc41871 100644
--- a/chromium/third_party/sqlite/src/src/resolve.c
+++ b/chromium/third_party/sqlite/src/src/resolve.c
@@ -1075,7 +1075,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
assert( !ExprHasProperty(pExpr, EP_Reduced) );
/* Handle special cases of "x IS TRUE", "x IS FALSE", "x IS NOT TRUE",
** and "x IS NOT FALSE". */
- if( pRight && pRight->op==TK_ID ){
+ if( pRight && (pRight->op==TK_ID || pRight->op==TK_TRUEFALSE) ){
int rc = resolveExprStep(pWalker, pRight);
if( rc==WRC_Abort ) return WRC_Abort;
if( pRight->op==TK_TRUEFALSE ){
@@ -1284,6 +1284,7 @@ static int resolveCompoundOrderBy(
Expr *pE, *pDup;
if( pItem->done ) continue;
pE = sqlite3ExprSkipCollateAndLikely(pItem->pExpr);
+ if( NEVER(pE==0) ) continue;
if( sqlite3ExprIsInteger(pE, &iCol) ){
if( iCol<=0 || iCol>pEList->nExpr ){
resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr);
@@ -1463,6 +1464,7 @@ static int resolveOrderGroupBy(
for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
Expr *pE = pItem->pExpr;
Expr *pE2 = sqlite3ExprSkipCollateAndLikely(pE);
+ if( NEVER(pE2==0) ) continue;
if( zType[0]!='G' ){
iCol = resolveAsName(pParse, pSelect->pEList, pE2);
if( iCol>0 ){
diff --git a/chromium/third_party/sqlite/src/src/select.c b/chromium/third_party/sqlite/src/src/select.c
index 8b1fae75a51..b4f27267939 100644
--- a/chromium/third_party/sqlite/src/src/select.c
+++ b/chromium/third_party/sqlite/src/src/select.c
@@ -1972,6 +1972,7 @@ int sqlite3ColumnsFromExprList(
char *zName; /* Column name */
int nName; /* Size of name in zName[] */
Hash ht; /* Hash table of column names */
+ Table *pTab;
sqlite3HashInit(&ht);
if( pEList ){
@@ -1994,15 +1995,13 @@ int sqlite3ColumnsFromExprList(
/* If the column contains an "AS <name>" phrase, use <name> as the name */
}else{
Expr *pColExpr = sqlite3ExprSkipCollateAndLikely(pEList->a[i].pExpr);
- while( pColExpr->op==TK_DOT ){
+ while( ALWAYS(pColExpr!=0) && pColExpr->op==TK_DOT ){
pColExpr = pColExpr->pRight;
assert( pColExpr!=0 );
}
- if( pColExpr->op==TK_COLUMN ){
+ if( pColExpr->op==TK_COLUMN && (pTab = pColExpr->y.pTab)!=0 ){
/* For columns use the column name name */
int iCol = pColExpr->iColumn;
- Table *pTab = pColExpr->y.pTab;
- assert( pTab!=0 );
if( iCol<0 ) iCol = pTab->iPKey;
zName = iCol>=0 ? pTab->aCol[iCol].zName : "rowid";
}else if( pColExpr->op==TK_ID ){
@@ -2340,6 +2339,7 @@ static void generateWithRecursiveQuery(
int nCol = p->pEList->nExpr; /* Number of columns in the recursive table */
Vdbe *v = pParse->pVdbe; /* The prepared statement under construction */
Select *pSetup = p->pPrior; /* The setup query */
+ Select *pFirstRec; /* Left-most recursive term */
int addrTop; /* Top of the loop */
int addrCont, addrBreak; /* CONTINUE and BREAK addresses */
int iCurrent = 0; /* The Current table */
@@ -2415,7 +2415,25 @@ static void generateWithRecursiveQuery(
/* Detach the ORDER BY clause from the compound SELECT */
p->pOrderBy = 0;
+ /* Figure out how many elements of the compound SELECT are part of the
+ ** recursive query. Make sure no recursive elements use aggregate
+ ** functions. Mark the recursive elements as UNION ALL even if they
+ ** are really UNION because the distinctness will be enforced by the
+ ** iDistinct table. pFirstRec is left pointing to the left-most
+ ** recursive term of the CTE.
+ */
+ pFirstRec = p;
+ for(pFirstRec=p; ALWAYS(pFirstRec!=0); pFirstRec=pFirstRec->pPrior){
+ if( pFirstRec->selFlags & SF_Aggregate ){
+ sqlite3ErrorMsg(pParse, "recursive aggregate queries not supported");
+ goto end_of_recursive_query;
+ }
+ pFirstRec->op = TK_ALL;
+ if( (pFirstRec->pPrior->selFlags & SF_Recursive)==0 ) break;
+ }
+
/* Store the results of the setup-query in Queue. */
+ pSetup = pFirstRec->pPrior;
pSetup->pNext = 0;
ExplainQueryPlan((pParse, 1, "SETUP"));
rc = sqlite3Select(pParse, pSetup, &destQueue);
@@ -2448,15 +2466,11 @@ static void generateWithRecursiveQuery(
/* Execute the recursive SELECT taking the single row in Current as
** the value for the recursive-table. Store the results in the Queue.
*/
- if( p->selFlags & SF_Aggregate ){
- sqlite3ErrorMsg(pParse, "recursive aggregate queries not supported");
- }else{
- p->pPrior = 0;
- ExplainQueryPlan((pParse, 1, "RECURSIVE STEP"));
- sqlite3Select(pParse, p, &destQueue);
- assert( p->pPrior==0 );
- p->pPrior = pSetup;
- }
+ pFirstRec->pPrior = 0;
+ ExplainQueryPlan((pParse, 1, "RECURSIVE STEP"));
+ sqlite3Select(pParse, p, &destQueue);
+ assert( pFirstRec->pPrior==0 );
+ pFirstRec->pPrior = pSetup;
/* Keep running the loop until the Queue is empty */
sqlite3VdbeGoto(v, addrTop);
@@ -2526,6 +2540,16 @@ static int multiSelectValues(
}
/*
+** Return true if the SELECT statement which is known to be the recursive
+** part of a recursive CTE still has its anchor terms attached. If the
+** anchor terms have already been removed, then return false.
+*/
+static int hasAnchor(Select *p){
+ while( p && (p->selFlags & SF_Recursive)!=0 ){ p = p->pPrior; }
+ return p!=0;
+}
+
+/*
** This routine is called to process a compound query form from
** two or more separate queries using UNION, UNION ALL, EXCEPT, or
** INTERSECT
@@ -2610,7 +2634,7 @@ static int multiSelect(
assert( p->pEList->nExpr==pPrior->pEList->nExpr );
#ifndef SQLITE_OMIT_CTE
- if( p->selFlags & SF_Recursive ){
+ if( (p->selFlags & SF_Recursive)!=0 && hasAnchor(p) ){
generateWithRecursiveQuery(pParse, p, &dest);
}else
#endif
@@ -2701,6 +2725,7 @@ static int multiSelect(
findRightmost(p)->selFlags |= SF_UsesEphemeral;
assert( p->pEList );
}
+
/* Code the SELECT statements to our left
*/
@@ -3506,7 +3531,7 @@ static Expr *substExpr(
ifNullRow.op = TK_IF_NULL_ROW;
ifNullRow.pLeft = pCopy;
ifNullRow.iTable = pSubst->iNewTable;
- ifNullRow.flags = EP_Skip;
+ ifNullRow.flags = EP_IfNullRow;
pCopy = &ifNullRow;
}
testcase( ExprHasProperty(pCopy, EP_Subquery) );
@@ -3515,8 +3540,7 @@ static Expr *substExpr(
ExprSetProperty(pNew, EP_CanBeNull);
}
if( pNew && ExprHasProperty(pExpr,EP_FromJoin) ){
- pNew->iRightJoinTable = pExpr->iRightJoinTable;
- ExprSetProperty(pNew, EP_FromJoin);
+ sqlite3SetJoinExpr(pNew, pExpr->iRightJoinTable);
}
sqlite3ExprDelete(db, pExpr);
pExpr = pNew;
@@ -4795,8 +4819,10 @@ static int withExpand(
ExprList *pEList;
Select *pSel;
Select *pLeft; /* Left-most SELECT statement */
+ Select *pRecTerm; /* Left-most recursive term */
int bMayRecursive; /* True if compound joined by UNION [ALL] */
With *pSavedWith; /* Initial value of pParse->pWith */
+ int iRecTab = -1; /* Cursor for recursive table */
/* If pCte->zCteErr is non-NULL at this point, then this is an illegal
** recursive reference to CTE pCte. Leave an error in pParse and return
@@ -4821,44 +4847,48 @@ static int withExpand(
assert( pFrom->pSelect );
/* Check if this is a recursive CTE. */
- pSel = pFrom->pSelect;
+ pRecTerm = pSel = pFrom->pSelect;
bMayRecursive = ( pSel->op==TK_ALL || pSel->op==TK_UNION );
- if( bMayRecursive ){
+ while( bMayRecursive && pRecTerm->op==pSel->op ){
int i;
- SrcList *pSrc = pFrom->pSelect->pSrc;
+ SrcList *pSrc = pRecTerm->pSrc;
+ assert( pRecTerm->pPrior!=0 );
for(i=0; i<pSrc->nSrc; i++){
struct SrcList_item *pItem = &pSrc->a[i];
if( pItem->zDatabase==0
&& pItem->zName!=0
&& 0==sqlite3StrICmp(pItem->zName, pCte->zName)
- ){
+ ){
pItem->pTab = pTab;
- pItem->fg.isRecursive = 1;
pTab->nTabRef++;
- pSel->selFlags |= SF_Recursive;
+ pItem->fg.isRecursive = 1;
+ if( pRecTerm->selFlags & SF_Recursive ){
+ sqlite3ErrorMsg(pParse,
+ "multiple references to recursive table: %s", pCte->zName
+ );
+ return SQLITE_ERROR;
+ }
+ pRecTerm->selFlags |= SF_Recursive;
+ if( iRecTab<0 ) iRecTab = pParse->nTab++;
+ pItem->iCursor = iRecTab;
}
}
+ if( (pRecTerm->selFlags & SF_Recursive)==0 ) break;
+ pRecTerm = pRecTerm->pPrior;
}
- /* Only one recursive reference is permitted. */
- if( pTab->nTabRef>2 ){
- sqlite3ErrorMsg(
- pParse, "multiple references to recursive table: %s", pCte->zName
- );
- return SQLITE_ERROR;
- }
- assert( pTab->nTabRef==1 ||
- ((pSel->selFlags&SF_Recursive) && pTab->nTabRef==2 ));
-
pCte->zCteErr = "circular reference: %s";
pSavedWith = pParse->pWith;
pParse->pWith = pWith;
- if( bMayRecursive ){
- Select *pPrior = pSel->pPrior;
- assert( pPrior->pWith==0 );
- pPrior->pWith = pSel->pWith;
- sqlite3WalkSelect(pWalker, pPrior);
- pPrior->pWith = 0;
+ if( pSel->selFlags & SF_Recursive ){
+ assert( pRecTerm!=0 );
+ assert( (pRecTerm->selFlags & SF_Recursive)==0 );
+ assert( pRecTerm->pNext!=0 );
+ assert( (pRecTerm->pNext->selFlags & SF_Recursive)!=0 );
+ assert( pRecTerm->pWith==0 );
+ pRecTerm->pWith = pSel->pWith;
+ sqlite3WalkSelect(pWalker, pRecTerm);
+ pRecTerm->pWith = 0;
}else{
sqlite3WalkSelect(pWalker, pSel);
}
@@ -5585,7 +5615,9 @@ static void explainSimpleCount(
static int havingToWhereExprCb(Walker *pWalker, Expr *pExpr){
if( pExpr->op!=TK_AND ){
Select *pS = pWalker->u.pSelect;
- if( sqlite3ExprIsConstantOrGroupBy(pWalker->pParse, pExpr, pS->pGroupBy) ){
+ if( sqlite3ExprIsConstantOrGroupBy(pWalker->pParse, pExpr, pS->pGroupBy)
+ && ExprAlwaysFalse(pExpr)==0
+ ){
sqlite3 *db = pWalker->pParse->db;
Expr *pNew = sqlite3Expr(db, TK_INTEGER, "1");
if( pNew ){
@@ -5808,13 +5840,11 @@ int sqlite3Select(
assert( p->pOrderBy==0 || pDest->eDest!=SRT_Fifo );
assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistQueue );
assert( p->pOrderBy==0 || pDest->eDest!=SRT_Queue );
- if( IgnorableOrderby(pDest) ){
- assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union ||
- pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard ||
- pDest->eDest==SRT_Queue || pDest->eDest==SRT_DistFifo ||
- pDest->eDest==SRT_DistQueue || pDest->eDest==SRT_Fifo);
- /* If ORDER BY makes no difference in the output then neither does
- ** DISTINCT so it can be removed too. */
+ if( IgnorableDistinct(pDest) ){
+ assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union ||
+ pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard ||
+ pDest->eDest==SRT_DistQueue || pDest->eDest==SRT_DistFifo );
+ /* All of these destinations are also able to ignore the ORDER BY clause */
sqlite3ExprListDelete(db, p->pOrderBy);
p->pOrderBy = 0;
p->selFlags &= ~SF_Distinct;
diff --git a/chromium/third_party/sqlite/src/src/shell.c.in b/chromium/third_party/sqlite/src/src/shell.c.in
index 894462acba6..2d98d23c2db 100644
--- a/chromium/third_party/sqlite/src/src/shell.c.in
+++ b/chromium/third_party/sqlite/src/src/shell.c.in
@@ -553,8 +553,6 @@ static void utf8_width_print(FILE *pOut, int w, const char *zUtf){
int i;
int n;
int aw = w<0 ? -w : w;
- char zBuf[1000];
- if( aw>(int)sizeof(zBuf)/3 ) aw = (int)sizeof(zBuf)/3;
for(i=n=0; zUtf[i]; i++){
if( (zUtf[i]&0xc0)!=0x80 ){
n++;
@@ -1028,6 +1026,7 @@ INCLUDE ../ext/misc/memtrace.c
INCLUDE ../ext/misc/uint.c
INCLUDE ../ext/misc/decimal.c
INCLUDE ../ext/misc/ieee754.c
+INCLUDE ../ext/misc/series.c
#ifdef SQLITE_HAVE_ZLIB
INCLUDE ../ext/misc/zipfile.c
INCLUDE ../ext/misc/sqlar.c
@@ -1185,6 +1184,8 @@ struct ShellState {
#define SHFLG_CountChanges 0x00000020 /* .changes setting */
#define SHFLG_Echo 0x00000040 /* .echo or --echo setting */
#define SHFLG_HeaderSet 0x00000080 /* .header has been used */
+#define SHFLG_DumpDataOnly 0x00000100 /* .dump show data only */
+#define SHFLG_DumpNoSys 0x00000200 /* .dump omits system tables */
/*
** Macros for testing and setting shellFlgs
@@ -3705,19 +3706,25 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
const char *zType;
const char *zSql;
ShellState *p = (ShellState *)pArg;
+ int dataOnly;
+ int noSys;
UNUSED_PARAMETER(azNotUsed);
if( nArg!=3 || azArg==0 ) return 0;
zTable = azArg[0];
zType = azArg[1];
zSql = azArg[2];
+ dataOnly = (p->shellFlgs & SHFLG_DumpDataOnly)!=0;
+ noSys = (p->shellFlgs & SHFLG_DumpNoSys)!=0;
- if( strcmp(zTable, "sqlite_sequence")==0 ){
- raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
- }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){
- raw_printf(p->out, "ANALYZE sqlite_schema;\n");
+ if( strcmp(zTable, "sqlite_sequence")==0 && !noSys ){
+ if( !dataOnly ) raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
+ }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 && !noSys ){
+ if( !dataOnly ) raw_printf(p->out, "ANALYZE sqlite_schema;\n");
}else if( strncmp(zTable, "sqlite_", 7)==0 ){
return 0;
+ }else if( dataOnly ){
+ /* no-op */
}else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
char *zIns;
if( !p->writableSchema ){
@@ -3890,8 +3897,10 @@ static const char *(azHelp[]) = {
".dbinfo ?DB? Show status information about the database",
".dump ?TABLE? Render database content as SQL",
" Options:",
- " --preserve-rowids Include ROWID values in the output",
+ " --data-only Output only INSERT statements",
" --newlines Allow unescaped newline characters in output",
+ " --nosys Omit system tables (ex: \"sqlite_stat1\")",
+ " --preserve-rowids Include ROWID values in the output",
" TABLE is a LIKE pattern for the tables to dump",
" Additional LIKE patterns can be given in subsequent arguments",
".echo on|off Turn command echo on or off",
@@ -4016,8 +4025,9 @@ static const char *(azHelp[]) = {
".save FILE Write in-memory database into FILE",
".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off",
".schema ?PATTERN? Show the CREATE statements matching PATTERN",
- " Options:",
- " --indent Try to pretty-print the schema",
+ " Options:",
+ " --indent Try to pretty-print the schema",
+ " --nosys Omit objects whose names start with \"sqlite_\"",
".selftest ?OPTIONS? Run tests defined in the SELFTEST table",
" Options:",
" --init Create a new SELFTEST table",
@@ -4427,6 +4437,20 @@ static void shellIdQuote(
}
/*
+** Scalar function "usleep(X)" invokes sqlite3_sleep(X) and returns X.
+*/
+static void shellUSleepFunc(
+ sqlite3_context *context,
+ int argcUnused,
+ sqlite3_value **argv
+){
+ int sleep = sqlite3_value_int(argv[0]);
+ (void)argcUnused;
+ sqlite3_sleep(sleep/1000);
+ sqlite3_result_int(context, sleep);
+}
+
+/*
** Scalar function "shell_escape_crnl" used by the .recover command.
** The argument passed to this function is the output of built-in
** function quote(). If the first character of the input is "'",
@@ -4590,6 +4614,7 @@ static void open_db(ShellState *p, int openFlags){
sqlite3_uint_init(p->db, 0, 0);
sqlite3_decimal_init(p->db, 0, 0);
sqlite3_ieee_init(p->db, 0, 0);
+ sqlite3_series_init(p->db, 0, 0);
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
sqlite3_dbdata_init(p->db, 0, 0);
#endif
@@ -4609,6 +4634,8 @@ static void open_db(ShellState *p, int openFlags){
shellInt32, 0, 0);
sqlite3_create_function(p->db, "shell_idquote", 1, SQLITE_UTF8, 0,
shellIdQuote, 0, 0);
+ sqlite3_create_function(p->db, "usleep",1,SQLITE_UTF8,0,
+ shellUSleepFunc, 0, 0);
#ifndef SQLITE_NOHAVE_SYSTEM
sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0,
editFunc, 0, 0);
@@ -7583,21 +7610,41 @@ static int do_meta_command(char *zLine, ShellState *p){
}else
if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
- ShellState data;
- char *zErrMsg = 0;
+ char **azName = 0;
+ int nName = 0;
+ sqlite3_stmt *pStmt;
+ int i;
open_db(p, 0);
- memcpy(&data, p, sizeof(data));
- data.showHeader = 0;
- data.cMode = data.mode = MODE_List;
- sqlite3_snprintf(sizeof(data.colSeparator),data.colSeparator,": ");
- data.cnt = 0;
- sqlite3_exec(p->db, "SELECT name, file FROM pragma_database_list",
- callback, &data, &zErrMsg);
- if( zErrMsg ){
- utf8_printf(stderr,"Error: %s\n", zErrMsg);
- sqlite3_free(zErrMsg);
+ rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
+ if( rc ){
+ utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
rc = 1;
+ }else{
+ while( sqlite3_step(pStmt)==SQLITE_ROW ){
+ const char *zSchema = (const char *)sqlite3_column_text(pStmt,1);
+ const char *zFile = (const char*)sqlite3_column_text(pStmt,2);
+ azName = sqlite3_realloc(azName, (nName+1)*2*sizeof(char*));
+ if( azName==0 ){ shell_out_of_memory(); /* Does not return */ }
+ azName[nName*2] = strdup(zSchema);
+ azName[nName*2+1] = strdup(zFile);
+ nName++;
+ }
}
+ sqlite3_finalize(pStmt);
+ for(i=0; i<nName; i++){
+ int eTxn = sqlite3_txn_state(p->db, azName[i*2]);
+ int bRdonly = sqlite3_db_readonly(p->db, azName[i*2]);
+ const char *z = azName[i*2+1];
+ utf8_printf(p->out, "%s: %s %s%s\n",
+ azName[i*2],
+ z && z[0] ? z : "\"\"",
+ bRdonly ? "r/o" : "r/w",
+ eTxn==SQLITE_TXN_NONE ? "" :
+ eTxn==SQLITE_TXN_READ ? " read-txn" : " write-txn");
+ free(azName[i*2]);
+ free(azName[i*2+1]);
+ }
+ sqlite3_free(azName);
}else
if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){
@@ -7656,7 +7703,9 @@ static int do_meta_command(char *zLine, ShellState *p){
int i;
int savedShowHeader = p->showHeader;
int savedShellFlags = p->shellFlgs;
- ShellClearFlag(p, SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo);
+ ShellClearFlag(p,
+ SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo
+ |SHFLG_DumpDataOnly|SHFLG_DumpNoSys);
for(i=1; i<nArg; i++){
if( azArg[i][0]=='-' ){
const char *z = azArg[i]+1;
@@ -7675,6 +7724,12 @@ static int do_meta_command(char *zLine, ShellState *p){
if( strcmp(z,"newlines")==0 ){
ShellSetFlag(p, SHFLG_Newlines);
}else
+ if( strcmp(z,"data-only")==0 ){
+ ShellSetFlag(p, SHFLG_DumpDataOnly);
+ }else
+ if( strcmp(z,"nosys")==0 ){
+ ShellSetFlag(p, SHFLG_DumpNoSys);
+ }else
{
raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
rc = 1;
@@ -7691,11 +7746,13 @@ static int do_meta_command(char *zLine, ShellState *p){
open_db(p, 0);
- /* When playing back a "dump", the content might appear in an order
- ** which causes immediate foreign key constraints to be violated.
- ** So disable foreign-key constraint enforcement to prevent problems. */
- raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
- raw_printf(p->out, "BEGIN TRANSACTION;\n");
+ if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
+ /* When playing back a "dump", the content might appear in an order
+ ** which causes immediate foreign key constraints to be violated.
+ ** So disable foreign-key constraint enforcement to prevent problems. */
+ raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
+ raw_printf(p->out, "BEGIN TRANSACTION;\n");
+ }
p->writableSchema = 0;
p->showHeader = 0;
/* Set writable_schema=ON since doing so forces SQLite to initialize
@@ -7713,14 +7770,16 @@ static int do_meta_command(char *zLine, ShellState *p){
);
run_schema_dump_query(p,zSql);
sqlite3_free(zSql);
- zSql = sqlite3_mprintf(
- "SELECT sql FROM sqlite_schema "
- "WHERE (%s) AND sql NOT NULL"
- " AND type IN ('index','trigger','view')",
- zLike
- );
- run_table_dump_query(p, zSql);
- sqlite3_free(zSql);
+ if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
+ zSql = sqlite3_mprintf(
+ "SELECT sql FROM sqlite_schema "
+ "WHERE (%s) AND sql NOT NULL"
+ " AND type IN ('index','trigger','view')",
+ zLike
+ );
+ run_table_dump_query(p, zSql);
+ sqlite3_free(zSql);
+ }
sqlite3_free(zLike);
if( p->writableSchema ){
raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
@@ -7728,7 +7787,9 @@ static int do_meta_command(char *zLine, ShellState *p){
}
sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
- raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
+ if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
+ raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
+ }
p->showHeader = savedShowHeader;
p->shellFlgs = savedShellFlags;
}else
@@ -8167,7 +8228,7 @@ static int do_meta_command(char *zLine, ShellState *p){
while( (nSkip--)>0 ){
while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
}
- zSql = sqlite3_mprintf("SELECT * FROM %s", zTable);
+ zSql = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
if( zSql==0 ){
import_cleanup(&sCtx);
shell_out_of_memory();
@@ -8176,7 +8237,7 @@ static int do_meta_command(char *zLine, ShellState *p){
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
- char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable);
+ char *zCreate = sqlite3_mprintf("CREATE TABLE \"%w\"", zTable);
char cSep = '(';
while( xRead(&sCtx) ){
zCreate = sqlite3_mprintf("%z%c\n \"%w\" TEXT", zCreate, cSep, sCtx.z);
@@ -8197,7 +8258,7 @@ static int do_meta_command(char *zLine, ShellState *p){
rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
sqlite3_free(zCreate);
if( rc ){
- utf8_printf(stderr, "CREATE TABLE %s(...) failed: %s\n", zTable,
+ utf8_printf(stderr, "CREATE TABLE \"%s\"(...) failed: %s\n", zTable,
sqlite3_errmsg(p->db));
import_cleanup(&sCtx);
rc = 1;
@@ -8962,9 +9023,16 @@ static int do_meta_command(char *zLine, ShellState *p){
rc = 1;
goto meta_command_exit;
}
- if( notNormalFile(azArg[1])
- || (p->in = fopen(azArg[1], "rb"))==0
- ){
+ if( azArg[1][0]=='|' ){
+ p->in = popen(azArg[1]+1, "r");
+ if( p->in==0 ){
+ utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
+ rc = 1;
+ }else{
+ rc = process_input(p);
+ pclose(p->in);
+ }
+ }else if( notNormalFile(azArg[1]) || (p->in = fopen(azArg[1], "rb"))==0 ){
utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
rc = 1;
}else{
@@ -9046,6 +9114,7 @@ static int do_meta_command(char *zLine, ShellState *p){
const char *zName = 0;
int iSchema = 0;
int bDebug = 0;
+ int bNoSystemTabs = 0;
int ii;
open_db(p, 0);
@@ -9058,10 +9127,16 @@ static int do_meta_command(char *zLine, ShellState *p){
data.cMode = data.mode = MODE_Pretty;
}else if( optionMatch(azArg[ii],"debug") ){
bDebug = 1;
+ }else if( optionMatch(azArg[ii],"nosys") ){
+ bNoSystemTabs = 1;
+ }else if( azArg[ii][0]=='-' ){
+ utf8_printf(stderr, "Unknown option: \"%s\"\n", azArg[ii]);
+ rc = 1;
+ goto meta_command_exit;
}else if( zName==0 ){
zName = azArg[ii];
}else{
- raw_printf(stderr, "Usage: .schema ?--indent? ?LIKE-PATTERN?\n");
+ raw_printf(stderr, "Usage: .schema ?--indent? ?--nosys? ?LIKE-PATTERN?\n");
rc = 1;
goto meta_command_exit;
}
@@ -9147,7 +9222,10 @@ static int do_meta_command(char *zLine, ShellState *p){
appendText(&sSelect, " AND ", 0);
sqlite3_free(zQarg);
}
- appendText(&sSelect, "type!='meta' AND sql IS NOT NULL"
+ if( bNoSystemTabs ){
+ appendText(&sSelect, "name NOT LIKE 'sqlite_%%' AND ", 0);
+ }
+ appendText(&sSelect, "sql IS NOT NULL"
" ORDER BY snum, rowid", 0);
if( bDebug ){
utf8_printf(p->out, "SQL: %s;\n", sSelect.z);
@@ -9844,6 +9922,7 @@ static int do_meta_command(char *zLine, ShellState *p){
{ "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE, "" },
{ "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, "" },
{ "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, "SEED ?db?" },
+ { "seek_count", SQLITE_TESTCTRL_SEEK_COUNT, "" },
};
int testctrl = -1;
int iCtrl = -1;
@@ -9906,7 +9985,6 @@ static int do_meta_command(char *zLine, ShellState *p){
/* sqlite3_test_control(int) */
case SQLITE_TESTCTRL_PRNG_SAVE:
case SQLITE_TESTCTRL_PRNG_RESTORE:
- case SQLITE_TESTCTRL_PRNG_RESET:
case SQLITE_TESTCTRL_BYTEORDER:
if( nArg==2 ){
rc2 = sqlite3_test_control(testctrl);
@@ -9980,6 +10058,14 @@ static int do_meta_command(char *zLine, ShellState *p){
}
break;
+ case SQLITE_TESTCTRL_SEEK_COUNT: {
+ u64 x = 0;
+ rc2 = sqlite3_test_control(testctrl, p->db, &x);
+ utf8_printf(p->out, "%llu\n", x);
+ isOk = 3;
+ break;
+ }
+
#ifdef YYCOVERAGE
case SQLITE_TESTCTRL_PARSER_COVERAGE:
if( nArg==2 ){
@@ -10558,8 +10644,11 @@ static void process_sqliterc(
if( stdin_is_interactive ){
utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc);
}
- process_input(p);
+ if( process_input(p) && bail_on_error ) exit(1);
fclose(p->in);
+ }else if( sqliterc_override!=0 ){
+ utf8_printf(stderr,"cannot open: \"%s\"\n", sqliterc);
+ if( bail_on_error ) exit(1);
}
p->in = inSaved;
p->lineno = savedLineno;
@@ -10618,6 +10707,7 @@ static const char zOptions[] =
#endif
" -stats print memory stats before each finalize\n"
" -table set output mode to 'table'\n"
+ " -tabs set output mode to 'tabs'\n"
" -version show SQLite version\n"
" -vfs NAME use NAME as the default VFS\n"
#ifdef SQLITE_ENABLE_VFSTRACE
@@ -10875,11 +10965,14 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
(void)cmdline_option_value(argc, argv, ++i);
#endif
}else if( strcmp(z,"-pagecache")==0 ){
- int n, sz;
- sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
+ sqlite3_int64 n, sz;
+ sz = integerValue(cmdline_option_value(argc,argv,++i));
if( sz>70000 ) sz = 70000;
if( sz<0 ) sz = 0;
- n = (int)integerValue(cmdline_option_value(argc,argv,++i));
+ n = integerValue(cmdline_option_value(argc,argv,++i));
+ if( sz>0 && n>0 && 0xffffffffffffLL/sz<n ){
+ n = 0xffffffffffffLL/sz;
+ }
sqlite3_config(SQLITE_CONFIG_PAGECACHE,
(n>0 && sz>0) ? malloc(n*sz) : 0, sz, n);
data.shellFlgs |= SHFLG_Pagecache;
@@ -10941,6 +11034,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
#endif
}else if( strcmp(z, "-memtrace")==0 ){
sqlite3MemTraceActivate(stderr);
+ }else if( strcmp(z,"-bail")==0 ){
+ bail_on_error = 1;
}
}
verify_uninitialized();
@@ -11015,6 +11110,8 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
data.mode = MODE_List;
}else if( strcmp(z,"-quote")==0 ){
data.mode = MODE_Quote;
+ sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Comma);
+ sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
}else if( strcmp(z,"-line")==0 ){
data.mode = MODE_Line;
}else if( strcmp(z,"-column")==0 ){
@@ -11048,10 +11145,12 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
data.openFlags |= SQLITE_OPEN_NOFOLLOW;
}else if( strcmp(z,"-ascii")==0 ){
data.mode = MODE_Ascii;
- sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
- SEP_Unit);
- sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
- SEP_Record);
+ sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Unit);
+ sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Record);
+ }else if( strcmp(z,"-tabs")==0 ){
+ data.mode = MODE_List;
+ sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Tab);
+ sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
}else if( strcmp(z,"-separator")==0 ){
sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
"%s",cmdline_option_value(argc,argv,++i));
@@ -11083,7 +11182,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
*/
ShellSetFlag(&data, SHFLG_Backslash);
}else if( strcmp(z,"-bail")==0 ){
- bail_on_error = 1;
+ /* No-op. The bail_on_error flag should already be set. */
}else if( strcmp(z,"-version")==0 ){
printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid());
return 0;
@@ -11171,20 +11270,25 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
for(i=0; i<nCmd; i++){
if( azCmd[i][0]=='.' ){
rc = do_meta_command(azCmd[i], &data);
- if( rc ) return rc==2 ? 0 : rc;
+ if( rc ){
+ free(azCmd);
+ return rc==2 ? 0 : rc;
+ }
}else{
open_db(&data, 0);
rc = shell_exec(&data, azCmd[i], &zErrMsg);
- if( zErrMsg!=0 ){
- utf8_printf(stderr,"Error: %s\n", zErrMsg);
+ if( zErrMsg || rc ){
+ if( zErrMsg!=0 ){
+ utf8_printf(stderr,"Error: %s\n", zErrMsg);
+ }else{
+ utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]);
+ }
+ sqlite3_free(zErrMsg);
+ free(azCmd);
return rc!=0 ? rc : 1;
- }else if( rc!=0 ){
- utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]);
- return rc;
}
}
}
- free(azCmd);
}else{
/* Run commands received from standard input
*/
@@ -11230,6 +11334,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
rc = process_input(&data);
}
}
+ free(azCmd);
set_table_name(&data, 0);
if( data.db ){
session_close_all(&data);
diff --git a/chromium/third_party/sqlite/src/src/sqlite.h.in b/chromium/third_party/sqlite/src/src/sqlite.h.in
index dbcc0e98934..3ec8efeab0d 100644
--- a/chromium/third_party/sqlite/src/src/sqlite.h.in
+++ b/chromium/third_party/sqlite/src/src/sqlite.h.in
@@ -504,6 +504,7 @@ int sqlite3_exec(
#define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8))
#define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8))
#define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8))
+#define SQLITE_IOERR_CORRUPTFS (SQLITE_IOERR | (33<<8))
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8))
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
@@ -6187,6 +6188,57 @@ const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
int sqlite3_db_readonly(sqlite3 *db, const char *zDbName);
/*
+** CAPI3REF: Determine the transaction state of a database
+** METHOD: sqlite3
+**
+** ^The sqlite3_txn_state(D,S) interface returns the current
+** [transaction state] of schema S in database connection D. ^If S is NULL,
+** then the highest transaction state of any schema on database connection D
+** is returned. Transaction states are (in order of lowest to highest):
+** <ol>
+** <li value="0"> SQLITE_TXN_NONE
+** <li value="1"> SQLITE_TXN_READ
+** <li value="2"> SQLITE_TXN_WRITE
+** </ol>
+** ^If the S argument to sqlite3_txn_state(D,S) is not the name of
+** a valid schema, then -1 is returned.
+*/
+int sqlite3_txn_state(sqlite3*,const char *zSchema);
+
+/*
+** CAPI3REF: Allowed return values from [sqlite3_txn_state()]
+** KEYWORDS: {transaction state}
+**
+** These constants define the current transaction state of a database file.
+** ^The [sqlite3_txn_state(D,S)] interface returns one of these
+** constants in order to describe the transaction state of schema S
+** in [database connection] D.
+**
+** <dl>
+** [[SQLITE_TXN_NONE]] <dt>SQLITE_TXN_NONE</dt>
+** <dd>The SQLITE_TXN_NONE state means that no transaction is currently
+** pending.</dd>
+**
+** [[SQLITE_TXN_READ]] <dt>SQLITE_TXN_READ</dt>
+** <dd>The SQLITE_TXN_READ state means that the database is currently
+** in a read transaction. Content has been read from the database file
+** but nothing in the database file has changed. The transaction state
+** will advanced to SQLITE_TXN_WRITE if any changes occur and there are
+** no other conflicting concurrent write transactions. The transaction
+** state will revert to SQLITE_TXN_NONE following a [ROLLBACK] or
+** [COMMIT].</dd>
+**
+** [[SQLITE_TXN_WRITE]] <dt>SQLITE_TXN_WRITE</dt>
+** <dd>The SQLITE_TXN_WRITE state means that the database is currently
+** in a write transaction. Content has been written to the database file
+** but has not yet committed. The transaction state will change to
+** to SQLITE_TXN_NONE at the next [ROLLBACK] or [COMMIT].</dd>
+*/
+#define SQLITE_TXN_NONE 0
+#define SQLITE_TXN_READ 1
+#define SQLITE_TXN_WRITE 2
+
+/*
** CAPI3REF: Find the next prepared statement
** METHOD: sqlite3
**
@@ -7712,7 +7764,8 @@ int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_RESULT_INTREAL 27
#define SQLITE_TESTCTRL_PRNG_SEED 28
#define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29
-#define SQLITE_TESTCTRL_LAST 29 /* Largest TESTCTRL */
+#define SQLITE_TESTCTRL_SEEK_COUNT 30
+#define SQLITE_TESTCTRL_LAST 30 /* Largest TESTCTRL */
/*
** CAPI3REF: SQL Keyword Checking
@@ -9192,10 +9245,11 @@ int sqlite3_vtab_on_conflict(sqlite3 *);
** CAPI3REF: Determine If Virtual Table Column Access Is For UPDATE
**
** If the sqlite3_vtab_nochange(X) routine is called within the [xColumn]
-** method of a [virtual table], then it returns true if and only if the
+** method of a [virtual table], then it might return true if the
** column is being fetched as part of an UPDATE operation during which the
-** column value will not change. Applications might use this to substitute
-** a return value that is less expensive to compute and that the corresponding
+** column value will not change. The virtual table implementation can use
+** this hint as permission to substitute a return value that is less
+** expensive to compute and that the corresponding
** [xUpdate] method understands as a "no-change" value.
**
** If the [xColumn] method calls sqlite3_vtab_nochange() and finds that
@@ -9204,6 +9258,12 @@ int sqlite3_vtab_on_conflict(sqlite3 *);
** any of the [sqlite3_result_int|sqlite3_result_xxxxx() interfaces].
** In that case, [sqlite3_value_nochange(X)] will return true for the
** same column in the [xUpdate] method.
+**
+** The sqlite3_vtab_nochange() routine is an optimization. Virtual table
+** implementations should continue to give a correct answer even if the
+** sqlite3_vtab_nochange() interface were to always return false. In the
+** current implementation, the sqlite3_vtab_nochange() interface does always
+** returns false for the enhanced [UPDATE FROM] statement.
*/
int sqlite3_vtab_nochange(sqlite3_context*);
@@ -9345,6 +9405,7 @@ void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
/*
** CAPI3REF: Flush caches to disk mid-transaction
+** METHOD: sqlite3
**
** ^If a write-transaction is open on [database connection] D when the
** [sqlite3_db_cacheflush(D)] interface invoked, any dirty
@@ -9377,6 +9438,7 @@ int sqlite3_db_cacheflush(sqlite3*);
/*
** CAPI3REF: The pre-update hook.
+** METHOD: sqlite3
**
** ^These interfaces are only available if SQLite is compiled using the
** [SQLITE_ENABLE_PREUPDATE_HOOK] compile-time option.
@@ -9417,7 +9479,7 @@ int sqlite3_db_cacheflush(sqlite3*);
** seventh parameter is the final rowid value of the row being inserted
** or updated. The value of the seventh parameter passed to the callback
** function is not defined for operations on WITHOUT ROWID tables, or for
-** INSERT operations on rowid tables.
+** DELETE operations on rowid tables.
**
** The [sqlite3_preupdate_old()], [sqlite3_preupdate_new()],
** [sqlite3_preupdate_count()], and [sqlite3_preupdate_depth()] interfaces
@@ -9479,6 +9541,7 @@ int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **);
/*
** CAPI3REF: Low-level system error code
+** METHOD: sqlite3
**
** ^Attempt to return the underlying operating system error code or error
** number that caused the most recent I/O error or failure to open a file.
diff --git a/chromium/third_party/sqlite/src/src/sqlite3ext.h b/chromium/third_party/sqlite/src/src/sqlite3ext.h
index 78c19a0d10c..217601fd908 100644
--- a/chromium/third_party/sqlite/src/src/sqlite3ext.h
+++ b/chromium/third_party/sqlite/src/src/sqlite3ext.h
@@ -335,6 +335,8 @@ struct sqlite3_api_routines {
int,const char**);
void (*free_filename)(char*);
sqlite3_file *(*database_file_object)(const char*);
+ /* Version 3.34.0 and later */
+ int (*txn_state)(sqlite3*,const char*);
};
/*
@@ -639,6 +641,8 @@ typedef int (*sqlite3_loadext_entry)(
#define sqlite3_create_filename sqlite3_api->create_filename
#define sqlite3_free_filename sqlite3_api->free_filename
#define sqlite3_database_file_object sqlite3_api->database_file_object
+/* Version 3.34.0 and later */
+#define sqlite3_txn_state sqlite3_api->txn_state
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
diff --git a/chromium/third_party/sqlite/src/src/sqliteInt.h b/chromium/third_party/sqlite/src/src/sqliteInt.h
index 74e854452b8..245070d4f82 100644
--- a/chromium/third_party/sqlite/src/src/sqliteInt.h
+++ b/chromium/third_party/sqlite/src/src/sqliteInt.h
@@ -2187,6 +2187,7 @@ struct Table {
#define TF_OOOHidden 0x0400 /* Out-of-Order hidden columns */
#define TF_HasNotNull 0x0800 /* Contains NOT NULL constraints */
#define TF_Shadow 0x1000 /* True for a shadow table */
+#define TF_HasStat4 0x2000 /* STAT4 info available for this table */
/*
** Test to see whether or not a table is a virtual table. This is
@@ -2715,7 +2716,7 @@ struct Expr {
#define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */
#define EP_Win 0x008000 /* Contains window functions */
#define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */
- /* 0x020000 // available for reuse */
+#define EP_IfNullRow 0x020000 /* The TK_IF_NULL_ROW opcode */
#define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */
#define EP_ConstFunc 0x080000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */
#define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */
@@ -2953,9 +2954,9 @@ struct SrcList {
#define WHERE_DISTINCTBY 0x0080 /* pOrderby is really a DISTINCT clause */
#define WHERE_WANT_DISTINCT 0x0100 /* All output needs to be distinct */
#define WHERE_SORTBYGROUP 0x0200 /* Support sqlite3WhereIsSorted() */
-#define WHERE_SEEK_TABLE 0x0400 /* Do not defer seeks on main table */
+ /* 0x0400 not currently used */
#define WHERE_ORDERBY_LIMIT 0x0800 /* ORDERBY+LIMIT on the inner loop */
-#define WHERE_SEEK_UNIQ_TABLE 0x1000 /* Do not defer seeks if unique */
+ /* 0x1000 not currently used */
/* 0x2000 not currently used */
#define WHERE_USE_LIMIT 0x4000 /* Use the LIMIT in cost estimates */
/* 0x8000 not currently used */
@@ -3152,9 +3153,6 @@ struct Select {
** statements within triggers whose only purpose is
** the side-effects of functions.
**
-** All of the above are free to ignore their ORDER BY clause. Those that
-** follow must honor the ORDER BY clause.
-**
** SRT_Output Generate a row of output (using the OP_ResultRow
** opcode) for each row in the result set.
**
@@ -3211,13 +3209,18 @@ struct Select {
#define SRT_Except 2 /* Remove result from a UNION index */
#define SRT_Exists 3 /* Store 1 if the result is not empty */
#define SRT_Discard 4 /* Do not save the results anywhere */
-#define SRT_Fifo 5 /* Store result as data with an automatic rowid */
-#define SRT_DistFifo 6 /* Like SRT_Fifo, but unique results only */
+#define SRT_DistFifo 5 /* Like SRT_Fifo, but unique results only */
+#define SRT_DistQueue 6 /* Like SRT_Queue, but unique results only */
+
+/* The DISTINCT clause is ignored for all of the above. Not that
+** IgnorableDistinct() implies IgnorableOrderby() */
+#define IgnorableDistinct(X) ((X->eDest)<=SRT_DistQueue)
+
#define SRT_Queue 7 /* Store result in an queue */
-#define SRT_DistQueue 8 /* Like SRT_Queue, but unique results only */
+#define SRT_Fifo 8 /* Store result as data with an automatic rowid */
/* The ORDER BY clause is ignored for all of the above */
-#define IgnorableOrderby(X) ((X->eDest)<=SRT_DistQueue)
+#define IgnorableOrderby(X) ((X->eDest)<=SRT_Fifo)
#define SRT_Output 9 /* Output each row of result */
#define SRT_Mem 10 /* Store result in a memory cell */
@@ -3872,7 +3875,6 @@ int sqlite3WindowCompare(Parse*, Window*, Window*, int);
void sqlite3WindowCodeInit(Parse*, Select*);
void sqlite3WindowCodeStep(Parse*, Select*, WhereInfo*, int, int);
int sqlite3WindowRewrite(Parse*, Select*);
-int sqlite3ExpandSubquery(Parse*, struct SrcList_item*);
void sqlite3WindowUpdate(Parse*, Window*, Window*, FuncDef*);
Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p);
Window *sqlite3WindowListDup(sqlite3 *db, Window *p);
@@ -4184,7 +4186,7 @@ void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int);
void sqlite3AddColumn(Parse*,Token*,Token*);
void sqlite3AddNotNull(Parse*, int);
void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int);
-void sqlite3AddCheckConstraint(Parse*, Expr*);
+void sqlite3AddCheckConstraint(Parse*, Expr*, const char*, const char*);
void sqlite3AddDefaultValue(Parse*,Expr*,const char*,const char*);
void sqlite3AddCollateType(Parse*, Token*);
void sqlite3AddGenerated(Parse*,Expr*,Token*);
@@ -4610,6 +4612,7 @@ void sqlite3ExpirePreparedStatements(sqlite3*, int);
void sqlite3CodeRhsOfIN(Parse*, Expr*, int);
int sqlite3CodeSubselect(Parse*, Expr*);
void sqlite3SelectPrep(Parse*, Select*, NameContext*);
+int sqlite3ExpandSubquery(Parse*, struct SrcList_item*);
void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p);
int sqlite3MatchEName(
const struct ExprList_item*,
diff --git a/chromium/third_party/sqlite/src/src/sqliteLimit.h b/chromium/third_party/sqlite/src/src/sqliteLimit.h
index a7302575c5b..08703cb73af 100644
--- a/chromium/third_party/sqlite/src/src/sqliteLimit.h
+++ b/chromium/third_party/sqlite/src/src/sqliteLimit.h
@@ -60,11 +60,7 @@
** The maximum depth of an expression tree. This is limited to
** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might
** want to place more severe limits on the complexity of an
-** expression.
-**
-** A value of 0 used to mean that the limit was not enforced.
-** But that is no longer true. The limit is now strictly enforced
-** at all times.
+** expression. A value of 0 means that there is no limit.
*/
#ifndef SQLITE_MAX_EXPR_DEPTH
# define SQLITE_MAX_EXPR_DEPTH 1000
diff --git a/chromium/third_party/sqlite/src/src/test1.c b/chromium/third_party/sqlite/src/src/test1.c
index 99044021080..49461ea5fc5 100644
--- a/chromium/third_party/sqlite/src/src/test1.c
+++ b/chromium/third_party/sqlite/src/src/test1.c
@@ -3940,7 +3940,7 @@ static int SQLITE_TCLAPI test_bind_blob(
char zBuf[200];
sqlite3_snprintf(sizeof(zBuf), zBuf,
"cannot use %d blob bytes, have %d", bytes, len);
- Tcl_AppendResult(interp, zBuf, -1);
+ Tcl_AppendResult(interp, zBuf, (char*)0);
return TCL_ERROR;
}
@@ -3953,6 +3953,195 @@ static int SQLITE_TCLAPI test_bind_blob(
return TCL_OK;
}
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/*
+** sqlite3_carray_bind [options...] STMT NAME VALUE ...
+**
+** Options:
+** -transient
+** -static
+** -int32
+** -int64
+** -double
+** -text
+**
+** Each call clears static data. Called with no options does nothing
+** but clear static data.
+*/
+static int SQLITE_TCLAPI test_carray_bind(
+ void * clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+ sqlite3_stmt *pStmt;
+ int eType = 0; /* CARRAY_INT32 */
+ int nData = 0;
+ void *aData = 0;
+ int isTransient = 0;
+ int isStatic = 0;
+ int idx;
+ int i, j;
+ int rc;
+ void (*xDel)(void*) = sqlite3_free;
+ static void *aStaticData = 0;
+ static int nStaticData = 0;
+ static int eStaticType = 0;
+ extern int sqlite3_carray_bind(
+ sqlite3_stmt *pStmt,
+ int i,
+ void *aData,
+ int nData,
+ int mFlags,
+ void (*xDestroy)(void*)
+ );
+
+ if( aStaticData ){
+ /* Always clear preexisting static data on every call */
+ if( eStaticType==3 ){
+ for(i=0; i<nStaticData; i++){
+ sqlite3_free(((char**)aStaticData)[i]);
+ }
+ }
+ sqlite3_free(aStaticData);
+ aStaticData = 0;
+ nStaticData = 0;
+ eStaticType = 0;
+ }
+ if( objc==1 ) return TCL_OK;
+
+ for(i=1; i<objc && Tcl_GetString(objv[i])[0]=='-'; i++){
+ const char *z = Tcl_GetString(objv[i]);
+ if( strcmp(z, "-transient")==0 ){
+ isTransient = 1;
+ xDel = SQLITE_TRANSIENT;
+ }else
+ if( strcmp(z, "-static")==0 ){
+ isStatic = 1;
+ xDel = SQLITE_STATIC;
+ }else
+ if( strcmp(z, "-int32")==0 ){
+ eType = 0; /* CARRAY_INT32 */
+ }else
+ if( strcmp(z, "-int64")==0 ){
+ eType = 1; /* CARRAY_INT64 */
+ }else
+ if( strcmp(z, "-double")==0 ){
+ eType = 2; /* CARRAY_DOUBLE */
+ }else
+ if( strcmp(z, "-text")==0 ){
+ eType = 3; /* CARRAY_TEXT */
+ }else
+ if( strcmp(z, "--")==0 ){
+ break;
+ }else
+ {
+ Tcl_AppendResult(interp, "unknown option: ", z, (char*)0);
+ return TCL_ERROR;
+ }
+ }
+ if( eType==3 && !isStatic && !isTransient ){
+ Tcl_AppendResult(interp, "text data must be either -static or -transient",
+ (char*)0);
+ return TCL_ERROR;
+ }
+ if( isStatic && isTransient ){
+ Tcl_AppendResult(interp, "cannot be both -static and -transient",
+ (char*)0);
+ return TCL_ERROR;
+ }
+ if( objc-i < 2 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "[OPTIONS] STMT IDX VALUE ...");
+ return TCL_ERROR;
+ }
+ if( getStmtPointer(interp, Tcl_GetString(objv[i]), &pStmt) ) return TCL_ERROR;
+ i++;
+ if( Tcl_GetIntFromObj(interp, objv[i], &idx) ) return TCL_ERROR;
+ i++;
+ nData = objc - i;
+ switch( eType + 4*(nData<=0) ){
+ case 0: { /* INT32 */
+ int *a = sqlite3_malloc( sizeof(int)*nData );
+ if( a==0 ){ rc = SQLITE_NOMEM; goto carray_bind_done; }
+ for(j=0; j<nData; j++){
+ int v;
+ if( Tcl_GetIntFromObj(interp, objv[i+j], &v) ){
+ sqlite3_free(a);
+ return TCL_ERROR;
+ }
+ a[j] = v;
+ }
+ aData = a;
+ break;
+ }
+ case 1: { /* INT64 */
+ sqlite3_int64 *a = sqlite3_malloc( sizeof(sqlite3_int64)*nData );
+ if( a==0 ){ rc = SQLITE_NOMEM; goto carray_bind_done; }
+ for(j=0; j<nData; j++){
+ Tcl_WideInt v;
+ if( Tcl_GetWideIntFromObj(interp, objv[i+j], &v) ){
+ sqlite3_free(a);
+ return TCL_ERROR;
+ }
+ a[j] = v;
+ }
+ aData = a;
+ break;
+ }
+ case 2: { /* DOUBLE */
+ double *a = sqlite3_malloc( sizeof(double)*nData );
+ if( a==0 ){ rc = SQLITE_NOMEM; goto carray_bind_done; }
+ for(j=0; j<nData; j++){
+ double v;
+ if( Tcl_GetDoubleFromObj(interp, objv[i+j], &v) ){
+ sqlite3_free(a);
+ return TCL_ERROR;
+ }
+ a[j] = v;
+ }
+ aData = a;
+ break;
+ }
+ case 3: { /* TEXT */
+ char **a = sqlite3_malloc( sizeof(char*)*nData );
+ if( a==0 ){ rc = SQLITE_NOMEM; goto carray_bind_done; }
+ for(j=0; j<nData; j++){
+ const char *v = Tcl_GetString(objv[i+j]);
+ a[j] = sqlite3_mprintf("%s", v);
+ }
+ aData = a;
+ break;
+ }
+ case 4: { /* nData==0 */
+ aData = "";
+ xDel = SQLITE_STATIC;
+ isTransient = 0;
+ isStatic = 0;
+ break;
+ }
+ }
+ if( isStatic ){
+ aStaticData = aData;
+ nStaticData = nData;
+ eStaticType = eType;
+ }
+ rc = sqlite3_carray_bind(pStmt, idx, aData, nData, eType, xDel);
+ if( isTransient ){
+ if( eType==3 ){
+ for(i=0; i<nData; i++) sqlite3_free(((char**)aData)[i]);
+ }
+ sqlite3_free(aData);
+ }
+carray_bind_done:
+ if( rc ){
+ Tcl_AppendResult(interp, sqlite3_errstr(rc), (char*)0);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
/*
** Usage: sqlite3_bind_parameter_count STMT
**
@@ -6240,6 +6429,36 @@ static int SQLITE_TCLAPI file_control_vfsname(
}
/*
+** tclcmd: file_control_reservebytes DB N
+*/
+static int SQLITE_TCLAPI file_control_reservebytes(
+ ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
+ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
+ int objc, /* Number of arguments */
+ Tcl_Obj *CONST objv[] /* Command arguments */
+){
+ sqlite3 *db;
+ const char *zDbName = "main";
+ int n = 0;
+ int rc;
+
+ if( objc!=3 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "DB N");
+ return TCL_ERROR;
+ }
+ if( getDbPointer(interp, Tcl_GetString(objv[1]), &db)
+ || Tcl_GetIntFromObj(interp, objv[2], &n)
+ ){
+ return TCL_ERROR;
+ }
+
+ rc = sqlite3_file_control(db, zDbName, SQLITE_FCNTL_RESERVE_BYTES, (void*)&n);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
+ return TCL_OK;
+}
+
+
+/*
** tclcmd: file_control_tempfilename DB ?AUXDB?
**
** Return a string that is a temporary filename
@@ -7749,6 +7968,33 @@ static int SQLITE_TCLAPI test_sqlite3_db_config(
Tcl_SetObjResult(interp, Tcl_NewIntObj(v));
return TCL_OK;
}
+/*
+** tclcmd: sqlite3_txn_state DB ?SCHEMA?
+**
+** Invoke sqlite3_txn_state(DB,SCHEMA) and return the
+** numeric value that results. Use NULL for SCHEMA if the 3 argument
+** is omitted.
+*/
+static int SQLITE_TCLAPI test_sqlite3_txn_state(
+ void *clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+ sqlite3 *db;
+ const char *zSchema;
+ int iTxn;
+
+ if( objc!=2 && objc!=3 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "DB ?SCHEMA?");
+ return TCL_ERROR;
+ }
+ if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
+ zSchema = objc==3 ? Tcl_GetString(objv[2]) : 0;
+ iTxn = sqlite3_txn_state(db, zSchema);
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(iTxn));
+ return TCL_OK;
+}
/*
** Change the name of the main database schema from "main" to "icecube".
@@ -7838,6 +8084,48 @@ static int SQLITE_TCLAPI test_write_db(
}
/*
+** Usage: sqlite3_register_cksumvfs
+**
+*/
+static int SQLITE_TCLAPI test_register_cksumvfs(
+ void * clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+ if( objc!=1 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "");
+ return TCL_ERROR;
+ }else{
+ extern int sqlite3_register_cksumvfs(const char*);
+ int rc = sqlite3_register_cksumvfs(0);
+ Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
+ }
+ return TCL_OK;
+}
+
+/*
+** Usage: sqlite3_unregister_cksumvfs
+**
+*/
+static int SQLITE_TCLAPI test_unregister_cksumvfs(
+ void * clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+ if( objc!=1 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "");
+ return TCL_ERROR;
+ }else{
+ extern int sqlite3_unregister_cksumvfs(void);
+ int rc = sqlite3_unregister_cksumvfs();
+ Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
+ }
+ return TCL_OK;
+}
+
+/*
** Usage: decode_hexdb TEXT
**
** Example: db deserialize [decode_hexdb $output_of_dbtotxt]
@@ -7985,6 +8273,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
void *clientData;
} aObjCmd[] = {
{ "sqlite3_db_config", test_sqlite3_db_config, 0 },
+ { "sqlite3_txn_state", test_sqlite3_txn_state, 0 },
{ "bad_behavior", test_bad_behavior, (void*)&iZero },
{ "register_dbstat_vtab", test_register_dbstat_vtab },
{ "sqlite3_connection_pointer", get_sqlite_pointer, 0 },
@@ -8001,6 +8290,9 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "sqlite3_bind_text", test_bind_text ,0 },
{ "sqlite3_bind_text16", test_bind_text16 ,0 },
{ "sqlite3_bind_blob", test_bind_blob ,0 },
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ { "sqlite3_carray_bind", test_carray_bind ,0 },
+#endif
{ "sqlite3_bind_parameter_count", test_bind_parameter_count, 0},
{ "sqlite3_bind_parameter_name", test_bind_parameter_name, 0},
{ "sqlite3_bind_parameter_index", test_bind_parameter_index, 0},
@@ -8132,6 +8424,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "file_control_persist_wal", file_control_persist_wal, 0 },
{ "file_control_powersafe_overwrite",file_control_powersafe_overwrite,0},
{ "file_control_vfsname", file_control_vfsname, 0 },
+ { "file_control_reservebytes", file_control_reservebytes, 0 },
{ "file_control_tempfilename", file_control_tempfilename, 0 },
{ "sqlite3_vfs_list", vfs_list, 0 },
{ "sqlite3_create_function_v2", test_create_function_v2, 0 },
@@ -8202,6 +8495,8 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "sqlite3_config_sorterref", test_config_sorterref, 0 },
{ "decode_hexdb", test_decode_hexdb, 0 },
{ "test_write_db", test_write_db, 0 },
+ { "sqlite3_register_cksumvfs", test_register_cksumvfs, 0 },
+ { "sqlite3_unregister_cksumvfs", test_unregister_cksumvfs, 0 },
};
static int bitmask_size = sizeof(Bitmask)*8;
static int longdouble_size = sizeof(LONGDOUBLE_TYPE);
diff --git a/chromium/third_party/sqlite/src/src/test6.c b/chromium/third_party/sqlite/src/src/test6.c
index 9a3aa093f06..aa94b9b5ea9 100644
--- a/chromium/third_party/sqlite/src/src/test6.c
+++ b/chromium/third_party/sqlite/src/src/test6.c
@@ -550,13 +550,16 @@ static int cfDeviceCharacteristics(sqlite3_file *pFile){
** Pass-throughs for WAL support.
*/
static int cfShmLock(sqlite3_file *pFile, int ofst, int n, int flags){
- return sqlite3OsShmLock(((CrashFile*)pFile)->pRealFile, ofst, n, flags);
+ sqlite3_file *pReal = ((CrashFile*)pFile)->pRealFile;
+ return pReal->pMethods->xShmLock(pReal, ofst, n, flags);
}
static void cfShmBarrier(sqlite3_file *pFile){
- sqlite3OsShmBarrier(((CrashFile*)pFile)->pRealFile);
+ sqlite3_file *pReal = ((CrashFile*)pFile)->pRealFile;
+ pReal->pMethods->xShmBarrier(pReal);
}
static int cfShmUnmap(sqlite3_file *pFile, int delFlag){
- return sqlite3OsShmUnmap(((CrashFile*)pFile)->pRealFile, delFlag);
+ sqlite3_file *pReal = ((CrashFile*)pFile)->pRealFile;
+ return pReal->pMethods->xShmUnmap(pReal, delFlag);
}
static int cfShmMap(
sqlite3_file *pFile, /* Handle open on database file */
@@ -565,7 +568,8 @@ static int cfShmMap(
int w, /* True to extend file if necessary */
void volatile **pp /* OUT: Mapped memory */
){
- return sqlite3OsShmMap(((CrashFile*)pFile)->pRealFile, iRegion, sz, w, pp);
+ sqlite3_file *pReal = ((CrashFile*)pFile)->pRealFile;
+ return pReal->pMethods->xShmMap(pReal, iRegion, sz, w, pp);
}
static const sqlite3_io_methods CrashFileVtab = {
diff --git a/chromium/third_party/sqlite/src/src/test_devsym.c b/chromium/third_party/sqlite/src/src/test_devsym.c
index 23354312c5d..7847bc300ba 100644
--- a/chromium/third_party/sqlite/src/src/test_devsym.c
+++ b/chromium/third_party/sqlite/src/src/test_devsym.c
@@ -191,7 +191,7 @@ static int devsymDeviceCharacteristics(sqlite3_file *pFile){
*/
static int devsymShmLock(sqlite3_file *pFile, int ofst, int n, int flags){
devsym_file *p = (devsym_file *)pFile;
- return sqlite3OsShmLock(p->pReal, ofst, n, flags);
+ return p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags);
}
static int devsymShmMap(
sqlite3_file *pFile,
@@ -201,15 +201,15 @@ static int devsymShmMap(
void volatile **pp
){
devsym_file *p = (devsym_file *)pFile;
- return sqlite3OsShmMap(p->pReal, iRegion, szRegion, isWrite, pp);
+ return p->pReal->pMethods->xShmMap(p->pReal, iRegion, szRegion, isWrite, pp);
}
static void devsymShmBarrier(sqlite3_file *pFile){
devsym_file *p = (devsym_file *)pFile;
- sqlite3OsShmBarrier(p->pReal);
+ p->pReal->pMethods->xShmBarrier(p->pReal);
}
static int devsymShmUnmap(sqlite3_file *pFile, int delFlag){
devsym_file *p = (devsym_file *)pFile;
- return sqlite3OsShmUnmap(p->pReal, delFlag);
+ return p->pReal->pMethods->xShmUnmap(p->pReal, delFlag);
}
diff --git a/chromium/third_party/sqlite/src/src/test_hexio.c b/chromium/third_party/sqlite/src/src/test_hexio.c
index 78a5ba2d0c5..61a41d5b1c3 100644
--- a/chromium/third_party/sqlite/src/src/test_hexio.c
+++ b/chromium/third_party/sqlite/src/src/test_hexio.c
@@ -168,7 +168,7 @@ static int SQLITE_TCLAPI hexio_write(
if( Tcl_GetIntFromObj(interp, objv[2], &offset) ) return TCL_ERROR;
zFile = Tcl_GetString(objv[1]);
zIn = (const unsigned char *)Tcl_GetStringFromObj(objv[3], &nIn);
- aOut = sqlite3_malloc( nIn/2 );
+ aOut = sqlite3_malloc( 1 + nIn/2 );
if( aOut==0 ){
return TCL_ERROR;
}
@@ -213,7 +213,7 @@ static int SQLITE_TCLAPI hexio_get_int(
return TCL_ERROR;
}
zIn = (const unsigned char *)Tcl_GetStringFromObj(objv[1], &nIn);
- aOut = sqlite3_malloc( nIn/2 );
+ aOut = sqlite3_malloc( 1 + nIn/2 );
if( aOut==0 ){
return TCL_ERROR;
}
@@ -309,7 +309,7 @@ static int SQLITE_TCLAPI utf8_to_utf8(
return TCL_ERROR;
}
zOrig = (unsigned char *)Tcl_GetStringFromObj(objv[1], &n);
- z = sqlite3_malloc( n+3 );
+ z = sqlite3_malloc( n+4 );
n = sqlite3TestHexToBin(zOrig, n, z);
z[n] = 0;
nOut = sqlite3Utf8To8(z);
diff --git a/chromium/third_party/sqlite/src/src/test_vfs.c b/chromium/third_party/sqlite/src/src/test_vfs.c
index 9d753896e9f..f3e8297ac73 100644
--- a/chromium/third_party/sqlite/src/src/test_vfs.c
+++ b/chromium/third_party/sqlite/src/src/test_vfs.c
@@ -895,7 +895,8 @@ static int tvfsShmMap(
Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
if( p->isFullshm ){
- return sqlite3OsShmMap(pFd->pReal, iPage, pgsz, isWrite, pp);
+ sqlite3_file *pReal = pFd->pReal;
+ return pReal->pMethods->xShmMap(pReal, iPage, pgsz, isWrite, pp);
}
if( 0==pFd->pShm ){
@@ -945,7 +946,8 @@ static int tvfsShmLock(
char zLock[80];
if( p->isFullshm ){
- return sqlite3OsShmLock(pFd->pReal, ofst, n, flags);
+ sqlite3_file *pReal = pFd->pReal;
+ return pReal->pMethods->xShmLock(pReal, ofst, n, flags);
}
if( p->pScript && p->mask&TESTVFS_SHMLOCK_MASK ){
@@ -1009,7 +1011,8 @@ static void tvfsShmBarrier(sqlite3_file *pFile){
}
if( p->isFullshm ){
- sqlite3OsShmBarrier(pFd->pReal);
+ sqlite3_file *pReal = pFd->pReal;
+ pReal->pMethods->xShmBarrier(pReal);
return;
}
}
@@ -1025,7 +1028,8 @@ static int tvfsShmUnmap(
TestvfsFd **ppFd;
if( p->isFullshm ){
- return sqlite3OsShmUnmap(pFd->pReal, deleteFlag);
+ sqlite3_file *pReal = pFd->pReal;
+ return pReal->pMethods->xShmUnmap(pReal, deleteFlag);
}
if( !pBuffer ) return SQLITE_OK;
diff --git a/chromium/third_party/sqlite/src/src/trigger.c b/chromium/third_party/sqlite/src/src/trigger.c
index 7ab5d95be30..dd4ed8c2e8b 100644
--- a/chromium/third_party/sqlite/src/src/trigger.c
+++ b/chromium/third_party/sqlite/src/src/trigger.c
@@ -157,22 +157,11 @@ void sqlite3BeginTrigger(
pTab = sqlite3SrcListLookup(pParse, pTableName);
if( !pTab ){
/* The table does not exist. */
- if( db->init.iDb==1 ){
- /* Ticket #3810.
- ** Normally, whenever a table is dropped, all associated triggers are
- ** dropped too. But if a TEMP trigger is created on a non-TEMP table
- ** and the table is dropped by a different database connection, the
- ** trigger is not visible to the database connection that does the
- ** drop so the trigger cannot be dropped. This results in an
- ** "orphaned trigger" - a trigger whose associated table is missing.
- */
- db->init.orphanTrigger = 1;
- }
- goto trigger_cleanup;
+ goto trigger_orphan_error;
}
if( IsVirtual(pTab) ){
sqlite3ErrorMsg(pParse, "cannot create triggers on virtual tables");
- goto trigger_cleanup;
+ goto trigger_orphan_error;
}
/* Check that the trigger name is not reserved and that no trigger of the
@@ -210,12 +199,12 @@ void sqlite3BeginTrigger(
if( pTab->pSelect && tr_tm!=TK_INSTEAD ){
sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S",
(tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0);
- goto trigger_cleanup;
+ goto trigger_orphan_error;
}
if( !pTab->pSelect && tr_tm==TK_INSTEAD ){
sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF"
" trigger on table: %S", pTableName, 0);
- goto trigger_cleanup;
+ goto trigger_orphan_error;
}
#ifndef SQLITE_OMIT_AUTHORIZATION
@@ -275,6 +264,23 @@ trigger_cleanup:
}else{
assert( pParse->pNewTrigger==pTrigger );
}
+ return;
+
+trigger_orphan_error:
+ if( db->init.iDb==1 ){
+ /* Ticket #3810.
+ ** Normally, whenever a table is dropped, all associated triggers are
+ ** dropped too. But if a TEMP trigger is created on a non-TEMP table
+ ** and the table is dropped by a different database connection, the
+ ** trigger is not visible to the database connection that does the
+ ** drop so the trigger cannot be dropped. This results in an
+ ** "orphaned trigger" - a trigger whose associated table is missing.
+ **
+ ** 2020-11-05 see also https://sqlite.org/forum/forumpost/157dc791df
+ */
+ db->init.orphanTrigger = 1;
+ }
+ goto trigger_cleanup;
}
/*
diff --git a/chromium/third_party/sqlite/src/src/update.c b/chromium/third_party/sqlite/src/src/update.c
index a9c43d62eb3..f8cb2afedb6 100644
--- a/chromium/third_party/sqlite/src/src/update.c
+++ b/chromium/third_party/sqlite/src/src/update.c
@@ -234,7 +234,7 @@ static void updateFromSelect(
#endif
pList = sqlite3ExprListAppend(pParse, pList, pNew);
}
- eDest = SRT_Upfrom;
+ eDest = IsVirtual(pTab) ? SRT_Table : SRT_Upfrom;
}else if( pTab->pSelect ){
for(i=0; i<pTab->nCol; i++){
pList = sqlite3ExprListAppend(pParse, pList, exprRowColumn(pParse, i));
@@ -651,6 +651,8 @@ void sqlite3Update(
if( nChangeFrom==0 && HasRowid(pTab) ){
sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid);
+ iEph = pParse->nTab++;
+ addrOpen = sqlite3VdbeAddOp3(v, OP_OpenEphemeral, iEph, 0, regRowSet);
}else{
assert( pPk!=0 || HasRowid(pTab) );
nPk = pPk ? pPk->nKeyCol : 0;
@@ -705,7 +707,7 @@ void sqlite3Update(
** be deleted as a result of REPLACE conflict handling. Any of these
** things might disturb a cursor being used to scan through the table
** or index, causing a single-pass approach to malfunction. */
- flags = WHERE_ONEPASS_DESIRED|WHERE_SEEK_UNIQ_TABLE;
+ flags = WHERE_ONEPASS_DESIRED;
if( !pParse->nested && !pTrigger && !hasFK && !chngKey && !bReplace ){
flags |= WHERE_ONEPASS_MULTIROW;
}
@@ -742,9 +744,10 @@ void sqlite3Update(
** leave it in register regOldRowid. */
sqlite3VdbeAddOp2(v, OP_Rowid, iDataCur, regOldRowid);
if( eOnePass==ONEPASS_OFF ){
- /* We need to use regRowSet, so reallocate aRegIdx[nAllIdx] */
aRegIdx[nAllIdx] = ++pParse->nMem;
- sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid);
+ sqlite3VdbeAddOp3(v, OP_Insert, iEph, regRowSet, regOldRowid);
+ }else{
+ if( ALWAYS(addrOpen) ) sqlite3VdbeChangeToNoop(v, addrOpen);
}
}else{
/* Read the PK of the current row into an array of registers. In
@@ -832,8 +835,9 @@ void sqlite3Update(
VdbeCoverage(v);
}
}else{
- labelContinue = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet,labelBreak,
- regOldRowid);
+ sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak); VdbeCoverage(v);
+ labelContinue = sqlite3VdbeMakeLabel(pParse);
+ addrTop = sqlite3VdbeAddOp2(v, OP_Rowid, iEph, regOldRowid);
VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid);
VdbeCoverage(v);
@@ -1083,11 +1087,9 @@ void sqlite3Update(
}else if( eOnePass==ONEPASS_MULTI ){
sqlite3VdbeResolveLabel(v, labelContinue);
sqlite3WhereEnd(pWInfo);
- }else if( pPk || nChangeFrom ){
+ }else{
sqlite3VdbeResolveLabel(v, labelContinue);
sqlite3VdbeAddOp2(v, OP_Next, iEph, addrTop); VdbeCoverage(v);
- }else{
- sqlite3VdbeGoto(v, labelContinue);
}
sqlite3VdbeResolveLabel(v, labelBreak);
@@ -1187,12 +1189,26 @@ static void updateVirtualTable(
regArg = pParse->nMem + 1;
pParse->nMem += nArg;
if( pSrc->nSrc>1 ){
+ Index *pPk = 0;
Expr *pRow;
ExprList *pList;
- if( pRowid ){
- pRow = sqlite3ExprDup(db, pRowid, 0);
+ if( HasRowid(pTab) ){
+ if( pRowid ){
+ pRow = sqlite3ExprDup(db, pRowid, 0);
+ }else{
+ pRow = sqlite3PExpr(pParse, TK_ROW, 0, 0);
+ }
}else{
- pRow = sqlite3PExpr(pParse, TK_ROW, 0, 0);
+ i16 iPk; /* PRIMARY KEY column */
+ pPk = sqlite3PrimaryKeyIndex(pTab);
+ assert( pPk!=0 );
+ assert( pPk->nKeyCol==1 );
+ iPk = pPk->aiColumn[0];
+ if( aXRef[iPk]>=0 ){
+ pRow = sqlite3ExprDup(db, pChanges->a[aXRef[iPk]].pExpr, 0);
+ }else{
+ pRow = exprRowColumn(pParse, iPk);
+ }
}
pList = sqlite3ExprListAppend(pParse, 0, pRow);
@@ -1206,7 +1222,7 @@ static void updateVirtualTable(
}
}
- updateFromSelect(pParse, ephemTab, 0, pList, pSrc, pWhere, 0, 0);
+ updateFromSelect(pParse, ephemTab, pPk, pList, pSrc, pWhere, 0, 0);
sqlite3ExprListDelete(db, pList);
eOnePass = ONEPASS_OFF;
}else{
diff --git a/chromium/third_party/sqlite/src/src/util.c b/chromium/third_party/sqlite/src/src/util.c
index 2371aad17c0..fb86d7d118d 100644
--- a/chromium/third_party/sqlite/src/src/util.c
+++ b/chromium/third_party/sqlite/src/src/util.c
@@ -681,6 +681,7 @@ int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
incr = 1;
}else{
incr = 2;
+ length &= ~1;
assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
for(i=3-enc; i<length && zNum[i]==0; i+=2){}
nonNum = i<length;
diff --git a/chromium/third_party/sqlite/src/src/vacuum.c b/chromium/third_party/sqlite/src/src/vacuum.c
index 50875d8d3d7..93e2307d1a2 100644
--- a/chromium/third_party/sqlite/src/src/vacuum.c
+++ b/chromium/third_party/sqlite/src/src/vacuum.c
@@ -339,8 +339,8 @@ SQLITE_NOINLINE int sqlite3RunVacuum(
BTREE_APPLICATION_ID, 0, /* Preserve the application id */
};
- assert( 1==sqlite3BtreeIsInTrans(pTemp) );
- assert( pOut!=0 || 1==sqlite3BtreeIsInTrans(pMain) );
+ assert( SQLITE_TXN_WRITE==sqlite3BtreeTxnState(pTemp) );
+ assert( pOut!=0 || SQLITE_TXN_WRITE==sqlite3BtreeTxnState(pMain) );
/* Copy Btree meta values */
for(i=0; i<ArraySize(aCopy); i+=2){
diff --git a/chromium/third_party/sqlite/src/src/vdbe.c b/chromium/third_party/sqlite/src/src/vdbe.c
index 4d1e0560135..1507fb31819 100644
--- a/chromium/third_party/sqlite/src/src/vdbe.c
+++ b/chromium/third_party/sqlite/src/src/vdbe.c
@@ -3487,7 +3487,8 @@ case OP_AutoCommit: {
** active.
** If P2 is non-zero, then a write-transaction is started, or if a
** read-transaction is already active, it is upgraded to a write-transaction.
-** If P2 is zero, then a read-transaction is started.
+** If P2 is zero, then a read-transaction is started. If P2 is 2 or more
+** then an exclusive transaction is started.
**
** P1 is the index of the database file on which the transaction is
** started. Index 0 is the main database file and index 1 is the
@@ -3521,6 +3522,7 @@ case OP_Transaction: {
assert( p->bIsReader );
assert( p->readOnly==0 || pOp->p2==0 );
+ assert( pOp->p2>=0 && pOp->p2<=2 );
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( DbMaskTest(p->btreeMask, pOp->p1) );
if( pOp->p2 && (db->flags & SQLITE_QueryOnly)!=0 ){
@@ -3546,7 +3548,7 @@ case OP_Transaction: {
&& pOp->p2
&& (db->autoCommit==0 || db->nVdbeRead>1)
){
- assert( sqlite3BtreeIsInTrans(pBt) );
+ assert( sqlite3BtreeTxnState(pBt)==SQLITE_TXN_WRITE );
if( p->iStatement==0 ){
assert( db->nStatement>=0 && db->nSavepoint>=0 );
db->nStatement++;
@@ -3899,7 +3901,7 @@ case OP_OpenDup: {
}
-/* Opcode: OpenEphemeral P1 P2 * P4 P5
+/* Opcode: OpenEphemeral P1 P2 P3 P4 P5
** Synopsis: nColumn=P2
**
** Open a new cursor P1 to a transient table.
@@ -3919,6 +3921,10 @@ case OP_OpenDup: {
** in btree.h. These flags control aspects of the operation of
** the btree. The BTREE_OMIT_JOURNAL and BTREE_SINGLE flags are
** added automatically.
+**
+** If P3 is positive, then reg[P3] is modified slightly so that it
+** can be used as zero-length data for OP_Insert. This is an optimization
+** that avoids an extra OP_Blob opcode to initialize that register.
*/
/* Opcode: OpenAutoindex P1 P2 * P4 *
** Synopsis: nColumn=P2
@@ -3941,6 +3947,15 @@ case OP_OpenEphemeral: {
SQLITE_OPEN_TRANSIENT_DB;
assert( pOp->p1>=0 );
assert( pOp->p2>=0 );
+ if( pOp->p3>0 ){
+ /* Make register reg[P3] into a value that can be used as the data
+ ** form sqlite3BtreeInsert() where the length of the data is zero. */
+ assert( pOp->p2==0 ); /* Only used when number of columns is zero */
+ assert( pOp->opcode==OP_OpenEphemeral );
+ assert( aMem[pOp->p3].flags & MEM_Null );
+ aMem[pOp->p3].n = 0;
+ aMem[pOp->p3].z = "";
+ }
pCx = p->apCsr[pOp->p1];
if( pCx && pCx->pBtx ){
/* If the ephermeral table is already open, erase all existing content
@@ -4383,22 +4398,172 @@ seek_not_found:
break;
}
-/* Opcode: SeekHit P1 P2 * * *
-** Synopsis: seekHit=P2
+
+/* Opcode: SeekScan P1 P2 * * *
+** Synopsis: Scan-ahead up to P1 rows
+**
+** This opcode is a prefix opcode to OP_SeekGE. In other words, this
+** opcode must be immediately followed by OP_SeekGE. This constraint is
+** checked by assert() statements.
+**
+** This opcode uses the P1 through P4 operands of the subsequent
+** OP_SeekGE. In the text that follows, the operands of the subsequent
+** OP_SeekGE opcode are denoted as SeekOP.P1 through SeekOP.P4. Only
+** the P1 and P2 operands of this opcode are also used, and are called
+** This.P1 and This.P2.
+**
+** This opcode helps to optimize IN operators on a multi-column index
+** where the IN operator is on the later terms of the index by avoiding
+** unnecessary seeks on the btree, substituting steps to the next row
+** of the b-tree instead. A correct answer is obtained if this opcode
+** is omitted or is a no-op.
+**
+** The SeekGE.P3 and SeekGE.P4 operands identify an unpacked key which
+** is the desired entry that we want the cursor SeekGE.P1 to be pointing
+** to. Call this SeekGE.P4/P5 row the "target".
+**
+** If the SeekGE.P1 cursor is not currently pointing to a valid row,
+** then this opcode is a no-op and control passes through into the OP_SeekGE.
+**
+** If the SeekGE.P1 cursor is pointing to a valid row, then that row
+** might be the target row, or it might be near and slightly before the
+** target row. This opcode attempts to position the cursor on the target
+** row by, perhaps by invoking sqlite3BtreeStep() on the cursor
+** between 0 and This.P1 times.
+**
+** There are three possible outcomes from this opcode:<ol>
+**
+** <li> If after This.P1 steps, the cursor is still point to a place that
+** is earlier in the btree than the target row,
+** then fall through into the subsquence OP_SeekGE opcode.
+**
+** <li> If the cursor is successfully moved to the target row by 0 or more
+** sqlite3BtreeNext() calls, then jump to This.P2, which will land just
+** past the OP_IdxGT opcode that follows the OP_SeekGE.
+**
+** <li> If the cursor ends up past the target row (indicating the the target
+** row does not exist in the btree) then jump to SeekOP.P2.
+** </ol>
+*/
+case OP_SeekScan: {
+ VdbeCursor *pC;
+ int res;
+ int nStep;
+ UnpackedRecord r;
+
+ assert( pOp[1].opcode==OP_SeekGE );
+
+ /* pOp->p2 points to the first instruction past the OP_IdxGT that
+ ** follows the OP_SeekGE. */
+ assert( pOp->p2>=(int)(pOp-aOp)+2 );
+ assert( aOp[pOp->p2-1].opcode==OP_IdxGT );
+ assert( pOp[1].p1==aOp[pOp->p2-1].p1 );
+ assert( pOp[1].p2==aOp[pOp->p2-1].p2 );
+ assert( pOp[1].p3==aOp[pOp->p2-1].p3 );
+
+ assert( pOp->p1>0 );
+ pC = p->apCsr[pOp[1].p1];
+ assert( pC!=0 );
+ assert( pC->eCurType==CURTYPE_BTREE );
+ assert( !pC->isTable );
+ if( !sqlite3BtreeCursorIsValidNN(pC->uc.pCursor) ){
+#ifdef SQLITE_DEBUG
+ if( db->flags&SQLITE_VdbeTrace ){
+ printf("... cursor not valid - fall through\n");
+ }
+#endif
+ break;
+ }
+ nStep = pOp->p1;
+ assert( nStep>=1 );
+ r.pKeyInfo = pC->pKeyInfo;
+ r.nField = (u16)pOp[1].p4.i;
+ r.default_rc = 0;
+ r.aMem = &aMem[pOp[1].p3];
+#ifdef SQLITE_DEBUG
+ {
+ int i;
+ for(i=0; i<r.nField; i++){
+ assert( memIsValid(&r.aMem[i]) );
+ REGISTER_TRACE(pOp[1].p3+i, &aMem[pOp[1].p3+i]);
+ }
+ }
+#endif
+ res = 0; /* Not needed. Only used to silence a warning. */
+ while(1){
+ rc = sqlite3VdbeIdxKeyCompare(db, pC, &r, &res);
+ if( rc ) goto abort_due_to_error;
+ if( res>0 ){
+ seekscan_search_fail:
+#ifdef SQLITE_DEBUG
+ if( db->flags&SQLITE_VdbeTrace ){
+ printf("... %d steps and then skip\n", pOp->p1 - nStep);
+ }
+#endif
+ VdbeBranchTaken(1,3);
+ pOp++;
+ goto jump_to_p2;
+ }
+ if( res==0 ){
+#ifdef SQLITE_DEBUG
+ if( db->flags&SQLITE_VdbeTrace ){
+ printf("... %d steps and then success\n", pOp->p1 - nStep);
+ }
+#endif
+ VdbeBranchTaken(2,3);
+ goto jump_to_p2;
+ break;
+ }
+ if( nStep<=0 ){
+#ifdef SQLITE_DEBUG
+ if( db->flags&SQLITE_VdbeTrace ){
+ printf("... fall through after %d steps\n", pOp->p1);
+ }
+#endif
+ VdbeBranchTaken(0,3);
+ break;
+ }
+ nStep--;
+ rc = sqlite3BtreeNext(pC->uc.pCursor, 0);
+ if( rc ){
+ if( rc==SQLITE_DONE ){
+ rc = SQLITE_OK;
+ goto seekscan_search_fail;
+ }else{
+ goto abort_due_to_error;
+ }
+ }
+ }
+
+ break;
+}
+
+
+/* Opcode: SeekHit P1 P2 P3 * *
+** Synopsis: set P2<=seekHit<=P3
+**
+** Increase or decrease the seekHit value for cursor P1, if necessary,
+** so that it is no less than P2 and no greater than P3.
**
-** Set the seekHit flag on cursor P1 to the value in P2.
-** The seekHit flag is used by the IfNoHope opcode.
+** The seekHit integer represents the maximum of terms in an index for which
+** there is known to be at least one match. If the seekHit value is smaller
+** than the total number of equality terms in an index lookup, then the
+** OP_IfNoHope opcode might run to see if the IN loop can be abandoned
+** early, thus saving work. This is part of the IN-early-out optimization.
**
-** P1 must be a valid b-tree cursor. P2 must be a boolean value,
-** either 0 or 1.
+** P1 must be a valid b-tree cursor.
*/
case OP_SeekHit: {
VdbeCursor *pC;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
- assert( pOp->p2==0 || pOp->p2==1 );
- pC->seekHit = pOp->p2 & 1;
+ assert( pOp->p3>=pOp->p2 );
+ if( pC->seekHit<pOp->p2 ){
+ pC->seekHit = pOp->p2;
+ }else if( pC->seekHit>pOp->p3 ){
+ pC->seekHit = pOp->p3;
+ }
break;
}
@@ -4456,16 +4621,20 @@ case OP_IfNotOpen: { /* jump */
** Synopsis: key=r[P3@P4]
**
** Register P3 is the first of P4 registers that form an unpacked
-** record.
+** record. Cursor P1 is an index btree. P2 is a jump destination.
+** In other words, the operands to this opcode are the same as the
+** operands to OP_NotFound and OP_IdxGT.
**
-** Cursor P1 is on an index btree. If the seekHit flag is set on P1, then
-** this opcode is a no-op. But if the seekHit flag of P1 is clear, then
-** check to see if there is any entry in P1 that matches the
-** prefix identified by P3 and P4. If no entry matches the prefix,
-** jump to P2. Otherwise fall through.
+** This opcode is an optimization attempt only. If this opcode always
+** falls through, the correct answer is still obtained, but extra works
+** is performed.
**
-** This opcode behaves like OP_NotFound if the seekHit
-** flag is clear and it behaves like OP_Noop if the seekHit flag is set.
+** A value of N in the seekHit flag of cursor P1 means that there exists
+** a key P3:N that will match some record in the index. We want to know
+** if it is possible for a record P3:P4 to match some record in the
+** index. If it is not possible, we can skips some work. So if seekHit
+** is less than P4, attempt to find out if a match is possible by running
+** OP_NotFound.
**
** This opcode is used in IN clause processing for a multi-column key.
** If an IN clause is attached to an element of the key other than the
@@ -4507,7 +4676,7 @@ case OP_IfNoHope: { /* jump, in3 */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
- if( pC->seekHit ) break;
+ if( pC->seekHit>=pOp->p4.i ) break;
/* Fall through into OP_NotFound */
/* no break */ deliberate_fall_through
}
@@ -4589,6 +4758,7 @@ case OP_Found: { /* jump, in3 */
}else{
VdbeBranchTaken(takeJump||alreadyExists==0,2);
if( takeJump || !alreadyExists ) goto jump_to_p2;
+ if( pOp->opcode==OP_IfNoHope ) pC->seekHit = pOp->p4.i;
}
break;
}
@@ -4945,7 +5115,7 @@ case OP_Insert: {
if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = x.nKey;
- assert( pData->flags & (MEM_Blob|MEM_Str) );
+ assert( (pData->flags & (MEM_Blob|MEM_Str))!=0 || pData->n==0 );
x.pData = pData->z;
x.nData = pData->n;
seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0);
@@ -5821,7 +5991,7 @@ case OP_FinishSeek: {
break;
}
-/* Opcode: IdxGE P1 P2 P3 P4 P5
+/* Opcode: IdxGE P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
** The P4 register values beginning with P3 form an unpacked index
@@ -5832,7 +6002,7 @@ case OP_FinishSeek: {
** If the P1 index entry is greater than or equal to the key value
** then jump to P2. Otherwise fall through to the next instruction.
*/
-/* Opcode: IdxGT P1 P2 P3 P4 P5
+/* Opcode: IdxGT P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
** The P4 register values beginning with P3 form an unpacked index
@@ -5843,7 +6013,7 @@ case OP_FinishSeek: {
** If the P1 index entry is greater than the key value
** then jump to P2. Otherwise fall through to the next instruction.
*/
-/* Opcode: IdxLT P1 P2 P3 P4 P5
+/* Opcode: IdxLT P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
** The P4 register values beginning with P3 form an unpacked index
@@ -5854,7 +6024,7 @@ case OP_FinishSeek: {
** If the P1 index entry is less than the key value then jump to P2.
** Otherwise fall through to the next instruction.
*/
-/* Opcode: IdxLE P1 P2 P3 P4 P5
+/* Opcode: IdxLE P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
** The P4 register values beginning with P3 form an unpacked index
@@ -5880,7 +6050,6 @@ case OP_IdxGE: { /* jump */
assert( pC->eCurType==CURTYPE_BTREE );
assert( pC->uc.pCursor!=0);
assert( pC->deferredMoveto==0 );
- assert( pOp->p5==0 || pOp->p5==1 );
assert( pOp->p4type==P4_INT32 );
r.pKeyInfo = pC->pKeyInfo;
r.nField = (u16)pOp->p4.i;
@@ -5901,8 +6070,31 @@ case OP_IdxGE: { /* jump */
}
}
#endif
- res = 0; /* Not needed. Only used to silence a warning. */
- rc = sqlite3VdbeIdxKeyCompare(db, pC, &r, &res);
+
+ /* Inlined version of sqlite3VdbeIdxKeyCompare() */
+ {
+ i64 nCellKey = 0;
+ BtCursor *pCur;
+ Mem m;
+
+ assert( pC->eCurType==CURTYPE_BTREE );
+ pCur = pC->uc.pCursor;
+ assert( sqlite3BtreeCursorIsValid(pCur) );
+ nCellKey = sqlite3BtreePayloadSize(pCur);
+ /* nCellKey will always be between 0 and 0xffffffff because of the way
+ ** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */
+ if( nCellKey<=0 || nCellKey>0x7fffffff ){
+ rc = SQLITE_CORRUPT_BKPT;
+ goto abort_due_to_error;
+ }
+ sqlite3VdbeMemInit(&m, db, 0);
+ rc = sqlite3VdbeMemFromBtreeZeroOffset(pCur, (u32)nCellKey, &m);
+ if( rc ) goto abort_due_to_error;
+ res = sqlite3VdbeRecordCompareWithSkip(m.n, m.z, &r, 0);
+ sqlite3VdbeMemRelease(&m);
+ }
+ /* End of inlined sqlite3VdbeIdxKeyCompare() */
+
assert( (OP_IdxLE&1)==(OP_IdxLT&1) && (OP_IdxGE&1)==(OP_IdxGT&1) );
if( (pOp->opcode&1)==(OP_IdxLT&1) ){
assert( pOp->opcode==OP_IdxLE || pOp->opcode==OP_IdxLT );
@@ -5912,7 +6104,7 @@ case OP_IdxGE: { /* jump */
res++;
}
VdbeBranchTaken(res>0,2);
- if( rc ) goto abort_due_to_error;
+ assert( rc==SQLITE_OK );
if( res>0 ) goto jump_to_p2;
break;
}
@@ -7038,7 +7230,7 @@ case OP_JournalMode: { /* out2 */
/* Open a transaction on the database file. Regardless of the journal
** mode, this transaction always uses a rollback journal.
*/
- assert( sqlite3BtreeIsInTrans(pBt)==0 );
+ assert( sqlite3BtreeTxnState(pBt)!=SQLITE_TXN_WRITE );
if( rc==SQLITE_OK ){
rc = sqlite3BtreeSetVersion(pBt, (eNew==PAGER_JOURNALMODE_WAL ? 2 : 1));
}
@@ -7978,7 +8170,11 @@ default: { /* This is really OP_Noop, OP_Explain */
** an error of some kind.
*/
abort_due_to_error:
- if( db->mallocFailed ) rc = SQLITE_NOMEM_BKPT;
+ if( db->mallocFailed ){
+ rc = SQLITE_NOMEM_BKPT;
+ }else if( rc==SQLITE_IOERR_CORRUPTFS ){
+ rc = SQLITE_CORRUPT_BKPT;
+ }
assert( rc );
if( p->zErrMsg==0 && rc!=SQLITE_IOERR_NOMEM ){
sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc));
diff --git a/chromium/third_party/sqlite/src/src/vdbeInt.h b/chromium/third_party/sqlite/src/src/vdbeInt.h
index 901569742f5..7d22cb8093b 100644
--- a/chromium/third_party/sqlite/src/src/vdbeInt.h
+++ b/chromium/third_party/sqlite/src/src/vdbeInt.h
@@ -86,7 +86,7 @@ struct VdbeCursor {
Bool isEphemeral:1; /* True for an ephemeral table */
Bool useRandomRowid:1; /* Generate new record numbers semi-randomly */
Bool isOrdered:1; /* True if the table is not BTREE_UNORDERED */
- Bool seekHit:1; /* See the OP_SeekHit and OP_IfNoHope opcodes */
+ u16 seekHit; /* See the OP_SeekHit and OP_IfNoHope opcodes */
Btree *pBtx; /* Separate file holding temporary table */
i64 seqCount; /* Sequence counter */
u32 *aAltMap; /* Mapping from table to index column numbers */
diff --git a/chromium/third_party/sqlite/src/src/vdbeaux.c b/chromium/third_party/sqlite/src/src/vdbeaux.c
index 5f8b8a817b7..dfd259d7188 100644
--- a/chromium/third_party/sqlite/src/src/vdbeaux.c
+++ b/chromium/third_party/sqlite/src/src/vdbeaux.c
@@ -475,6 +475,7 @@ void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere){
int j;
sqlite3VdbeAddOp4(p, OP_ParseSchema, iDb, 0, 0, zWhere, P4_DYNAMIC);
for(j=0; j<p->db->nDb; j++) sqlite3VdbeUsesBtree(p, j);
+ sqlite3MayAbort(p->pParse);
}
/*
@@ -703,7 +704,7 @@ int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename
|| opcode==OP_VDestroy
|| opcode==OP_VCreate
- || (opcode==OP_ParseSchema && pOp->p4.z==0)
+ || opcode==OP_ParseSchema
|| ((opcode==OP_Halt || opcode==OP_HaltIfNull)
&& ((pOp->p1)!=SQLITE_OK && pOp->p2==OE_Abort))
){
@@ -1521,7 +1522,7 @@ char *sqlite3VdbeDisplayComment(
sqlite3_str_appendf(&x, "%d", v1);
}else if( pCtx->argc>1 ){
sqlite3_str_appendf(&x, "%d..%d", v1, v1+pCtx->argc-1);
- }else{
+ }else if( x.accError==0 ){
assert( x.nChar>2 );
x.nChar -= 2;
ii++;
@@ -2663,7 +2664,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
*/
for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
- if( sqlite3BtreeIsInTrans(pBt) ){
+ if( sqlite3BtreeTxnState(pBt)==SQLITE_TXN_WRITE ){
/* Whether or not a database might need a super-journal depends upon
** its journal mode (among other things). This matrix determines which
** journal modes use a super-journal and which do not */
@@ -2798,7 +2799,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
*/
for(i=0; i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
- if( sqlite3BtreeIsInTrans(pBt) ){
+ if( sqlite3BtreeTxnState(pBt)==SQLITE_TXN_WRITE ){
char const *zFile = sqlite3BtreeGetJournalname(pBt);
if( zFile==0 ){
continue; /* Ignore TEMP and :memory: databases */
@@ -4294,9 +4295,12 @@ SQLITE_NOINLINE int sqlite3BlobCompare(const Mem *pB1, const Mem *pB2){
static int sqlite3IntFloatCompare(i64 i, double r){
if( sizeof(LONGDOUBLE_TYPE)>8 ){
LONGDOUBLE_TYPE x = (LONGDOUBLE_TYPE)i;
+ testcase( x<r );
+ testcase( x>r );
+ testcase( x==r );
if( x<r ) return -1;
- if( x>r ) return +1;
- return 0;
+ if( x>r ) return +1; /*NO_TEST*/ /* work around bugs in gcov */
+ return 0; /*NO_TEST*/ /* work around bugs in gcov */
}else{
i64 y;
double s;
diff --git a/chromium/third_party/sqlite/src/src/vdbesort.c b/chromium/third_party/sqlite/src/src/vdbesort.c
index 777c2054e89..f61b8b73200 100644
--- a/chromium/third_party/sqlite/src/src/vdbesort.c
+++ b/chromium/third_party/sqlite/src/src/vdbesort.c
@@ -970,13 +970,16 @@ int sqlite3VdbeSorterInit(
if( pSorter==0 ){
rc = SQLITE_NOMEM_BKPT;
}else{
+ Btree *pBt = db->aDb[0].pBt;
pSorter->pKeyInfo = pKeyInfo = (KeyInfo*)((u8*)pSorter + sz);
memcpy(pKeyInfo, pCsr->pKeyInfo, szKeyInfo);
pKeyInfo->db = 0;
if( nField && nWorker==0 ){
pKeyInfo->nKeyField = nField;
}
- pSorter->pgsz = pgsz = sqlite3BtreeGetPageSize(db->aDb[0].pBt);
+ sqlite3BtreeEnter(pBt);
+ pSorter->pgsz = pgsz = sqlite3BtreeGetPageSize(pBt);
+ sqlite3BtreeLeave(pBt);
pSorter->nTask = nWorker + 1;
pSorter->iPrev = (u8)(nWorker - 1);
pSorter->bUseThreads = (pSorter->nTask>1);
diff --git a/chromium/third_party/sqlite/src/src/where.c b/chromium/third_party/sqlite/src/src/where.c
index e3f74351fde..2b97114e6b6 100644
--- a/chromium/third_party/sqlite/src/src/where.c
+++ b/chromium/third_party/sqlite/src/src/where.c
@@ -236,6 +236,16 @@ static void createMask(WhereMaskSet *pMaskSet, int iCursor){
}
/*
+** If the right-hand branch of the expression is a TK_COLUMN, then return
+** a pointer to the right-hand branch. Otherwise, return NULL.
+*/
+static Expr *whereRightSubexprIsColumn(Expr *p){
+ p = sqlite3ExprSkipCollateAndLikely(p->pRight);
+ if( ALWAYS(p!=0) && p->op==TK_COLUMN ) return p;
+ return 0;
+}
+
+/*
** Advance to the next WhereTerm that matches according to the criteria
** established when the pScan object was initialized by whereScanInit().
** Return NULL if there are no more matching WhereTerms.
@@ -257,7 +267,7 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
do{
for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){
if( pTerm->leftCursor==iCur
- && pTerm->u.leftColumn==iColumn
+ && pTerm->u.x.leftColumn==iColumn
&& (iColumn!=XN_EXPR
|| sqlite3ExprCompareSkip(pTerm->pExpr->pLeft,
pScan->pIdxExpr,iCur)==0)
@@ -265,8 +275,7 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
){
if( (pTerm->eOperator & WO_EQUIV)!=0
&& pScan->nEquiv<ArraySize(pScan->aiCur)
- && (pX = sqlite3ExprSkipCollateAndLikely(pTerm->pExpr->pRight))->op
- ==TK_COLUMN
+ && (pX = whereRightSubexprIsColumn(pTerm->pExpr))!=0
){
int j;
for(j=0; j<pScan->nEquiv; j++){
@@ -462,7 +471,8 @@ static int findIndexCol(
for(i=0; i<pList->nExpr; i++){
Expr *p = sqlite3ExprSkipCollateAndLikely(pList->a[i].pExpr);
- if( p->op==TK_COLUMN
+ if( ALWAYS(p!=0)
+ && p->op==TK_COLUMN
&& p->iColumn==pIdx->aiColumn[iCol]
&& p->iTable==iBase
){
@@ -526,6 +536,7 @@ static int isDistinctRedundant(
*/
for(i=0; i<pDistinct->nExpr; i++){
Expr *p = sqlite3ExprSkipCollateAndLikely(pDistinct->a[i].pExpr);
+ if( NEVER(p==0) ) continue;
if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1;
}
@@ -679,8 +690,8 @@ static int termCanDriveIndex(
return 0;
}
if( (pTerm->prereqRight & notReady)!=0 ) return 0;
- if( pTerm->u.leftColumn<0 ) return 0;
- aff = pSrc->pTab->aCol[pTerm->u.leftColumn].affinity;
+ if( pTerm->u.x.leftColumn<0 ) return 0;
+ aff = pSrc->pTab->aCol[pTerm->u.x.leftColumn].affinity;
if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0;
testcase( pTerm->pExpr->op==TK_IS );
return 1;
@@ -751,7 +762,7 @@ static void constructAutomaticIndex(
sqlite3ExprDup(pParse->db, pExpr, 0));
}
if( termCanDriveIndex(pTerm, pSrc, notReady) ){
- int iCol = pTerm->u.leftColumn;
+ int iCol = pTerm->u.x.leftColumn;
Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol);
testcase( iCol==BMS );
testcase( iCol==BMS-1 );
@@ -804,14 +815,14 @@ static void constructAutomaticIndex(
idxCols = 0;
for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
if( termCanDriveIndex(pTerm, pSrc, notReady) ){
- int iCol = pTerm->u.leftColumn;
+ int iCol = pTerm->u.x.leftColumn;
Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol);
testcase( iCol==BMS-1 );
testcase( iCol==BMS );
if( (idxCols & cMask)==0 ){
Expr *pX = pTerm->pExpr;
idxCols |= cMask;
- pIdx->aiColumn[n] = pTerm->u.leftColumn;
+ pIdx->aiColumn[n] = pTerm->u.x.leftColumn;
pColl = sqlite3ExprCompareCollSeq(pParse, pX);
assert( pColl!=0 || pParse->nErr>0 ); /* TH3 collate01.800 */
pIdx->azColl[n] = pColl ? pColl->zName : sqlite3StrBINARY;
@@ -932,7 +943,7 @@ static sqlite3_index_info *allocateIndexInfo(
testcase( pTerm->eOperator & WO_ALL );
if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue;
if( pTerm->wtFlags & TERM_VNULL ) continue;
- assert( pTerm->u.leftColumn>=(-1) );
+ assert( pTerm->u.x.leftColumn>=(-1) );
nTerm++;
}
@@ -992,8 +1003,8 @@ static sqlite3_index_info *allocateIndexInfo(
){
continue;
}
- assert( pTerm->u.leftColumn>=(-1) );
- pIdxCons[j].iColumn = pTerm->u.leftColumn;
+ assert( pTerm->u.x.leftColumn>=(-1) );
+ pIdxCons[j].iColumn = pTerm->u.x.leftColumn;
pIdxCons[j].iTermOffset = i;
op = pTerm->eOperator & WO_ALL;
if( op==WO_IN ) op = WO_EQ;
@@ -1756,9 +1767,9 @@ void sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm){
if( pTerm->wtFlags & TERM_CODED ) zType[3] = 'C';
if( pTerm->eOperator & WO_SINGLE ){
sqlite3_snprintf(sizeof(zLeft),zLeft,"left={%d:%d}",
- pTerm->leftCursor, pTerm->u.leftColumn);
+ pTerm->leftCursor, pTerm->u.x.leftColumn);
}else if( (pTerm->eOperator & WO_OR)!=0 && pTerm->u.pOrInfo!=0 ){
- sqlite3_snprintf(sizeof(zLeft),zLeft,"indexable=0x%lld",
+ sqlite3_snprintf(sizeof(zLeft),zLeft,"indexable=0x%llx",
pTerm->u.pOrInfo->indexable);
}else{
sqlite3_snprintf(sizeof(zLeft),zLeft,"left=%d", pTerm->leftCursor);
@@ -1772,8 +1783,8 @@ void sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm){
sqlite3DebugPrintf(" prob=%-3d prereq=%llx,%llx",
pTerm->truthProb, (u64)pTerm->prereqAll, (u64)pTerm->prereqRight);
}
- if( pTerm->iField ){
- sqlite3DebugPrintf(" iField=%d", pTerm->iField);
+ if( pTerm->u.x.iField ){
+ sqlite3DebugPrintf(" iField=%d", pTerm->u.x.iField);
}
if( pTerm->iParent>=0 ){
sqlite3DebugPrintf(" iParent=%d", pTerm->iParent);
@@ -2440,9 +2451,9 @@ static int whereLoopAddBtreeIndex(
pNew = pBuilder->pNew;
if( db->mallocFailed ) return SQLITE_NOMEM_BKPT;
- WHERETRACE(0x800, ("BEGIN %s.addBtreeIdx(%s), nEq=%d, nSkip=%d\n",
+ WHERETRACE(0x800, ("BEGIN %s.addBtreeIdx(%s), nEq=%d, nSkip=%d, rRun=%d\n",
pProbe->pTable->zName,pProbe->zName,
- pNew->u.btree.nEq, pNew->nSkip));
+ pNew->u.btree.nEq, pNew->nSkip, pNew->rRun));
assert( (pNew->wsFlags & WHERE_VIRTUALTABLE)==0 );
assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 );
@@ -2536,7 +2547,7 @@ static int whereLoopAddBtreeIndex(
/* "x IN (value, value, ...)" */
nIn = sqlite3LogEst(pExpr->x.pList->nExpr);
}
- if( pProbe->hasStat1 ){
+ if( pProbe->hasStat1 && rLogSize>=10 ){
LogEst M, logK, safetyMargin;
/* Let:
** N = the total number of rows in the table
@@ -2555,7 +2566,8 @@ static int whereLoopAddBtreeIndex(
** a safety margin of 2 (LogEst: 10) that favors using the IN operator
** with the index, as using an index has better worst-case behavior.
** If we do not have real sqlite_stat1 data, always prefer to use
- ** the index.
+ ** the index. Do not bother with this optimization on very small
+ ** tables (less than 2 rows) as it is pointless in that case.
*/
M = pProbe->aiRowLogEst[saved_nEq];
logK = estLog(nIn);
@@ -2564,7 +2576,7 @@ static int whereLoopAddBtreeIndex(
WHERETRACE(0x40,
("Scan preferred over IN operator on column %d of \"%s\" (%d<%d)\n",
saved_nEq, pProbe->zName, M+logK+10, nIn+rLogSize));
- continue;
+ pNew->wsFlags |= WHERE_IN_SEEKSCAN;
}else{
WHERETRACE(0x40,
("IN operator preferred on column %d of \"%s\" (%d>=%d)\n",
@@ -2810,6 +2822,7 @@ static int indexMightHelpWithOrderBy(
if( (pOB = pBuilder->pWInfo->pOrderBy)==0 ) return 0;
for(ii=0; ii<pOB->nExpr; ii++){
Expr *pExpr = sqlite3ExprSkipCollateAndLikely(pOB->a[ii].pExpr);
+ if( NEVER(pExpr==0) ) continue;
if( pExpr->op==TK_COLUMN && pExpr->iTable==iCursor ){
if( pExpr->iColumn<0 ) return 1;
for(jj=0; jj<pIndex->nKeyCol; jj++){
@@ -3041,8 +3054,23 @@ static int whereLoopAddBtree(
/* Full table scan */
pNew->iSortIdx = b ? iSortIdx : 0;
- /* TUNING: Cost of full table scan is (N*3.0). */
+ /* TUNING: Cost of full table scan is 3.0*N. The 3.0 factor is an
+ ** extra cost designed to discourage the use of full table scans,
+ ** since index lookups have better worst-case performance if our
+ ** stat guesses are wrong. Reduce the 3.0 penalty slightly
+ ** (to 2.75) if we have valid STAT4 information for the table.
+ ** At 2.75, a full table scan is preferred over using an index on
+ ** a column with just two distinct values where each value has about
+ ** an equal number of appearances. Without STAT4 data, we still want
+ ** to use an index in that case, since the constraint might be for
+ ** the scarcer of the two values, and in that case an index lookup is
+ ** better.
+ */
+#ifdef SQLITE_ENABLE_STAT4
+ pNew->rRun = rSize + 16 - 2*((pTab->tabFlags & TF_HasStat4)!=0);
+#else
pNew->rRun = rSize + 16;
+#endif
ApplyCostMultiplier(pNew->rRun, pTab->costMult);
whereLoopOutputAdjust(pWC, pNew, rSize);
rc = whereLoopInsert(pBuilder, pNew);
@@ -3773,6 +3801,7 @@ static i8 wherePathSatisfiesOrderBy(
for(i=0; i<nOrderBy; i++){
if( MASKBIT(i) & obSat ) continue;
pOBExpr = sqlite3ExprSkipCollateAndLikely(pOrderBy->a[i].pExpr);
+ if( NEVER(pOBExpr==0) ) continue;
if( pOBExpr->op!=TK_COLUMN ) continue;
if( pOBExpr->iTable!=iCur ) continue;
pTerm = sqlite3WhereFindTerm(&pWInfo->sWC, iCur, pOBExpr->iColumn,
@@ -3899,6 +3928,7 @@ static i8 wherePathSatisfiesOrderBy(
pOBExpr = sqlite3ExprSkipCollateAndLikely(pOrderBy->a[i].pExpr);
testcase( wctrlFlags & WHERE_GROUPBY );
testcase( wctrlFlags & WHERE_DISTINCTBY );
+ if( NEVER(pOBExpr==0) ) continue;
if( (wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0 ) bOnce = 0;
if( iColumn>=XN_ROWID ){
if( pOBExpr->op!=TK_COLUMN ) continue;
@@ -4053,16 +4083,24 @@ static LogEst whereSortingCost(
** cost = (3.0 * N * log(N)) * (Y/X)
**
** The (Y/X) term is implemented using stack variable rScale
- ** below. */
+ ** below.
+ */
LogEst rScale, rSortCost;
assert( nOrderBy>0 && 66==sqlite3LogEst(100) );
rScale = sqlite3LogEst((nOrderBy-nSorted)*100/nOrderBy) - 66;
rSortCost = nRow + rScale + 16;
/* Multiple by log(M) where M is the number of output rows.
- ** Use the LIMIT for M if it is smaller */
+ ** Use the LIMIT for M if it is smaller. Or if this sort is for
+ ** a DISTINCT operator, M will be the number of distinct output
+ ** rows, so fudge it downwards a bit.
+ */
if( (pWInfo->wctrlFlags & WHERE_USE_LIMIT)!=0 && pWInfo->iLimit<nRow ){
nRow = pWInfo->iLimit;
+ }else if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT) ){
+ /* TUNING: In the sort for a DISTINCT operator, assume that the DISTINCT
+ ** reduces the number of output rows by a factor of 2 */
+ if( nRow>10 ) nRow -= 10; assert( 10==sqlite3LogEst(2) );
}
rSortCost += estLog(nRow);
return rSortCost;
@@ -5189,6 +5227,7 @@ WhereInfo *sqlite3WhereBegin(
if( (pLoop->wsFlags & WHERE_CONSTRAINT)!=0
&& (pLoop->wsFlags & (WHERE_COLUMN_RANGE|WHERE_SKIPSCAN))==0
&& (pLoop->wsFlags & WHERE_BIGNULL_SORT)==0
+ && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0
&& (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)==0
&& pWInfo->eDistinct!=WHERE_DISTINCT_ORDERED
){
@@ -5246,6 +5285,7 @@ WhereInfo *sqlite3WhereBegin(
/* Done. */
VdbeModuleComment((v, "Begin WHERE-core"));
+ pWInfo->iEndWhere = sqlite3VdbeCurrentAddr(v);
return pWInfo;
/* Jump here if malloc fails */
@@ -5289,6 +5329,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
WhereLoop *pLoop;
SrcList *pTabList = pWInfo->pTabList;
sqlite3 *db = pParse->db;
+ int iEnd = sqlite3VdbeCurrentAddr(v);
/* Generate loop termination code.
*/
@@ -5349,7 +5390,9 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
if( pIn->eEndLoopOp!=OP_Noop ){
if( pIn->nPrefix ){
- assert( pLoop->wsFlags & WHERE_IN_EARLYOUT );
+ int bEarlyOut =
+ (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0
+ && (pLoop->wsFlags & WHERE_IN_EARLYOUT)!=0;
if( pLevel->iLeftJoin ){
/* For LEFT JOIN queries, cursor pIn->iCur may not have been
** opened yet. This occurs for WHERE clauses such as
@@ -5360,12 +5403,10 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
** jump over the OP_Next or OP_Prev instruction about to
** be coded. */
sqlite3VdbeAddOp2(v, OP_IfNotOpen, pIn->iCur,
- sqlite3VdbeCurrentAddr(v) + 2 +
- ((pLoop->wsFlags & WHERE_VIRTUALTABLE)==0)
- );
+ sqlite3VdbeCurrentAddr(v) + 2 + bEarlyOut);
VdbeCoverage(v);
}
- if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 ){
+ if( bEarlyOut ){
sqlite3VdbeAddOp4Int(v, OP_IfNoHope, pLevel->iIdxCur,
sqlite3VdbeCurrentAddr(v)+2,
pIn->iBase, pIn->nPrefix);
@@ -5426,7 +5467,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
assert( pWInfo->nLevel<=pTabList->nSrc );
for(i=0, pLevel=pWInfo->a; i<pWInfo->nLevel; i++, pLevel++){
int k, last;
- VdbeOp *pOp;
+ VdbeOp *pOp, *pLastOp;
Index *pIdx = 0;
struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom];
Table *pTab = pTabItem->pTab;
@@ -5484,20 +5525,31 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
pIdx = pLevel->u.pCovidx;
}
if( pIdx
- && (pWInfo->eOnePass==ONEPASS_OFF || !HasRowid(pIdx->pTable))
&& !db->mallocFailed
){
- last = sqlite3VdbeCurrentAddr(v);
- k = pLevel->addrBody;
+ if( pWInfo->eOnePass==ONEPASS_OFF || !HasRowid(pIdx->pTable) ){
+ last = iEnd;
+ }else{
+ last = pWInfo->iEndWhere;
+ }
+ k = pLevel->addrBody + 1;
#ifdef SQLITE_DEBUG
if( db->flags & SQLITE_VdbeAddopTrace ){
printf("TRANSLATE opcodes in range %d..%d\n", k, last-1);
}
+ /* Proof that the "+1" on the k value above is safe */
+ pOp = sqlite3VdbeGetOp(v, k - 1);
+ assert( pOp->opcode!=OP_Column || pOp->p1!=pLevel->iTabCur );
+ assert( pOp->opcode!=OP_Rowid || pOp->p1!=pLevel->iTabCur );
+ assert( pOp->opcode!=OP_IfNullRow || pOp->p1!=pLevel->iTabCur );
#endif
pOp = sqlite3VdbeGetOp(v, k);
- for(; k<last; k++, pOp++){
- if( pOp->p1!=pLevel->iTabCur ) continue;
- if( pOp->opcode==OP_Column
+ pLastOp = pOp + (last - k);
+ assert( pOp<pLastOp );
+ do{
+ if( pOp->p1!=pLevel->iTabCur ){
+ /* no-op */
+ }else if( pOp->opcode==OP_Column
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
|| pOp->opcode==OP_Offset
#endif
@@ -5528,7 +5580,10 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
pOp->p1 = pLevel->iIdxCur;
OpcodeRewriteTrace(db, k, pOp);
}
- }
+#ifdef SQLITE_DEBUG
+ k++;
+#endif
+ }while( (++pOp)<pLastOp );
#ifdef SQLITE_DEBUG
if( db->flags & SQLITE_VdbeAddopTrace ) printf("TRANSLATE complete\n");
#endif
diff --git a/chromium/third_party/sqlite/src/src/whereInt.h b/chromium/third_party/sqlite/src/src/whereInt.h
index e33dde55e29..6c969af9c2c 100644
--- a/chromium/third_party/sqlite/src/src/whereInt.h
+++ b/chromium/third_party/sqlite/src/src/whereInt.h
@@ -261,9 +261,11 @@ struct WhereTerm {
u8 eMatchOp; /* Op for vtab MATCH/LIKE/GLOB/REGEXP terms */
int iParent; /* Disable pWC->a[iParent] when this term disabled */
int leftCursor; /* Cursor number of X in "X <op> <expr>" */
- int iField; /* Field in (?,?,?) IN (SELECT...) vector */
union {
- int leftColumn; /* Column number of X in "X <op> <expr>" */
+ struct {
+ int leftColumn; /* Column number of X in "X <op> <expr>" */
+ int iField; /* Field in (?,?,?) IN (SELECT...) vector */
+ } x; /* Opcode other than OP_OR or OP_AND */
WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */
WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */
} u;
@@ -488,6 +490,7 @@ struct WhereInfo {
unsigned sorted :1; /* True if really sorted (not just grouped) */
LogEst nRowOut; /* Estimated number of output rows */
int iTop; /* The very beginning of the WHERE loop */
+ int iEndWhere; /* End of the WHERE clause itself */
WhereLoop *pLoops; /* List of all WhereLoop objects */
WhereExprMod *pExprMods; /* Expression modifications */
Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
@@ -616,5 +619,6 @@ void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereClause*);
#define WHERE_PARTIALIDX 0x00020000 /* The automatic index is partial */
#define WHERE_IN_EARLYOUT 0x00040000 /* Perhaps quit IN loops early */
#define WHERE_BIGNULL_SORT 0x00080000 /* Column nEq of index is BIGNULL */
+#define WHERE_IN_SEEKSCAN 0x00100000 /* Seek-scan optimization for IN */
#endif /* !defined(SQLITE_WHEREINT_H) */
diff --git a/chromium/third_party/sqlite/src/src/wherecode.c b/chromium/third_party/sqlite/src/src/wherecode.c
index 5473a0282ec..4afe0ac9c90 100644
--- a/chromium/third_party/sqlite/src/src/wherecode.c
+++ b/chromium/third_party/sqlite/src/src/wherecode.c
@@ -427,7 +427,7 @@ static Expr *removeUnindexableInClauseTerms(
for(i=iEq; i<pLoop->nLTerm; i++){
if( pLoop->aLTerm[i]->pExpr==pX ){
- int iField = pLoop->aLTerm[i]->iField - 1;
+ int iField = pLoop->aLTerm[i]->u.x.iField - 1;
if( pOrigRhs->a[iField].pExpr==0 ) continue; /* Duplicate PK column */
pRhs = sqlite3ExprListAppend(pParse, pRhs, pOrigRhs->a[iField].pExpr);
pOrigRhs->a[iField].pExpr = 0;
@@ -570,6 +570,9 @@ static int codeEqualityTerm(
if( pLevel->u.in.nIn==0 ){
pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse);
}
+ if( iEq>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0 ){
+ pLoop->wsFlags |= WHERE_IN_EARLYOUT;
+ }
i = pLevel->u.in.nIn;
pLevel->u.in.nIn += nEq;
@@ -596,7 +599,6 @@ static int codeEqualityTerm(
if( iEq>0 ){
pIn->iBase = iReg - i;
pIn->nPrefix = i;
- pLoop->wsFlags |= WHERE_IN_EARLYOUT;
}else{
pIn->nPrefix = 0;
}
@@ -606,6 +608,14 @@ static int codeEqualityTerm(
pIn++;
}
}
+ testcase( iEq>0
+ && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0
+ && (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 );
+ if( iEq>0
+ && (pLoop->wsFlags & (WHERE_IN_SEEKSCAN|WHERE_VIRTUALTABLE))==0
+ ){
+ sqlite3VdbeAddOp3(v, OP_SeekHit, pLevel->iIdxCur, 0, iEq);
+ }
}else{
pLevel->u.in.nIn = 0;
}
@@ -1392,6 +1402,9 @@ Bitmask sqlite3WhereCodeOneLoopStart(
pLoop->u.vtab.needFree ? P4_DYNAMIC : P4_STATIC);
VdbeCoverage(v);
pLoop->u.vtab.needFree = 0;
+ /* An OOM inside of AddOp4(OP_VFilter) instruction above might have freed
+ ** the u.vtab.idxStr. NULL it out to prevent a use-after-free */
+ if( db->mallocFailed ) pLoop->u.vtab.idxStr = 0;
pLevel->p1 = iCur;
pLevel->op = pWInfo->eOnePass ? OP_Noop : OP_VNext;
pLevel->p2 = sqlite3VdbeCurrentAddr(v);
@@ -1650,6 +1663,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
u8 bStopAtNull = 0; /* Add condition to terminate at NULLs */
int omitTable; /* True if we use the index only */
int regBignull = 0; /* big-null flag register */
+ int addrSeekScan = 0; /* Opcode of the OP_SeekScan, if any */
pIdx = pLoop->u.btree.pIndex;
iIdxCur = pLevel->iIdxCur;
@@ -1788,9 +1802,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
** above has already left the cursor sitting on the correct row,
** so no further seeking is needed */
}else{
- if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){
- sqlite3VdbeAddOp1(v, OP_SeekHit, iIdxCur);
- }
if( regBignull ){
sqlite3VdbeAddOp2(v, OP_Integer, 1, regBignull);
VdbeComment((v, "NULL-scan pass ctr"));
@@ -1798,6 +1809,20 @@ Bitmask sqlite3WhereCodeOneLoopStart(
op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
assert( op!=0 );
+ if( (pLoop->wsFlags & WHERE_IN_SEEKSCAN)!=0 && op==OP_SeekGE ){
+ assert( regBignull==0 );
+ /* TUNING: The OP_SeekScan opcode seeks to reduce the number
+ ** of expensive seek operations by replacing a single seek with
+ ** 1 or more step operations. The question is, how many steps
+ ** should we try before giving up and going with a seek. The cost
+ ** of a seek is proportional to the logarithm of the of the number
+ ** of entries in the tree, so basing the number of steps to try
+ ** on the estimated number of rows in the btree seems like a good
+ ** guess. */
+ addrSeekScan = sqlite3VdbeAddOp1(v, OP_SeekScan,
+ (pIdx->aiRowLogEst[0]+9)/10);
+ VdbeCoverage(v);
+ }
sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
VdbeCoverage(v);
VdbeCoverageIf(v, op==OP_Rewind); testcase( op==OP_Rewind );
@@ -1880,6 +1905,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
testcase( op==OP_IdxGE ); VdbeCoverageIf(v, op==OP_IdxGE );
testcase( op==OP_IdxLT ); VdbeCoverageIf(v, op==OP_IdxLT );
testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE );
+ if( addrSeekScan ) sqlite3VdbeJumpHere(v, addrSeekScan);
}
if( regBignull ){
/* During a NULL-scan, check to see if we have reached the end of
@@ -1899,8 +1925,8 @@ Bitmask sqlite3WhereCodeOneLoopStart(
testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE );
}
- if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){
- sqlite3VdbeAddOp2(v, OP_SeekHit, iIdxCur, 1);
+ if( (pLoop->wsFlags & WHERE_IN_EARLYOUT)!=0 ){
+ sqlite3VdbeAddOp3(v, OP_SeekHit, iIdxCur, nEq, nEq);
}
/* Seek the table cursor, if required */
@@ -1909,17 +1935,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
if( omitTable ){
/* pIdx is a covering index. No need to access the main table. */
}else if( HasRowid(pIdx->pTable) ){
- if( (pWInfo->wctrlFlags & WHERE_SEEK_TABLE)
- || ( (pWInfo->wctrlFlags & WHERE_SEEK_UNIQ_TABLE)!=0
- && (pWInfo->eOnePass==ONEPASS_SINGLE || pLoop->nLTerm==0) )
- ){
- iRowidReg = ++pParse->nMem;
- sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg);
- sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowidReg);
- VdbeCoverage(v);
- }else{
- codeDeferredSeek(pWInfo, pIdx, iCur, iIdxCur);
- }
+ codeDeferredSeek(pWInfo, pIdx, iCur, iIdxCur);
}else if( iCur!=iIdxCur ){
Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable);
iRowidReg = sqlite3GetTempRange(pParse, pPk->nKeyCol);
@@ -2046,7 +2062,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
int iRetInit; /* Address of regReturn init */
int untestedTerms = 0; /* Some terms not completely tested */
int ii; /* Loop counter */
- u16 wctrlFlags; /* Flags for sub-WHERE clause */
Expr *pAndExpr = 0; /* An ".. AND (...)" expression */
Table *pTab = pTabItem->pTab;
@@ -2147,7 +2162,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
** eliminating duplicates from other WHERE clauses, the action for each
** sub-WHERE clause is to to invoke the main loop body as a subroutine.
*/
- wctrlFlags = WHERE_OR_SUBCLAUSE | (pWInfo->wctrlFlags & WHERE_SEEK_TABLE);
ExplainQueryPlan((pParse, 1, "MULTI-INDEX OR"));
for(ii=0; ii<pOrWc->nTerm; ii++){
WhereTerm *pOrTerm = &pOrWc->a[ii];
@@ -2166,7 +2180,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
ExplainQueryPlan((pParse, 1, "INDEX %d", ii+1));
WHERETRACE(0xffff, ("Subplan for OR-clause:\n"));
pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
- wctrlFlags, iCovCur);
+ WHERE_OR_SUBCLAUSE, iCovCur);
assert( pSubWInfo || pParse->nErr || db->mallocFailed );
if( pSubWInfo ){
WhereLoop *pSubLoop;
@@ -2264,6 +2278,9 @@ Bitmask sqlite3WhereCodeOneLoopStart(
}else{
pCov = 0;
}
+ if( sqlite3WhereUsesDeferredSeek(pSubWInfo) ){
+ pWInfo->bDeferredSeek = 1;
+ }
/* Finish the loop through table entries that match term pOrTerm. */
sqlite3WhereEnd(pSubWInfo);
@@ -2416,7 +2433,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
#endif
assert( !ExprHasProperty(pE, EP_FromJoin) );
assert( (pTerm->prereqRight & pLevel->notReady)!=0 );
- pAlt = sqlite3WhereFindTerm(pWC, iCur, pTerm->u.leftColumn, notReady,
+ pAlt = sqlite3WhereFindTerm(pWC, iCur, pTerm->u.x.leftColumn, notReady,
WO_EQ|WO_IN|WO_IS, 0);
if( pAlt==0 ) continue;
if( pAlt->wtFlags & (TERM_CODED) ) continue;
diff --git a/chromium/third_party/sqlite/src/src/whereexpr.c b/chromium/third_party/sqlite/src/src/whereexpr.c
index 3c91fc3539d..a77eb36106c 100644
--- a/chromium/third_party/sqlite/src/src/whereexpr.c
+++ b/chromium/third_party/sqlite/src/src/whereexpr.c
@@ -798,7 +798,7 @@ static void exprAnalyzeOrTerm(
assert( pOrTerm->wtFlags & (TERM_COPIED|TERM_VIRTUAL) );
continue;
}
- iColumn = pOrTerm->u.leftColumn;
+ iColumn = pOrTerm->u.x.leftColumn;
iCursor = pOrTerm->leftCursor;
pLeft = pOrTerm->pExpr->pLeft;
break;
@@ -820,7 +820,7 @@ static void exprAnalyzeOrTerm(
assert( pOrTerm->eOperator & WO_EQ );
if( pOrTerm->leftCursor!=iCursor ){
pOrTerm->wtFlags &= ~TERM_OR_OK;
- }else if( pOrTerm->u.leftColumn!=iColumn || (iColumn==XN_EXPR
+ }else if( pOrTerm->u.x.leftColumn!=iColumn || (iColumn==XN_EXPR
&& sqlite3ExprCompare(pParse, pOrTerm->pExpr->pLeft, pLeft, -1)
)){
okToChngToIN = 0;
@@ -855,7 +855,7 @@ static void exprAnalyzeOrTerm(
if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue;
assert( pOrTerm->eOperator & WO_EQ );
assert( pOrTerm->leftCursor==iCursor );
- assert( pOrTerm->u.leftColumn==iColumn );
+ assert( pOrTerm->u.x.leftColumn==iColumn );
pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0);
pList = sqlite3ExprListAppend(pWInfo->pParse, pList, pDup);
pLeft = pOrTerm->pExpr->pLeft;
@@ -1091,15 +1091,15 @@ static void exprAnalyze(
Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight);
u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV;
- if( pTerm->iField>0 ){
+ if( pTerm->u.x.iField>0 ){
assert( op==TK_IN );
assert( pLeft->op==TK_VECTOR );
- pLeft = pLeft->x.pList->a[pTerm->iField-1].pExpr;
+ pLeft = pLeft->x.pList->a[pTerm->u.x.iField-1].pExpr;
}
if( exprMightBeIndexed(pSrc, prereqLeft, aiCurCol, pLeft, op) ){
pTerm->leftCursor = aiCurCol[0];
- pTerm->u.leftColumn = aiCurCol[1];
+ pTerm->u.x.leftColumn = aiCurCol[1];
pTerm->eOperator = operatorMask(op) & opMask;
}
if( op==TK_IS ) pTerm->wtFlags |= TERM_IS;
@@ -1109,7 +1109,7 @@ static void exprAnalyze(
WhereTerm *pNew;
Expr *pDup;
u16 eExtraOp = 0; /* Extra bits for pNew->eOperator */
- assert( pTerm->iField==0 );
+ assert( pTerm->u.x.iField==0 );
if( pTerm->leftCursor>=0 ){
int idxNew;
pDup = sqlite3ExprDup(db, pExpr, 0);
@@ -1135,7 +1135,7 @@ static void exprAnalyze(
}
pNew->wtFlags |= exprCommute(pParse, pDup);
pNew->leftCursor = aiCurCol[0];
- pNew->u.leftColumn = aiCurCol[1];
+ pNew->u.x.leftColumn = aiCurCol[1];
testcase( (prereqLeft | extraRight) != prereqLeft );
pNew->prereqRight = prereqLeft | extraRight;
pNew->prereqAll = prereqAll;
@@ -1309,7 +1309,7 @@ static void exprAnalyze(
pNewTerm = &pWC->a[idxNew];
pNewTerm->prereqRight = prereqExpr;
pNewTerm->leftCursor = pLeft->iTable;
- pNewTerm->u.leftColumn = pLeft->iColumn;
+ pNewTerm->u.x.leftColumn = pLeft->iColumn;
pNewTerm->eOperator = WO_AUX;
pNewTerm->eMatchOp = eOp2;
markTermAsChild(pWC, idxNew, idxTerm);
@@ -1356,13 +1356,13 @@ static void exprAnalyze(
/* If there is a vector IN term - e.g. "(a, b) IN (SELECT ...)" - create
** a virtual term for each vector component. The expression object
** used by each such virtual term is pExpr (the full vector IN(...)
- ** expression). The WhereTerm.iField variable identifies the index within
+ ** expression). The WhereTerm.u.x.iField variable identifies the index within
** the vector on the LHS that the virtual term represents.
**
** This only works if the RHS is a simple SELECT (not a compound) that does
** not use window functions.
*/
- if( pWC->op==TK_AND && pExpr->op==TK_IN && pTerm->iField==0
+ if( pWC->op==TK_AND && pExpr->op==TK_IN && pTerm->u.x.iField==0
&& pExpr->pLeft->op==TK_VECTOR
&& pExpr->x.pSelect->pPrior==0
#ifndef SQLITE_OMIT_WINDOWFUNC
@@ -1373,7 +1373,7 @@ static void exprAnalyze(
for(i=0; i<sqlite3ExprVectorSize(pExpr->pLeft); i++){
int idxNew;
idxNew = whereClauseInsert(pWC, pExpr, TERM_VIRTUAL);
- pWC->a[idxNew].iField = i+1;
+ pWC->a[idxNew].u.x.iField = i+1;
exprAnalyze(pSrc, pWC, idxNew);
markTermAsChild(pWC, idxNew, idxTerm);
}
@@ -1408,7 +1408,7 @@ static void exprAnalyze(
pNewTerm = &pWC->a[idxNew];
pNewTerm->prereqRight = 0;
pNewTerm->leftCursor = pLeft->iTable;
- pNewTerm->u.leftColumn = pLeft->iColumn;
+ pNewTerm->u.x.leftColumn = pLeft->iColumn;
pNewTerm->eOperator = WO_GT;
markTermAsChild(pWC, idxNew, idxTerm);
pTerm = &pWC->a[idxTerm];
@@ -1451,6 +1451,7 @@ static void exprAnalyze(
void sqlite3WhereSplit(WhereClause *pWC, Expr *pExpr, u8 op){
Expr *pE2 = sqlite3ExprSkipCollateAndLikely(pExpr);
pWC->op = op;
+ assert( pE2!=0 || pExpr==0 );
if( pE2==0 ) return;
if( pE2->op!=op ){
whereClauseInsert(pWC, pExpr, 0);
diff --git a/chromium/third_party/sqlite/src/tool/GetFile.cs b/chromium/third_party/sqlite/src/tool/GetFile.cs
index f188dbbb4d9..1784a792638 100644
--- a/chromium/third_party/sqlite/src/tool/GetFile.cs
+++ b/chromium/third_party/sqlite/src/tool/GetFile.cs
@@ -11,461 +11,461 @@
*************************************************************************
** This file contains C# code to download a single file based on a URI.
*/
-
-using System;
-using System.ComponentModel;
-using System.Diagnostics;
-using System.IO;
-using System.Net;
-using System.Reflection;
-using System.Runtime.InteropServices;
-using System.Threading;
-
-///////////////////////////////////////////////////////////////////////////////
-
-#region Assembly Metadata
-[assembly: AssemblyTitle("GetFile Tool")]
-[assembly: AssemblyDescription("Download a single file based on a URI.")]
-[assembly: AssemblyCompany("SQLite Development Team")]
-[assembly: AssemblyProduct("SQLite")]
-[assembly: AssemblyCopyright("Public Domain")]
-[assembly: ComVisible(false)]
-[assembly: Guid("5c4b3728-1693-4a33-a218-8e6973ca15a6")]
-[assembly: AssemblyVersion("1.0.*")]
-
-#if DEBUG
-[assembly: AssemblyConfiguration("Debug")]
-#else
-[assembly: AssemblyConfiguration("Release")]
-#endif
-#endregion
-
-///////////////////////////////////////////////////////////////////////////////
-
-namespace GetFile
-{
- /// <summary>
- /// This enumeration is used to represent all the possible exit codes from
- /// this tool.
- /// </summary>
- internal enum ExitCode
- {
- /// <summary>
- /// The file download was a success.
- /// </summary>
- Success = 0,
-
- /// <summary>
- /// The command line arguments are missing (i.e. null). Generally,
- /// this should not happen.
- /// </summary>
- MissingArgs = 1,
-
- /// <summary>
- /// The wrong number of command line arguments was supplied.
- /// </summary>
- WrongNumArgs = 2,
-
- /// <summary>
- /// The URI specified on the command line could not be parsed as a
- /// supported absolute URI.
- /// </summary>
- BadUri = 3,
-
- /// <summary>
- /// The file name portion of the URI specified on the command line
- /// could not be extracted from it.
- /// </summary>
- BadFileName = 4,
-
- /// <summary>
- /// The temporary directory is either invalid (i.e. null) or does not
- /// represent an available directory.
- /// </summary>
- BadTempPath = 5,
-
- /// <summary>
- /// An exception was caught in <see cref="Main" />. Generally, this
- /// should not happen.
- /// </summary>
- Exception = 6,
-
- /// <summary>
- /// The file download was canceled. This tool does not make use of
- /// the <see cref="WebClient.CancelAsync" /> method; therefore, this
- /// should not happen.
- /// </summary>
- DownloadCanceled = 7,
-
- /// <summary>
- /// The file download encountered an error. Further information about
- /// this error should be displayed on the console.
- /// </summary>
- DownloadError = 8
- }
-
- ///////////////////////////////////////////////////////////////////////////
-
- internal static class Program
- {
- #region Private Data
- /// <summary>
- /// This is used to synchronize multithreaded access to the
- /// <see cref="previousPercent" /> and <see cref="exitCode"/>
- /// fields.
- /// </summary>
- private static readonly object syncRoot = new object();
-
- ///////////////////////////////////////////////////////////////////////
-
- /// <summary>
- /// This event will be signed when the file download has completed,
- /// even if the file download itself was canceled or unsuccessful.
- /// </summary>
- private static EventWaitHandle doneEvent;
-
- ///////////////////////////////////////////////////////////////////////
-
- /// <summary>
- /// The previous file download completion percentage seen by the
- /// <see cref="DownloadProgressChanged" /> event handler. This value
- /// is never decreased, nor is it ever reset to zero.
- /// </summary>
- private static int previousPercent = 0;
-
- ///////////////////////////////////////////////////////////////////////
-
- /// <summary>
- /// This will be the exit code returned by this tool after the file
- /// download completes, successfully or otherwise. This value is only
- /// changed by the <see cref="DownloadFileCompleted" /> event handler.
- /// </summary>
- private static ExitCode exitCode = ExitCode.Success;
- #endregion
-
- ///////////////////////////////////////////////////////////////////////
-
- #region Private Support Methods
- /// <summary>
- /// This method displays an error message to the console and/or
- /// displays the command line usage information for this tool.
- /// </summary>
- /// <param name="message">
- /// The error message to display, if any.
- /// </param>
- /// <param name="usage">
- /// Non-zero to display the command line usage information.
- /// </param>
- private static void Error(
- string message,
- bool usage
- )
- {
- if (message != null)
- Console.WriteLine(message);
-
- string fileName = Path.GetFileName(
- Process.GetCurrentProcess().MainModule.FileName);
-
- Console.WriteLine(String.Format(
- "usage: {0} <uri> [fileName]", fileName));
- }
-
- ///////////////////////////////////////////////////////////////////////
-
- /// <summary>
- /// This method attempts to determine the file name portion of the
- /// specified URI.
- /// </summary>
- /// <param name="uri">
- /// The URI to process.
- /// </param>
- /// <returns>
- /// The file name portion of the specified URI -OR- null if it cannot
- /// be determined.
- /// </returns>
- private static string GetFileName(
- Uri uri
- )
- {
- if (uri == null)
- return null;
-
- string pathAndQuery = uri.PathAndQuery;
-
- if (String.IsNullOrEmpty(pathAndQuery))
- return null;
-
- int index = pathAndQuery.LastIndexOf('/');
-
- if ((index < 0) || (index == pathAndQuery.Length))
- return null;
-
- return pathAndQuery.Substring(index + 1);
- }
- #endregion
-
- ///////////////////////////////////////////////////////////////////////
-
- #region Private Event Handlers
- /// <summary>
- /// This method is an event handler that is called when the file
- /// download completion percentage changes. It will display progress
- /// on the console. Special care is taken to make sure that progress
- /// events are not displayed out-of-order, even if duplicate and/or
- /// out-of-order events are received.
- /// </summary>
- /// <param name="sender">
- /// The source of the event.
- /// </param>
- /// <param name="e">
- /// Information for the event being processed.
- /// </param>
- private static void DownloadProgressChanged(
- object sender,
- DownloadProgressChangedEventArgs e
- )
- {
- if (e != null)
- {
- int percent = e.ProgressPercentage;
-
- lock (syncRoot)
- {
- if (percent > previousPercent)
- {
- Console.Write('.');
-
- if ((percent % 10) == 0)
- Console.Write(" {0}% ", percent);
-
- previousPercent = percent;
- }
- }
- }
- }
-
- ///////////////////////////////////////////////////////////////////////
-
- /// <summary>
- /// This method is an event handler that is called when the file
- /// download has completed, successfully or otherwise. It will
- /// display the overall result of the file download on the console,
- /// including any <see cref="Exception" /> information, if applicable.
- /// The <see cref="exitCode" /> field is changed by this method to
- /// indicate the overall result of the file download and the event
- /// within the <see cref="doneEvent" /> field will be signaled.
- /// </summary>
- /// <param name="sender">
- /// The source of the event.
- /// </param>
- /// <param name="e">
- /// Information for the event being processed.
- /// </param>
- private static void DownloadFileCompleted(
- object sender,
- AsyncCompletedEventArgs e
- )
- {
- if (e != null)
- {
- lock (syncRoot)
- {
- if (previousPercent < 100)
- Console.Write(' ');
- }
-
- if (e.Cancelled)
- {
- Console.WriteLine("Canceled");
-
- lock (syncRoot)
- {
- exitCode = ExitCode.DownloadCanceled;
- }
- }
- else
- {
- Exception error = e.Error;
-
- if (error != null)
- {
- Console.WriteLine("Error: {0}", error);
-
- lock (syncRoot)
- {
- exitCode = ExitCode.DownloadError;
- }
- }
- else
- {
- Console.WriteLine("Done");
- }
- }
- }
-
- if (doneEvent != null)
- doneEvent.Set();
- }
- #endregion
-
- ///////////////////////////////////////////////////////////////////////
-
- #region Program Entry Point
- /// <summary>
- /// This is the entry-point for this tool. It handles processing the
- /// command line arguments, setting up the web client, downloading the
- /// file, and saving it to the file system.
- /// </summary>
- /// <param name="args">
- /// The command line arguments.
- /// </param>
- /// <returns>
- /// Zero upon success; non-zero on failure. This will be one of the
- /// values from the <see cref="ExitCode" /> enumeration.
- /// </returns>
- private static int Main(
- string[] args
- )
- {
- //
- // NOTE: Sanity check the command line arguments.
- //
- if (args == null)
- {
- Error(null, true);
- return (int)ExitCode.MissingArgs;
- }
-
- if ((args.Length < 1) || (args.Length > 2))
- {
- Error(null, true);
- return (int)ExitCode.WrongNumArgs;
- }
-
- //
- // NOTE: Attempt to convert the first (and only) command line
- // argument to an absolute URI.
- //
- Uri uri;
-
- if (!Uri.TryCreate(args[0], UriKind.Absolute, out uri))
- {
- Error("Could not create absolute URI from argument.", false);
- return (int)ExitCode.BadUri;
- }
-
- //
- // NOTE: If a file name was specified on the command line, try to
- // use it (without its directory name); otherwise, fallback
- // to using the file name portion of the URI.
- //
- string fileName = (args.Length == 2) ?
- Path.GetFileName(args[1]) : null;
-
- if (String.IsNullOrEmpty(fileName))
- {
- //
- // NOTE: Attempt to extract the file name portion of the URI
- // we just created.
- //
- fileName = GetFileName(uri);
-
- if (fileName == null)
- {
- Error("Could not extract file name from URI.", false);
- return (int)ExitCode.BadFileName;
- }
- }
-
- //
- // NOTE: Grab the temporary path setup for this process. If it is
- // unavailable, we will not continue.
- //
- string directory = Path.GetTempPath();
-
- if (String.IsNullOrEmpty(directory) ||
- !Directory.Exists(directory))
- {
- Error("Temporary directory is invalid or unavailable.", false);
- return (int)ExitCode.BadTempPath;
- }
-
- try
- {
- //
- // HACK: For use of the TLS 1.2 security protocol because some
- // web servers fail without it. In order to support the
- // .NET Framework 2.0+ at compilation time, must use its
- // integer constant here.
- //
- ServicePointManager.SecurityProtocol =
- (SecurityProtocolType)0xC00;
-
- using (WebClient webClient = new WebClient())
- {
- //
- // NOTE: Create the event used to signal completion of the
- // file download.
- //
- doneEvent = new ManualResetEvent(false);
-
- //
- // NOTE: Hookup the event handlers we care about on the web
- // client. These are necessary because the file is
- // downloaded asynchronously.
- //
- webClient.DownloadProgressChanged +=
- new DownloadProgressChangedEventHandler(
- DownloadProgressChanged);
-
- webClient.DownloadFileCompleted +=
- new AsyncCompletedEventHandler(
- DownloadFileCompleted);
-
- //
- // NOTE: Build the fully qualified path and file name,
- // within the temporary directory, where the file to
- // be downloaded will be saved.
- //
- fileName = Path.Combine(directory, fileName);
-
- //
- // NOTE: If the file name already exists (in the temporary)
- // directory, delete it.
- //
- // TODO: Perhaps an error should be raised here instead?
- //
- if (File.Exists(fileName))
- File.Delete(fileName);
-
- //
- // NOTE: After kicking off the asynchronous file download
- // process, wait [forever] until the "done" event is
- // signaled.
- //
- Console.WriteLine(
- "Downloading \"{0}\" to \"{1}\"...", uri, fileName);
-
- webClient.DownloadFileAsync(uri, fileName);
- doneEvent.WaitOne();
- }
-
- lock (syncRoot)
- {
- return (int)exitCode;
- }
- }
- catch (Exception e)
- {
- //
- // NOTE: An exception was caught. Report it via the console
- // and return failure.
- //
- Error(e.ToString(), false);
- return (int)ExitCode.Exception;
- }
- }
- #endregion
- }
-}
+
+using System;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.IO;
+using System.Net;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Threading;
+
+///////////////////////////////////////////////////////////////////////////////
+
+#region Assembly Metadata
+[assembly: AssemblyTitle("GetFile Tool")]
+[assembly: AssemblyDescription("Download a single file based on a URI.")]
+[assembly: AssemblyCompany("SQLite Development Team")]
+[assembly: AssemblyProduct("SQLite")]
+[assembly: AssemblyCopyright("Public Domain")]
+[assembly: ComVisible(false)]
+[assembly: Guid("5c4b3728-1693-4a33-a218-8e6973ca15a6")]
+[assembly: AssemblyVersion("1.0.*")]
+
+#if DEBUG
+[assembly: AssemblyConfiguration("Debug")]
+#else
+[assembly: AssemblyConfiguration("Release")]
+#endif
+#endregion
+
+///////////////////////////////////////////////////////////////////////////////
+
+namespace GetFile
+{
+ /// <summary>
+ /// This enumeration is used to represent all the possible exit codes from
+ /// this tool.
+ /// </summary>
+ internal enum ExitCode
+ {
+ /// <summary>
+ /// The file download was a success.
+ /// </summary>
+ Success = 0,
+
+ /// <summary>
+ /// The command line arguments are missing (i.e. null). Generally,
+ /// this should not happen.
+ /// </summary>
+ MissingArgs = 1,
+
+ /// <summary>
+ /// The wrong number of command line arguments was supplied.
+ /// </summary>
+ WrongNumArgs = 2,
+
+ /// <summary>
+ /// The URI specified on the command line could not be parsed as a
+ /// supported absolute URI.
+ /// </summary>
+ BadUri = 3,
+
+ /// <summary>
+ /// The file name portion of the URI specified on the command line
+ /// could not be extracted from it.
+ /// </summary>
+ BadFileName = 4,
+
+ /// <summary>
+ /// The temporary directory is either invalid (i.e. null) or does not
+ /// represent an available directory.
+ /// </summary>
+ BadTempPath = 5,
+
+ /// <summary>
+ /// An exception was caught in <see cref="Main" />. Generally, this
+ /// should not happen.
+ /// </summary>
+ Exception = 6,
+
+ /// <summary>
+ /// The file download was canceled. This tool does not make use of
+ /// the <see cref="WebClient.CancelAsync" /> method; therefore, this
+ /// should not happen.
+ /// </summary>
+ DownloadCanceled = 7,
+
+ /// <summary>
+ /// The file download encountered an error. Further information about
+ /// this error should be displayed on the console.
+ /// </summary>
+ DownloadError = 8
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ internal static class Program
+ {
+ #region Private Data
+ /// <summary>
+ /// This is used to synchronize multithreaded access to the
+ /// <see cref="previousPercent" /> and <see cref="exitCode"/>
+ /// fields.
+ /// </summary>
+ private static readonly object syncRoot = new object();
+
+ ///////////////////////////////////////////////////////////////////////
+
+ /// <summary>
+ /// This event will be signed when the file download has completed,
+ /// even if the file download itself was canceled or unsuccessful.
+ /// </summary>
+ private static EventWaitHandle doneEvent;
+
+ ///////////////////////////////////////////////////////////////////////
+
+ /// <summary>
+ /// The previous file download completion percentage seen by the
+ /// <see cref="DownloadProgressChanged" /> event handler. This value
+ /// is never decreased, nor is it ever reset to zero.
+ /// </summary>
+ private static int previousPercent = 0;
+
+ ///////////////////////////////////////////////////////////////////////
+
+ /// <summary>
+ /// This will be the exit code returned by this tool after the file
+ /// download completes, successfully or otherwise. This value is only
+ /// changed by the <see cref="DownloadFileCompleted" /> event handler.
+ /// </summary>
+ private static ExitCode exitCode = ExitCode.Success;
+ #endregion
+
+ ///////////////////////////////////////////////////////////////////////
+
+ #region Private Support Methods
+ /// <summary>
+ /// This method displays an error message to the console and/or
+ /// displays the command line usage information for this tool.
+ /// </summary>
+ /// <param name="message">
+ /// The error message to display, if any.
+ /// </param>
+ /// <param name="usage">
+ /// Non-zero to display the command line usage information.
+ /// </param>
+ private static void Error(
+ string message,
+ bool usage
+ )
+ {
+ if (message != null)
+ Console.WriteLine(message);
+
+ string fileName = Path.GetFileName(
+ Process.GetCurrentProcess().MainModule.FileName);
+
+ Console.WriteLine(String.Format(
+ "usage: {0} <uri> [fileName]", fileName));
+ }
+
+ ///////////////////////////////////////////////////////////////////////
+
+ /// <summary>
+ /// This method attempts to determine the file name portion of the
+ /// specified URI.
+ /// </summary>
+ /// <param name="uri">
+ /// The URI to process.
+ /// </param>
+ /// <returns>
+ /// The file name portion of the specified URI -OR- null if it cannot
+ /// be determined.
+ /// </returns>
+ private static string GetFileName(
+ Uri uri
+ )
+ {
+ if (uri == null)
+ return null;
+
+ string pathAndQuery = uri.PathAndQuery;
+
+ if (String.IsNullOrEmpty(pathAndQuery))
+ return null;
+
+ int index = pathAndQuery.LastIndexOf('/');
+
+ if ((index < 0) || (index == pathAndQuery.Length))
+ return null;
+
+ return pathAndQuery.Substring(index + 1);
+ }
+ #endregion
+
+ ///////////////////////////////////////////////////////////////////////
+
+ #region Private Event Handlers
+ /// <summary>
+ /// This method is an event handler that is called when the file
+ /// download completion percentage changes. It will display progress
+ /// on the console. Special care is taken to make sure that progress
+ /// events are not displayed out-of-order, even if duplicate and/or
+ /// out-of-order events are received.
+ /// </summary>
+ /// <param name="sender">
+ /// The source of the event.
+ /// </param>
+ /// <param name="e">
+ /// Information for the event being processed.
+ /// </param>
+ private static void DownloadProgressChanged(
+ object sender,
+ DownloadProgressChangedEventArgs e
+ )
+ {
+ if (e != null)
+ {
+ int percent = e.ProgressPercentage;
+
+ lock (syncRoot)
+ {
+ if (percent > previousPercent)
+ {
+ Console.Write('.');
+
+ if ((percent % 10) == 0)
+ Console.Write(" {0}% ", percent);
+
+ previousPercent = percent;
+ }
+ }
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////
+
+ /// <summary>
+ /// This method is an event handler that is called when the file
+ /// download has completed, successfully or otherwise. It will
+ /// display the overall result of the file download on the console,
+ /// including any <see cref="Exception" /> information, if applicable.
+ /// The <see cref="exitCode" /> field is changed by this method to
+ /// indicate the overall result of the file download and the event
+ /// within the <see cref="doneEvent" /> field will be signaled.
+ /// </summary>
+ /// <param name="sender">
+ /// The source of the event.
+ /// </param>
+ /// <param name="e">
+ /// Information for the event being processed.
+ /// </param>
+ private static void DownloadFileCompleted(
+ object sender,
+ AsyncCompletedEventArgs e
+ )
+ {
+ if (e != null)
+ {
+ lock (syncRoot)
+ {
+ if (previousPercent < 100)
+ Console.Write(' ');
+ }
+
+ if (e.Cancelled)
+ {
+ Console.WriteLine("Canceled");
+
+ lock (syncRoot)
+ {
+ exitCode = ExitCode.DownloadCanceled;
+ }
+ }
+ else
+ {
+ Exception error = e.Error;
+
+ if (error != null)
+ {
+ Console.WriteLine("Error: {0}", error);
+
+ lock (syncRoot)
+ {
+ exitCode = ExitCode.DownloadError;
+ }
+ }
+ else
+ {
+ Console.WriteLine("Done");
+ }
+ }
+ }
+
+ if (doneEvent != null)
+ doneEvent.Set();
+ }
+ #endregion
+
+ ///////////////////////////////////////////////////////////////////////
+
+ #region Program Entry Point
+ /// <summary>
+ /// This is the entry-point for this tool. It handles processing the
+ /// command line arguments, setting up the web client, downloading the
+ /// file, and saving it to the file system.
+ /// </summary>
+ /// <param name="args">
+ /// The command line arguments.
+ /// </param>
+ /// <returns>
+ /// Zero upon success; non-zero on failure. This will be one of the
+ /// values from the <see cref="ExitCode" /> enumeration.
+ /// </returns>
+ private static int Main(
+ string[] args
+ )
+ {
+ //
+ // NOTE: Sanity check the command line arguments.
+ //
+ if (args == null)
+ {
+ Error(null, true);
+ return (int)ExitCode.MissingArgs;
+ }
+
+ if ((args.Length < 1) || (args.Length > 2))
+ {
+ Error(null, true);
+ return (int)ExitCode.WrongNumArgs;
+ }
+
+ //
+ // NOTE: Attempt to convert the first (and only) command line
+ // argument to an absolute URI.
+ //
+ Uri uri;
+
+ if (!Uri.TryCreate(args[0], UriKind.Absolute, out uri))
+ {
+ Error("Could not create absolute URI from argument.", false);
+ return (int)ExitCode.BadUri;
+ }
+
+ //
+ // NOTE: If a file name was specified on the command line, try to
+ // use it (without its directory name); otherwise, fallback
+ // to using the file name portion of the URI.
+ //
+ string fileName = (args.Length == 2) ?
+ Path.GetFileName(args[1]) : null;
+
+ if (String.IsNullOrEmpty(fileName))
+ {
+ //
+ // NOTE: Attempt to extract the file name portion of the URI
+ // we just created.
+ //
+ fileName = GetFileName(uri);
+
+ if (fileName == null)
+ {
+ Error("Could not extract file name from URI.", false);
+ return (int)ExitCode.BadFileName;
+ }
+ }
+
+ //
+ // NOTE: Grab the temporary path setup for this process. If it is
+ // unavailable, we will not continue.
+ //
+ string directory = Path.GetTempPath();
+
+ if (String.IsNullOrEmpty(directory) ||
+ !Directory.Exists(directory))
+ {
+ Error("Temporary directory is invalid or unavailable.", false);
+ return (int)ExitCode.BadTempPath;
+ }
+
+ try
+ {
+ //
+ // HACK: For use of the TLS 1.2 security protocol because some
+ // web servers fail without it. In order to support the
+ // .NET Framework 2.0+ at compilation time, must use its
+ // integer constant here.
+ //
+ ServicePointManager.SecurityProtocol =
+ (SecurityProtocolType)0xC00;
+
+ using (WebClient webClient = new WebClient())
+ {
+ //
+ // NOTE: Create the event used to signal completion of the
+ // file download.
+ //
+ doneEvent = new ManualResetEvent(false);
+
+ //
+ // NOTE: Hookup the event handlers we care about on the web
+ // client. These are necessary because the file is
+ // downloaded asynchronously.
+ //
+ webClient.DownloadProgressChanged +=
+ new DownloadProgressChangedEventHandler(
+ DownloadProgressChanged);
+
+ webClient.DownloadFileCompleted +=
+ new AsyncCompletedEventHandler(
+ DownloadFileCompleted);
+
+ //
+ // NOTE: Build the fully qualified path and file name,
+ // within the temporary directory, where the file to
+ // be downloaded will be saved.
+ //
+ fileName = Path.Combine(directory, fileName);
+
+ //
+ // NOTE: If the file name already exists (in the temporary)
+ // directory, delete it.
+ //
+ // TODO: Perhaps an error should be raised here instead?
+ //
+ if (File.Exists(fileName))
+ File.Delete(fileName);
+
+ //
+ // NOTE: After kicking off the asynchronous file download
+ // process, wait [forever] until the "done" event is
+ // signaled.
+ //
+ Console.WriteLine(
+ "Downloading \"{0}\" to \"{1}\"...", uri, fileName);
+
+ webClient.DownloadFileAsync(uri, fileName);
+ doneEvent.WaitOne();
+ }
+
+ lock (syncRoot)
+ {
+ return (int)exitCode;
+ }
+ }
+ catch (Exception e)
+ {
+ //
+ // NOTE: An exception was caught. Report it via the console
+ // and return failure.
+ //
+ Error(e.ToString(), false);
+ return (int)ExitCode.Exception;
+ }
+ }
+ #endregion
+ }
+}
diff --git a/chromium/third_party/sqlite/src/tool/GetTclKit.bat b/chromium/third_party/sqlite/src/tool/GetTclKit.bat
index a0077c470ce..e2be7c7f6c1 100644
--- a/chromium/third_party/sqlite/src/tool/GetTclKit.bat
+++ b/chromium/third_party/sqlite/src/tool/GetTclKit.bat
@@ -1,299 +1,331 @@
-@ECHO OFF
-
-::
-:: GetTclKit.bat --
-::
-:: TclKit Download Tool
-::
-
-SETLOCAL
-
-REM SET __ECHO=ECHO
-REM SET __ECHO2=ECHO
-REM SET __ECHO3=ECHO
-IF NOT DEFINED _AECHO (SET _AECHO=REM)
-IF NOT DEFINED _CECHO (SET _CECHO=REM)
-IF NOT DEFINED _VECHO (SET _VECHO=REM)
-
-SET OVERWRITE=^>
-IF DEFINED __ECHO SET OVERWRITE=^^^>
-
-SET APPEND=^>^>
-IF DEFINED __ECHO SET APPEND=^^^>^^^>
-
-SET PROCESSOR=%1
-
-IF DEFINED PROCESSOR (
- CALL :fn_UnquoteVariable PROCESSOR
-) ELSE (
- GOTO usage
-)
-
-SET PROCESSOR=%PROCESSOR:AMD64=x64%
-
-%_VECHO% Processor = '%PROCESSOR%'
-
-SET DUMMY2=%2
-
-IF DEFINED DUMMY2 (
- GOTO usage
-)
-
-SET ROOT=%~dp0\..
-SET ROOT=%ROOT:\\=\%
-
-%_VECHO% Root = '%ROOT%'
-
-SET TOOLS=%~dp0
-SET TOOLS=%TOOLS:~0,-1%
-
-%_VECHO% Tools = '%TOOLS%'
-
-IF NOT DEFINED windir (
- ECHO The windir environment variable must be set first.
- GOTO errors
-)
-
-%_VECHO% WinDir = '%windir%'
-
-IF NOT DEFINED TEMP (
- ECHO The TEMP environment variable must be set first.
- GOTO errors
-)
-
-%_VECHO% Temp = '%TEMP%'
-
-IF NOT DEFINED TCLKIT_URI (
- SET TCLKIT_URI=https://tclsh.com/
-)
-
-%_VECHO% TclKitUri = '%TCLKIT_URI%'
-
-IF /I "%PROCESSOR%" == "x86" (
- CALL :fn_TclKitX86Variables
-) ELSE IF /I "%PROCESSOR%" == "x64" (
- CALL :fn_TclKitX64Variables
-) ELSE (
- GOTO usage
-)
-
-%_VECHO% TclKitVersion = '%TCLKIT_VERSION%'
-%_VECHO% TclKitPatchLevel = '%TCLKIT_PATCHLEVEL%'
-%_VECHO% TclKitNoEnv = '%TCLKIT_NOENV%'
-%_VECHO% TclKitNoSdk = '%TCLKIT_NOSDK%'
-%_VECHO% TclKitExe = '%TCLKIT_EXE%'
-%_VECHO% TclKitLib = '%TCLKIT_LIB%'
-%_VECHO% TclKitLibStub = '%TCLKIT_LIB_STUB%'
-%_VECHO% TclKitSdk = '%TCLKIT_SDK%'
-%_VECHO% TclKitSdkZip = '%TCLKIT_SDK_ZIP%'
-%_VECHO% TclKitFiles = '%TCLKIT_FILES%'
-
-CALL :fn_ResetErrorLevel
-
-FOR %%T IN (csc.exe) DO (
- SET %%T_PATH=%%~dp$PATH:T
-)
-
-%_VECHO% Csc.exe_PATH = '%csc.exe_PATH%'
-
-IF DEFINED csc.exe_PATH (
- GOTO skip_addToPath
-)
-
-IF DEFINED FRAMEWORKDIR (
- REM Use the existing .NET Framework directory...
-) ELSE IF EXIST "%windir%\Microsoft.NET\Framework64\v2.0.50727" (
- SET FRAMEWORKDIR=%windir%\Microsoft.NET\Framework64\v2.0.50727
-) ELSE IF EXIST "%windir%\Microsoft.NET\Framework64\v3.5" (
- SET FRAMEWORKDIR=%windir%\Microsoft.NET\Framework64\v3.5
-) ELSE IF EXIST "%windir%\Microsoft.NET\Framework64\v4.0.30319" (
- SET FRAMEWORKDIR=%windir%\Microsoft.NET\Framework64\v4.0.30319
-) ELSE IF EXIST "%windir%\Microsoft.NET\Framework\v2.0.50727" (
- SET FRAMEWORKDIR=%windir%\Microsoft.NET\Framework\v2.0.50727
-) ELSE IF EXIST "%windir%\Microsoft.NET\Framework\v3.5" (
- SET FRAMEWORKDIR=%windir%\Microsoft.NET\Framework\v3.5
-) ELSE IF EXIST "%windir%\Microsoft.NET\Framework\v4.0.30319" (
- SET FRAMEWORKDIR=%windir%\Microsoft.NET\Framework\v4.0.30319
-) ELSE (
- ECHO No suitable version of the .NET Framework appears to be installed.
- GOTO errors
-)
-
-%_VECHO% FrameworkDir = '%FRAMEWORKDIR%'
-
-IF NOT EXIST "%FRAMEWORKDIR%\csc.exe" (
- ECHO The file "%FRAMEWORKDIR%\csc.exe" is missing.
- GOTO errors
-)
-
-CALL :fn_PrependToPath FRAMEWORKDIR
-
-:skip_addToPath
-
-IF NOT EXIST "%TEMP%\GetFile.exe" (
- %__ECHO% csc.exe "/out:%TEMP%\GetFile.exe" /target:exe "%TOOLS%\GetFile.cs"
-
- IF ERRORLEVEL 1 (
- ECHO Compilation of "%TOOLS%\GetFile.cs" failed.
- GOTO errors
- )
-)
-
-FOR %%F IN (%TCLKIT_FILES%) DO (
- IF NOT EXIST "%TEMP%\%%F" (
- %__ECHO% "%TEMP%\GetFile.exe" "%TCLKIT_URI%%%F"
-
- IF ERRORLEVEL 1 (
- ECHO Download of "%%F" from "%TCLKIT_URI%" failed.
- GOTO errors
- )
- )
-)
-
-IF DEFINED TCLKIT_NOENV GOTO skip_sdkUnZip
-IF DEFINED TCLKIT_NOSDK GOTO skip_sdkUnZip
-
-IF NOT EXIST "%TEMP%\%TCLKIT_SDK%" (
- %__ECHO% MKDIR "%TEMP%\%TCLKIT_SDK%"
-
- IF ERRORLEVEL 1 (
- ECHO Could not create directory "%TEMP%\%TCLKIT_SDK%".
- GOTO errors
- )
-)
-
-%__ECHO% "%TEMP%\unzip.exe" -n "%TEMP%\%TCLKIT_SDK_ZIP%" -d "%TEMP%\%TCLKIT_SDK%"
-
-IF ERRORLEVEL 1 (
- ECHO Could not unzip "%TEMP%\%TCLKIT_SDK_ZIP%" to "%TEMP%\%TCLKIT_SDK%".
- GOTO errors
-)
-
-:skip_sdkUnZip
-
-IF DEFINED TCLKIT_NOENV GOTO skip_sdkEnvironment
-
-%__ECHO% ECHO SET TCLSH_CMD=%TEMP%\%TCLKIT_EXE%%OVERWRITE%"%ROOT%\SetTclKitEnv.bat"
-
-IF DEFINED TCLKIT_NOSDK GOTO skip_sdkVariables
-
-%__ECHO% ECHO SET TCLINCDIR=%TEMP%\%TCLKIT_SDK%\include%APPEND%"%ROOT%\SetTclKitEnv.bat"
-%__ECHO% ECHO SET TCLLIBDIR=%TEMP%\%TCLKIT_SDK%\lib%APPEND%"%ROOT%\SetTclKitEnv.bat"
-%__ECHO% ECHO SET LIBTCLPATH=%TEMP%\%TCLKIT_SDK%\lib%APPEND%"%ROOT%\SetTclKitEnv.bat"
-%__ECHO% ECHO SET LIBTCL=%TCLKIT_LIB%%APPEND%"%ROOT%\SetTclKitEnv.bat"
-%__ECHO% ECHO SET LIBTCLSTUB=%TCLKIT_LIB_STUB%%APPEND%"%ROOT%\SetTclKitEnv.bat"
-
-:skip_sdkVariables
-
-ECHO.
-ECHO Wrote "%ROOT%\SetTclKitEnv.bat".
-ECHO Please run it to set the necessary Tcl environment variables.
-ECHO.
-
-:skip_sdkEnvironment
-
-GOTO no_errors
-
-:fn_TclKitX86Variables
- REM
- REM NOTE: By default, use latest available version of the TclKit SDK
- REM for x86. However, the "default" TclKit executable for x86
- REM is still used here because it is the only one "well-known"
- REM to be available for download.
- REM
- IF NOT DEFINED TCLKIT_PATCHLEVEL (
- SET TCLKIT_PATCHLEVEL=8.6.6
- )
- SET TCLKIT_VERSION=%TCLKIT_PATCHLEVEL:.=%
- SET TCLKIT_VERSION=%TCLKIT_VERSION:~0,2%
- REM SET TCLKIT_EXE=tclkit-%TCLKIT_PATCHLEVEL%.exe
- SET TCLKIT_EXE=tclkit-8.6.4.exe
- SET TCLKIT_LIB=libtclkit%TCLKIT_PATCHLEVEL:.=%.lib
- SET TCLKIT_LIB_STUB=libtclstub%TCLKIT_VERSION:.=%.a
- SET TCLKIT_SDK=libtclkit-sdk-x86-%TCLKIT_PATCHLEVEL%
- SET TCLKIT_SDK_ZIP=%TCLKIT_SDK%.zip
- SET TCLKIT_FILES=%TCLKIT_EXE%
- IF NOT DEFINED TCLKIT_NOENV IF NOT DEFINED TCLKIT_NOSDK (
- SET TCLKIT_FILES=%TCLKIT_FILES% unzip.exe %TCLKIT_SDK_ZIP%
- )
- GOTO :EOF
-
-:fn_TclKitX64Variables
- REM
- REM NOTE: By default, use latest available version of the TclKit SDK
- REM for x64. However, the "default" TclKit executable for x86
- REM is still used here because it is the only one "well-known"
- REM to be available for download.
- REM
- IF NOT DEFINED TCLKIT_PATCHLEVEL (
- SET TCLKIT_PATCHLEVEL=8.6.6
- )
- SET TCLKIT_VERSION=%TCLKIT_PATCHLEVEL:.=%
- SET TCLKIT_VERSION=%TCLKIT_VERSION:~0,2%
- REM SET TCLKIT_EXE=tclkit-%TCLKIT_PATCHLEVEL%.exe
- SET TCLKIT_EXE=tclkit-8.6.4.exe
- SET TCLKIT_LIB=libtclkit%TCLKIT_PATCHLEVEL:.=%.lib
- SET TCLKIT_LIB_STUB=libtclstub%TCLKIT_VERSION:.=%.a
- SET TCLKIT_SDK=libtclkit-sdk-x64-%TCLKIT_PATCHLEVEL%
- SET TCLKIT_SDK_ZIP=%TCLKIT_SDK%.zip
- SET TCLKIT_FILES=%TCLKIT_EXE%
- IF NOT DEFINED TCLKIT_NOENV IF NOT DEFINED TCLKIT_NOSDK (
- SET TCLKIT_FILES=%TCLKIT_FILES% unzip.exe %TCLKIT_SDK_ZIP%
- )
- GOTO :EOF
-
-:fn_UnquoteVariable
- IF NOT DEFINED %1 GOTO :EOF
- SETLOCAL
- SET __ECHO_CMD=ECHO %%%1%%
- FOR /F "delims=" %%V IN ('%__ECHO_CMD%') DO (
- SET VALUE=%%V
- )
- SET VALUE=%VALUE:"=%
- REM "
- ENDLOCAL && SET %1=%VALUE%
- GOTO :EOF
-
-:fn_PrependToPath
- IF NOT DEFINED %1 GOTO :EOF
- SETLOCAL
- SET __ECHO_CMD=ECHO %%%1%%
- FOR /F "delims=" %%V IN ('%__ECHO_CMD%') DO (
- SET VALUE=%%V
- )
- SET VALUE=%VALUE:"=%
- REM "
- ENDLOCAL && SET PATH=%VALUE%;%PATH%
- GOTO :EOF
-
-:fn_ResetErrorLevel
- VERIFY > NUL
- GOTO :EOF
-
-:fn_SetErrorLevel
- VERIFY MAYBE 2> NUL
- GOTO :EOF
-
-:usage
- ECHO.
- ECHO Usage: %~nx0 ^<processor^>
- ECHO.
- ECHO The only supported values for processor are "x86" and "x64".
- GOTO errors
-
-:errors
- CALL :fn_SetErrorLevel
- ENDLOCAL
- ECHO.
- ECHO Failure, errors were encountered.
- GOTO end_of_file
-
-:no_errors
- CALL :fn_ResetErrorLevel
- ENDLOCAL
- ECHO.
- ECHO Success, no errors were encountered.
- GOTO end_of_file
-
-:end_of_file
-%__ECHO% EXIT /B %ERRORLEVEL%
+@ECHO OFF
+
+::
+:: GetTclKit.bat --
+::
+:: TclKit Download Tool
+::
+
+SETLOCAL
+
+REM SET __ECHO=ECHO
+REM SET __ECHO2=ECHO
+REM SET __ECHO3=ECHO
+IF NOT DEFINED _AECHO (SET _AECHO=REM)
+IF NOT DEFINED _CECHO (SET _CECHO=REM)
+IF NOT DEFINED _VECHO (SET _VECHO=REM)
+
+SET OVERWRITE=^>
+IF DEFINED __ECHO SET OVERWRITE=^^^>
+
+SET APPEND=^>^>
+IF DEFINED __ECHO SET APPEND=^^^>^^^>
+
+SET PROCESSOR=%1
+
+IF DEFINED PROCESSOR (
+ CALL :fn_UnquoteVariable PROCESSOR
+) ELSE (
+ GOTO usage
+)
+
+SET PROCESSOR=%PROCESSOR:AMD64=x64%
+
+%_VECHO% Processor = '%PROCESSOR%'
+
+SET DUMMY2=%2
+
+IF DEFINED DUMMY2 (
+ GOTO usage
+)
+
+IF NOT DEFINED ENVDIR (
+ SET ENVDIR=%CD%
+)
+
+%_VECHO% EnvDir = '%ENVDIR%'
+
+SET TOOLS=%~dp0
+SET TOOLS=%TOOLS:~0,-1%
+
+%_VECHO% Tools = '%TOOLS%'
+
+IF NOT DEFINED windir (
+ ECHO The windir environment variable must be set first.
+ GOTO errors
+)
+
+%_VECHO% WinDir = '%windir%'
+
+IF NOT DEFINED TEMP (
+ ECHO The TEMP environment variable must be set first.
+ GOTO errors
+)
+
+%_VECHO% Temp = '%TEMP%'
+
+IF NOT DEFINED TCLKIT_URI (
+ SET TCLKIT_URI=https://urn.to/r/tclsh/
+)
+
+%_VECHO% TclKitUri = '%TCLKIT_URI%'
+
+IF NOT DEFINED TCLKIT_PATCHLEVEL (
+ SET TCLKIT_PATCHLEVEL=8.6.6
+)
+
+%_VECHO% TclKitPatchLevel = '%TCLKIT_PATCHLEVEL%'
+
+IF NOT DEFINED TCLKIT_EXE_PATCHLEVEL (
+ SET TCLKIT_EXE_PATCHLEVEL=8.6.4
+)
+
+%_VECHO% TclKitExePatchLevel = '%TCLKIT_EXE_PATCHLEVEL%'
+
+IF /I "%PROCESSOR%" == "x86" (
+ CALL :fn_TclKitX86Variables
+
+ IF ERRORLEVEL 1 (
+ GOTO errors
+ )
+) ELSE IF /I "%PROCESSOR%" == "x64" (
+ CALL :fn_TclKitX64Variables
+
+ IF ERRORLEVEL 1 (
+ GOTO errors
+ )
+) ELSE (
+ GOTO usage
+)
+
+%_VECHO% TclKitVersion = '%TCLKIT_VERSION%'
+%_VECHO% TclKitPatchLevel = '%TCLKIT_PATCHLEVEL%'
+%_VECHO% TclKitExePatchLevel = '%TCLKIT_EXE_PATCHLEVEL%'
+%_VECHO% TclKitNoEnv = '%TCLKIT_NOENV%'
+%_VECHO% TclKitNoSdk = '%TCLKIT_NOSDK%'
+%_VECHO% TclKitExe = '%TCLKIT_EXE%'
+%_VECHO% TclKitLib = '%TCLKIT_LIB%'
+%_VECHO% TclKitLibStub = '%TCLKIT_LIB_STUB%'
+%_VECHO% TclKitSdk = '%TCLKIT_SDK%'
+%_VECHO% TclKitSdkZip = '%TCLKIT_SDK_ZIP%'
+%_VECHO% TclKitFiles = '%TCLKIT_FILES%'
+
+CALL :fn_ResetErrorLevel
+
+FOR %%T IN (csc.exe) DO (
+ SET %%T_PATH=%%~dp$PATH:T
+)
+
+%_VECHO% Csc.exe_PATH = '%csc.exe_PATH%'
+
+IF DEFINED csc.exe_PATH (
+ GOTO skip_addToPath
+)
+
+IF DEFINED FRAMEWORKDIR (
+ REM Use the existing .NET Framework directory...
+) ELSE IF EXIST "%windir%\Microsoft.NET\Framework64\v2.0.50727" (
+ SET FRAMEWORKDIR=%windir%\Microsoft.NET\Framework64\v2.0.50727
+) ELSE IF EXIST "%windir%\Microsoft.NET\Framework64\v3.5" (
+ SET FRAMEWORKDIR=%windir%\Microsoft.NET\Framework64\v3.5
+) ELSE IF EXIST "%windir%\Microsoft.NET\Framework64\v4.0.30319" (
+ SET FRAMEWORKDIR=%windir%\Microsoft.NET\Framework64\v4.0.30319
+) ELSE IF EXIST "%windir%\Microsoft.NET\Framework\v2.0.50727" (
+ SET FRAMEWORKDIR=%windir%\Microsoft.NET\Framework\v2.0.50727
+) ELSE IF EXIST "%windir%\Microsoft.NET\Framework\v3.5" (
+ SET FRAMEWORKDIR=%windir%\Microsoft.NET\Framework\v3.5
+) ELSE IF EXIST "%windir%\Microsoft.NET\Framework\v4.0.30319" (
+ SET FRAMEWORKDIR=%windir%\Microsoft.NET\Framework\v4.0.30319
+) ELSE (
+ ECHO No suitable version of the .NET Framework appears to be installed.
+ GOTO errors
+)
+
+%_VECHO% FrameworkDir = '%FRAMEWORKDIR%'
+
+IF NOT EXIST "%FRAMEWORKDIR%\csc.exe" (
+ ECHO The file "%FRAMEWORKDIR%\csc.exe" is missing.
+ GOTO errors
+)
+
+CALL :fn_PrependToPath FRAMEWORKDIR
+
+:skip_addToPath
+
+IF NOT EXIST "%TEMP%\GetFile.exe" (
+ %__ECHO% csc.exe "/out:%TEMP%\GetFile.exe" /target:exe "%TOOLS%\GetFile.cs"
+
+ IF ERRORLEVEL 1 (
+ ECHO Compilation of "%TOOLS%\GetFile.cs" failed.
+ GOTO errors
+ )
+)
+
+FOR %%F IN (%TCLKIT_FILES%) DO (
+ IF NOT EXIST "%TEMP%\%%F" (
+ %__ECHO% "%TEMP%\GetFile.exe" "%TCLKIT_URI%%%F"
+
+ IF ERRORLEVEL 1 (
+ ECHO Download of "%%F" from "%TCLKIT_URI%" failed.
+ GOTO errors
+ )
+ )
+)
+
+IF DEFINED TCLKIT_NOENV GOTO skip_sdkUnZip
+IF DEFINED TCLKIT_NOSDK GOTO skip_sdkUnZip
+
+IF NOT EXIST "%TEMP%\%TCLKIT_SDK%" (
+ %__ECHO% MKDIR "%TEMP%\%TCLKIT_SDK%"
+
+ IF ERRORLEVEL 1 (
+ ECHO Could not create directory "%TEMP%\%TCLKIT_SDK%".
+ GOTO errors
+ )
+)
+
+%__ECHO% "%TEMP%\unzip.exe" -n "%TEMP%\%TCLKIT_SDK_ZIP%" -d "%TEMP%\%TCLKIT_SDK%"
+
+IF ERRORLEVEL 1 (
+ ECHO Could not unzip "%TEMP%\%TCLKIT_SDK_ZIP%" to "%TEMP%\%TCLKIT_SDK%".
+ GOTO errors
+)
+
+:skip_sdkUnZip
+
+IF DEFINED TCLKIT_NOENV GOTO skip_sdkEnvironment
+
+%__ECHO% ECHO SET TCLSH_CMD=%TEMP%\%TCLKIT_EXE%%OVERWRITE%"%ENVDIR%\SetTclKitEnv.bat"
+
+IF DEFINED TCLKIT_NOSDK GOTO skip_sdkVariables
+
+%__ECHO% ECHO SET TCLINCDIR=%TEMP%\%TCLKIT_SDK%\include%APPEND%"%ENVDIR%\SetTclKitEnv.bat"
+%__ECHO% ECHO SET TCLLIBDIR=%TEMP%\%TCLKIT_SDK%\lib%APPEND%"%ENVDIR%\SetTclKitEnv.bat"
+%__ECHO% ECHO SET LIBTCLPATH=%TEMP%\%TCLKIT_SDK%\lib%APPEND%"%ENVDIR%\SetTclKitEnv.bat"
+%__ECHO% ECHO SET LIBTCL=%TCLKIT_LIB%%APPEND%"%ENVDIR%\SetTclKitEnv.bat"
+%__ECHO% ECHO SET LIBTCLSTUB=%TCLKIT_LIB_STUB%%APPEND%"%ENVDIR%\SetTclKitEnv.bat"
+
+:skip_sdkVariables
+
+ECHO.
+ECHO Wrote "%ENVDIR%\SetTclKitEnv.bat".
+ECHO Please run it to set the necessary Tcl environment variables.
+ECHO.
+
+:skip_sdkEnvironment
+
+GOTO no_errors
+
+:fn_TclKitX86Variables
+ REM
+ REM NOTE: By default, use latest available version of the TclKit SDK
+ REM for x86. However, the "default" TclKit executable for x86
+ REM is still used here because it is the only one "well-known"
+ REM to be available for download.
+ REM
+ IF NOT DEFINED TCLKIT_PATCHLEVEL (
+ ECHO The TCLKIT_PATCHLEVEL environment variable must be set first.
+ CALL :fn_SetErrorLevel
+ GOTO :EOF
+ )
+ SET TCLKIT_VERSION=%TCLKIT_PATCHLEVEL:.=%
+ SET TCLKIT_VERSION=%TCLKIT_VERSION:~0,2%
+ IF DEFINED TCLKIT_EXE_PATCHLEVEL (
+ SET TCLKIT_EXE=tclkit-%TCLKIT_EXE_PATCHLEVEL%.exe
+ ) ELSE (
+ SET TCLKIT_EXE=tclkit-%TCLKIT_PATCHLEVEL%.exe
+ )
+ SET TCLKIT_LIB=libtclkit%TCLKIT_PATCHLEVEL:.=%.lib
+ SET TCLKIT_LIB_STUB=libtclstub%TCLKIT_VERSION:.=%.a
+ SET TCLKIT_SDK=libtclkit-sdk-x86-%TCLKIT_PATCHLEVEL%
+ SET TCLKIT_SDK_ZIP=%TCLKIT_SDK%.zip
+ SET TCLKIT_FILES=%TCLKIT_EXE%
+ IF NOT DEFINED TCLKIT_NOENV IF NOT DEFINED TCLKIT_NOSDK (
+ SET TCLKIT_FILES=%TCLKIT_FILES% unzip.exe %TCLKIT_SDK_ZIP%
+ )
+ GOTO :EOF
+
+:fn_TclKitX64Variables
+ REM
+ REM NOTE: By default, use latest available version of the TclKit SDK
+ REM for x64. However, the "default" TclKit executable for x86
+ REM is still used here because it is the only one "well-known"
+ REM to be available for download.
+ REM
+ IF NOT DEFINED TCLKIT_PATCHLEVEL (
+ ECHO The TCLKIT_PATCHLEVEL environment variable must be set first.
+ CALL :fn_SetErrorLevel
+ GOTO :EOF
+ )
+ SET TCLKIT_VERSION=%TCLKIT_PATCHLEVEL:.=%
+ SET TCLKIT_VERSION=%TCLKIT_VERSION:~0,2%
+ IF DEFINED TCLKIT_EXE_PATCHLEVEL (
+ SET TCLKIT_EXE=tclkit-%TCLKIT_EXE_PATCHLEVEL%.exe
+ ) ELSE (
+ SET TCLKIT_EXE=tclkit-%TCLKIT_PATCHLEVEL%.exe
+ )
+ SET TCLKIT_LIB=libtclkit%TCLKIT_PATCHLEVEL:.=%.lib
+ SET TCLKIT_LIB_STUB=libtclstub%TCLKIT_VERSION:.=%.a
+ SET TCLKIT_SDK=libtclkit-sdk-x64-%TCLKIT_PATCHLEVEL%
+ SET TCLKIT_SDK_ZIP=%TCLKIT_SDK%.zip
+ SET TCLKIT_FILES=%TCLKIT_EXE%
+ IF NOT DEFINED TCLKIT_NOENV IF NOT DEFINED TCLKIT_NOSDK (
+ SET TCLKIT_FILES=%TCLKIT_FILES% unzip.exe %TCLKIT_SDK_ZIP%
+ )
+ GOTO :EOF
+
+:fn_UnquoteVariable
+ IF NOT DEFINED %1 GOTO :EOF
+ SETLOCAL
+ SET __ECHO_CMD=ECHO %%%1%%
+ FOR /F "delims=" %%V IN ('%__ECHO_CMD%') DO (
+ SET VALUE=%%V
+ )
+ SET VALUE=%VALUE:"=%
+ REM "
+ ENDLOCAL && SET %1=%VALUE%
+ GOTO :EOF
+
+:fn_PrependToPath
+ IF NOT DEFINED %1 GOTO :EOF
+ SETLOCAL
+ SET __ECHO_CMD=ECHO %%%1%%
+ FOR /F "delims=" %%V IN ('%__ECHO_CMD%') DO (
+ SET VALUE=%%V
+ )
+ SET VALUE=%VALUE:"=%
+ REM "
+ ENDLOCAL && SET PATH=%VALUE%;%PATH%
+ GOTO :EOF
+
+:fn_ResetErrorLevel
+ VERIFY > NUL
+ GOTO :EOF
+
+:fn_SetErrorLevel
+ VERIFY MAYBE 2> NUL
+ GOTO :EOF
+
+:usage
+ ECHO.
+ ECHO Usage: %~nx0 ^<processor^>
+ ECHO.
+ ECHO The only supported values for processor are "x86" and "x64".
+ GOTO errors
+
+:errors
+ CALL :fn_SetErrorLevel
+ ENDLOCAL
+ ECHO.
+ ECHO Failure, errors were encountered.
+ GOTO end_of_file
+
+:no_errors
+ CALL :fn_ResetErrorLevel
+ ENDLOCAL
+ ECHO.
+ ECHO Success, no errors were encountered.
+ GOTO end_of_file
+
+:end_of_file
+%__ECHO% EXIT /B %ERRORLEVEL%
diff --git a/chromium/third_party/sqlite/src/tool/build-all-msvc.bat b/chromium/third_party/sqlite/src/tool/build-all-msvc.bat
index bdf055e6028..aaeb67bdfb9 100755
--- a/chromium/third_party/sqlite/src/tool/build-all-msvc.bat
+++ b/chromium/third_party/sqlite/src/tool/build-all-msvc.bat
@@ -1,859 +1,859 @@
-@ECHO OFF
-
-::
-:: build-all-msvc.bat --
-::
-:: Multi-Platform Build Tool for MSVC
-::
-
-REM
-REM This batch script is used to build the SQLite DLL for multiple platforms
-REM and configurations using MSVC. The built SQLite DLLs, their associated
-REM import libraries, and optionally their symbols files, are placed within
-REM the directory specified on the command line, in sub-directories named for
-REM their respective platforms and configurations. This batch script must be
-REM run from inside a Visual Studio Command Prompt for the desired version of
-REM Visual Studio ^(the initial platform configured for the command prompt does
-REM not really matter^). Exactly one command line argument is required, the
-REM name of an existing directory to be used as the final destination directory
-REM for the generated output files, which will be placed in sub-directories
-REM created therein. Ideally, the directory specified should be empty.
-REM
-REM Example:
-REM
-REM CD /D C:\dev\sqlite\core
-REM CALL tool\build-all-msvc.bat C:\Temp
-REM
-REM In the example above, "C:\dev\sqlite\core" represents the root of the
-REM source tree for SQLite and "C:\Temp" represents the final destination
-REM directory for the generated output files.
-REM
-REM Please note that the SQLite build process performed by the Makefile
-REM associated with this batch script requires a Tcl shell to be present
-REM in a directory contained in the PATH environment variable unless a
-REM pre-existing amalgamation file is used.
-REM
-REM There are several environment variables that may be set to modify the
-REM behavior of this batch script and its associated Makefile. The list of
-REM platforms to build may be overriden by using the PLATFORMS environment
-REM variable, which should contain a list of platforms ^(e.g. x86 x86_amd64
-REM x86_arm^). All platforms must be supported by the version of Visual Studio
-REM being used. The list of configurations to build may be overridden by
-REM setting the CONFIGURATIONS environment variable, which should contain a
-REM list of configurations to build ^(e.g. Debug Retail^). Neither of these
-REM variable values may contain any double quotes, surrounding or embedded.
-REM
-REM Finally, the NCRTLIBPATH, NUCRTLIBPATH, and NSDKLIBPATH environment
-REM variables may be set to specify the location of the CRT, Universal CRT, and
-REM Windows SDK, respectively, that may be needed to compile executables native
-REM to the architecture of the build machine during any cross-compilation that
-REM may be necessary, depending on the platforms to be built. These values in
-REM these three variables should be surrounded by double quotes if they contain
-REM spaces.
-REM
-REM There are a few other environment variables that impact the build process
-REM when set ^(to anything^), they are:
-REM
-REM USE_AUTOCONF_MAKEFILE
-REM
-REM When set, the "autoconf" Makefile for MSVC will be used instead of the main
-REM Makefile for MSVC. It must exist at "%ROOT%\autoconf\Makefile.msc".
-REM
-REM NOCLEAN
-REM
-REM When set, the "clean" target will not be used during each build iteration.
-REM However, the target binaries, if any, will still be deleted manually prior
-REM to being rebuilt. Setting this environment variable is only rarely needed
-REM and could cause issues in some circumstances; therefore, setting it is not
-REM recommended.
-REM
-REM NOSYMBOLS
-REM
-REM When set, copying of symbol files ^(*.pdb^) created during the build will
-REM be skipped and they will not appear in the final destination directory.
-REM Setting this environment variable is never strictly needed and could cause
-REM issues in some circumstances; therefore, setting it is not recommended.
-REM
-REM NOMEMDEBUG
-REM
-REM When set, disables use of MEMDEBUG when building binaries for the "Debug"
-REM configuration.
-REM
-REM BUILD_ALL_SHELL
-REM
-REM When set, the command line shell will be built for each selected platform
-REM and configuration as well. In addition, the command line shell binaries
-REM will be copied, with their symbols, to the final destination directory.
-REM
-REM USE_WINV63_NSDKLIBPATH
-REM
-REM When set, modifies how the NSDKLIBPATH environment variable is built, based
-REM on the WindowsSdkDir environment variable. It forces this batch script to
-REM assume the Windows 8.1 SDK location should be used.
-REM
-REM USE_WINV100_NSDKLIBPATH
-REM
-REM When set, modifies how the NSDKLIBPATH environment variable is built, based
-REM on the WindowsSdkDir environment variable. It causes this batch script to
-REM assume the Windows 10.0 SDK location should be used.
-REM
-REM NMAKE_ARGS
-REM NMAKE_ARGS_DEBUG
-REM NMAKE_ARGS_RETAIL
-REM
-REM When set, these values are expanded and passed to the NMAKE command line,
-REM after its other arguments. These may be used to specify additional NMAKE
-REM options, for example:
-REM
-REM SET NMAKE_ARGS=FOR_WINRT=1
-REM SET NMAKE_ARGS_DEBUG=MEMDEBUG=1
-REM SET NMAKE_ARGS_RETAIL=WIN32HEAP=1
-REM
-REM Using the above command before running this tool will cause the compiled
-REM binaries to target the WinRT environment, which provides a subset of the
-REM Win32 API.
-REM
-REM DLL_FILE_NAME
-REM DLL_PDB_FILE_NAME
-REM LIB_FILE_NAME
-REM EXE_FILE_NAME
-REM EXE_PDB_FILE_NAME
-REM
-REM When set, these values will override the associated target file name used
-REM for the build.
-REM
-SETLOCAL
-
-REM SET __ECHO=ECHO
-REM SET __ECHO2=ECHO
-REM SET __ECHO3=ECHO
-IF NOT DEFINED _AECHO (SET _AECHO=REM)
-IF NOT DEFINED _CECHO (SET _CECHO=REM)
-IF NOT DEFINED _VECHO (SET _VECHO=REM)
-
-SET REDIRECT=^>
-IF DEFINED __ECHO SET REDIRECT=^^^>
-
-%_AECHO% Running %0 %*
-
-REM SET DFLAGS=/L
-
-%_VECHO% DFlags = '%DFLAGS%'
-
-SET FFLAGS=/V /F /G /H /I /R /Y /Z
-
-%_VECHO% FFlags = '%FFLAGS%'
-
-SET ROOT=%~dp0\..
-SET ROOT=%ROOT:\\=\%
-
-%_VECHO% Root = '%ROOT%'
-
-REM
-REM NOTE: The first and only argument to this batch file should be the output
-REM directory where the platform-specific binary directories should be
-REM created.
-REM
-SET BINARYDIRECTORY=%1
-
-IF NOT DEFINED BINARYDIRECTORY (
- GOTO usage
-)
-
-%_VECHO% BinaryDirectory = '%BINARYDIRECTORY%'
-
-SET DUMMY=%2
-
-IF DEFINED DUMMY (
- GOTO usage
-)
-
-REM
-REM NOTE: From this point, we need a clean error level. Reset it now.
-REM
-CALL :fn_ResetErrorLevel
-
-REM
-REM NOTE: Change the current directory to the root of the source tree, saving
-REM the current directory on the directory stack.
-REM
-%__ECHO2% PUSHD "%ROOT%"
-
-IF ERRORLEVEL 1 (
- ECHO Could not change directory to "%ROOT%".
- GOTO errors
-)
-
-REM
-REM NOTE: This batch file requires the ComSpec environment variable to be set,
-REM typically to something like "C:\Windows\System32\cmd.exe".
-REM
-IF NOT DEFINED ComSpec (
- ECHO The ComSpec environment variable must be defined.
- GOTO errors
-)
-
-REM
-REM NOTE: This batch file requires the VcInstallDir environment variable to be
-REM set. Tyipcally, this means this batch file needs to be run from an
-REM MSVC command prompt.
-REM
-IF NOT DEFINED VCINSTALLDIR (
- ECHO The VCINSTALLDIR environment variable must be defined.
- GOTO errors
-)
-
-REM
-REM NOTE: If the list of platforms is not already set, use the default list.
-REM
-IF NOT DEFINED PLATFORMS (
- SET PLATFORMS=x86 x86_amd64 x86_arm
-)
-
-%_VECHO% Platforms = '%PLATFORMS%'
-
-REM
-REM NOTE: If the list of configurations is not already set, use the default
-REM list.
-REM
-IF NOT DEFINED CONFIGURATIONS (
- SET CONFIGURATIONS=Debug Retail
-)
-
-%_VECHO% Configurations = '%CONFIGURATIONS%'
-
-REM
-REM NOTE: If the command used to invoke NMAKE is not already set, use the
-REM default.
-REM
-IF NOT DEFINED NMAKE_CMD (
- IF DEFINED USE_AUTOCONF_MAKEFILE (
- SET NMAKE_CMD=nmake -B -f autoconf\Makefile.msc
- ) ELSE (
- SET NMAKE_CMD=nmake -B -f Makefile.msc
- )
-)
-
-%_VECHO% NmakeCmd = '%NMAKE_CMD%'
-%_VECHO% NmakeArgs = '%NMAKE_ARGS%'
-%_VECHO% NmakeArgsDebug = '%NMAKE_ARGS_DEBUG%'
-%_VECHO% NmakeArgsRetail = '%NMAKE_ARGS_RETAIL%'
-
-REM
-REM NOTE: Setup environment variables to translate between the MSVC platform
-REM names and the names to be used for the platform-specific binary
-REM directories.
-REM
-SET amd64_NAME=x64
-SET arm_NAME=ARM
-SET x64_NAME=x64
-SET x86_NAME=x86
-SET x86_amd64_NAME=x64
-SET x86_arm_NAME=ARM
-SET x86_x64_NAME=x64
-
-%_VECHO% amd64_Name = '%amd64_NAME%'
-%_VECHO% arm_Name = '%arm_NAME%'
-%_VECHO% x64_Name = '%x64_NAME%'
-%_VECHO% x86_Name = '%x86_NAME%'
-%_VECHO% x86_amd64_Name = '%x86_amd64_NAME%'
-%_VECHO% x86_arm_Name = '%x86_arm_NAME%'
-%_VECHO% x86_x64_Name = '%x86_x64_NAME%'
-
-REM
-REM NOTE: Check for the external tools needed during the build process ^(i.e.
-REM those that do not get compiled as part of the build process itself^)
-REM along the PATH.
-REM
-IF DEFINED TCLSH_CMD (
- SET TCLSH_FILE=%TCLSH_CMD%
-) ELSE (
- SET TCLSH_FILE=tclsh.exe
-)
-
-FOR %%T IN (%TCLSH_FILE%) DO (
- SET %%T_PATH=%%~dp$PATH:T
-)
-
-REM
-REM NOTE: A Tcl shell executable is required during the SQLite build process
-REM unless a pre-existing amalgamation file is used.
-REM
-IF NOT DEFINED %TCLSH_FILE%_PATH (
- ECHO The Tcl shell executable "%TCLSH_FILE%" is required to be in the PATH.
- GOTO errors
-)
-
-REM
-REM NOTE: Setup the default names for the build targets we are creating. Any
-REM ^(or all^) of these may end up being overridden.
-REM
-IF NOT DEFINED DLL_FILE_NAME (
- SET DLL_FILE_NAME=sqlite3.dll
-)
-
-IF NOT DEFINED DLL_PDB_FILE_NAME (
- SET DLL_PDB_FILE_NAME=sqlite3.pdb
-)
-
-IF NOT DEFINED LIB_FILE_NAME (
- SET LIB_FILE_NAME=sqlite3.lib
-)
-
-IF NOT DEFINED EXE_FILE_NAME (
- SET EXE_FILE_NAME=sqlite3.exe
-)
-
-IF NOT DEFINED EXE_PDB_FILE_NAME (
- SET EXE_PDB_FILE_NAME=sqlite3sh.pdb
-)
-
-REM
-REM NOTE: Set the TOOLPATH variable to contain all the directories where the
-REM external tools were found in the search above.
-REM
-CALL :fn_CopyVariable %TCLSH_FILE%_PATH TOOLPATH
-
-%_VECHO% ToolPath = '%TOOLPATH%'
-
-REM
-REM NOTE: Setting the Windows SDK library path is only required for MSVC
-REM 2012, 2013, and 2015.
-REM
-CALL :fn_UnsetVariable SET_NSDKLIBPATH
-
-REM
-REM NOTE: Setting the Universal CRT library path is only required for MSVC
-REM 2015.
-REM
-CALL :fn_UnsetVariable SET_NUCRTLIBPATH
-
-REM
-REM NOTE: Check for MSVC 2012, 2013, and 2015 specially because the Windows
-REM SDK directory handling is slightly different for those versions.
-REM
-IF "%VisualStudioVersion%" == "11.0" (
- REM
- REM NOTE: If the Windows SDK library path has already been set, do not set
- REM it to something else later on.
- REM
- IF NOT DEFINED NSDKLIBPATH (
- SET SET_NSDKLIBPATH=1
- )
-) ELSE IF "%VisualStudioVersion%" == "12.0" (
- REM
- REM NOTE: If the Windows SDK library path has already been set, do not set
- REM it to something else later on.
- REM
- IF NOT DEFINED NSDKLIBPATH (
- SET SET_NSDKLIBPATH=1
- )
-) ELSE IF "%VisualStudioVersion%" == "14.0" (
- REM
- REM NOTE: If the Windows SDK library path has already been set, do not set
- REM it to something else later on.
- REM
- IF NOT DEFINED NSDKLIBPATH (
- SET SET_NSDKLIBPATH=1
- )
-
- REM
- REM NOTE: If the Universal CRT library path has already been set, do not set
- REM it to something else later on.
- REM
- IF NOT DEFINED NUCRTLIBPATH (
- SET SET_NUCRTLIBPATH=1
- )
-)
-
-REM
-REM NOTE: This is the name of the sub-directory where the UCRT libraries may
-REM be found. It is only used when compiling against the UCRT.
-REM
-IF DEFINED UCRTVersion (
- SET NUCRTVER=%UCRTVersion%
-) ELSE (
- SET NUCRTVER=10.0.10586.0
-)
-
-REM
-REM NOTE: This is the name of the sub-directory where the Windows 10.0 SDK
-REM libraries may be found. It is only used when compiling with the
-REM Windows 10.0 SDK.
-REM
-IF DEFINED WindowsSDKLibVersion (
- SET WIN10SDKVER=%WindowsSDKLibVersion:\=%
-) ELSE (
- SET WIN10SDKVER=%NUCRTVER%
-)
-
-REM
-REM NOTE: Check if this is the Windows Phone SDK. If so, a different batch
-REM file is necessary to setup the build environment. Since the variable
-REM values involved here may contain parenthesis, using GOTO instead of
-REM an IF block is required.
-REM
-IF DEFINED WindowsPhoneKitDir GOTO set_vcvarsall_phone
-SET VCVARSALL=%VCINSTALLDIR%\vcvarsall.bat
-GOTO set_vcvarsall_done
-:set_vcvarsall_phone
-SET VCVARSALL=%VCINSTALLDIR%\WPSDK\WP80\vcvarsphoneall.bat
-:set_vcvarsall_done
-SET VCVARSALL=%VCVARSALL:\\=\%
-
-REM
-REM NOTE: This is the outer loop. There should be exactly one iteration per
-REM platform.
-REM
-FOR %%P IN (%PLATFORMS%) DO (
- REM
- REM NOTE: Using the MSVC platform name, lookup the simpler platform name to
- REM be used for the name of the platform-specific binary directory via
- REM the environment variables setup earlier.
- REM
- CALL :fn_CopyVariable %%P_NAME PLATFORMNAME
-
- REM
- REM NOTE: This is the second loop. There should be exactly one iteration.
- REM This loop is necessary because the PlatformName environment
- REM variable was set above and that value is needed by some of the
- REM commands contained in the inner loop. If these commands were
- REM directly contained in the outer loop, the PlatformName environment
- REM variable would be stuck with its initial empty value instead.
- REM
- FOR /F "tokens=2* delims==" %%D IN ('SET PLATFORMNAME') DO (
- REM
- REM NOTE: Attempt to clean the environment of all variables used by MSVC
- REM and/or Visual Studio. This block may need to be updated in the
- REM future to account for additional environment variables.
- REM
- CALL :fn_UnsetVariable CommandPromptType
- CALL :fn_UnsetVariable DevEnvDir
- CALL :fn_UnsetVariable DNX_HOME
- CALL :fn_UnsetVariable ExtensionSdkDir
- CALL :fn_UnsetVariable Framework35Version
- CALL :fn_UnsetVariable Framework40Version
- CALL :fn_UnsetVariable FrameworkDir
- CALL :fn_UnsetVariable FrameworkDir32
- CALL :fn_UnsetVariable FrameworkVersion
- CALL :fn_UnsetVariable FrameworkVersion32
- CALL :fn_UnsetVariable FSHARPINSTALLDIR
- CALL :fn_UnsetVariable INCLUDE
- CALL :fn_UnsetVariable LIB
- CALL :fn_UnsetVariable LIBPATH
- CALL :fn_UnsetVariable NETFXSDKDir
- CALL :fn_UnsetVariable Platform
- CALL :fn_UnsetVariable UCRTVersion
- CALL :fn_UnsetVariable UniversalCRTSdkDir
- REM CALL :fn_UnsetVariable VCINSTALLDIR
- CALL :fn_UnsetVariable VSINSTALLDIR
- CALL :fn_UnsetVariable WindowsLibPath
- CALL :fn_UnsetVariable WindowsPhoneKitDir
- CALL :fn_UnsetVariable WindowsSdkDir
- CALL :fn_UnsetVariable WindowsSdkDir_35
- CALL :fn_UnsetVariable WindowsSdkDir_old
- CALL :fn_UnsetVariable WindowsSDKLibVersion
- CALL :fn_UnsetVariable WindowsSDKVersion
- CALL :fn_UnsetVariable WindowsSDK_ExecutablePath_x86
- CALL :fn_UnsetVariable WindowsSDK_ExecutablePath_x64
-
- REM
- REM NOTE: Reset the PATH here to the absolute bare minimum required.
- REM
- CALL :fn_ResetPath
-
- REM
- REM NOTE: This is the inner loop. There are normally two iterations, one
- REM for each supported build configuration, e.g. Debug or Retail.
- REM
- FOR %%B IN (%CONFIGURATIONS%) DO (
- REM
- REM NOTE: When preparing the debug build, set the DEBUG and MEMDEBUG
- REM environment variables to be picked up by the MSVC makefile
- REM itself.
- REM
- %_AECHO% Building the %%B configuration for platform %%P with name %%D...
-
- IF /I "%%B" == "Debug" (
- REM
- REM NOTE: Using this level for the DEBUG environment variable should
- REM disable all compiler optimizations and prevent use of the
- REM NDEBUG define. Additionally, both SQLITE_ENABLE_API_ARMOR
- REM and SQLITE_DEBUG defines should be enabled.
- REM
- SET DEBUG=3
-
- REM
- REM NOTE: Setting this to non-zero should enable the SQLITE_MEMDEBUG
- REM define.
- REM
- IF NOT DEFINED NOMEMDEBUG (
- SET MEMDEBUG=1
- )
- ) ELSE (
- CALL :fn_UnsetVariable DEBUG
- CALL :fn_UnsetVariable MEMDEBUG
- )
-
- REM
- REM NOTE: Copy the extra NMAKE arguments for this configuration into the
- REM common variable used by the actual commands.
- REM
- CALL :fn_CopyVariable NMAKE_ARGS_%%B NMAKE_ARGS_CFG
-
- REM
- REM NOTE: Launch a nested command shell to perform the following steps:
- REM
- REM 1. Setup the MSVC environment for this platform using the
- REM official batch file.
- REM
- REM 2. Make sure that no stale build output files are present.
- REM
- REM 3. Build the "sqlite3.dll" and "sqlite3.lib" binaries for this
- REM platform.
- REM
- REM 4. Copy the "sqlite3.dll" and "sqlite3.lib" binaries for this
- REM platform to the platform-specific directory beneath the
- REM binary directory.
- REM
- REM 5. Unless prevented from doing so, copy the "sqlite3.pdb"
- REM symbols file for this platform to the platform-specific
- REM directory beneath the binary directory.
- REM
- "%ComSpec%" /C (
- REM
- REM NOTE: Attempt to setup the MSVC environment for this platform.
- REM
- %__ECHO3% CALL "%VCVARSALL%" %%P
-
- IF ERRORLEVEL 1 (
- ECHO Failed to call "%VCVARSALL%" for platform %%P.
- GOTO errors
- )
-
- REM
- REM NOTE: If this batch file is not running in "what-if" mode, check to
- REM be sure we were actually able to setup the MSVC environment
- REM as current versions of their official batch file do not set
- REM the exit code upon failure.
- REM
- IF NOT DEFINED __ECHO3 (
- IF NOT DEFINED WindowsPhoneKitDir (
- IF NOT DEFINED WindowsSdkDir (
- ECHO Cannot build, Windows SDK not found for platform %%P.
- GOTO errors
- )
- )
- )
-
- REM
- REM NOTE: When using MSVC 2012, 2013, or 2015, the native SDK path
- REM cannot simply be the "lib" sub-directory beneath the location
- REM specified in the WindowsSdkDir environment variable because
- REM that location does not actually contain the necessary library
- REM files for x86. This must be done for each iteration because
- REM it relies upon the WindowsSdkDir environment variable being
- REM set by the batch file used to setup the MSVC environment.
- REM
- IF DEFINED SET_NSDKLIBPATH (
- REM
- REM NOTE: The Windows Phone SDK has a slightly different directory
- REM structure and must be handled specially here.
- REM
- IF DEFINED WindowsPhoneKitDir (
- CALL :fn_CopyVariable WindowsPhoneKitDir NSDKLIBPATH
- CALL :fn_AppendVariable NSDKLIBPATH \lib\x86
- ) ELSE IF DEFINED WindowsSdkDir (
- CALL :fn_CopyVariable WindowsSdkDir NSDKLIBPATH
-
- REM
- REM NOTE: The Windows 8.x and Windows 10.0 SDKs have a slightly
- REM different directory naming conventions.
- REM
- IF DEFINED USE_WINV100_NSDKLIBPATH (
- CALL :fn_AppendVariable NSDKLIBPATH \..\10\lib\%WIN10SDKVER%\um\x86
- CALL :fn_CopyVariable WindowsSdkDir PSDKLIBPATH
- CALL :fn_AppendVariable PSDKLIBPATH lib\%WIN10SDKVER%\um\%%D
- ) ELSE IF DEFINED USE_WINV63_NSDKLIBPATH (
- CALL :fn_AppendVariable NSDKLIBPATH \lib\winv6.3\um\x86
- ) ELSE IF "%VisualStudioVersion%" == "12.0" (
- CALL :fn_AppendVariable NSDKLIBPATH \..\8.0\lib\win8\um\x86
- ) ELSE IF "%VisualStudioVersion%" == "14.0" (
- CALL :fn_AppendVariable NSDKLIBPATH \..\8.0\lib\win8\um\x86
- ) ELSE (
- CALL :fn_AppendVariable NSDKLIBPATH \lib\win8\um\x86
- )
- )
- )
-
- REM
- REM NOTE: When using MSVC 2015, setting the Universal CRT library path
- REM for x86 may be required as well. This must also be done for
- REM each iteration because it relies upon the UniversalCRTSdkDir
- REM environment variable being set by the batch file used to
- REM setup the MSVC environment.
- REM
- IF DEFINED SET_NUCRTLIBPATH (
- IF DEFINED UniversalCRTSdkDir (
- CALL :fn_CopyVariable UniversalCRTSdkDir NUCRTLIBPATH
- CALL :fn_AppendVariable NUCRTLIBPATH \lib\%NUCRTVER%\ucrt\x86
- )
- )
-
- REM
- REM NOTE: Unless prevented from doing so, invoke NMAKE with the MSVC
- REM makefile to clean any stale build output from previous
- REM iterations of this loop and/or previous runs of this batch
- REM file, etc.
- REM
- IF NOT DEFINED NOCLEAN (
- CALL :fn_MakeClean %%D
-
- IF ERRORLEVEL 1 (
- ECHO Failed to clean for platform %%P.
- GOTO errors
- )
- ) ELSE (
- REM
- REM NOTE: Even when the cleaning step has been disabled, we still
- REM need to remove the build output for all the files we are
- REM specifically wanting to build for each platform.
- REM
- %_AECHO% Cleaning final core library output files only...
- %__ECHO% DEL /Q *.lo "%DLL_FILE_NAME%" "%LIB_FILE_NAME%" "%DLL_PDB_FILE_NAME%" 2%REDIRECT% NUL
- )
-
- REM
- REM NOTE: Call NMAKE with the MSVC makefile to build the "sqlite3.dll"
- REM binary. The x86 compiler will be used to compile the native
- REM command line tools needed during the build process itself.
- REM Also, disable looking for and/or linking to the native Tcl
- REM runtime library.
- REM
- CALL :fn_MakeDll %%D
-
- IF ERRORLEVEL 1 (
- ECHO Failed to build %%B "%DLL_FILE_NAME%" for platform %%P.
- GOTO errors
- )
-
- REM
- REM NOTE: Copy the "sqlite3.dll" file to the appropriate directory for
- REM the build and platform beneath the binary directory.
- REM
- %__ECHO% XCOPY "%DLL_FILE_NAME%" "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS%
-
- IF ERRORLEVEL 1 (
- ECHO Failed to copy "%DLL_FILE_NAME%" to "%BINARYDIRECTORY%\%%B\%%D\".
- GOTO errors
- )
-
- REM
- REM NOTE: Copy the "sqlite3.lib" file to the appropriate directory for
- REM the build and platform beneath the binary directory.
- REM
- %__ECHO% XCOPY "%LIB_FILE_NAME%" "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS%
-
- IF ERRORLEVEL 1 (
- ECHO Failed to copy "%LIB_FILE_NAME%" to "%BINARYDIRECTORY%\%%B\%%D\".
- GOTO errors
- )
-
- REM
- REM NOTE: Copy the "sqlite3.pdb" file to the appropriate directory for
- REM the build and platform beneath the binary directory unless we
- REM are prevented from doing so.
- REM
- IF NOT DEFINED NOSYMBOLS (
- IF EXIST "%DLL_PDB_FILE_NAME%" (
- %__ECHO% XCOPY "%DLL_PDB_FILE_NAME%" "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS%
-
- IF ERRORLEVEL 1 (
- ECHO Failed to copy "%DLL_PDB_FILE_NAME%" to "%BINARYDIRECTORY%\%%B\%%D\".
- GOTO errors
- )
- )
- )
-
- REM
- REM NOTE: If requested, also build the shell executable.
- REM
- IF DEFINED BUILD_ALL_SHELL (
- REM
- REM NOTE: If necessary, make sure any previous build output for the
- REM shell executable is deleted.
- REM
- IF DEFINED NOCLEAN (
- REM
- REM NOTE: Even when the cleaning step has been disabled, we still
- REM need to remove the build output for all the files we are
- REM specifically wanting to build for each platform.
- REM
- %_AECHO% Cleaning final shell executable output files only...
- %__ECHO% DEL /Q "%EXE_FILE_NAME%" "%EXE_PDB_FILE_NAME%" 2%REDIRECT% NUL
- )
-
- REM
- REM NOTE: Call NMAKE with the MSVC makefile to build the "sqlite3.exe"
- REM binary. The x86 compiler will be used to compile the native
- REM command line tools needed during the build process itself.
- REM Also, disable looking for and/or linking to the native Tcl
- REM runtime library.
- REM
- CALL :fn_MakeExe %%D
-
- IF ERRORLEVEL 1 (
- ECHO Failed to build %%B "%EXE_FILE_NAME%" for platform %%P.
- GOTO errors
- )
-
- REM
- REM NOTE: Copy the "sqlite3.exe" file to the appropriate directory
- REM for the build and platform beneath the binary directory.
- REM
- %__ECHO% XCOPY "%EXE_FILE_NAME%" "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS%
-
- IF ERRORLEVEL 1 (
- ECHO Failed to copy "%EXE_FILE_NAME%" to "%BINARYDIRECTORY%\%%B\%%D\".
- GOTO errors
- )
-
- REM
- REM NOTE: Copy the "sqlite3sh.pdb" file to the appropriate directory
- REM for the build and platform beneath the binary directory
- REM unless we are prevented from doing so.
- REM
- IF NOT DEFINED NOSYMBOLS (
- IF EXIST "%EXE_PDB_FILE_NAME%" (
- %__ECHO% XCOPY "%EXE_PDB_FILE_NAME%" "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS%
-
- IF ERRORLEVEL 1 (
- ECHO Failed to copy "%EXE_PDB_FILE_NAME%" to "%BINARYDIRECTORY%\%%B\%%D\".
- GOTO errors
- )
- )
- )
- )
- )
- )
- )
-
- REM
- REM NOTE: Handle any errors generated during the nested command shell.
- REM
- IF ERRORLEVEL 1 (
- GOTO errors
- )
-)
-
-REM
-REM NOTE: Restore the saved current directory from the directory stack.
-REM
-%__ECHO2% POPD
-
-IF ERRORLEVEL 1 (
- ECHO Could not restore directory.
- GOTO errors
-)
-
-REM
-REM NOTE: If we get to this point, we have succeeded.
-REM
-GOTO no_errors
-
-:fn_MakeClean
- %__ECHO% %NMAKE_CMD% clean "PLATFORM=%1" XCOMPILE=1 USE_NATIVE_LIBPATHS=1 NO_TCL=1 %NMAKE_ARGS% %NMAKE_ARGS_CFG%
- GOTO :EOF
-
-:fn_MakeDll
- %__ECHO% %NMAKE_CMD% "%DLL_FILE_NAME%" "PLATFORM=%1" XCOMPILE=1 USE_NATIVE_LIBPATHS=1 NO_TCL=1 %NMAKE_ARGS% %NMAKE_ARGS_CFG%
- GOTO :EOF
-
-:fn_MakeExe
- %__ECHO% %NMAKE_CMD% "%EXE_FILE_NAME%" "PLATFORM=%1" XCOMPILE=1 USE_NATIVE_LIBPATHS=1 NO_TCL=1 %NMAKE_ARGS% %NMAKE_ARGS_CFG%
- GOTO :EOF
-
-:fn_ShowVariable
- SETLOCAL
- SET __ECHO_CMD=ECHO %%%2%%
- FOR /F "delims=" %%V IN ('%__ECHO_CMD%') DO (
- IF NOT "%%V" == "" (
- IF NOT "%%V" == "%%%2%%" (
- %_VECHO% %1 = '%%V'
- )
- )
- )
- ENDLOCAL
- GOTO :EOF
-
-:fn_ResetErrorLevel
- VERIFY > NUL
- GOTO :EOF
-
-:fn_SetErrorLevel
- VERIFY MAYBE 2> NUL
- GOTO :EOF
-
-:fn_CopyVariable
- IF NOT DEFINED %1 GOTO :EOF
- IF "%2" == "" GOTO :EOF
- SETLOCAL
- SET __ECHO_CMD=ECHO %%%1%%
- FOR /F "delims=" %%V IN ('%__ECHO_CMD%') DO (
- SET VALUE=%%V
- )
- ENDLOCAL && SET %2=%VALUE%
- GOTO :EOF
-
-:fn_UnsetVariable
- SETLOCAL
- SET VALUE=%1
- IF DEFINED VALUE (
- SET VALUE=
- ENDLOCAL
- SET %VALUE%=
- ) ELSE (
- ENDLOCAL
- )
- CALL :fn_ResetErrorLevel
- GOTO :EOF
-
-:fn_ResetPath
- SET PATH=%TOOLPATH%;%SystemRoot%\System32;%SystemRoot%
- GOTO :EOF
-
-:fn_AppendVariable
- SET __ECHO_CMD=ECHO %%%1%%
- IF DEFINED %1 (
- FOR /F "delims=" %%V IN ('%__ECHO_CMD%') DO (
- SET %1=%%V%~2
- )
- ) ELSE (
- SET %1=%~2
- )
- SET __ECHO_CMD=
- CALL :fn_ResetErrorLevel
- GOTO :EOF
-
-:usage
- ECHO.
- ECHO Usage: %~nx0 ^<binaryDirectory^>
- ECHO.
- GOTO errors
-
-:errors
- CALL :fn_SetErrorLevel
- ENDLOCAL
- ECHO.
- ECHO Failure, errors were encountered.
- GOTO end_of_file
-
-:no_errors
- CALL :fn_ResetErrorLevel
- ENDLOCAL
- ECHO.
- ECHO Success, no errors were encountered.
- GOTO end_of_file
-
-:end_of_file
-%__ECHO% EXIT /B %ERRORLEVEL%
+@ECHO OFF
+
+::
+:: build-all-msvc.bat --
+::
+:: Multi-Platform Build Tool for MSVC
+::
+
+REM
+REM This batch script is used to build the SQLite DLL for multiple platforms
+REM and configurations using MSVC. The built SQLite DLLs, their associated
+REM import libraries, and optionally their symbols files, are placed within
+REM the directory specified on the command line, in sub-directories named for
+REM their respective platforms and configurations. This batch script must be
+REM run from inside a Visual Studio Command Prompt for the desired version of
+REM Visual Studio ^(the initial platform configured for the command prompt does
+REM not really matter^). Exactly one command line argument is required, the
+REM name of an existing directory to be used as the final destination directory
+REM for the generated output files, which will be placed in sub-directories
+REM created therein. Ideally, the directory specified should be empty.
+REM
+REM Example:
+REM
+REM CD /D C:\dev\sqlite\core
+REM CALL tool\build-all-msvc.bat C:\Temp
+REM
+REM In the example above, "C:\dev\sqlite\core" represents the root of the
+REM source tree for SQLite and "C:\Temp" represents the final destination
+REM directory for the generated output files.
+REM
+REM Please note that the SQLite build process performed by the Makefile
+REM associated with this batch script requires a Tcl shell to be present
+REM in a directory contained in the PATH environment variable unless a
+REM pre-existing amalgamation file is used.
+REM
+REM There are several environment variables that may be set to modify the
+REM behavior of this batch script and its associated Makefile. The list of
+REM platforms to build may be overriden by using the PLATFORMS environment
+REM variable, which should contain a list of platforms ^(e.g. x86 x86_amd64
+REM x86_arm^). All platforms must be supported by the version of Visual Studio
+REM being used. The list of configurations to build may be overridden by
+REM setting the CONFIGURATIONS environment variable, which should contain a
+REM list of configurations to build ^(e.g. Debug Retail^). Neither of these
+REM variable values may contain any double quotes, surrounding or embedded.
+REM
+REM Finally, the NCRTLIBPATH, NUCRTLIBPATH, and NSDKLIBPATH environment
+REM variables may be set to specify the location of the CRT, Universal CRT, and
+REM Windows SDK, respectively, that may be needed to compile executables native
+REM to the architecture of the build machine during any cross-compilation that
+REM may be necessary, depending on the platforms to be built. These values in
+REM these three variables should be surrounded by double quotes if they contain
+REM spaces.
+REM
+REM There are a few other environment variables that impact the build process
+REM when set ^(to anything^), they are:
+REM
+REM USE_AUTOCONF_MAKEFILE
+REM
+REM When set, the "autoconf" Makefile for MSVC will be used instead of the main
+REM Makefile for MSVC. It must exist at "%ROOT%\autoconf\Makefile.msc".
+REM
+REM NOCLEAN
+REM
+REM When set, the "clean" target will not be used during each build iteration.
+REM However, the target binaries, if any, will still be deleted manually prior
+REM to being rebuilt. Setting this environment variable is only rarely needed
+REM and could cause issues in some circumstances; therefore, setting it is not
+REM recommended.
+REM
+REM NOSYMBOLS
+REM
+REM When set, copying of symbol files ^(*.pdb^) created during the build will
+REM be skipped and they will not appear in the final destination directory.
+REM Setting this environment variable is never strictly needed and could cause
+REM issues in some circumstances; therefore, setting it is not recommended.
+REM
+REM NOMEMDEBUG
+REM
+REM When set, disables use of MEMDEBUG when building binaries for the "Debug"
+REM configuration.
+REM
+REM BUILD_ALL_SHELL
+REM
+REM When set, the command line shell will be built for each selected platform
+REM and configuration as well. In addition, the command line shell binaries
+REM will be copied, with their symbols, to the final destination directory.
+REM
+REM USE_WINV63_NSDKLIBPATH
+REM
+REM When set, modifies how the NSDKLIBPATH environment variable is built, based
+REM on the WindowsSdkDir environment variable. It forces this batch script to
+REM assume the Windows 8.1 SDK location should be used.
+REM
+REM USE_WINV100_NSDKLIBPATH
+REM
+REM When set, modifies how the NSDKLIBPATH environment variable is built, based
+REM on the WindowsSdkDir environment variable. It causes this batch script to
+REM assume the Windows 10.0 SDK location should be used.
+REM
+REM NMAKE_ARGS
+REM NMAKE_ARGS_DEBUG
+REM NMAKE_ARGS_RETAIL
+REM
+REM When set, these values are expanded and passed to the NMAKE command line,
+REM after its other arguments. These may be used to specify additional NMAKE
+REM options, for example:
+REM
+REM SET NMAKE_ARGS=FOR_WINRT=1
+REM SET NMAKE_ARGS_DEBUG=MEMDEBUG=1
+REM SET NMAKE_ARGS_RETAIL=WIN32HEAP=1
+REM
+REM Using the above command before running this tool will cause the compiled
+REM binaries to target the WinRT environment, which provides a subset of the
+REM Win32 API.
+REM
+REM DLL_FILE_NAME
+REM DLL_PDB_FILE_NAME
+REM LIB_FILE_NAME
+REM EXE_FILE_NAME
+REM EXE_PDB_FILE_NAME
+REM
+REM When set, these values will override the associated target file name used
+REM for the build.
+REM
+SETLOCAL
+
+REM SET __ECHO=ECHO
+REM SET __ECHO2=ECHO
+REM SET __ECHO3=ECHO
+IF NOT DEFINED _AECHO (SET _AECHO=REM)
+IF NOT DEFINED _CECHO (SET _CECHO=REM)
+IF NOT DEFINED _VECHO (SET _VECHO=REM)
+
+SET REDIRECT=^>
+IF DEFINED __ECHO SET REDIRECT=^^^>
+
+%_AECHO% Running %0 %*
+
+REM SET DFLAGS=/L
+
+%_VECHO% DFlags = '%DFLAGS%'
+
+SET FFLAGS=/V /F /G /H /I /R /Y /Z
+
+%_VECHO% FFlags = '%FFLAGS%'
+
+SET ROOT=%~dp0\..
+SET ROOT=%ROOT:\\=\%
+
+%_VECHO% Root = '%ROOT%'
+
+REM
+REM NOTE: The first and only argument to this batch file should be the output
+REM directory where the platform-specific binary directories should be
+REM created.
+REM
+SET BINARYDIRECTORY=%1
+
+IF NOT DEFINED BINARYDIRECTORY (
+ GOTO usage
+)
+
+%_VECHO% BinaryDirectory = '%BINARYDIRECTORY%'
+
+SET DUMMY=%2
+
+IF DEFINED DUMMY (
+ GOTO usage
+)
+
+REM
+REM NOTE: From this point, we need a clean error level. Reset it now.
+REM
+CALL :fn_ResetErrorLevel
+
+REM
+REM NOTE: Change the current directory to the root of the source tree, saving
+REM the current directory on the directory stack.
+REM
+%__ECHO2% PUSHD "%ROOT%"
+
+IF ERRORLEVEL 1 (
+ ECHO Could not change directory to "%ROOT%".
+ GOTO errors
+)
+
+REM
+REM NOTE: This batch file requires the ComSpec environment variable to be set,
+REM typically to something like "C:\Windows\System32\cmd.exe".
+REM
+IF NOT DEFINED ComSpec (
+ ECHO The ComSpec environment variable must be defined.
+ GOTO errors
+)
+
+REM
+REM NOTE: This batch file requires the VcInstallDir environment variable to be
+REM set. Tyipcally, this means this batch file needs to be run from an
+REM MSVC command prompt.
+REM
+IF NOT DEFINED VCINSTALLDIR (
+ ECHO The VCINSTALLDIR environment variable must be defined.
+ GOTO errors
+)
+
+REM
+REM NOTE: If the list of platforms is not already set, use the default list.
+REM
+IF NOT DEFINED PLATFORMS (
+ SET PLATFORMS=x86 x86_amd64 x86_arm
+)
+
+%_VECHO% Platforms = '%PLATFORMS%'
+
+REM
+REM NOTE: If the list of configurations is not already set, use the default
+REM list.
+REM
+IF NOT DEFINED CONFIGURATIONS (
+ SET CONFIGURATIONS=Debug Retail
+)
+
+%_VECHO% Configurations = '%CONFIGURATIONS%'
+
+REM
+REM NOTE: If the command used to invoke NMAKE is not already set, use the
+REM default.
+REM
+IF NOT DEFINED NMAKE_CMD (
+ IF DEFINED USE_AUTOCONF_MAKEFILE (
+ SET NMAKE_CMD=nmake -B -f autoconf\Makefile.msc
+ ) ELSE (
+ SET NMAKE_CMD=nmake -B -f Makefile.msc
+ )
+)
+
+%_VECHO% NmakeCmd = '%NMAKE_CMD%'
+%_VECHO% NmakeArgs = '%NMAKE_ARGS%'
+%_VECHO% NmakeArgsDebug = '%NMAKE_ARGS_DEBUG%'
+%_VECHO% NmakeArgsRetail = '%NMAKE_ARGS_RETAIL%'
+
+REM
+REM NOTE: Setup environment variables to translate between the MSVC platform
+REM names and the names to be used for the platform-specific binary
+REM directories.
+REM
+SET amd64_NAME=x64
+SET arm_NAME=ARM
+SET x64_NAME=x64
+SET x86_NAME=x86
+SET x86_amd64_NAME=x64
+SET x86_arm_NAME=ARM
+SET x86_x64_NAME=x64
+
+%_VECHO% amd64_Name = '%amd64_NAME%'
+%_VECHO% arm_Name = '%arm_NAME%'
+%_VECHO% x64_Name = '%x64_NAME%'
+%_VECHO% x86_Name = '%x86_NAME%'
+%_VECHO% x86_amd64_Name = '%x86_amd64_NAME%'
+%_VECHO% x86_arm_Name = '%x86_arm_NAME%'
+%_VECHO% x86_x64_Name = '%x86_x64_NAME%'
+
+REM
+REM NOTE: Check for the external tools needed during the build process ^(i.e.
+REM those that do not get compiled as part of the build process itself^)
+REM along the PATH.
+REM
+IF DEFINED TCLSH_CMD (
+ SET TCLSH_FILE=%TCLSH_CMD%
+) ELSE (
+ SET TCLSH_FILE=tclsh.exe
+)
+
+FOR %%T IN (%TCLSH_FILE%) DO (
+ SET %%T_PATH=%%~dp$PATH:T
+)
+
+REM
+REM NOTE: A Tcl shell executable is required during the SQLite build process
+REM unless a pre-existing amalgamation file is used.
+REM
+IF NOT DEFINED %TCLSH_FILE%_PATH (
+ ECHO The Tcl shell executable "%TCLSH_FILE%" is required to be in the PATH.
+ GOTO errors
+)
+
+REM
+REM NOTE: Setup the default names for the build targets we are creating. Any
+REM ^(or all^) of these may end up being overridden.
+REM
+IF NOT DEFINED DLL_FILE_NAME (
+ SET DLL_FILE_NAME=sqlite3.dll
+)
+
+IF NOT DEFINED DLL_PDB_FILE_NAME (
+ SET DLL_PDB_FILE_NAME=sqlite3.pdb
+)
+
+IF NOT DEFINED LIB_FILE_NAME (
+ SET LIB_FILE_NAME=sqlite3.lib
+)
+
+IF NOT DEFINED EXE_FILE_NAME (
+ SET EXE_FILE_NAME=sqlite3.exe
+)
+
+IF NOT DEFINED EXE_PDB_FILE_NAME (
+ SET EXE_PDB_FILE_NAME=sqlite3sh.pdb
+)
+
+REM
+REM NOTE: Set the TOOLPATH variable to contain all the directories where the
+REM external tools were found in the search above.
+REM
+CALL :fn_CopyVariable %TCLSH_FILE%_PATH TOOLPATH
+
+%_VECHO% ToolPath = '%TOOLPATH%'
+
+REM
+REM NOTE: Setting the Windows SDK library path is only required for MSVC
+REM 2012, 2013, and 2015.
+REM
+CALL :fn_UnsetVariable SET_NSDKLIBPATH
+
+REM
+REM NOTE: Setting the Universal CRT library path is only required for MSVC
+REM 2015.
+REM
+CALL :fn_UnsetVariable SET_NUCRTLIBPATH
+
+REM
+REM NOTE: Check for MSVC 2012, 2013, and 2015 specially because the Windows
+REM SDK directory handling is slightly different for those versions.
+REM
+IF "%VisualStudioVersion%" == "11.0" (
+ REM
+ REM NOTE: If the Windows SDK library path has already been set, do not set
+ REM it to something else later on.
+ REM
+ IF NOT DEFINED NSDKLIBPATH (
+ SET SET_NSDKLIBPATH=1
+ )
+) ELSE IF "%VisualStudioVersion%" == "12.0" (
+ REM
+ REM NOTE: If the Windows SDK library path has already been set, do not set
+ REM it to something else later on.
+ REM
+ IF NOT DEFINED NSDKLIBPATH (
+ SET SET_NSDKLIBPATH=1
+ )
+) ELSE IF "%VisualStudioVersion%" == "14.0" (
+ REM
+ REM NOTE: If the Windows SDK library path has already been set, do not set
+ REM it to something else later on.
+ REM
+ IF NOT DEFINED NSDKLIBPATH (
+ SET SET_NSDKLIBPATH=1
+ )
+
+ REM
+ REM NOTE: If the Universal CRT library path has already been set, do not set
+ REM it to something else later on.
+ REM
+ IF NOT DEFINED NUCRTLIBPATH (
+ SET SET_NUCRTLIBPATH=1
+ )
+)
+
+REM
+REM NOTE: This is the name of the sub-directory where the UCRT libraries may
+REM be found. It is only used when compiling against the UCRT.
+REM
+IF DEFINED UCRTVersion (
+ SET NUCRTVER=%UCRTVersion%
+) ELSE (
+ SET NUCRTVER=10.0.10586.0
+)
+
+REM
+REM NOTE: This is the name of the sub-directory where the Windows 10.0 SDK
+REM libraries may be found. It is only used when compiling with the
+REM Windows 10.0 SDK.
+REM
+IF DEFINED WindowsSDKLibVersion (
+ SET WIN10SDKVER=%WindowsSDKLibVersion:\=%
+) ELSE (
+ SET WIN10SDKVER=%NUCRTVER%
+)
+
+REM
+REM NOTE: Check if this is the Windows Phone SDK. If so, a different batch
+REM file is necessary to setup the build environment. Since the variable
+REM values involved here may contain parenthesis, using GOTO instead of
+REM an IF block is required.
+REM
+IF DEFINED WindowsPhoneKitDir GOTO set_vcvarsall_phone
+SET VCVARSALL=%VCINSTALLDIR%\vcvarsall.bat
+GOTO set_vcvarsall_done
+:set_vcvarsall_phone
+SET VCVARSALL=%VCINSTALLDIR%\WPSDK\WP80\vcvarsphoneall.bat
+:set_vcvarsall_done
+SET VCVARSALL=%VCVARSALL:\\=\%
+
+REM
+REM NOTE: This is the outer loop. There should be exactly one iteration per
+REM platform.
+REM
+FOR %%P IN (%PLATFORMS%) DO (
+ REM
+ REM NOTE: Using the MSVC platform name, lookup the simpler platform name to
+ REM be used for the name of the platform-specific binary directory via
+ REM the environment variables setup earlier.
+ REM
+ CALL :fn_CopyVariable %%P_NAME PLATFORMNAME
+
+ REM
+ REM NOTE: This is the second loop. There should be exactly one iteration.
+ REM This loop is necessary because the PlatformName environment
+ REM variable was set above and that value is needed by some of the
+ REM commands contained in the inner loop. If these commands were
+ REM directly contained in the outer loop, the PlatformName environment
+ REM variable would be stuck with its initial empty value instead.
+ REM
+ FOR /F "tokens=2* delims==" %%D IN ('SET PLATFORMNAME') DO (
+ REM
+ REM NOTE: Attempt to clean the environment of all variables used by MSVC
+ REM and/or Visual Studio. This block may need to be updated in the
+ REM future to account for additional environment variables.
+ REM
+ CALL :fn_UnsetVariable CommandPromptType
+ CALL :fn_UnsetVariable DevEnvDir
+ CALL :fn_UnsetVariable DNX_HOME
+ CALL :fn_UnsetVariable ExtensionSdkDir
+ CALL :fn_UnsetVariable Framework35Version
+ CALL :fn_UnsetVariable Framework40Version
+ CALL :fn_UnsetVariable FrameworkDir
+ CALL :fn_UnsetVariable FrameworkDir32
+ CALL :fn_UnsetVariable FrameworkVersion
+ CALL :fn_UnsetVariable FrameworkVersion32
+ CALL :fn_UnsetVariable FSHARPINSTALLDIR
+ CALL :fn_UnsetVariable INCLUDE
+ CALL :fn_UnsetVariable LIB
+ CALL :fn_UnsetVariable LIBPATH
+ CALL :fn_UnsetVariable NETFXSDKDir
+ CALL :fn_UnsetVariable Platform
+ CALL :fn_UnsetVariable UCRTVersion
+ CALL :fn_UnsetVariable UniversalCRTSdkDir
+ REM CALL :fn_UnsetVariable VCINSTALLDIR
+ CALL :fn_UnsetVariable VSINSTALLDIR
+ CALL :fn_UnsetVariable WindowsLibPath
+ CALL :fn_UnsetVariable WindowsPhoneKitDir
+ CALL :fn_UnsetVariable WindowsSdkDir
+ CALL :fn_UnsetVariable WindowsSdkDir_35
+ CALL :fn_UnsetVariable WindowsSdkDir_old
+ CALL :fn_UnsetVariable WindowsSDKLibVersion
+ CALL :fn_UnsetVariable WindowsSDKVersion
+ CALL :fn_UnsetVariable WindowsSDK_ExecutablePath_x86
+ CALL :fn_UnsetVariable WindowsSDK_ExecutablePath_x64
+
+ REM
+ REM NOTE: Reset the PATH here to the absolute bare minimum required.
+ REM
+ CALL :fn_ResetPath
+
+ REM
+ REM NOTE: This is the inner loop. There are normally two iterations, one
+ REM for each supported build configuration, e.g. Debug or Retail.
+ REM
+ FOR %%B IN (%CONFIGURATIONS%) DO (
+ REM
+ REM NOTE: When preparing the debug build, set the DEBUG and MEMDEBUG
+ REM environment variables to be picked up by the MSVC makefile
+ REM itself.
+ REM
+ %_AECHO% Building the %%B configuration for platform %%P with name %%D...
+
+ IF /I "%%B" == "Debug" (
+ REM
+ REM NOTE: Using this level for the DEBUG environment variable should
+ REM disable all compiler optimizations and prevent use of the
+ REM NDEBUG define. Additionally, both SQLITE_ENABLE_API_ARMOR
+ REM and SQLITE_DEBUG defines should be enabled.
+ REM
+ SET DEBUG=3
+
+ REM
+ REM NOTE: Setting this to non-zero should enable the SQLITE_MEMDEBUG
+ REM define.
+ REM
+ IF NOT DEFINED NOMEMDEBUG (
+ SET MEMDEBUG=1
+ )
+ ) ELSE (
+ CALL :fn_UnsetVariable DEBUG
+ CALL :fn_UnsetVariable MEMDEBUG
+ )
+
+ REM
+ REM NOTE: Copy the extra NMAKE arguments for this configuration into the
+ REM common variable used by the actual commands.
+ REM
+ CALL :fn_CopyVariable NMAKE_ARGS_%%B NMAKE_ARGS_CFG
+
+ REM
+ REM NOTE: Launch a nested command shell to perform the following steps:
+ REM
+ REM 1. Setup the MSVC environment for this platform using the
+ REM official batch file.
+ REM
+ REM 2. Make sure that no stale build output files are present.
+ REM
+ REM 3. Build the "sqlite3.dll" and "sqlite3.lib" binaries for this
+ REM platform.
+ REM
+ REM 4. Copy the "sqlite3.dll" and "sqlite3.lib" binaries for this
+ REM platform to the platform-specific directory beneath the
+ REM binary directory.
+ REM
+ REM 5. Unless prevented from doing so, copy the "sqlite3.pdb"
+ REM symbols file for this platform to the platform-specific
+ REM directory beneath the binary directory.
+ REM
+ "%ComSpec%" /C (
+ REM
+ REM NOTE: Attempt to setup the MSVC environment for this platform.
+ REM
+ %__ECHO3% CALL "%VCVARSALL%" %%P
+
+ IF ERRORLEVEL 1 (
+ ECHO Failed to call "%VCVARSALL%" for platform %%P.
+ GOTO errors
+ )
+
+ REM
+ REM NOTE: If this batch file is not running in "what-if" mode, check to
+ REM be sure we were actually able to setup the MSVC environment
+ REM as current versions of their official batch file do not set
+ REM the exit code upon failure.
+ REM
+ IF NOT DEFINED __ECHO3 (
+ IF NOT DEFINED WindowsPhoneKitDir (
+ IF NOT DEFINED WindowsSdkDir (
+ ECHO Cannot build, Windows SDK not found for platform %%P.
+ GOTO errors
+ )
+ )
+ )
+
+ REM
+ REM NOTE: When using MSVC 2012, 2013, or 2015, the native SDK path
+ REM cannot simply be the "lib" sub-directory beneath the location
+ REM specified in the WindowsSdkDir environment variable because
+ REM that location does not actually contain the necessary library
+ REM files for x86. This must be done for each iteration because
+ REM it relies upon the WindowsSdkDir environment variable being
+ REM set by the batch file used to setup the MSVC environment.
+ REM
+ IF DEFINED SET_NSDKLIBPATH (
+ REM
+ REM NOTE: The Windows Phone SDK has a slightly different directory
+ REM structure and must be handled specially here.
+ REM
+ IF DEFINED WindowsPhoneKitDir (
+ CALL :fn_CopyVariable WindowsPhoneKitDir NSDKLIBPATH
+ CALL :fn_AppendVariable NSDKLIBPATH \lib\x86
+ ) ELSE IF DEFINED WindowsSdkDir (
+ CALL :fn_CopyVariable WindowsSdkDir NSDKLIBPATH
+
+ REM
+ REM NOTE: The Windows 8.x and Windows 10.0 SDKs have a slightly
+ REM different directory naming conventions.
+ REM
+ IF DEFINED USE_WINV100_NSDKLIBPATH (
+ CALL :fn_AppendVariable NSDKLIBPATH \..\10\lib\%WIN10SDKVER%\um\x86
+ CALL :fn_CopyVariable WindowsSdkDir PSDKLIBPATH
+ CALL :fn_AppendVariable PSDKLIBPATH lib\%WIN10SDKVER%\um\%%D
+ ) ELSE IF DEFINED USE_WINV63_NSDKLIBPATH (
+ CALL :fn_AppendVariable NSDKLIBPATH \lib\winv6.3\um\x86
+ ) ELSE IF "%VisualStudioVersion%" == "12.0" (
+ CALL :fn_AppendVariable NSDKLIBPATH \..\8.0\lib\win8\um\x86
+ ) ELSE IF "%VisualStudioVersion%" == "14.0" (
+ CALL :fn_AppendVariable NSDKLIBPATH \..\8.0\lib\win8\um\x86
+ ) ELSE (
+ CALL :fn_AppendVariable NSDKLIBPATH \lib\win8\um\x86
+ )
+ )
+ )
+
+ REM
+ REM NOTE: When using MSVC 2015, setting the Universal CRT library path
+ REM for x86 may be required as well. This must also be done for
+ REM each iteration because it relies upon the UniversalCRTSdkDir
+ REM environment variable being set by the batch file used to
+ REM setup the MSVC environment.
+ REM
+ IF DEFINED SET_NUCRTLIBPATH (
+ IF DEFINED UniversalCRTSdkDir (
+ CALL :fn_CopyVariable UniversalCRTSdkDir NUCRTLIBPATH
+ CALL :fn_AppendVariable NUCRTLIBPATH \lib\%NUCRTVER%\ucrt\x86
+ )
+ )
+
+ REM
+ REM NOTE: Unless prevented from doing so, invoke NMAKE with the MSVC
+ REM makefile to clean any stale build output from previous
+ REM iterations of this loop and/or previous runs of this batch
+ REM file, etc.
+ REM
+ IF NOT DEFINED NOCLEAN (
+ CALL :fn_MakeClean %%D
+
+ IF ERRORLEVEL 1 (
+ ECHO Failed to clean for platform %%P.
+ GOTO errors
+ )
+ ) ELSE (
+ REM
+ REM NOTE: Even when the cleaning step has been disabled, we still
+ REM need to remove the build output for all the files we are
+ REM specifically wanting to build for each platform.
+ REM
+ %_AECHO% Cleaning final core library output files only...
+ %__ECHO% DEL /Q *.lo "%DLL_FILE_NAME%" "%LIB_FILE_NAME%" "%DLL_PDB_FILE_NAME%" 2%REDIRECT% NUL
+ )
+
+ REM
+ REM NOTE: Call NMAKE with the MSVC makefile to build the "sqlite3.dll"
+ REM binary. The x86 compiler will be used to compile the native
+ REM command line tools needed during the build process itself.
+ REM Also, disable looking for and/or linking to the native Tcl
+ REM runtime library.
+ REM
+ CALL :fn_MakeDll %%D
+
+ IF ERRORLEVEL 1 (
+ ECHO Failed to build %%B "%DLL_FILE_NAME%" for platform %%P.
+ GOTO errors
+ )
+
+ REM
+ REM NOTE: Copy the "sqlite3.dll" file to the appropriate directory for
+ REM the build and platform beneath the binary directory.
+ REM
+ %__ECHO% XCOPY "%DLL_FILE_NAME%" "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS%
+
+ IF ERRORLEVEL 1 (
+ ECHO Failed to copy "%DLL_FILE_NAME%" to "%BINARYDIRECTORY%\%%B\%%D\".
+ GOTO errors
+ )
+
+ REM
+ REM NOTE: Copy the "sqlite3.lib" file to the appropriate directory for
+ REM the build and platform beneath the binary directory.
+ REM
+ %__ECHO% XCOPY "%LIB_FILE_NAME%" "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS%
+
+ IF ERRORLEVEL 1 (
+ ECHO Failed to copy "%LIB_FILE_NAME%" to "%BINARYDIRECTORY%\%%B\%%D\".
+ GOTO errors
+ )
+
+ REM
+ REM NOTE: Copy the "sqlite3.pdb" file to the appropriate directory for
+ REM the build and platform beneath the binary directory unless we
+ REM are prevented from doing so.
+ REM
+ IF NOT DEFINED NOSYMBOLS (
+ IF EXIST "%DLL_PDB_FILE_NAME%" (
+ %__ECHO% XCOPY "%DLL_PDB_FILE_NAME%" "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS%
+
+ IF ERRORLEVEL 1 (
+ ECHO Failed to copy "%DLL_PDB_FILE_NAME%" to "%BINARYDIRECTORY%\%%B\%%D\".
+ GOTO errors
+ )
+ )
+ )
+
+ REM
+ REM NOTE: If requested, also build the shell executable.
+ REM
+ IF DEFINED BUILD_ALL_SHELL (
+ REM
+ REM NOTE: If necessary, make sure any previous build output for the
+ REM shell executable is deleted.
+ REM
+ IF DEFINED NOCLEAN (
+ REM
+ REM NOTE: Even when the cleaning step has been disabled, we still
+ REM need to remove the build output for all the files we are
+ REM specifically wanting to build for each platform.
+ REM
+ %_AECHO% Cleaning final shell executable output files only...
+ %__ECHO% DEL /Q "%EXE_FILE_NAME%" "%EXE_PDB_FILE_NAME%" 2%REDIRECT% NUL
+ )
+
+ REM
+ REM NOTE: Call NMAKE with the MSVC makefile to build the "sqlite3.exe"
+ REM binary. The x86 compiler will be used to compile the native
+ REM command line tools needed during the build process itself.
+ REM Also, disable looking for and/or linking to the native Tcl
+ REM runtime library.
+ REM
+ CALL :fn_MakeExe %%D
+
+ IF ERRORLEVEL 1 (
+ ECHO Failed to build %%B "%EXE_FILE_NAME%" for platform %%P.
+ GOTO errors
+ )
+
+ REM
+ REM NOTE: Copy the "sqlite3.exe" file to the appropriate directory
+ REM for the build and platform beneath the binary directory.
+ REM
+ %__ECHO% XCOPY "%EXE_FILE_NAME%" "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS%
+
+ IF ERRORLEVEL 1 (
+ ECHO Failed to copy "%EXE_FILE_NAME%" to "%BINARYDIRECTORY%\%%B\%%D\".
+ GOTO errors
+ )
+
+ REM
+ REM NOTE: Copy the "sqlite3sh.pdb" file to the appropriate directory
+ REM for the build and platform beneath the binary directory
+ REM unless we are prevented from doing so.
+ REM
+ IF NOT DEFINED NOSYMBOLS (
+ IF EXIST "%EXE_PDB_FILE_NAME%" (
+ %__ECHO% XCOPY "%EXE_PDB_FILE_NAME%" "%BINARYDIRECTORY%\%%B\%%D\" %FFLAGS% %DFLAGS%
+
+ IF ERRORLEVEL 1 (
+ ECHO Failed to copy "%EXE_PDB_FILE_NAME%" to "%BINARYDIRECTORY%\%%B\%%D\".
+ GOTO errors
+ )
+ )
+ )
+ )
+ )
+ )
+ )
+
+ REM
+ REM NOTE: Handle any errors generated during the nested command shell.
+ REM
+ IF ERRORLEVEL 1 (
+ GOTO errors
+ )
+)
+
+REM
+REM NOTE: Restore the saved current directory from the directory stack.
+REM
+%__ECHO2% POPD
+
+IF ERRORLEVEL 1 (
+ ECHO Could not restore directory.
+ GOTO errors
+)
+
+REM
+REM NOTE: If we get to this point, we have succeeded.
+REM
+GOTO no_errors
+
+:fn_MakeClean
+ %__ECHO% %NMAKE_CMD% clean "PLATFORM=%1" XCOMPILE=1 USE_NATIVE_LIBPATHS=1 NO_TCL=1 %NMAKE_ARGS% %NMAKE_ARGS_CFG%
+ GOTO :EOF
+
+:fn_MakeDll
+ %__ECHO% %NMAKE_CMD% "%DLL_FILE_NAME%" "PLATFORM=%1" XCOMPILE=1 USE_NATIVE_LIBPATHS=1 NO_TCL=1 %NMAKE_ARGS% %NMAKE_ARGS_CFG%
+ GOTO :EOF
+
+:fn_MakeExe
+ %__ECHO% %NMAKE_CMD% "%EXE_FILE_NAME%" "PLATFORM=%1" XCOMPILE=1 USE_NATIVE_LIBPATHS=1 NO_TCL=1 %NMAKE_ARGS% %NMAKE_ARGS_CFG%
+ GOTO :EOF
+
+:fn_ShowVariable
+ SETLOCAL
+ SET __ECHO_CMD=ECHO %%%2%%
+ FOR /F "delims=" %%V IN ('%__ECHO_CMD%') DO (
+ IF NOT "%%V" == "" (
+ IF NOT "%%V" == "%%%2%%" (
+ %_VECHO% %1 = '%%V'
+ )
+ )
+ )
+ ENDLOCAL
+ GOTO :EOF
+
+:fn_ResetErrorLevel
+ VERIFY > NUL
+ GOTO :EOF
+
+:fn_SetErrorLevel
+ VERIFY MAYBE 2> NUL
+ GOTO :EOF
+
+:fn_CopyVariable
+ IF NOT DEFINED %1 GOTO :EOF
+ IF "%2" == "" GOTO :EOF
+ SETLOCAL
+ SET __ECHO_CMD=ECHO %%%1%%
+ FOR /F "delims=" %%V IN ('%__ECHO_CMD%') DO (
+ SET VALUE=%%V
+ )
+ ENDLOCAL && SET %2=%VALUE%
+ GOTO :EOF
+
+:fn_UnsetVariable
+ SETLOCAL
+ SET VALUE=%1
+ IF DEFINED VALUE (
+ SET VALUE=
+ ENDLOCAL
+ SET %VALUE%=
+ ) ELSE (
+ ENDLOCAL
+ )
+ CALL :fn_ResetErrorLevel
+ GOTO :EOF
+
+:fn_ResetPath
+ SET PATH=%TOOLPATH%;%SystemRoot%\System32;%SystemRoot%
+ GOTO :EOF
+
+:fn_AppendVariable
+ SET __ECHO_CMD=ECHO %%%1%%
+ IF DEFINED %1 (
+ FOR /F "delims=" %%V IN ('%__ECHO_CMD%') DO (
+ SET %1=%%V%~2
+ )
+ ) ELSE (
+ SET %1=%~2
+ )
+ SET __ECHO_CMD=
+ CALL :fn_ResetErrorLevel
+ GOTO :EOF
+
+:usage
+ ECHO.
+ ECHO Usage: %~nx0 ^<binaryDirectory^>
+ ECHO.
+ GOTO errors
+
+:errors
+ CALL :fn_SetErrorLevel
+ ENDLOCAL
+ ECHO.
+ ECHO Failure, errors were encountered.
+ GOTO end_of_file
+
+:no_errors
+ CALL :fn_ResetErrorLevel
+ ENDLOCAL
+ ECHO.
+ ECHO Success, no errors were encountered.
+ GOTO end_of_file
+
+:end_of_file
+%__ECHO% EXIT /B %ERRORLEVEL%
diff --git a/chromium/third_party/sqlite/src/tool/lemon.c b/chromium/third_party/sqlite/src/tool/lemon.c
index 40e4e2894f7..54c8946a0df 100644
--- a/chromium/third_party/sqlite/src/tool/lemon.c
+++ b/chromium/third_party/sqlite/src/tool/lemon.c
@@ -1591,14 +1591,14 @@ static struct rule *Rule_merge(struct rule *pA, struct rule *pB){
** Sort a list of rules in order of increasing iRule value
*/
static struct rule *Rule_sort(struct rule *rp){
- int i;
+ unsigned int i;
struct rule *pNext;
struct rule *x[32];
memset(x, 0, sizeof(x));
while( rp ){
pNext = rp->next;
rp->next = 0;
- for(i=0; i<sizeof(x)/sizeof(x[0]) && x[i]; i++){
+ for(i=0; i<sizeof(x)/sizeof(x[0])-1 && x[i]; i++){
rp = Rule_merge(x[i], rp);
x[i] = 0;
}
@@ -1625,8 +1625,7 @@ static void stats_line(const char *zLabel, int iValue){
}
/* The main program. Parse the command line and do it... */
-int main(int argc, char **argv)
-{
+int main(int argc, char **argv){
static int version = 0;
static int rpflag = 0;
static int basisflag = 0;
@@ -1669,6 +1668,7 @@ int main(int argc, char **argv)
struct lemon lem;
struct rule *rp;
+ (void)argc;
OptInit(argv,options,stderr);
if( version ){
printf("Lemon version 1.0\n");
@@ -2266,7 +2266,7 @@ static void parseonetoken(struct pstate *psp)
psp->preccounter = 0;
psp->firstrule = psp->lastrule = 0;
psp->gp->nrule = 0;
- /* Fall thru to next case */
+ /* fall through */
case WAITING_FOR_DECL_OR_RULE:
if( x[0]=='%' ){
psp->state = WAITING_FOR_DECL_KEYWORD;
@@ -2426,7 +2426,7 @@ static void parseonetoken(struct pstate *psp)
psp->alias[psp->nrhs] = 0;
psp->nrhs++;
}
- }else if( (x[0]=='|' || x[0]=='/') && psp->nrhs>0 ){
+ }else if( (x[0]=='|' || x[0]=='/') && psp->nrhs>0 && ISUPPER(x[1]) ){
struct symbol *msp = psp->rhs[psp->nrhs-1];
if( msp->type!=MULTITERMINAL ){
struct symbol *origsp = msp;
@@ -2638,8 +2638,10 @@ static void parseonetoken(struct pstate *psp)
}
nOld = lemonStrlen(zOld);
n = nOld + nNew + 20;
- addLineMacro = !psp->gp->nolinenosflag && psp->insertLineMacro &&
- (psp->decllinenoslot==0 || psp->decllinenoslot[0]!=0);
+ addLineMacro = !psp->gp->nolinenosflag
+ && psp->insertLineMacro
+ && psp->tokenlineno>1
+ && (psp->decllinenoslot==0 || psp->decllinenoslot[0]!=0);
if( addLineMacro ){
for(z=psp->filename, nBack=0; *z; z++){
if( *z=='\\' ) nBack++;
@@ -3515,8 +3517,8 @@ void ReportOutput(struct lemon *lemp)
PRIVATE char *pathsearch(char *argv0, char *name, int modemask)
{
const char *pathlist;
- char *pathbufptr;
- char *pathbuf;
+ char *pathbufptr = 0;
+ char *pathbuf = 0;
char *path,*cp;
char c;
@@ -3550,8 +3552,8 @@ PRIVATE char *pathsearch(char *argv0, char *name, int modemask)
else pathbuf = &cp[1];
if( access(path,modemask)==0 ) break;
}
- free(pathbufptr);
}
+ free(pathbufptr);
}
return path;
}
@@ -3617,6 +3619,16 @@ PRIVATE void tplt_xfer(char *name, FILE *in, FILE *out, int *lineno)
}
}
+/* Skip forward past the header of the template file to the first "%%"
+*/
+PRIVATE void tplt_skip_header(FILE *in, int *lineno)
+{
+ char line[LINESIZE];
+ while( fgets(line,LINESIZE,in) && (line[0]!='%' || line[1]!='%') ){
+ (*lineno)++;
+ }
+}
+
/* The next function finds the template file and opens it, returning
** a pointer to the opened file. */
PRIVATE FILE *tplt_open(struct lemon *lemp)
@@ -3625,6 +3637,7 @@ PRIVATE FILE *tplt_open(struct lemon *lemp)
char buf[1000];
FILE *in;
char *tpltname;
+ char *toFree = 0;
char *cp;
/* first, see if user specified a template filename on the command line. */
@@ -3656,7 +3669,7 @@ PRIVATE FILE *tplt_open(struct lemon *lemp)
}else if( access(templatename,004)==0 ){
tpltname = templatename;
}else{
- tpltname = pathsearch(lemp->argv0,templatename,0);
+ toFree = tpltname = pathsearch(lemp->argv0,templatename,0);
}
if( tpltname==0 ){
fprintf(stderr,"Can't find the parser driver template file \"%s\".\n",
@@ -3666,10 +3679,10 @@ PRIVATE FILE *tplt_open(struct lemon *lemp)
}
in = fopen(tpltname,"rb");
if( in==0 ){
- fprintf(stderr,"Can't open the template file \"%s\".\n",templatename);
+ fprintf(stderr,"Can't open the template file \"%s\".\n",tpltname);
lemp->errorcnt++;
- return 0;
}
+ free(toFree);
return in;
}
@@ -4287,6 +4300,7 @@ void ReportTable(
int mnTknOfst, mxTknOfst;
int mnNtOfst, mxNtOfst;
struct axset *ax;
+ char *prefix;
lemp->minShiftReduce = lemp->nstate;
lemp->errAction = lemp->minShiftReduce + lemp->nrule;
@@ -4375,7 +4389,26 @@ void ReportTable(
fprintf(sql, "COMMIT;\n");
}
lineno = 1;
- tplt_xfer(lemp->name,in,out,&lineno);
+
+ fprintf(out,
+ "/* This file is automatically generated by Lemon from input grammar\n"
+ "** source file \"%s\". */\n", lemp->filename); lineno += 2;
+
+ /* The first %include directive begins with a C-language comment,
+ ** then skip over the header comment of the template file
+ */
+ if( lemp->include==0 ) lemp->include = "";
+ for(i=0; ISSPACE(lemp->include[i]); i++){
+ if( lemp->include[i]=='\n' ){
+ lemp->include += i+1;
+ i = -1;
+ }
+ }
+ if( lemp->include[0]=='/' ){
+ tplt_skip_header(in,&lineno);
+ }else{
+ tplt_xfer(lemp->name,in,out,&lineno);
+ }
/* Generate the include code, if any */
tplt_print(out,lemp,lemp->include,&lineno);
@@ -4387,17 +4420,18 @@ void ReportTable(
tplt_xfer(lemp->name,in,out,&lineno);
/* Generate #defines for all tokens */
+ if( lemp->tokenprefix ) prefix = lemp->tokenprefix;
+ else prefix = "";
if( mhflag ){
- const char *prefix;
fprintf(out,"#if INTERFACE\n"); lineno++;
- if( lemp->tokenprefix ) prefix = lemp->tokenprefix;
- else prefix = "";
- for(i=1; i<lemp->nterminal; i++){
- fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
- lineno++;
- }
- fprintf(out,"#endif\n"); lineno++;
+ }else{
+ fprintf(out,"#ifndef %s%s\n", prefix, lemp->symbols[1]->name);
+ }
+ for(i=1; i<lemp->nterminal; i++){
+ fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
+ lineno++;
}
+ fprintf(out,"#endif\n"); lineno++;
tplt_xfer(lemp->name,in,out,&lineno);
/* Generate the defines */
diff --git a/chromium/third_party/sqlite/src/tool/lempar.c b/chromium/third_party/sqlite/src/tool/lempar.c
index c82e33298ad..71a51cf4487 100644
--- a/chromium/third_party/sqlite/src/tool/lempar.c
+++ b/chromium/third_party/sqlite/src/tool/lempar.c
@@ -22,17 +22,13 @@
** The following is the concatenation of all %include directives from the
** input grammar file:
*/
-#include <stdio.h>
-#include <assert.h>
/************ Begin %include sections from the grammar ************************/
%%
/**************** End of %include directives **********************************/
-/* These constants specify the various numeric values for terminal symbols
-** in a format understandable to "makeheaders". This section is blank unless
-** "lemon" is run with the "-m" command-line option.
-***************** Begin makeheaders token definitions *************************/
+/* These constants specify the various numeric values for terminal symbols.
+***************** Begin token definitions *************************************/
%%
-/**************** End makeheaders token definitions ***************************/
+/**************** End token definitions ***************************************/
/* The next sections is a series of control #defines.
** various aspects of the generated parser.
@@ -229,6 +225,7 @@ typedef struct yyParser yyParser;
#ifndef NDEBUG
#include <stdio.h>
+#include <assert.h>
static FILE *yyTraceFILE = 0;
static char *yyTracePrompt = 0;
#endif /* NDEBUG */
@@ -562,7 +559,7 @@ static YYACTIONTYPE yy_find_shift_action(
#endif /* YYWILDCARD */
return yy_default[stateno];
}else{
- assert( i>=0 && i<sizeof(yy_action)/sizeof(yy_action[0]) );
+ assert( i>=0 && i<(int)(sizeof(yy_action)/sizeof(yy_action[0])) );
return yy_action[i];
}
}while(1);
@@ -721,8 +718,9 @@ static YYACTIONTYPE yy_reduce(
(void)yyLookahead;
(void)yyLookaheadToken;
yymsp = yypParser->yytos;
+ assert( yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) );
#ifndef NDEBUG
- if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
+ if( yyTraceFILE ){
yysize = yyRuleInfoNRhs[yyruleno];
if( yysize ){
fprintf(yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n",
diff --git a/chromium/third_party/sqlite/src/tool/mksqlite3c.tcl b/chromium/third_party/sqlite/src/tool/mksqlite3c.tcl
index 36663ff3b14..41cf8aa95c8 100644
--- a/chromium/third_party/sqlite/src/tool/mksqlite3c.tcl
+++ b/chromium/third_party/sqlite/src/tool/mksqlite3c.tcl
@@ -88,6 +88,18 @@ if {$addstatic} {
#endif}
}
+# Examine the parse.c file. If it contains lines of the form:
+#
+# "#ifndef SQLITE_ENABLE_UPDATE_LIMIT
+#
+# then set the SQLITE_UDL_CAPABLE_PARSER flag in the amalgamation.
+#
+set in [open tsrc/parse.c]
+if {[regexp {ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT} [read $in]]} {
+ puts $out "#define SQLITE_UDL_CAPABLE_PARSER 1"
+}
+close $in
+
# These are the header files used by SQLite. The first time any of these
# files are seen in a #include statement in the C code, include the complete
# text of the file in-line. The file only needs to be included once.
diff --git a/chromium/third_party/sqlite/src/tool/restore_jrnl.tcl b/chromium/third_party/sqlite/src/tool/restore_jrnl.tcl
index 65dee80ca27..05af4f9a2a8 100644
--- a/chromium/third_party/sqlite/src/tool/restore_jrnl.tcl
+++ b/chromium/third_party/sqlite/src/tool/restore_jrnl.tcl
@@ -114,40 +114,40 @@ proc dump_jrnl_page {jrnl_pgno} {
set db_pgno [hexio_get_int [hexio_read $jrnl_name [expr $jrnl_pg_offset] 4]]
set chksum [hexio_get_int [hexio_read $jrnl_name [expr $jrnl_pg_offset+4+$db_pgsz] 4]]
set nonce [calc_nonce $jrnl_pgno]
- puts [ format {jrnl_pg_offset: %08x (%d) jrnl_pgno: %d db_pgno: %d} \
- $jrnl_pg_offset $jrnl_pg_offset \
- $jrnl_pgno $db_pgno]
- puts [ format {nonce: %08x chksum: %08x} \
- $nonce $chksum]
+ puts [ format {jrnl_pg_offset: %08x (%d) jrnl_pgno: %d db_pgno: %d} \
+ $jrnl_pg_offset $jrnl_pg_offset \
+ $jrnl_pgno $db_pgno]
+ puts [ format {nonce: %08x chksum: %08x} \
+ $nonce $chksum]
# now hex dump the data
- # This is derived from the Tcler's WIKI
- set fid [open $jrnl_name r]
- fconfigure $fid -translation binary -encoding binary
- seek $fid [expr $jrnl_pg_offset+4]
- set data [read $fid $db_pgsz]
- close $fid
+ # This is derived from the Tcler's WIKI
+ set fid [open $jrnl_name r]
+ fconfigure $fid -translation binary -encoding binary
+ seek $fid [expr $jrnl_pg_offset+4]
+ set data [read $fid $db_pgsz]
+ close $fid
for {set addr 0} {$addr<$db_pgsz} {set addr [expr $addr+16]} {
- # get 16 bytes of data
- set s [string range $data $addr [expr $addr+16]]
-
- # Convert the data to hex and to characters.
- binary scan $s H*@0a* hex ascii
-
- # Replace non-printing characters in the data.
- regsub -all -- {[^[:graph:] ]} $ascii {.} ascii
-
- # Split the 16 bytes into two 8-byte chunks
- regexp -- {(.{16})(.{0,16})} $hex -> hex1 hex2
-
- # Convert the hex to pairs of hex digits
- regsub -all -- {..} $hex1 {& } hex1
- regsub -all -- {..} $hex2 {& } hex2
-
- # Print the hex and ascii data
- puts [ format {%08x %-24s %-24s %-16s} \
- $addr $hex1 $hex2 $ascii ]
- }
+ # get 16 bytes of data
+ set s [string range $data $addr [expr $addr+16]]
+
+ # Convert the data to hex and to characters.
+ binary scan $s H*@0a* hex ascii
+
+ # Replace non-printing characters in the data.
+ regsub -all -- {[^[:graph:] ]} $ascii {.} ascii
+
+ # Split the 16 bytes into two 8-byte chunks
+ regexp -- {(.{16})(.{0,16})} $hex -> hex1 hex2
+
+ # Convert the hex to pairs of hex digits
+ regsub -all -- {..} $hex1 {& } hex1
+ regsub -all -- {..} $hex2 {& } hex2
+
+ # Print the hex and ascii data
+ puts [ format {%08x %-24s %-24s %-16s} \
+ $addr $hex1 $hex2 $ascii ]
+ }
}
# Setup for the tests. Make a backup copy of the files.
diff --git a/chromium/third_party/sqlite/src/tool/sqldiff.c b/chromium/third_party/sqlite/src/tool/sqldiff.c
index 3590e2c06a7..123d5b49b78 100644
--- a/chromium/third_party/sqlite/src/tool/sqldiff.c
+++ b/chromium/third_party/sqlite/src/tool/sqldiff.c
@@ -473,6 +473,7 @@ static void dump_table(const char *zTab, FILE *out){
fprintf(out, "%s;\n", sqlite3_column_text(pStmt,0));
}
sqlite3_finalize(pStmt);
+ sqlite3_free(zId);
}
@@ -1544,6 +1545,7 @@ static void changeset_one_table(const char *zTab, FILE *out){
/* Check that the schemas of the two tables match. Exit early otherwise. */
checkSchemasMatch(zTab);
+ strInit(&sql);
pStmt = db_prepare("PRAGMA main.table_info=%Q", zTab);
while( SQLITE_ROW==sqlite3_step(pStmt) ){
@@ -1565,7 +1567,6 @@ static void changeset_one_table(const char *zTab, FILE *out){
}
sqlite3_finalize(pStmt);
if( nPk==0 ) goto end_changeset_one_table;
- strInit(&sql);
if( nCol>nPk ){
strPrintf(&sql, "SELECT %d", SQLITE_UPDATE);
for(i=0; i<nCol; i++){
@@ -1707,6 +1708,8 @@ end_changeset_one_table:
sqlite3_free(azCol);
sqlite3_free(aiPk);
sqlite3_free(zId);
+ sqlite3_free(aiFlg);
+ strFree(&sql);
}
/*
@@ -1971,6 +1974,8 @@ int main(int argc, char **argv){
#endif
zSql = sqlite3_mprintf("ATTACH %Q as aux;", zDb2);
rc = sqlite3_exec(g.db, zSql, 0, 0, &zErrMsg);
+ sqlite3_free(zSql);
+ zSql = 0;
if( rc || zErrMsg ){
cmdlineError("cannot attach database \"%s\"", zDb2);
}