summaryrefslogtreecommitdiff
path: root/chromium
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2019-02-13 11:23:05 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2019-02-13 12:02:39 +0000
commit48192fb6548bf3178a82621e8e3cc2c80edd5a21 (patch)
treeeb7aa47ccb1b1922132eebe43e40ed09376c91b4 /chromium
parent5bebe28ae4d07711d13703c3637aed972384cd1f (diff)
downloadqtwebengine-chromium-48192fb6548bf3178a82621e8e3cc2c80edd5a21.tar.gz
[Backport] Update sqlite
Updates sqlite to 3.26.0 with patches to what it is in Chromium 72. Includes fixing security issue 911253 Change-Id: I713fa142e6d847965a3a40285013c49f9005a53f Reviewed-by: Michael Brüning <michael.bruning@qt.io>
Diffstat (limited to 'chromium')
-rw-r--r--chromium/third_party/sqlite/.gitignore3
-rw-r--r--chromium/third_party/sqlite/BUILD.gn61
-rw-r--r--chromium/third_party/sqlite/README.chromium6
-rw-r--r--chromium/third_party/sqlite/amalgamation/rename_exports.h610
-rw-r--r--chromium/third_party/sqlite/amalgamation/shell/shell.c548
-rw-r--r--chromium/third_party/sqlite/amalgamation/sqlite3.c2658
-rw-r--r--chromium/third_party/sqlite/amalgamation/sqlite3.h142
-rw-r--r--chromium/third_party/sqlite/fuzz/sqlite3_prepare_v2_fuzzer.cc86
-rw-r--r--chromium/third_party/sqlite/patches/0001-Modify-default-VFS-to-support-WebDatabase.patch179
-rw-r--r--chromium/third_party/sqlite/patches/0001-test-SQLite-tests-compiling-on-Linux.patch6
-rw-r--r--chromium/third_party/sqlite/patches/0002-Modify-default-VFS-to-support-WebDatabase.patch24
-rw-r--r--chromium/third_party/sqlite/patches/0002-Virtual-table-supporting-recovery-of-corrupted-datab.patch3905
-rw-r--r--chromium/third_party/sqlite/patches/0003-Custom-shell.c-helpers-to-load-Chromium-s-ICU-data.patch145
-rw-r--r--chromium/third_party/sqlite/patches/0003-Virtual-table-supporting-recovery-of-corrupted-datab.patch13
-rw-r--r--chromium/third_party/sqlite/patches/0004-Custom-shell.c-helpers-to-load-Chromium-s-ICU-data.patch10
-rw-r--r--chromium/third_party/sqlite/patches/0004-fts3-Disable-fts3_tokenizer-and-fts4.patch60
-rw-r--r--chromium/third_party/sqlite/patches/0005-fts3-Disable-fts3_tokenizer-and-fts4.patch10
-rw-r--r--chromium/third_party/sqlite/patches/0005-fuchsia-Use-dot-file-locking-for-sqlite.patch27
-rw-r--r--chromium/third_party/sqlite/patches/0006-Fix-dbfuzz2-for-Clusterfuzz.patch25
-rw-r--r--chromium/third_party/sqlite/patches/0006-fts3-Fix-uninit-variable-in-fts3EvalDeferredPhrase.patch31
-rw-r--r--chromium/third_party/sqlite/patches/0006-fuchsia-Use-dot-file-locking-for-sqlite.patch27
-rw-r--r--chromium/third_party/sqlite/patches/0007-Fix-the-Makefile-so-that-it-honors-CFLAGS-when-build.patch27
-rw-r--r--chromium/third_party/sqlite/patches/0008-Adjustments-to-the-page-cache-to-try-to-avoid-harmle.patch38
-rw-r--r--chromium/third_party/sqlite/patches/0009-Remove-an-ALWAYS-from-a-branch-that-is-not-always-ta.patch29
-rw-r--r--chromium/third_party/sqlite/patches/0010-Fix-a-problem-with-nested-CTEs-with-the-same-table.patch42
-rw-r--r--chromium/third_party/sqlite/patches/0011-Fix-detection-of-self-referencing-rows-in-foreign-ke.patch50
-rw-r--r--chromium/third_party/sqlite/patches/0012-Fix-a-segfault-caused-by-using-the-RAISE-function-in.patch29
-rw-r--r--chromium/third_party/sqlite/patches/0013-Fix-for-an-assert-that-could-be-false.patch33
-rw-r--r--chromium/third_party/sqlite/patches/0014-Fix-another-problem-found-by-Matthew-Denton-s-new-fu.patch40
-rw-r--r--chromium/third_party/sqlite/patches/0015-Report-a-new-corruption-case.patch47
-rw-r--r--chromium/third_party/sqlite/patches/0016-Avoid-a-buffer-overread-in-ptrmapPutOvflPtr.patch33
-rw-r--r--chromium/third_party/sqlite/patches/0017-Improved-detection-of-cell-corruption-in-sqlite3Vdbe.patch35
-rw-r--r--chromium/third_party/sqlite/sqlite3.h25
-rw-r--r--chromium/third_party/sqlite/src/Makefile.in47
-rw-r--r--chromium/third_party/sqlite/src/Makefile.msc15
-rw-r--r--chromium/third_party/sqlite/src/VERSION2
-rw-r--r--chromium/third_party/sqlite/src/art/sqlite370.eps12
-rwxr-xr-xchromium/third_party/sqlite/src/configure18
-rw-r--r--chromium/third_party/sqlite/src/doc/F2FS.txt87
-rw-r--r--chromium/third_party/sqlite/src/doc/lemon.html3
-rw-r--r--chromium/third_party/sqlite/src/ext/expert/sqlite3expert.c1
-rw-r--r--chromium/third_party/sqlite/src/ext/fts3/fts3.c20
-rw-r--r--chromium/third_party/sqlite/src/ext/fts3/fts3Int.h2
-rw-r--r--chromium/third_party/sqlite/src/ext/fts3/fts3_aux.c3
-rw-r--r--chromium/third_party/sqlite/src/ext/fts3/fts3_term.c3
-rw-r--r--chromium/third_party/sqlite/src/ext/fts3/fts3_tokenize_vtab.c3
-rw-r--r--chromium/third_party/sqlite/src/ext/fts5/fts5_index.c2
-rw-r--r--chromium/third_party/sqlite/src/ext/fts5/fts5_main.c18
-rw-r--r--chromium/third_party/sqlite/src/ext/fts5/fts5_test_tok.c3
-rw-r--r--chromium/third_party/sqlite/src/ext/fts5/fts5_vocab.c7
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/amatch.c3
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/btreeinfo.c1
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/closure.c3
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/completion.c3
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/csv.c131
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/explain.c322
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/fileio.c88
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/json1.c68
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/memstat.c428
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/series.c62
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/sha1.c2
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/shathree.c2
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/spellfix.c12
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/stmt.c1
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/templatevtab.c3
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/unionvtab.c3
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/vtablog.c1
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/zipfile.c23
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbu1.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbu10.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbu11.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbu12.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbu13.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbu14.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbu3.test2
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbu5.test4
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbu6.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbu7.test2
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbu8.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbu9.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbuA.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbuB.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbuC.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbucollate.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbucrash.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbucrash2.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbudiff.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbudor.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbufault.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbufault2.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbufault3.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbufault4.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbufts.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbumulti.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbuprogress.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rburesume.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbusave.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbusplit.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbutemplimit.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbuvacuum.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbuvacuum2.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/sqlite3rbu.c100
-rw-r--r--chromium/third_party/sqlite/src/ext/rtree/geopoly.c202
-rw-r--r--chromium/third_party/sqlite/src/ext/rtree/rtree.c19
-rw-r--r--chromium/third_party/sqlite/src/ext/rtree/rtree8.test2
-rw-r--r--chromium/third_party/sqlite/src/ext/rtree/rtreeA.test3
-rw-r--r--chromium/third_party/sqlite/src/ext/rtree/rtreecheck.test4
-rw-r--r--chromium/third_party/sqlite/src/ext/rtree/sqlite3rtree.h2
-rw-r--r--chromium/third_party/sqlite/src/ext/rtree/util/randomshape.tcl87
-rw-r--r--chromium/third_party/sqlite/src/ext/rtree/visual01.txt602
-rw-r--r--chromium/third_party/sqlite/src/ext/session/changesetfuzz.c1240
-rw-r--r--chromium/third_party/sqlite/src/ext/session/changesetfuzz1.test84
-rw-r--r--chromium/third_party/sqlite/src/ext/session/session1.test7
-rw-r--r--chromium/third_party/sqlite/src/ext/session/sessionC.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/session/sessionD.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/session/sessionE.test2
-rw-r--r--chromium/third_party/sqlite/src/ext/session/sessionF.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/session/sessionG.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/session/sessionH.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/session/session_common.tcl17
-rw-r--r--chromium/third_party/sqlite/src/ext/session/sessionfault2.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/session/sessioninvert.test159
-rw-r--r--chromium/third_party/sqlite/src/ext/session/sessionrebase.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/session/sessionstat1.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/session/sessionwor.test1
-rw-r--r--chromium/third_party/sqlite/src/ext/session/sqlite3session.c201
-rw-r--r--chromium/third_party/sqlite/src/ext/session/sqlite3session.h79
-rw-r--r--chromium/third_party/sqlite/src/ext/session/test_session.c117
-rw-r--r--chromium/third_party/sqlite/src/main.mk13
-rw-r--r--chromium/third_party/sqlite/src/manifest555
-rw-r--r--chromium/third_party/sqlite/src/manifest.uuid2
-rw-r--r--chromium/third_party/sqlite/src/src/alter.c44
-rw-r--r--chromium/third_party/sqlite/src/src/attach.c2
-rw-r--r--chromium/third_party/sqlite/src/src/auth.c2
-rw-r--r--chromium/third_party/sqlite/src/src/btree.c27
-rw-r--r--chromium/third_party/sqlite/src/src/build.c89
-rw-r--r--chromium/third_party/sqlite/src/src/callback.c19
-rw-r--r--chromium/third_party/sqlite/src/src/ctime.c6
-rw-r--r--chromium/third_party/sqlite/src/src/dbpage.c10
-rw-r--r--chromium/third_party/sqlite/src/src/dbstat.c45
-rw-r--r--chromium/third_party/sqlite/src/src/delete.c51
-rw-r--r--chromium/third_party/sqlite/src/src/expr.c117
-rw-r--r--chromium/third_party/sqlite/src/src/fkey.c15
-rw-r--r--chromium/third_party/sqlite/src/src/global.c1
-rw-r--r--chromium/third_party/sqlite/src/src/hash.c56
-rw-r--r--chromium/third_party/sqlite/src/src/insert.c37
-rw-r--r--chromium/third_party/sqlite/src/src/loadext.c9
-rw-r--r--chromium/third_party/sqlite/src/src/main.c21
-rw-r--r--chromium/third_party/sqlite/src/src/os_unix.c125
-rw-r--r--chromium/third_party/sqlite/src/src/os_win.c31
-rw-r--r--chromium/third_party/sqlite/src/src/pager.c35
-rw-r--r--chromium/third_party/sqlite/src/src/pager.h9
-rw-r--r--chromium/third_party/sqlite/src/src/parse.y5
-rw-r--r--chromium/third_party/sqlite/src/src/pcache.c11
-rw-r--r--chromium/third_party/sqlite/src/src/pcache.h4
-rw-r--r--chromium/third_party/sqlite/src/src/pcache1.c7
-rw-r--r--chromium/third_party/sqlite/src/src/pragma.c66
-rw-r--r--chromium/third_party/sqlite/src/src/pragma.h169
-rw-r--r--chromium/third_party/sqlite/src/src/prepare.c292
-rw-r--r--chromium/third_party/sqlite/src/src/resolve.c64
-rw-r--r--chromium/third_party/sqlite/src/src/select.c25
-rw-r--r--chromium/third_party/sqlite/src/src/shell.c.in425
-rw-r--r--chromium/third_party/sqlite/src/src/sqlite.h.in55
-rw-r--r--chromium/third_party/sqlite/src/src/sqlite3ext.h5
-rw-r--r--chromium/third_party/sqlite/src/src/sqliteInt.h67
-rw-r--r--chromium/third_party/sqlite/src/src/test1.c120
-rw-r--r--chromium/third_party/sqlite/src/src/test_config.c8
-rw-r--r--chromium/third_party/sqlite/src/src/test_intarray.c5
-rw-r--r--chromium/third_party/sqlite/src/src/test_intarray.h9
-rw-r--r--chromium/third_party/sqlite/src/src/test_onefile.c1
-rw-r--r--chromium/third_party/sqlite/src/src/test_window.c349
-rw-r--r--chromium/third_party/sqlite/src/src/tokenize.c67
-rw-r--r--chromium/third_party/sqlite/src/src/treeview.c70
-rw-r--r--chromium/third_party/sqlite/src/src/update.c60
-rw-r--r--chromium/third_party/sqlite/src/src/vacuum.c3
-rw-r--r--chromium/third_party/sqlite/src/src/vdbe.c20
-rw-r--r--chromium/third_party/sqlite/src/src/vdbeInt.h7
-rw-r--r--chromium/third_party/sqlite/src/src/vdbeapi.c10
-rw-r--r--chromium/third_party/sqlite/src/src/vdbeaux.c23
-rw-r--r--chromium/third_party/sqlite/src/src/vdbemem.c3
-rw-r--r--chromium/third_party/sqlite/src/src/vtab.c7
-rw-r--r--chromium/third_party/sqlite/src/src/walker.c4
-rw-r--r--chromium/third_party/sqlite/src/src/where.c57
-rw-r--r--chromium/third_party/sqlite/src/src/whereInt.h21
-rw-r--r--chromium/third_party/sqlite/src/src/wherecode.c2
-rw-r--r--chromium/third_party/sqlite/src/src/whereexpr.c20
-rw-r--r--chromium/third_party/sqlite/src/src/window.c12
-rw-r--r--chromium/third_party/sqlite/src/tool/genfkey.test1
-rw-r--r--chromium/third_party/sqlite/src/tool/lempar.c4
-rw-r--r--chromium/third_party/sqlite/src/tool/mkpragmatab.tcl65
-rw-r--r--chromium/third_party/sqlite/src/tool/sqldiff.c30
-rw-r--r--chromium/third_party/sqlite/src/tool/warnings.sh8
192 files changed, 14251 insertions, 2631 deletions
diff --git a/chromium/third_party/sqlite/.gitignore b/chromium/third_party/sqlite/.gitignore
new file mode 100644
index 00000000000..180a4374a66
--- /dev/null
+++ b/chromium/third_party/sqlite/.gitignore
@@ -0,0 +1,3 @@
+!main.mk
+!vsixtest.sln
+!vsixtest.vcxproj.filters
diff --git a/chromium/third_party/sqlite/BUILD.gn b/chromium/third_party/sqlite/BUILD.gn
index 5d629ba4626..2b8413ba69d 100644
--- a/chromium/third_party/sqlite/BUILD.gn
+++ b/chromium/third_party/sqlite/BUILD.gn
@@ -52,13 +52,29 @@ config("chromium_sqlite3_compile_options") {
# TODO(pwnall): Figure out if exceeding this is costly.
"SQLITE_MAX_MMAP_SIZE=268435456",
+ # The default POSIX permissions for a newly created SQLite database.
+ #
+ # If unspecified, this defaults to 0644. All the data stored by Chrome is
+ # private, so our databases use stricter settings.
+ "SQLITE_DEFAULT_FILE_PERMISSIONS=0600",
+
# SQLite uses a lookaside buffer to improve performance of small mallocs.
# Chrome already depends on small mallocs being efficient, so we disable
# this to avoid the extra memory overhead.
"SQLITE_DEFAULT_LOOKASIDE=0,0",
+ # Needed by the SQL MemoryDumpProvider.
+ #
+ # Setting this to 1 is needed to collect the information reported by
+ # sqlite3_status64(SQLITE_STATUS_MEMORY_USED). Without this setting, the API
+ # still exists, but does not work as promised.
+ "SQLITE_DEFAULT_MEMSTATUS=1",
+
+ # Must match sql::Database::kDefaultPageSize.
+ "SQLITE_DEFAULT_PAGE_SIZE=4096",
+
# By default SQLite pre-allocates 100 pages of pcache data, which will not
- # be released until the handle is closed. This is contrary to Chromium's
+ # be released until the handle is closed. This is contrary to Chrome's
# memory-usage goals.
"SQLITE_DEFAULT_PCACHE_INITSZ=0",
@@ -72,37 +88,43 @@ config("chromium_sqlite3_compile_options") {
# src/tool/mkkeywordhash.c
# The flags below are recommended in the SQLite documentation, and disable
- # features Chromium doesn't use.
+ # features Chrome doesn't use.
"SQLITE_LIKE_DOESNT_MATCH_BLOBS",
"SQLITE_OMIT_DEPRECATED",
"SQLITE_OMIT_PROGRESS_CALLBACK",
"SQLITE_OMIT_SHARED_CACHE",
"SQLITE_USE_ALLOCA",
- # Chromium initializes SQLite manually in //sql/connection.cc.
+ # Chrome initializes SQLite manually in //sql/connection.cc.
"SQLITE_OMIT_AUTOINIT",
- # Chromium calls sqlite3_reset() correctly to reset prepared statements.
+ # Chrome calls sqlite3_reset() correctly to reset prepared statements.
"SQLITE_OMIT_AUTORESET",
# Chromium does not use sqlite3_{get,free}_table().
# Chrome doesn't use sqlite3_compileoption_{used,get}().
"SQLITE_OMIT_COMPILEOPTION_DIAGS",
- # Chromium does not use sqlite3_{get,free}_table().
+ # Chrome doesn't ship the SQLite shell, so command auto-completion is not
+ # needed. Chrome developers who build the SQLite shell living at
+ # //third_party/sqlite:sqlite_shell for diagnostic purposes will have to
+ # live without auto-completion.
+ "SQLITE_OMIT_COMPLETE",
+
+ # Chrome does not use sqlite3_{get,free}_table().
"SQLITE_OMIT_GET_TABLE",
- # Chromium does not use sqlite3_{enable_}load_extension().
+ # Chrome does not use sqlite3_{enable_}load_extension().
# Asides from giving us fairly minor code savings, this option disables code
# that breaks our method for renaming SQLite's exported symbols. Last,
# there's a tiny security benefit to knowing that WebSQL can't possibly
# reach extension loading code.
"SQLITE_OMIT_LOAD_EXTENSION",
- # Chromium doesn't use TCL variables.
+ # Chrome doesn't use TCL variables.
"SQLITE_OMIT_TCL_VARIABLE",
- # Chromium doesn't use sqlite3_{profile,trace}().
+ # Chrome doesn't use sqlite3_{profile,trace}().
"SQLITE_OMIT_TRACE",
# Chrome doesn't use UPSERT.
@@ -111,8 +133,8 @@ config("chromium_sqlite3_compile_options") {
# Chrome doesn't use window functions in SQL.
"SQLITE_OMIT_WINDOWFUNC",
- # TODO(pwnall): Add SQLITE_OMIT_COMPLETE when we import a SQLite release
- # including https://www.sqlite.org/src/info/c3e816cca4ddf096
+ # Uses isnan() in the C99 standard library.
+ "SQLITE_HAVE_ISNAN",
]
# On OSX, SQLite has extra logic for detecting the use of network
@@ -214,18 +236,23 @@ config("sqlite_warnings") {
# Naming the library "sqlite3" can cause conflicts with the system library.
component("chromium_sqlite3") {
visibility = [ ":*" ]
+
+ public = [
+ "sqlite3.h",
+ "src/src/recover.h",
+ ]
+
sources = [
"amalgamation/sqlite3.h",
"sqlite3_shim.c",
"src/src/recover.c",
- "src/src/recover.h",
"src/src/recover_varint.c",
]
inputs = [
- # This file is #included into sqlite3_shim.c, which injects Chrome-specific
- # definitions into the SQLite amalgamation code.
- "amalgamation/sqlite3.c",
+ # This file is #included into sqlite3_shim.c, which injects Chrome-specific
+ # definitions into the SQLite amalgamation code.
+ "amalgamation/sqlite3.c",
]
cflags = []
@@ -274,9 +301,7 @@ component("chromium_sqlite3") {
":sqlite_warnings",
]
- if (is_linux) {
- libs = [ "dl" ]
- } else if (is_mac || is_ios) {
+ if (is_mac || is_ios) {
libs = [ "CoreFoundation.framework" ]
if (!is_ios) {
libs += [ "CoreServices.framework" ]
@@ -286,8 +311,6 @@ component("chromium_sqlite3") {
"SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT=1048576",
"SQLITE_DEFAULT_AUTOVACUUM=1",
"SQLITE_TEMP_STORE=3",
- "SQLITE_ENABLE_FTS3_BACKWARDS",
- "DSQLITE_DEFAULT_FILE_FORMAT=4",
]
}
diff --git a/chromium/third_party/sqlite/README.chromium b/chromium/third_party/sqlite/README.chromium
index b34116f6a5e..420e7ca2956 100644
--- a/chromium/third_party/sqlite/README.chromium
+++ b/chromium/third_party/sqlite/README.chromium
@@ -1,6 +1,6 @@
Name: sqlite
URL: https://sqlite.org/
-Version: 3.25.3
+Version: 3.26.0
Included In Release: Yes
Security Critical: Yes
License: Public domain
@@ -140,8 +140,8 @@ cd third_party/sqlite
# The numbers below are SQLite version numbers, and use upstream's convention
# for tagging release binaries and source zipballs.
-export OLD=3250300
-export NEW=3260000
+export OLD=3260000
+export NEW=3270000
export GNU_SED=sed # OSX: "brew install gnu-sed", then use "gsed" here.
#### Download and unpack the new SQLite release.
diff --git a/chromium/third_party/sqlite/amalgamation/rename_exports.h b/chromium/third_party/sqlite/amalgamation/rename_exports.h
index bbf27c26f62..84e9f331790 100644
--- a/chromium/third_party/sqlite/amalgamation/rename_exports.h
+++ b/chromium/third_party/sqlite/amalgamation/rename_exports.h
@@ -7,384 +7,390 @@
#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 5530-5532
-#define sqlite3_activate_see chrome_sqlite3_activate_see // Lines 5520-5522
-#define sqlite3_aggregate_context chrome_sqlite3_aggregate_context // Line 5067
-#define sqlite3_aggregate_count chrome_sqlite3_aggregate_count // Line 4850
-#define sqlite3_auto_extension chrome_sqlite3_auto_extension // Line 6196
-#define sqlite3_backup_finish chrome_sqlite3_backup_finish // Line 8187
-#define sqlite3_backup_init chrome_sqlite3_backup_init // Lines 8180-8185
-#define sqlite3_backup_pagecount chrome_sqlite3_backup_pagecount // Line 8189
-#define sqlite3_backup_remaining chrome_sqlite3_backup_remaining // Line 8188
-#define sqlite3_backup_step chrome_sqlite3_backup_step // Line 8186
-#define sqlite3_bind_blob chrome_sqlite3_bind_blob // Line 4025
-#define sqlite3_bind_blob64 chrome_sqlite3_bind_blob64 // Lines 4026-4027
-#define sqlite3_bind_double chrome_sqlite3_bind_double // Line 4028
-#define sqlite3_bind_int chrome_sqlite3_bind_int // Line 4029
-#define sqlite3_bind_int64 chrome_sqlite3_bind_int64 // Line 4030
-#define sqlite3_bind_null chrome_sqlite3_bind_null // Line 4031
+#define sqlite3_activate_cerod chrome_sqlite3_activate_cerod // Lines 5566-5568
+#define sqlite3_activate_see chrome_sqlite3_activate_see // Lines 5556-5558
+#define sqlite3_aggregate_context chrome_sqlite3_aggregate_context // Line 5103
+#define sqlite3_aggregate_count chrome_sqlite3_aggregate_count // Line 4886
+#define sqlite3_auto_extension chrome_sqlite3_auto_extension // Line 6232
+#define sqlite3_backup_finish chrome_sqlite3_backup_finish // Line 8227
+#define sqlite3_backup_init chrome_sqlite3_backup_init // Lines 8220-8225
+#define sqlite3_backup_pagecount chrome_sqlite3_backup_pagecount // Line 8229
+#define sqlite3_backup_remaining chrome_sqlite3_backup_remaining // Line 8228
+#define sqlite3_backup_step chrome_sqlite3_backup_step // Line 8226
+#define sqlite3_bind_blob chrome_sqlite3_bind_blob // Line 4061
+#define sqlite3_bind_blob64 chrome_sqlite3_bind_blob64 // Lines 4062-4063
+#define sqlite3_bind_double chrome_sqlite3_bind_double // Line 4064
+#define sqlite3_bind_int chrome_sqlite3_bind_int // Line 4065
+#define sqlite3_bind_int64 chrome_sqlite3_bind_int64 // Line 4066
+#define sqlite3_bind_null chrome_sqlite3_bind_null // Line 4067
#define sqlite3_bind_parameter_count \
- chrome_sqlite3_bind_parameter_count // Line 4060
+ chrome_sqlite3_bind_parameter_count // Line 4096
#define sqlite3_bind_parameter_index \
- chrome_sqlite3_bind_parameter_index // Line 4106
+ chrome_sqlite3_bind_parameter_index // Line 4142
#define sqlite3_bind_parameter_name \
- chrome_sqlite3_bind_parameter_name // Line 4088
-#define sqlite3_bind_pointer chrome_sqlite3_bind_pointer // Line 4037
-#define sqlite3_bind_text chrome_sqlite3_bind_text // Line 4032
-#define sqlite3_bind_text16 chrome_sqlite3_bind_text16 // Line 4033
-#define sqlite3_bind_text64 chrome_sqlite3_bind_text64 // Lines 4034-4035
-#define sqlite3_bind_value chrome_sqlite3_bind_value // Line 4036
-#define sqlite3_bind_zeroblob chrome_sqlite3_bind_zeroblob // Line 4038
-#define sqlite3_bind_zeroblob64 chrome_sqlite3_bind_zeroblob64 // Line 4039
-#define sqlite3_blob_bytes chrome_sqlite3_blob_bytes // Line 6742
-#define sqlite3_blob_close chrome_sqlite3_blob_close // Line 6726
-#define sqlite3_blob_open chrome_sqlite3_blob_open // Lines 6670-6678
-#define sqlite3_blob_read chrome_sqlite3_blob_read // Line 6771
-#define sqlite3_blob_reopen chrome_sqlite3_blob_reopen // Line 6703
-#define sqlite3_blob_write chrome_sqlite3_blob_write // Line 6813
-#define sqlite3_busy_handler chrome_sqlite3_busy_handler // Line 2485
-#define sqlite3_busy_timeout chrome_sqlite3_busy_timeout // Line 2508
+ chrome_sqlite3_bind_parameter_name // Line 4124
+#define sqlite3_bind_pointer chrome_sqlite3_bind_pointer // Line 4073
+#define sqlite3_bind_text chrome_sqlite3_bind_text // Line 4068
+#define sqlite3_bind_text16 chrome_sqlite3_bind_text16 // Line 4069
+#define sqlite3_bind_text64 chrome_sqlite3_bind_text64 // Lines 4070-4071
+#define sqlite3_bind_value chrome_sqlite3_bind_value // Line 4072
+#define sqlite3_bind_zeroblob chrome_sqlite3_bind_zeroblob // Line 4074
+#define sqlite3_bind_zeroblob64 chrome_sqlite3_bind_zeroblob64 // Line 4075
+#define sqlite3_blob_bytes chrome_sqlite3_blob_bytes // Line 6781
+#define sqlite3_blob_close chrome_sqlite3_blob_close // Line 6765
+#define sqlite3_blob_open chrome_sqlite3_blob_open // Lines 6709-6717
+#define sqlite3_blob_read chrome_sqlite3_blob_read // Line 6810
+#define sqlite3_blob_reopen chrome_sqlite3_blob_reopen // Line 6742
+#define sqlite3_blob_write chrome_sqlite3_blob_write // Line 6852
+#define sqlite3_busy_handler chrome_sqlite3_busy_handler // Line 2504
+#define sqlite3_busy_timeout chrome_sqlite3_busy_timeout // Line 2527
#define sqlite3_cancel_auto_extension \
- chrome_sqlite3_cancel_auto_extension // Line 6208
-#define sqlite3_changes chrome_sqlite3_changes // Line 2314
-#define sqlite3_clear_bindings chrome_sqlite3_clear_bindings // Line 4116
+ chrome_sqlite3_cancel_auto_extension // Line 6244
+#define sqlite3_changes chrome_sqlite3_changes // Line 2333
+#define sqlite3_clear_bindings chrome_sqlite3_clear_bindings // Line 4152
#define sqlite3_close chrome_sqlite3_close // Line 331
#define sqlite3_close_v2 chrome_sqlite3_close_v2 // Line 332
#define sqlite3_collation_needed \
- chrome_sqlite3_collation_needed // Lines 5469-5473
+ chrome_sqlite3_collation_needed // Lines 5505-5509
#define sqlite3_collation_needed16 \
- chrome_sqlite3_collation_needed16 // Lines 5474-5478
-#define sqlite3_column_blob chrome_sqlite3_column_blob // Line 4596
-#define sqlite3_column_bytes chrome_sqlite3_column_bytes // Line 4603
-#define sqlite3_column_bytes16 chrome_sqlite3_column_bytes16 // Line 4604
-#define sqlite3_column_count chrome_sqlite3_column_count // Line 4132
+ chrome_sqlite3_collation_needed16 // Lines 5510-5514
+#define sqlite3_column_blob chrome_sqlite3_column_blob // Line 4632
+#define sqlite3_column_bytes chrome_sqlite3_column_bytes // Line 4639
+#define sqlite3_column_bytes16 chrome_sqlite3_column_bytes16 // Line 4640
+#define sqlite3_column_count chrome_sqlite3_column_count // Line 4168
#define sqlite3_column_database_name \
- chrome_sqlite3_column_database_name // Line 4210
+ chrome_sqlite3_column_database_name // Line 4246
#define sqlite3_column_database_name16 \
- chrome_sqlite3_column_database_name16 // Line 4211
-#define sqlite3_column_decltype chrome_sqlite3_column_decltype // Line 4247
-#define sqlite3_column_decltype16 chrome_sqlite3_column_decltype16 // Line 4248
-#define sqlite3_column_double chrome_sqlite3_column_double // Line 4597
-#define sqlite3_column_int chrome_sqlite3_column_int // Line 4598
-#define sqlite3_column_int64 chrome_sqlite3_column_int64 // Line 4599
-#define sqlite3_column_name chrome_sqlite3_column_name // Line 4161
-#define sqlite3_column_name16 chrome_sqlite3_column_name16 // Line 4162
+ chrome_sqlite3_column_database_name16 // Line 4247
+#define sqlite3_column_decltype chrome_sqlite3_column_decltype // Line 4283
+#define sqlite3_column_decltype16 chrome_sqlite3_column_decltype16 // Line 4284
+#define sqlite3_column_double chrome_sqlite3_column_double // Line 4633
+#define sqlite3_column_int chrome_sqlite3_column_int // Line 4634
+#define sqlite3_column_int64 chrome_sqlite3_column_int64 // Line 4635
+#define sqlite3_column_name chrome_sqlite3_column_name // Line 4197
+#define sqlite3_column_name16 chrome_sqlite3_column_name16 // Line 4198
#define sqlite3_column_origin_name \
- chrome_sqlite3_column_origin_name // Line 4214
+ chrome_sqlite3_column_origin_name // Line 4250
#define sqlite3_column_origin_name16 \
- chrome_sqlite3_column_origin_name16 // Line 4215
-#define sqlite3_column_table_name chrome_sqlite3_column_table_name // Line 4212
+ chrome_sqlite3_column_origin_name16 // Line 4251
+#define sqlite3_column_table_name chrome_sqlite3_column_table_name // Line 4248
#define sqlite3_column_table_name16 \
- chrome_sqlite3_column_table_name16 // Line 4213
-#define sqlite3_column_text chrome_sqlite3_column_text // Line 4600
-#define sqlite3_column_text16 chrome_sqlite3_column_text16 // Line 4601
-#define sqlite3_column_type chrome_sqlite3_column_type // Line 4605
-#define sqlite3_column_value chrome_sqlite3_column_value // Line 4602
-#define sqlite3_commit_hook chrome_sqlite3_commit_hook // Line 5811
+ chrome_sqlite3_column_table_name16 // Line 4249
+#define sqlite3_column_text chrome_sqlite3_column_text // Line 4636
+#define sqlite3_column_text16 chrome_sqlite3_column_text16 // Line 4637
+#define sqlite3_column_type chrome_sqlite3_column_type // Line 4641
+#define sqlite3_column_value chrome_sqlite3_column_value // Line 4638
+#define sqlite3_commit_hook chrome_sqlite3_commit_hook // Line 5847
#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 2423
-#define sqlite3_complete16 chrome_sqlite3_complete16 // Line 2424
+#define sqlite3_complete chrome_sqlite3_complete // Line 2442
+#define sqlite3_complete16 chrome_sqlite3_complete16 // Line 2443
#define sqlite3_config chrome_sqlite3_config // Line 1540
-#define sqlite3_context_db_handle chrome_sqlite3_context_db_handle // Line 5094
+#define sqlite3_context_db_handle chrome_sqlite3_context_db_handle // Line 5130
#define sqlite3_create_collation \
- chrome_sqlite3_create_collation // Lines 5419-5425
+ chrome_sqlite3_create_collation // Lines 5455-5461
#define sqlite3_create_collation16 \
- chrome_sqlite3_create_collation16 // Lines 5434-5440
+ chrome_sqlite3_create_collation16 // Lines 5470-5476
#define sqlite3_create_collation_v2 \
- chrome_sqlite3_create_collation_v2 // Lines 5426-5433
+ chrome_sqlite3_create_collation_v2 // Lines 5462-5469
#define sqlite3_create_function \
- chrome_sqlite3_create_function // Lines 4772-4781
+ chrome_sqlite3_create_function // Lines 4808-4817
#define sqlite3_create_function16 \
- chrome_sqlite3_create_function16 // Lines 4782-4791
+ chrome_sqlite3_create_function16 // Lines 4818-4827
#define sqlite3_create_function_v2 \
- chrome_sqlite3_create_function_v2 // Lines 4792-4802
-#define sqlite3_create_module chrome_sqlite3_create_module // Lines 6473-6478
+ chrome_sqlite3_create_function_v2 // Lines 4828-4838
+#define sqlite3_create_module chrome_sqlite3_create_module // Lines 6512-6517
#define sqlite3_create_module_v2 \
- chrome_sqlite3_create_module_v2 // Lines 6479-6485
+ chrome_sqlite3_create_module_v2 // Lines 6518-6524
#define sqlite3_create_window_function \
- chrome_sqlite3_create_window_function // Lines 4803-4814
-#define sqlite3_data_count chrome_sqlite3_data_count // Line 4353
-#define sqlite3_data_directory chrome_sqlite3_data_directory // Line 5647
-#define sqlite3_db_cacheflush chrome_sqlite3_db_cacheflush // Line 8871
+ chrome_sqlite3_create_window_function // Lines 4839-4850
+#define sqlite3_data_count chrome_sqlite3_data_count // Line 4389
+#define sqlite3_data_directory chrome_sqlite3_data_directory // Line 5683
+#define sqlite3_db_cacheflush chrome_sqlite3_db_cacheflush // Line 8912
#define sqlite3_db_config chrome_sqlite3_db_config // Line 1559
-#define sqlite3_db_filename chrome_sqlite3_db_filename // Line 5736
-#define sqlite3_db_handle chrome_sqlite3_db_handle // Line 5719
-#define sqlite3_db_mutex chrome_sqlite3_db_mutex // Line 7117
-#define sqlite3_db_readonly chrome_sqlite3_db_readonly // Line 5746
-#define sqlite3_db_release_memory chrome_sqlite3_db_release_memory // Line 5934
-#define sqlite3_db_status chrome_sqlite3_db_status // Line 7537
-#define sqlite3_declare_vtab chrome_sqlite3_declare_vtab // Line 6542
-#define sqlite3_deserialize chrome_sqlite3_deserialize // Lines 9265-9272
+#define sqlite3_db_filename chrome_sqlite3_db_filename // Line 5772
+#define sqlite3_db_handle chrome_sqlite3_db_handle // Line 5755
+#define sqlite3_db_mutex chrome_sqlite3_db_mutex // Line 7156
+#define sqlite3_db_readonly chrome_sqlite3_db_readonly // Line 5782
+#define sqlite3_db_release_memory chrome_sqlite3_db_release_memory // Line 5970
+#define sqlite3_db_status chrome_sqlite3_db_status // Line 7577
+#define sqlite3_declare_vtab chrome_sqlite3_declare_vtab // Line 6581
+#define sqlite3_deserialize chrome_sqlite3_deserialize // Lines 9306-9313
#define sqlite3_enable_load_extension \
- chrome_sqlite3_enable_load_extension // Line 6158
+ chrome_sqlite3_enable_load_extension // Line 6194
#define sqlite3_enable_shared_cache \
- chrome_sqlite3_enable_shared_cache // Line 5904
-#define sqlite3_errcode chrome_sqlite3_errcode // Line 3449
-#define sqlite3_errmsg chrome_sqlite3_errmsg // Line 3451
-#define sqlite3_errmsg16 chrome_sqlite3_errmsg16 // Line 3452
-#define sqlite3_errstr chrome_sqlite3_errstr // Line 3453
+ chrome_sqlite3_enable_shared_cache // Line 5940
+#define sqlite3_errcode chrome_sqlite3_errcode // Line 3468
+#define sqlite3_errmsg chrome_sqlite3_errmsg // Line 3470
+#define sqlite3_errmsg16 chrome_sqlite3_errmsg16 // Line 3471
+#define sqlite3_errstr chrome_sqlite3_errstr // Line 3472
#define sqlite3_exec chrome_sqlite3_exec // Lines 403-409
-#define sqlite3_expanded_sql chrome_sqlite3_expanded_sql // Line 3794
-#define sqlite3_expired chrome_sqlite3_expired // Line 4851
-#define sqlite3_extended_errcode chrome_sqlite3_extended_errcode // Line 3450
+#define sqlite3_expanded_sql chrome_sqlite3_expanded_sql // Line 3829
+#define sqlite3_expired chrome_sqlite3_expired // Line 4887
+#define sqlite3_extended_errcode chrome_sqlite3_extended_errcode // Line 3469
#define sqlite3_extended_result_codes \
- chrome_sqlite3_extended_result_codes // Line 2184
-#define sqlite3_file_control chrome_sqlite3_file_control // Line 7160
-#define sqlite3_finalize chrome_sqlite3_finalize // Line 4633
-#define sqlite3_free chrome_sqlite3_free // Line 2730
-#define sqlite3_free_table chrome_sqlite3_free_table // Line 2591
-#define sqlite3_get_autocommit chrome_sqlite3_get_autocommit // Line 5706
-#define sqlite3_get_auxdata chrome_sqlite3_get_auxdata // Line 5153
-#define sqlite3_get_table chrome_sqlite3_get_table // Lines 2583-2590
-#define sqlite3_global_recover chrome_sqlite3_global_recover // Line 4853
+ chrome_sqlite3_extended_result_codes // Line 2203
+#define sqlite3_file_control chrome_sqlite3_file_control // Line 7199
+#define sqlite3_finalize chrome_sqlite3_finalize // Line 4669
+#define sqlite3_free chrome_sqlite3_free // Line 2749
+#define sqlite3_free_table chrome_sqlite3_free_table // Line 2610
+#define sqlite3_get_autocommit chrome_sqlite3_get_autocommit // Line 5742
+#define sqlite3_get_auxdata chrome_sqlite3_get_auxdata // Line 5189
+#define sqlite3_get_table chrome_sqlite3_get_table // Lines 2602-2609
+#define sqlite3_global_recover chrome_sqlite3_global_recover // Line 4889
#define sqlite3_initialize chrome_sqlite3_initialize // Line 1504
-#define sqlite3_interrupt chrome_sqlite3_interrupt // Line 2388
-#define sqlite3_key chrome_sqlite3_key // Lines 5488-5491
-#define sqlite3_key_v2 chrome_sqlite3_key_v2 // Lines 5492-5496
-#define sqlite3_keyword_check chrome_sqlite3_keyword_check // Line 7267
-#define sqlite3_keyword_count chrome_sqlite3_keyword_count // Line 7265
-#define sqlite3_keyword_name chrome_sqlite3_keyword_name // Line 7266
-#define sqlite3_last_insert_rowid chrome_sqlite3_last_insert_rowid // Line 2246
+#define sqlite3_interrupt chrome_sqlite3_interrupt // Line 2407
+#define sqlite3_key chrome_sqlite3_key // Lines 5524-5527
+#define sqlite3_key_v2 chrome_sqlite3_key_v2 // Lines 5528-5532
+#define sqlite3_keyword_check chrome_sqlite3_keyword_check // Line 7307
+#define sqlite3_keyword_count chrome_sqlite3_keyword_count // Line 7305
+#define sqlite3_keyword_name chrome_sqlite3_keyword_name // Line 7306
+#define sqlite3_last_insert_rowid chrome_sqlite3_last_insert_rowid // Line 2265
#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 3521
-#define sqlite3_load_extension chrome_sqlite3_load_extension // Lines 6126-6131
-#define sqlite3_log chrome_sqlite3_log // Line 8408
-#define sqlite3_malloc chrome_sqlite3_malloc // Line 2726
-#define sqlite3_malloc64 chrome_sqlite3_malloc64 // Line 2727
-#define sqlite3_memory_alarm chrome_sqlite3_memory_alarm // Lines 4855-4856
-#define sqlite3_memory_highwater chrome_sqlite3_memory_highwater // Line 2757
-#define sqlite3_memory_used chrome_sqlite3_memory_used // Line 2756
-#define sqlite3_mprintf chrome_sqlite3_mprintf // Line 2633
-#define sqlite3_msize chrome_sqlite3_msize // Line 2731
-#define sqlite3_mutex_alloc chrome_sqlite3_mutex_alloc // Line 6962
-#define sqlite3_mutex_enter chrome_sqlite3_mutex_enter // Line 6964
-#define sqlite3_mutex_free chrome_sqlite3_mutex_free // Line 6963
-#define sqlite3_mutex_held chrome_sqlite3_mutex_held // Line 7076
-#define sqlite3_mutex_leave chrome_sqlite3_mutex_leave // Line 6966
-#define sqlite3_mutex_notheld chrome_sqlite3_mutex_notheld // Line 7077
-#define sqlite3_mutex_try chrome_sqlite3_mutex_try // Line 6965
-#define sqlite3_next_stmt chrome_sqlite3_next_stmt // Line 5762
-#define sqlite3_open chrome_sqlite3_open // Lines 3338-3341
-#define sqlite3_open16 chrome_sqlite3_open16 // Lines 3342-3345
-#define sqlite3_open_v2 chrome_sqlite3_open_v2 // Lines 3346-3351
+#define sqlite3_limit chrome_sqlite3_limit // Line 3540
+#define sqlite3_load_extension chrome_sqlite3_load_extension // Lines 6162-6167
+#define sqlite3_log chrome_sqlite3_log // Line 8448
+#define sqlite3_malloc chrome_sqlite3_malloc // Line 2745
+#define sqlite3_malloc64 chrome_sqlite3_malloc64 // Line 2746
+#define sqlite3_memory_alarm chrome_sqlite3_memory_alarm // Lines 4891-4892
+#define sqlite3_memory_highwater chrome_sqlite3_memory_highwater // Line 2776
+#define sqlite3_memory_used chrome_sqlite3_memory_used // Line 2775
+#define sqlite3_mprintf chrome_sqlite3_mprintf // Line 2652
+#define sqlite3_msize chrome_sqlite3_msize // Line 2750
+#define sqlite3_mutex_alloc chrome_sqlite3_mutex_alloc // Line 7001
+#define sqlite3_mutex_enter chrome_sqlite3_mutex_enter // Line 7003
+#define sqlite3_mutex_free chrome_sqlite3_mutex_free // Line 7002
+#define sqlite3_mutex_held chrome_sqlite3_mutex_held // Line 7115
+#define sqlite3_mutex_leave chrome_sqlite3_mutex_leave // Line 7005
+#define sqlite3_mutex_notheld chrome_sqlite3_mutex_notheld // Line 7116
+#define sqlite3_mutex_try chrome_sqlite3_mutex_try // Line 7004
+#define sqlite3_next_stmt chrome_sqlite3_next_stmt // Line 5798
+#define sqlite3_normalized_sql chrome_sqlite3_normalized_sql // Line 3830
+#define sqlite3_open chrome_sqlite3_open // Lines 3357-3360
+#define sqlite3_open16 chrome_sqlite3_open16 // Lines 3361-3364
+#define sqlite3_open_v2 chrome_sqlite3_open_v2 // Lines 3365-3370
#define sqlite3_os_end chrome_sqlite3_os_end // Line 1507
#define sqlite3_os_init chrome_sqlite3_os_init // Line 1506
-#define sqlite3_overload_function chrome_sqlite3_overload_function // Line 6561
-#define sqlite3_prepare chrome_sqlite3_prepare // Lines 3716-3722
-#define sqlite3_prepare16 chrome_sqlite3_prepare16 // Lines 3738-3744
-#define sqlite3_prepare16_v2 chrome_sqlite3_prepare16_v2 // Lines 3745-3751
-#define sqlite3_prepare16_v3 chrome_sqlite3_prepare16_v3 // Lines 3752-3759
-#define sqlite3_prepare_v2 chrome_sqlite3_prepare_v2 // Lines 3723-3729
-#define sqlite3_prepare_v3 chrome_sqlite3_prepare_v3 // Lines 3730-3737
-#define sqlite3_preupdate_count chrome_sqlite3_preupdate_count // Line 8970
-#define sqlite3_preupdate_depth chrome_sqlite3_preupdate_depth // Line 8971
-#define sqlite3_preupdate_hook chrome_sqlite3_preupdate_hook // Lines 8956-8968
-#define sqlite3_preupdate_new chrome_sqlite3_preupdate_new // Line 8972
-#define sqlite3_preupdate_old chrome_sqlite3_preupdate_old // Line 8969
-#define sqlite3_profile chrome_sqlite3_profile // Lines 2981-2982
-#define sqlite3_progress_handler chrome_sqlite3_progress_handler // Line 3109
-#define sqlite3_randomness chrome_sqlite3_randomness // Line 2780
-#define sqlite3_realloc chrome_sqlite3_realloc // Line 2728
-#define sqlite3_realloc64 chrome_sqlite3_realloc64 // Line 2729
-#define sqlite3_rekey chrome_sqlite3_rekey // Lines 5506-5509
-#define sqlite3_rekey_v2 chrome_sqlite3_rekey_v2 // Lines 5510-5514
-#define sqlite3_release_memory chrome_sqlite3_release_memory // Line 5920
-#define sqlite3_reset chrome_sqlite3_reset // Line 4660
+#define sqlite3_overload_function chrome_sqlite3_overload_function // Line 6600
+#define sqlite3_prepare chrome_sqlite3_prepare // Lines 3745-3751
+#define sqlite3_prepare16 chrome_sqlite3_prepare16 // Lines 3767-3773
+#define sqlite3_prepare16_v2 chrome_sqlite3_prepare16_v2 // Lines 3774-3780
+#define sqlite3_prepare16_v3 chrome_sqlite3_prepare16_v3 // Lines 3781-3788
+#define sqlite3_prepare_v2 chrome_sqlite3_prepare_v2 // Lines 3752-3758
+#define sqlite3_prepare_v3 chrome_sqlite3_prepare_v3 // Lines 3759-3766
+#define sqlite3_preupdate_count chrome_sqlite3_preupdate_count // Line 9011
+#define sqlite3_preupdate_depth chrome_sqlite3_preupdate_depth // Line 9012
+#define sqlite3_preupdate_hook chrome_sqlite3_preupdate_hook // Lines 8997-9009
+#define sqlite3_preupdate_new chrome_sqlite3_preupdate_new // Line 9013
+#define sqlite3_preupdate_old chrome_sqlite3_preupdate_old // Line 9010
+#define sqlite3_profile chrome_sqlite3_profile // Lines 3000-3001
+#define sqlite3_progress_handler chrome_sqlite3_progress_handler // Line 3128
+#define sqlite3_randomness chrome_sqlite3_randomness // Line 2799
+#define sqlite3_realloc chrome_sqlite3_realloc // Line 2747
+#define sqlite3_realloc64 chrome_sqlite3_realloc64 // Line 2748
+#define sqlite3_rekey chrome_sqlite3_rekey // Lines 5542-5545
+#define sqlite3_rekey_v2 chrome_sqlite3_rekey_v2 // Lines 5546-5550
+#define sqlite3_release_memory chrome_sqlite3_release_memory // Line 5956
+#define sqlite3_reset chrome_sqlite3_reset // Line 4696
#define sqlite3_reset_auto_extension \
- chrome_sqlite3_reset_auto_extension // Line 6216
-#define sqlite3_result_blob chrome_sqlite3_result_blob // Line 5301
-#define sqlite3_result_blob64 chrome_sqlite3_result_blob64 // Lines 5302-5303
-#define sqlite3_result_double chrome_sqlite3_result_double // Line 5304
-#define sqlite3_result_error chrome_sqlite3_result_error // Line 5305
-#define sqlite3_result_error16 chrome_sqlite3_result_error16 // Line 5306
-#define sqlite3_result_error_code chrome_sqlite3_result_error_code // Line 5309
+ chrome_sqlite3_reset_auto_extension // Line 6252
+#define sqlite3_result_blob chrome_sqlite3_result_blob // Line 5337
+#define sqlite3_result_blob64 chrome_sqlite3_result_blob64 // Lines 5338-5339
+#define sqlite3_result_double chrome_sqlite3_result_double // Line 5340
+#define sqlite3_result_error chrome_sqlite3_result_error // Line 5341
+#define sqlite3_result_error16 chrome_sqlite3_result_error16 // Line 5342
+#define sqlite3_result_error_code chrome_sqlite3_result_error_code // Line 5345
#define sqlite3_result_error_nomem \
- chrome_sqlite3_result_error_nomem // Line 5308
+ chrome_sqlite3_result_error_nomem // Line 5344
#define sqlite3_result_error_toobig \
- chrome_sqlite3_result_error_toobig // Line 5307
-#define sqlite3_result_int chrome_sqlite3_result_int // Line 5310
-#define sqlite3_result_int64 chrome_sqlite3_result_int64 // Line 5311
-#define sqlite3_result_null chrome_sqlite3_result_null // Line 5312
-#define sqlite3_result_pointer chrome_sqlite3_result_pointer // Line 5320
-#define sqlite3_result_subtype chrome_sqlite3_result_subtype // Line 5337
-#define sqlite3_result_text chrome_sqlite3_result_text // Line 5313
-#define sqlite3_result_text16 chrome_sqlite3_result_text16 // Line 5316
-#define sqlite3_result_text16be chrome_sqlite3_result_text16be // Line 5318
-#define sqlite3_result_text16le chrome_sqlite3_result_text16le // Line 5317
-#define sqlite3_result_text64 chrome_sqlite3_result_text64 // Lines 5314-5315
-#define sqlite3_result_value chrome_sqlite3_result_value // Line 5319
-#define sqlite3_result_zeroblob chrome_sqlite3_result_zeroblob // Line 5321
-#define sqlite3_result_zeroblob64 chrome_sqlite3_result_zeroblob64 // Line 5322
-#define sqlite3_rollback_hook chrome_sqlite3_rollback_hook // Line 5812
+ chrome_sqlite3_result_error_toobig // Line 5343
+#define sqlite3_result_int chrome_sqlite3_result_int // Line 5346
+#define sqlite3_result_int64 chrome_sqlite3_result_int64 // Line 5347
+#define sqlite3_result_null chrome_sqlite3_result_null // Line 5348
+#define sqlite3_result_pointer chrome_sqlite3_result_pointer // Line 5356
+#define sqlite3_result_subtype chrome_sqlite3_result_subtype // Line 5373
+#define sqlite3_result_text chrome_sqlite3_result_text // Line 5349
+#define sqlite3_result_text16 chrome_sqlite3_result_text16 // Line 5352
+#define sqlite3_result_text16be chrome_sqlite3_result_text16be // Line 5354
+#define sqlite3_result_text16le chrome_sqlite3_result_text16le // Line 5353
+#define sqlite3_result_text64 chrome_sqlite3_result_text64 // Lines 5350-5351
+#define sqlite3_result_value chrome_sqlite3_result_value // Line 5355
+#define sqlite3_result_zeroblob chrome_sqlite3_result_zeroblob // Line 5357
+#define sqlite3_result_zeroblob64 chrome_sqlite3_result_zeroblob64 // Line 5358
+#define sqlite3_rollback_hook chrome_sqlite3_rollback_hook // Line 5848
#define sqlite3_rtree_geometry_callback \
- chrome_sqlite3_rtree_geometry_callback // Lines 9352-9357
+ chrome_sqlite3_rtree_geometry_callback // Lines 9393-9398
#define sqlite3_rtree_query_callback \
- chrome_sqlite3_rtree_query_callback // Lines 9378-9384
-#define sqlite3_serialize chrome_sqlite3_serialize // Lines 9213-9218
-#define sqlite3_set_authorizer chrome_sqlite3_set_authorizer // Lines 2871-2875
-#define sqlite3_set_auxdata chrome_sqlite3_set_auxdata // Line 5154
+ chrome_sqlite3_rtree_query_callback // Lines 9419-9425
+#define sqlite3_serialize chrome_sqlite3_serialize // Lines 9254-9259
+#define sqlite3_set_authorizer chrome_sqlite3_set_authorizer // Lines 2890-2894
+#define sqlite3_set_auxdata chrome_sqlite3_set_auxdata // Line 5190
#define sqlite3_set_last_insert_rowid \
- chrome_sqlite3_set_last_insert_rowid // Line 2256
+ chrome_sqlite3_set_last_insert_rowid // Line 2275
#define sqlite3_shutdown chrome_sqlite3_shutdown // Line 1505
-#define sqlite3_sleep chrome_sqlite3_sleep // Line 5552
-#define sqlite3_snapshot_cmp chrome_sqlite3_snapshot_cmp // Lines 9147-9150
-#define sqlite3_snapshot_free chrome_sqlite3_snapshot_free // Line 9120
-#define sqlite3_snapshot_get chrome_sqlite3_snapshot_get // Lines 9054-9058
-#define sqlite3_snapshot_open chrome_sqlite3_snapshot_open // Lines 9103-9107
-#define sqlite3_snapshot_recover chrome_sqlite3_snapshot_recover // Line 9175
-#define sqlite3_snprintf chrome_sqlite3_snprintf // Line 2635
-#define sqlite3_soft_heap_limit chrome_sqlite3_soft_heap_limit // Line 5998
-#define sqlite3_soft_heap_limit64 chrome_sqlite3_soft_heap_limit64 // Line 5987
+#define sqlite3_sleep chrome_sqlite3_sleep // Line 5588
+#define sqlite3_snapshot_cmp chrome_sqlite3_snapshot_cmp // Lines 9188-9191
+#define sqlite3_snapshot_free chrome_sqlite3_snapshot_free // Line 9161
+#define sqlite3_snapshot_get chrome_sqlite3_snapshot_get // Lines 9095-9099
+#define sqlite3_snapshot_open chrome_sqlite3_snapshot_open // Lines 9144-9148
+#define sqlite3_snapshot_recover chrome_sqlite3_snapshot_recover // Line 9216
+#define sqlite3_snprintf chrome_sqlite3_snprintf // Line 2654
+#define sqlite3_soft_heap_limit chrome_sqlite3_soft_heap_limit // Line 6034
+#define sqlite3_soft_heap_limit64 chrome_sqlite3_soft_heap_limit64 // Line 6023
#define sqlite3_sourceid chrome_sqlite3_sourceid // Line 164
-#define sqlite3_sql chrome_sqlite3_sql // Line 3793
-#define sqlite3_status chrome_sqlite3_status // Line 7427
-#define sqlite3_status64 chrome_sqlite3_status64 // Lines 7428-7433
-#define sqlite3_step chrome_sqlite3_step // Line 4332
-#define sqlite3_stmt_busy chrome_sqlite3_stmt_busy // Line 3851
-#define sqlite3_stmt_readonly chrome_sqlite3_stmt_readonly // Line 3830
+#define sqlite3_sql chrome_sqlite3_sql // Line 3828
+#define sqlite3_status chrome_sqlite3_status // Line 7467
+#define sqlite3_status64 chrome_sqlite3_status64 // Lines 7468-7473
+#define sqlite3_step chrome_sqlite3_step // Line 4368
+#define sqlite3_stmt_busy chrome_sqlite3_stmt_busy // Line 3887
+#define sqlite3_stmt_readonly chrome_sqlite3_stmt_readonly // Line 3866
#define sqlite3_stmt_scanstatus \
- chrome_sqlite3_stmt_scanstatus // Lines 8823-8828
+ chrome_sqlite3_stmt_scanstatus // Lines 8864-8869
#define sqlite3_stmt_scanstatus_reset \
- chrome_sqlite3_stmt_scanstatus_reset // Line 8839
-#define sqlite3_stmt_status chrome_sqlite3_stmt_status // Line 7690
-#define sqlite3_str_append chrome_sqlite3_str_append // Line 7363
-#define sqlite3_str_appendall chrome_sqlite3_str_appendall // Line 7364
-#define sqlite3_str_appendchar chrome_sqlite3_str_appendchar // Line 7365
-#define sqlite3_str_appendf chrome_sqlite3_str_appendf // Line 7361
-#define sqlite3_str_errcode chrome_sqlite3_str_errcode // Line 7397
-#define sqlite3_str_finish chrome_sqlite3_str_finish // Line 7327
-#define sqlite3_str_length chrome_sqlite3_str_length // Line 7398
-#define sqlite3_str_new chrome_sqlite3_str_new // Line 7312
-#define sqlite3_str_reset chrome_sqlite3_str_reset // Line 7366
-#define sqlite3_str_value chrome_sqlite3_str_value // Line 7399
-#define sqlite3_str_vappendf chrome_sqlite3_str_vappendf // Line 7362
-#define sqlite3_strglob chrome_sqlite3_strglob // Line 8339
-#define sqlite3_stricmp chrome_sqlite3_stricmp // Line 8321
-#define sqlite3_strlike chrome_sqlite3_strlike // Line 8385
-#define sqlite3_strnicmp chrome_sqlite3_strnicmp // Line 8322
-#define sqlite3_system_errno chrome_sqlite3_system_errno // Line 8985
+ chrome_sqlite3_stmt_scanstatus_reset // Line 8880
+#define sqlite3_stmt_status chrome_sqlite3_stmt_status // Line 7730
+#define sqlite3_str_append chrome_sqlite3_str_append // Line 7403
+#define sqlite3_str_appendall chrome_sqlite3_str_appendall // Line 7404
+#define sqlite3_str_appendchar chrome_sqlite3_str_appendchar // Line 7405
+#define sqlite3_str_appendf chrome_sqlite3_str_appendf // Line 7401
+#define sqlite3_str_errcode chrome_sqlite3_str_errcode // Line 7437
+#define sqlite3_str_finish chrome_sqlite3_str_finish // Line 7367
+#define sqlite3_str_length chrome_sqlite3_str_length // Line 7438
+#define sqlite3_str_new chrome_sqlite3_str_new // Line 7352
+#define sqlite3_str_reset chrome_sqlite3_str_reset // Line 7406
+#define sqlite3_str_value chrome_sqlite3_str_value // Line 7439
+#define sqlite3_str_vappendf chrome_sqlite3_str_vappendf // Line 7402
+#define sqlite3_strglob chrome_sqlite3_strglob // Line 8379
+#define sqlite3_stricmp chrome_sqlite3_stricmp // Line 8361
+#define sqlite3_strlike chrome_sqlite3_strlike // Line 8425
+#define sqlite3_strnicmp chrome_sqlite3_strnicmp // Line 8362
+#define sqlite3_system_errno chrome_sqlite3_system_errno // Line 9026
#define sqlite3_table_column_metadata \
- chrome_sqlite3_table_column_metadata // Lines 6070-6080
-#define sqlite3_temp_directory chrome_sqlite3_temp_directory // Line 5610
-#define sqlite3_test_control chrome_sqlite3_test_control // Line 7179
-#define sqlite3_thread_cleanup chrome_sqlite3_thread_cleanup // Line 4854
+ chrome_sqlite3_table_column_metadata // Lines 6106-6116
+#define sqlite3_temp_directory chrome_sqlite3_temp_directory // Line 5646
+#define sqlite3_test_control chrome_sqlite3_test_control // Line 7218
+#define sqlite3_thread_cleanup chrome_sqlite3_thread_cleanup // Line 4890
#define sqlite3_threadsafe chrome_sqlite3_threadsafe // Line 230
-#define sqlite3_total_changes chrome_sqlite3_total_changes // Line 2351
-#define sqlite3_trace chrome_sqlite3_trace // Lines 2979-2980
-#define sqlite3_trace_v2 chrome_sqlite3_trace_v2 // Lines 3070-3075
-#define sqlite3_transfer_bindings chrome_sqlite3_transfer_bindings // Line 4852
-#define sqlite3_unlock_notify chrome_sqlite3_unlock_notify // Lines 8306-8310
-#define sqlite3_update_hook chrome_sqlite3_update_hook // Lines 5863-5867
-#define sqlite3_uri_boolean chrome_sqlite3_uri_boolean // Line 3393
-#define sqlite3_uri_int64 chrome_sqlite3_uri_int64 // Line 3394
-#define sqlite3_uri_parameter chrome_sqlite3_uri_parameter // Line 3392
-#define sqlite3_user_data chrome_sqlite3_user_data // Line 5082
-#define sqlite3_value_blob chrome_sqlite3_value_blob // Line 4980
-#define sqlite3_value_bytes chrome_sqlite3_value_bytes // Line 4989
-#define sqlite3_value_bytes16 chrome_sqlite3_value_bytes16 // Line 4990
-#define sqlite3_value_double chrome_sqlite3_value_double // Line 4981
-#define sqlite3_value_dup chrome_sqlite3_value_dup // Line 5021
-#define sqlite3_value_free chrome_sqlite3_value_free // Line 5022
-#define sqlite3_value_int chrome_sqlite3_value_int // Line 4982
-#define sqlite3_value_int64 chrome_sqlite3_value_int64 // Line 4983
-#define sqlite3_value_nochange chrome_sqlite3_value_nochange // Line 4993
+#define sqlite3_total_changes chrome_sqlite3_total_changes // Line 2370
+#define sqlite3_trace chrome_sqlite3_trace // Lines 2998-2999
+#define sqlite3_trace_v2 chrome_sqlite3_trace_v2 // Lines 3089-3094
+#define sqlite3_transfer_bindings chrome_sqlite3_transfer_bindings // Line 4888
+#define sqlite3_unlock_notify chrome_sqlite3_unlock_notify // Lines 8346-8350
+#define sqlite3_update_hook chrome_sqlite3_update_hook // Lines 5899-5903
+#define sqlite3_uri_boolean chrome_sqlite3_uri_boolean // Line 3412
+#define sqlite3_uri_int64 chrome_sqlite3_uri_int64 // Line 3413
+#define sqlite3_uri_parameter chrome_sqlite3_uri_parameter // Line 3411
+#define sqlite3_user_data chrome_sqlite3_user_data // Line 5118
+#define sqlite3_value_blob chrome_sqlite3_value_blob // Line 5016
+#define sqlite3_value_bytes chrome_sqlite3_value_bytes // Line 5025
+#define sqlite3_value_bytes16 chrome_sqlite3_value_bytes16 // Line 5026
+#define sqlite3_value_double chrome_sqlite3_value_double // Line 5017
+#define sqlite3_value_dup chrome_sqlite3_value_dup // Line 5057
+#define sqlite3_value_free chrome_sqlite3_value_free // Line 5058
+#define sqlite3_value_int chrome_sqlite3_value_int // Line 5018
+#define sqlite3_value_int64 chrome_sqlite3_value_int64 // Line 5019
+#define sqlite3_value_nochange chrome_sqlite3_value_nochange // Line 5029
#define sqlite3_value_numeric_type \
- chrome_sqlite3_value_numeric_type // Line 4992
-#define sqlite3_value_pointer chrome_sqlite3_value_pointer // Line 4984
-#define sqlite3_value_subtype chrome_sqlite3_value_subtype // Line 5005
-#define sqlite3_value_text chrome_sqlite3_value_text // Line 4985
-#define sqlite3_value_text16 chrome_sqlite3_value_text16 // Line 4986
-#define sqlite3_value_text16be chrome_sqlite3_value_text16be // Line 4988
-#define sqlite3_value_text16le chrome_sqlite3_value_text16le // Line 4987
-#define sqlite3_value_type chrome_sqlite3_value_type // Line 4991
+ chrome_sqlite3_value_numeric_type // Line 5028
+#define sqlite3_value_pointer chrome_sqlite3_value_pointer // Line 5020
+#define sqlite3_value_subtype chrome_sqlite3_value_subtype // Line 5041
+#define sqlite3_value_text chrome_sqlite3_value_text // Line 5021
+#define sqlite3_value_text16 chrome_sqlite3_value_text16 // Line 5022
+#define sqlite3_value_text16be chrome_sqlite3_value_text16be // Line 5024
+#define sqlite3_value_text16le chrome_sqlite3_value_text16le // Line 5023
+#define sqlite3_value_type chrome_sqlite3_value_type // Line 5027
#define sqlite3_version chrome_sqlite3_version // Line 162
-#define sqlite3_vfs_find chrome_sqlite3_vfs_find // Line 6844
-#define sqlite3_vfs_register chrome_sqlite3_vfs_register // Line 6845
-#define sqlite3_vfs_unregister chrome_sqlite3_vfs_unregister // Line 6846
-#define sqlite3_vmprintf chrome_sqlite3_vmprintf // Line 2634
-#define sqlite3_vsnprintf chrome_sqlite3_vsnprintf // Line 2636
-#define sqlite3_vtab_collation chrome_sqlite3_vtab_collation // Line 8718
-#define sqlite3_vtab_config chrome_sqlite3_vtab_config // Line 8631
-#define sqlite3_vtab_nochange chrome_sqlite3_vtab_nochange // Line 8703
-#define sqlite3_vtab_on_conflict chrome_sqlite3_vtab_on_conflict // Line 8684
+#define sqlite3_vfs_find chrome_sqlite3_vfs_find // Line 6883
+#define sqlite3_vfs_register chrome_sqlite3_vfs_register // Line 6884
+#define sqlite3_vfs_unregister chrome_sqlite3_vfs_unregister // Line 6885
+#define sqlite3_vmprintf chrome_sqlite3_vmprintf // Line 2653
+#define sqlite3_vsnprintf chrome_sqlite3_vsnprintf // Line 2655
+#define sqlite3_vtab_collation chrome_sqlite3_vtab_collation // Line 8759
+#define sqlite3_vtab_config chrome_sqlite3_vtab_config // Line 8671
+#define sqlite3_vtab_nochange chrome_sqlite3_vtab_nochange // Line 8744
+#define sqlite3_vtab_on_conflict chrome_sqlite3_vtab_on_conflict // Line 8725
#define sqlite3_wal_autocheckpoint \
- chrome_sqlite3_wal_autocheckpoint // Line 8479
-#define sqlite3_wal_checkpoint chrome_sqlite3_wal_checkpoint // Line 8501
+ chrome_sqlite3_wal_autocheckpoint // Line 8519
+#define sqlite3_wal_checkpoint chrome_sqlite3_wal_checkpoint // Line 8541
#define sqlite3_wal_checkpoint_v2 \
- chrome_sqlite3_wal_checkpoint_v2 // Lines 8595-8601
-#define sqlite3_wal_hook chrome_sqlite3_wal_hook // Lines 8444-8448
+ chrome_sqlite3_wal_checkpoint_v2 // Lines 8635-8641
+#define sqlite3_wal_hook chrome_sqlite3_wal_hook // Lines 8484-8488
#define sqlite3_win32_set_directory \
- chrome_sqlite3_win32_set_directory // Lines 5668-5671
+ chrome_sqlite3_win32_set_directory // Lines 5704-5707
#define sqlite3_win32_set_directory16 \
- chrome_sqlite3_win32_set_directory16 // Line 5673
+ chrome_sqlite3_win32_set_directory16 // Line 5709
#define sqlite3_win32_set_directory8 \
- chrome_sqlite3_win32_set_directory8 // Line 5672
-#define sqlite3changegroup_add chrome_sqlite3changegroup_add // Line 10339
+ chrome_sqlite3_win32_set_directory8 // Line 5708
+#define sqlite3changegroup_add chrome_sqlite3changegroup_add // Line 10406
#define sqlite3changegroup_add_strm \
- chrome_sqlite3changegroup_add_strm // Lines 10989-10992
+ chrome_sqlite3changegroup_add_strm // Lines 11068-11071
#define sqlite3changegroup_delete \
- chrome_sqlite3changegroup_delete // Line 10376
-#define sqlite3changegroup_new chrome_sqlite3changegroup_new // Line 10261
+ chrome_sqlite3changegroup_delete // Line 10443
+#define sqlite3changegroup_new chrome_sqlite3changegroup_new // Line 10328
#define sqlite3changegroup_output \
- chrome_sqlite3changegroup_output // Lines 10366-10370
+ chrome_sqlite3changegroup_output // Lines 10433-10437
#define sqlite3changegroup_output_strm \
- chrome_sqlite3changegroup_output_strm // Lines 10993-10996
+ chrome_sqlite3changegroup_output_strm // Lines 11072-11075
#define sqlite3changeset_apply \
- chrome_sqlite3changeset_apply // Lines 10536-10550
+ chrome_sqlite3changeset_apply // Lines 10603-10617
#define sqlite3changeset_apply_strm \
- chrome_sqlite3changeset_apply_strm // Lines 10928-10942
+ chrome_sqlite3changeset_apply_strm // Lines 11001-11015
#define sqlite3changeset_apply_v2 \
- chrome_sqlite3changeset_apply_v2 // Lines 10551-10567
+ chrome_sqlite3changeset_apply_v2 // Lines 10618-10634
#define sqlite3changeset_apply_v2_strm \
- chrome_sqlite3changeset_apply_v2_strm // Lines 10943-10959
+ chrome_sqlite3changeset_apply_v2_strm // Lines 11016-11032
#define sqlite3changeset_concat \
- chrome_sqlite3changeset_concat // Lines 10207-10214
+ chrome_sqlite3changeset_concat // Lines 10274-10281
#define sqlite3changeset_concat_strm \
- chrome_sqlite3changeset_concat_strm // Lines 10960-10967
+ chrome_sqlite3changeset_concat_strm // Lines 11033-11040
#define sqlite3changeset_conflict \
- chrome_sqlite3changeset_conflict // Lines 10093-10097
+ chrome_sqlite3changeset_conflict // Lines 10160-10164
#define sqlite3changeset_finalize \
- chrome_sqlite3changeset_finalize // Line 10146
+ chrome_sqlite3changeset_finalize // Line 10213
#define sqlite3changeset_fk_conflicts \
- chrome_sqlite3changeset_fk_conflicts // Lines 10110-10113
+ chrome_sqlite3changeset_fk_conflicts // Lines 10177-10180
#define sqlite3changeset_invert \
- chrome_sqlite3changeset_invert // Lines 10176-10179
+ chrome_sqlite3changeset_invert // Lines 10243-10246
#define sqlite3changeset_invert_strm \
- chrome_sqlite3changeset_invert_strm // Lines 10968-10973
-#define sqlite3changeset_new chrome_sqlite3changeset_new // Lines 10065-10069
-#define sqlite3changeset_next chrome_sqlite3changeset_next // Line 9937
-#define sqlite3changeset_old chrome_sqlite3changeset_old // Lines 10031-10035
-#define sqlite3changeset_op chrome_sqlite3changeset_op // Lines 9966-9972
-#define sqlite3changeset_pk chrome_sqlite3changeset_pk // Lines 10000-10004
-#define sqlite3changeset_start chrome_sqlite3changeset_start // Lines 9907-9911
+ chrome_sqlite3changeset_invert_strm // Lines 11041-11046
+#define sqlite3changeset_new chrome_sqlite3changeset_new // Lines 10132-10136
+#define sqlite3changeset_next chrome_sqlite3changeset_next // Line 10004
+#define sqlite3changeset_old chrome_sqlite3changeset_old // Lines 10098-10102
+#define sqlite3changeset_op chrome_sqlite3changeset_op // Lines 10033-10039
+#define sqlite3changeset_pk chrome_sqlite3changeset_pk // Lines 10067-10071
+#define sqlite3changeset_start chrome_sqlite3changeset_start // Lines 9955-9959
#define sqlite3changeset_start_strm \
- chrome_sqlite3changeset_start_strm // Lines 10974-10978
+ chrome_sqlite3changeset_start_strm // Lines 11047-11051
+#define sqlite3changeset_start_v2 \
+ chrome_sqlite3changeset_start_v2 // Lines 9960-9965
+#define sqlite3changeset_start_v2_strm \
+ chrome_sqlite3changeset_start_v2_strm // Lines 11052-11057
#define sqlite3rebaser_configure \
- chrome_sqlite3rebaser_configure // Lines 10803-10806
-#define sqlite3rebaser_create chrome_sqlite3rebaser_create // Line 10792
-#define sqlite3rebaser_delete chrome_sqlite3rebaser_delete // Line 10836
-#define sqlite3rebaser_rebase chrome_sqlite3rebaser_rebase // Lines 10822-10826
+ chrome_sqlite3rebaser_configure // Lines 10876-10879
+#define sqlite3rebaser_create chrome_sqlite3rebaser_create // Line 10865
+#define sqlite3rebaser_delete chrome_sqlite3rebaser_delete // Line 10909
+#define sqlite3rebaser_rebase chrome_sqlite3rebaser_rebase // Lines 10895-10899
#define sqlite3rebaser_rebase_strm \
- chrome_sqlite3rebaser_rebase_strm // Lines 10997-11003
-#define sqlite3session_attach chrome_sqlite3session_attach // Lines 9621-9624
+ chrome_sqlite3rebaser_rebase_strm // Lines 11076-11082
+#define sqlite3session_attach chrome_sqlite3session_attach // Lines 9662-9665
#define sqlite3session_changeset \
- chrome_sqlite3session_changeset // Lines 9750-9754
+ chrome_sqlite3session_changeset // Lines 9791-9795
#define sqlite3session_changeset_strm \
- chrome_sqlite3session_changeset_strm // Lines 10979-10983
-#define sqlite3session_create chrome_sqlite3session_create // Lines 9491-9495
-#define sqlite3session_delete chrome_sqlite3session_delete // Line 9510
-#define sqlite3session_diff chrome_sqlite3session_diff // Lines 9813-9818
-#define sqlite3session_enable chrome_sqlite3session_enable // Line 9531
-#define sqlite3session_indirect chrome_sqlite3session_indirect // Line 9561
-#define sqlite3session_isempty chrome_sqlite3session_isempty // Line 9871
+ chrome_sqlite3session_changeset_strm // Lines 11058-11062
+#define sqlite3session_config chrome_sqlite3session_config // Line 11117
+#define sqlite3session_create chrome_sqlite3session_create // Lines 9532-9536
+#define sqlite3session_delete chrome_sqlite3session_delete // Line 9551
+#define sqlite3session_diff chrome_sqlite3session_diff // Lines 9854-9859
+#define sqlite3session_enable chrome_sqlite3session_enable // Line 9572
+#define sqlite3session_indirect chrome_sqlite3session_indirect // Line 9602
+#define sqlite3session_isempty chrome_sqlite3session_isempty // Line 9912
#define sqlite3session_patchset \
- chrome_sqlite3session_patchset // Lines 9850-9854
+ chrome_sqlite3session_patchset // Lines 9891-9895
#define sqlite3session_patchset_strm \
- chrome_sqlite3session_patchset_strm // Lines 10984-10988
+ chrome_sqlite3session_patchset_strm // Lines 11063-11067
#define sqlite3session_table_filter \
- chrome_sqlite3session_table_filter // Lines 9636-9643
+ chrome_sqlite3session_table_filter // Lines 9677-9684
#endif // THIRD_PARTY_SQLITE_AMALGAMATION_RENAME_EXPORTS_H_
diff --git a/chromium/third_party/sqlite/amalgamation/shell/shell.c b/chromium/third_party/sqlite/amalgamation/shell/shell.c
index 0871dde0e25..04ff4562761 100644
--- a/chromium/third_party/sqlite/amalgamation/shell/shell.c
+++ b/chromium/third_party/sqlite/amalgamation/shell/shell.c
@@ -1317,7 +1317,7 @@ INT closedir(
**
******************************************************************************
**
-** This SQLite extension implements a functions that compute SHA1 hashes.
+** This SQLite extension implements functions that compute SHA3 hashes.
** Two SQL functions are implemented:
**
** sha3(X,SIZE)
@@ -2128,7 +2128,18 @@ SQLITE_EXTENSION_INIT1
#include <errno.h>
+/*
+** Structure of the fsdir() table-valued function
+*/
+ /* 0 1 2 3 4 5 */
#define FSDIR_SCHEMA "(name,mode,mtime,data,path HIDDEN,dir HIDDEN)"
+#define FSDIR_COLUMN_NAME 0 /* Name of the file */
+#define FSDIR_COLUMN_MODE 1 /* Access mode */
+#define FSDIR_COLUMN_MTIME 2 /* Last modification time */
+#define FSDIR_COLUMN_DATA 3 /* File content */
+#define FSDIR_COLUMN_PATH 4 /* Path to top of search */
+#define FSDIR_COLUMN_DIR 5 /* Path is relative to this directory */
+
/*
** Set the result stored by context ctx to a blob containing the
@@ -2717,20 +2728,20 @@ static int fsdirColumn(
){
fsdir_cursor *pCur = (fsdir_cursor*)cur;
switch( i ){
- case 0: { /* name */
+ case FSDIR_COLUMN_NAME: {
sqlite3_result_text(ctx, &pCur->zPath[pCur->nBase], -1, SQLITE_TRANSIENT);
break;
}
- case 1: /* mode */
+ case FSDIR_COLUMN_MODE:
sqlite3_result_int64(ctx, pCur->sStat.st_mode);
break;
- case 2: /* mtime */
+ case FSDIR_COLUMN_MTIME:
sqlite3_result_int64(ctx, pCur->sStat.st_mtime);
break;
- case 3: { /* data */
+ case FSDIR_COLUMN_DATA: {
mode_t m = pCur->sStat.st_mode;
if( S_ISDIR(m) ){
sqlite3_result_null(ctx);
@@ -2760,6 +2771,12 @@ static int fsdirColumn(
readFileContents(ctx, pCur->zPath);
}
}
+ case FSDIR_COLUMN_PATH:
+ default: {
+ /* The FSDIR_COLUMN_PATH and FSDIR_COLUMN_DIR are input parameters.
+ ** always return their values as NULL */
+ break;
+ }
}
return SQLITE_OK;
}
@@ -2786,6 +2803,9 @@ static int fsdirEof(sqlite3_vtab_cursor *cur){
/*
** xFilter callback.
+**
+** idxNum==1 PATH parameter only
+** idxNum==2 Both PATH and DIR supplied
*/
static int fsdirFilter(
sqlite3_vtab_cursor *cur,
@@ -2838,40 +2858,63 @@ static int fsdirFilter(
** In this implementation idxNum is used to represent the
** query plan. idxStr is unused.
**
-** The query plan is represented by bits in idxNum:
+** The query plan is represented by values of idxNum:
**
-** (1) start = $value -- constraint exists
-** (2) stop = $value -- constraint exists
-** (4) step = $value -- constraint exists
-** (8) output in descending order
+** (1) The path value is supplied by argv[0]
+** (2) Path is in argv[0] and dir is in argv[1]
*/
static int fsdirBestIndex(
sqlite3_vtab *tab,
sqlite3_index_info *pIdxInfo
){
int i; /* Loop over constraints */
- int idx4 = -1;
- int idx5 = -1;
+ int idxPath = -1; /* Index in pIdxInfo->aConstraint of PATH= */
+ int idxDir = -1; /* Index in pIdxInfo->aConstraint of DIR= */
+ int seenPath = 0; /* True if an unusable PATH= constraint is seen */
+ int seenDir = 0; /* True if an unusable DIR= constraint is seen */
const struct sqlite3_index_constraint *pConstraint;
(void)tab;
pConstraint = pIdxInfo->aConstraint;
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
- if( pConstraint->usable==0 ) continue;
if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
- if( pConstraint->iColumn==4 ) idx4 = i;
- if( pConstraint->iColumn==5 ) idx5 = i;
+ switch( pConstraint->iColumn ){
+ case FSDIR_COLUMN_PATH: {
+ if( pConstraint->usable ){
+ idxPath = i;
+ seenPath = 0;
+ }else if( idxPath<0 ){
+ seenPath = 1;
+ }
+ break;
+ }
+ case FSDIR_COLUMN_DIR: {
+ if( pConstraint->usable ){
+ idxDir = i;
+ seenDir = 0;
+ }else if( idxDir<0 ){
+ seenDir = 1;
+ }
+ break;
+ }
+ }
+ }
+ if( seenPath || seenDir ){
+ /* If input parameters are unusable, disallow this plan */
+ return SQLITE_CONSTRAINT;
}
- if( idx4<0 ){
+ if( idxPath<0 ){
pIdxInfo->idxNum = 0;
- pIdxInfo->estimatedCost = (double)(((sqlite3_int64)1) << 50);
+ /* The pIdxInfo->estimatedCost should have been initialized to a huge
+ ** number. Leave it unchanged. */
+ pIdxInfo->estimatedRows = 0x7fffffff;
}else{
- pIdxInfo->aConstraintUsage[idx4].omit = 1;
- pIdxInfo->aConstraintUsage[idx4].argvIndex = 1;
- if( idx5>=0 ){
- pIdxInfo->aConstraintUsage[idx5].omit = 1;
- pIdxInfo->aConstraintUsage[idx5].argvIndex = 2;
+ pIdxInfo->aConstraintUsage[idxPath].omit = 1;
+ pIdxInfo->aConstraintUsage[idxPath].argvIndex = 1;
+ if( idxDir>=0 ){
+ pIdxInfo->aConstraintUsage[idxDir].omit = 1;
+ pIdxInfo->aConstraintUsage[idxDir].argvIndex = 2;
pIdxInfo->idxNum = 2;
pIdxInfo->estimatedCost = 10.0;
}else{
@@ -2910,7 +2953,8 @@ static int fsdirRegister(sqlite3 *db){
0, /* xRename */
0, /* xSavepoint */
0, /* xRelease */
- 0 /* xRollbackTo */
+ 0, /* xRollbackTo */
+ 0, /* xShadowName */
};
int rc = sqlite3_create_module(db, "fsdir", &fsdirModule, 0);
@@ -3418,7 +3462,8 @@ static sqlite3_module completionModule = {
0, /* xRename */
0, /* xSavepoint */
0, /* xRelease */
- 0 /* xRollbackTo */
+ 0, /* xRollbackTo */
+ 0 /* xShadowName */
};
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -5315,25 +5360,26 @@ static int zipfileBestIndex(
sqlite3_index_info *pIdxInfo
){
int i;
+ int idx = -1;
+ int unusable = 0;
for(i=0; i<pIdxInfo->nConstraint; i++){
const struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i];
- if( pCons->usable==0 ) continue;
- if( pCons->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
if( pCons->iColumn!=ZIPFILE_F_COLUMN_IDX ) continue;
- break;
+ if( pCons->usable==0 ){
+ unusable = 1;
+ }else if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){
+ idx = i;
+ }
}
-
- if( i<pIdxInfo->nConstraint ){
- pIdxInfo->aConstraintUsage[i].argvIndex = 1;
- pIdxInfo->aConstraintUsage[i].omit = 1;
+ if( idx>=0 ){
+ pIdxInfo->aConstraintUsage[idx].argvIndex = 1;
+ pIdxInfo->aConstraintUsage[idx].omit = 1;
pIdxInfo->estimatedCost = 1000.0;
pIdxInfo->idxNum = 1;
- }else{
- pIdxInfo->estimatedCost = (double)(((sqlite3_int64)1) << 50);
- pIdxInfo->idxNum = 0;
+ }else if( unusable ){
+ return SQLITE_CONSTRAINT;
}
-
return SQLITE_OK;
}
@@ -7136,6 +7182,7 @@ static int idxRegisterVtab(sqlite3expert *p){
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
+ 0, /* xShadowName */
};
return sqlite3_create_module(p->dbv, "expert", &expertModule, (void*)p);
@@ -8560,11 +8607,12 @@ struct ShellState {
/* Allowed values for ShellState.openMode
*/
-#define SHELL_OPEN_UNSPEC 0 /* No open-mode specified */
-#define SHELL_OPEN_NORMAL 1 /* Normal database file */
-#define SHELL_OPEN_APPENDVFS 2 /* Use appendvfs */
-#define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */
-#define SHELL_OPEN_READONLY 4 /* Open a normal database read-only */
+#define SHELL_OPEN_UNSPEC 0 /* No open-mode specified */
+#define SHELL_OPEN_NORMAL 1 /* Normal database file */
+#define SHELL_OPEN_APPENDVFS 2 /* Use appendvfs */
+#define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */
+#define SHELL_OPEN_READONLY 4 /* Open a normal database read-only */
+#define SHELL_OPEN_DESERIALIZE 5 /* Open using sqlite3_deserialize() */
/*
** These are the allowed shellFlgs values
@@ -8774,7 +8822,7 @@ static void editFunc(
if( bBin ){
sqlite3_result_blob64(context, p, sz, sqlite3_free);
}else{
- int i, j;
+ sqlite3_int64 i, j;
if( hasCRNL ){
/* If the original contains \r\n then do no conversions back to \n */
j = sz;
@@ -10836,137 +10884,238 @@ static int run_schema_dump_query(
}
/*
-** Text of a help message
+** Text of help messages.
+**
+** The help text for each individual command begins with a line that starts
+** with ".". Subsequent lines are supplimental information.
+**
+** There must be two or more spaces between the end of the command and the
+** start of the description of what that command does.
*/
-static char zHelp[] =
+static const char *(azHelp[]) = {
#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
- ".archive ... Manage SQL archives: \".archive --help\" for details\n"
+ ".archive ... Manage SQL archives",
+ " Each command must have exactly one of the following options:",
+ " -c, --create Create a new archive",
+ " -u, --update Update or add files to an existing archive",
+ " -t, --list List contents of archive",
+ " -x, --extract Extract files from archive",
+ " Optional arguments:",
+ " -v, --verbose Print each filename as it is processed",
+ " -f FILE, --file FILE Operate on archive FILE (default is current db)",
+ " -a FILE, --append FILE Operate on FILE opened using the apndvfs VFS",
+ " -C DIR, --directory DIR Change to directory DIR to read/extract files",
+ " -n, --dryrun Show the SQL that would have occurred",
+ " Examples:",
+ " .ar -cf archive.sar foo bar # Create archive.sar from files foo and bar",
+ " .ar -tf archive.sar # List members of archive.sar",
+ " .ar -xvf archive.sar # Verbosely extract files from archive.sar",
+ " See also:",
+ " http://sqlite.org/cli.html#sqlar_archive_support",
#endif
#ifndef SQLITE_OMIT_AUTHORIZATION
- ".auth ON|OFF Show authorizer callbacks\n"
-#endif
- ".backup ?DB? FILE Backup DB (default \"main\") to FILE\n"
- " Add \"--append\" to open using appendvfs.\n"
- ".bail on|off Stop after hitting an error. Default OFF\n"
- ".binary on|off Turn binary output on or off. Default OFF\n"
- ".cd DIRECTORY Change the working directory to DIRECTORY\n"
- ".changes on|off Show number of rows changed by SQL\n"
- ".check GLOB Fail if output since .testcase does not match\n"
- ".clone NEWDB Clone data into NEWDB from the existing database\n"
- ".databases List names and files of attached databases\n"
- ".dbconfig ?op? ?val? List or change sqlite3_db_config() options\n"
- ".dbinfo ?DB? Show status information about the database\n"
- ".dump ?TABLE? ... Dump the database in an SQL text format\n"
- " If TABLE specified, only dump tables matching\n"
- " LIKE pattern TABLE.\n"
- ".echo on|off Turn command echo on or off\n"
- ".eqp on|off|full Enable or disable automatic EXPLAIN QUERY PLAN\n"
- ".excel Display the output of next command in a spreadsheet\n"
- ".exit Exit this program\n"
- ".expert EXPERIMENTAL. Suggest indexes for specified queries\n"
+ ".auth ON|OFF Show authorizer callbacks",
+#endif
+ ".backup ?DB? FILE Backup DB (default \"main\") to FILE",
+ " --append Use the appendvfs",
+ ".bail on|off Stop after hitting an error. Default OFF",
+ ".binary on|off Turn binary output on or off. Default OFF",
+ ".cd DIRECTORY Change the working directory to DIRECTORY",
+ ".changes on|off Show number of rows changed by SQL",
+ ".check GLOB Fail if output since .testcase does not match",
+ ".clone NEWDB Clone data into NEWDB from the existing database",
+ ".databases List names and files of attached databases",
+ ".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
+ ".dbinfo ?DB? Show status information about the database",
+ ".dump ?TABLE? ... Render all database content as SQL",
+ " Options:",
+ " --preserve-rowids Include ROWID values in the output",
+ " --newlines Allow unescaped newline characters in output",
+ " TABLE is LIKE pattern for the tables to dump",
+ ".echo on|off Turn command echo on or off",
+ ".eqp on|off|full Enable or disable automatic EXPLAIN QUERY PLAN",
+ ".excel Display the output of next command in a spreadsheet",
+ ".exit ?CODE? Exit this program with return-code CODE",
+ ".expert EXPERIMENTAL. Suggest indexes for specified queries",
/* Because explain mode comes on automatically now, the ".explain" mode
** is removed from the help screen. It is still supported for legacy, however */
-/*".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic\n"*/
- ".fullschema ?--indent? Show schema and the content of sqlite_stat tables\n"
- ".headers on|off Turn display of headers on or off\n"
- ".help Show this message\n"
- ".import FILE TABLE Import data from FILE into TABLE\n"
+/*".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic",*/
+ ".fullschema ?--indent? Show schema and the content of sqlite_stat tables",
+ ".headers on|off Turn display of headers on or off",
+ ".help ?-all? ?PATTERN? Show help text for PATTERN",
+ ".import FILE TABLE Import data from FILE into TABLE",
#ifndef SQLITE_OMIT_TEST_CONTROL
- ".imposter INDEX TABLE Create imposter table TABLE on index INDEX\n"
+ ".imposter INDEX TABLE Create imposter table TABLE on index INDEX",
#endif
- ".indexes ?TABLE? Show names of all indexes\n"
- " If TABLE specified, only show indexes for tables\n"
- " matching LIKE pattern TABLE.\n"
+ ".indexes ?TABLE? Show names of indexes",
+ " If TABLE is specified, only show indexes for",
+ " tables matching TABLE using the LIKE operator.",
#ifdef SQLITE_ENABLE_IOTRACE
- ".iotrace FILE Enable I/O diagnostic logging to FILE\n"
+ ".iotrace FILE Enable I/O diagnostic logging to FILE",
#endif
- ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT\n"
- ".lint OPTIONS Report potential schema issues. Options:\n"
- " fkey-indexes Find missing foreign key indexes\n"
+ ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT",
+ ".lint OPTIONS Report potential schema issues.",
+ " Options:",
+ " fkey-indexes Find missing foreign key indexes",
#ifndef SQLITE_OMIT_LOAD_EXTENSION
- ".load FILE ?ENTRY? Load an extension library\n"
-#endif
- ".log FILE|off Turn logging on or off. FILE can be stderr/stdout\n"
- ".mode MODE ?TABLE? Set output mode where MODE is one of:\n"
- " ascii Columns/rows delimited by 0x1F and 0x1E\n"
- " csv Comma-separated values\n"
- " column Left-aligned columns. (See .width)\n"
- " html HTML <table> code\n"
- " insert SQL insert statements for TABLE\n"
- " line One value per line\n"
- " list Values delimited by \"|\"\n"
- " quote Escape answers as for SQL\n"
- " tabs Tab-separated values\n"
- " tcl TCL list elements\n"
- ".nullvalue STRING Use STRING in place of NULL values\n"
- ".once (-e|-x|FILE) Output for the next SQL command only to FILE\n"
- " or invoke system text editor (-e) or spreadsheet (-x)\n"
- " on the output.\n"
- ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE\n"
- " The --new option starts with an empty file\n"
- " Other options: --readonly --append --zip\n"
- ".output ?FILE? Send output to FILE or stdout\n"
- ".print STRING... Print literal STRING\n"
- ".prompt MAIN CONTINUE Replace the standard prompts\n"
- ".quit Exit this program\n"
- ".read FILENAME Execute SQL in FILENAME\n"
- ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n"
- ".save FILE Write in-memory database into FILE\n"
- ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off\n"
- ".schema ?PATTERN? Show the CREATE statements matching PATTERN\n"
- " Add --indent for pretty-printing\n"
- ".selftest ?--init? Run tests defined in the SELFTEST table\n"
- ".separator COL ?ROW? Change the column separator and optionally the row\n"
- " separator for both the output mode and .import\n"
+ ".load FILE ?ENTRY? Load an extension library",
+#endif
+ ".log FILE|off Turn logging on or off. FILE can be stderr/stdout",
+ ".mode MODE ?TABLE? Set output mode",
+ " MODE is one of:",
+ " ascii Columns/rows delimited by 0x1F and 0x1E",
+ " csv Comma-separated values",
+ " column Left-aligned columns. (See .width)",
+ " html HTML <table> code",
+ " insert SQL insert statements for TABLE",
+ " line One value per line",
+ " list Values delimited by \"|\"",
+ " quote Escape answers as for SQL",
+ " tabs Tab-separated values",
+ " tcl TCL list elements",
+ ".nullvalue STRING Use STRING in place of NULL values",
+ ".once (-e|-x|FILE) Output for the next SQL command only to FILE",
+ " If FILE begins with '|' then open as a pipe",
+ " Other options:",
+ " -e Invoke system text editor",
+ " -x Open in a spreadsheet",
+ ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE",
+ " Options:",
+ " --append Use appendvfs to append database to the end of FILE",
+#ifdef SQLITE_ENABLE_DESERIALIZE
+ " --deserialize Load into memory useing sqlite3_deserialize()",
+#endif
+ " --new Initialize FILE to an empty database",
+ " --readonly Open FILE readonly",
+ " --zip FILE is a ZIP archive",
+ ".output ?FILE? Send output to FILE or stdout if FILE is omitted",
+ " If FILE begins with '|' then open it as a pipe.",
+ ".print STRING... Print literal STRING",
+ ".prompt MAIN CONTINUE Replace the standard prompts",
+ ".quit Exit this program",
+ ".read FILE Read input from FILE",
+ ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE",
+ ".save FILE Write in-memory database into FILE",
+ ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off",
+ ".schema ?PATTERN? Show the CREATE statements matching PATTERN",
+ " Options:",
+ " --indent Try to pretty-print the schema",
+ ".selftest ?OPTIONS? Run tests defined in the SELFTEST table",
+ " Options:",
+ " --init Create a new SELFTEST table",
+ " -v Verbose output",
+ ".separator COL ?ROW? Change the column and row separators",
#if defined(SQLITE_ENABLE_SESSION)
- ".session CMD ... Create or control sessions\n"
+ ".session ?NAME? CMD ... Create or control sessions",
+ " Subcommands:",
+ " attach TABLE Attach TABLE",
+ " changeset FILE Write a changeset into FILE",
+ " close Close one session",
+ " enable ?BOOLEAN? Set or query the enable bit",
+ " filter GLOB... Reject tables matching GLOBs",
+ " indirect ?BOOLEAN? Mark or query the indirect status",
+ " isempty Query whether the session is empty",
+ " list List currently open session names",
+ " open DB NAME Open a new session on DB",
+ " patchset FILE Write a patchset into FILE",
+ " If ?NAME? is omitted, the first defined session is used.",
#endif
- ".sha3sum ?OPTIONS...? Compute a SHA3 hash of database content\n"
+ ".sha3sum ... Compute a SHA3 hash of database content",
+ " Options:",
+ " --schema Also hash the sqlite_master table",
+ " --sha3-224 Use the sha3-224 algorithm",
+ " --sha3-256 Use the sha3-256 algorithm. This is the default.",
+ " --sha3-384 Use the sha3-384 algorithm",
+ " --sha3-512 Use the sha3-512 algorithm",
+ " Any other argument is a LIKE pattern for tables to hash",
#ifndef SQLITE_NOHAVE_SYSTEM
- ".shell CMD ARGS... Run CMD ARGS... in a system shell\n"
+ ".shell CMD ARGS... Run CMD ARGS... in a system shell",
#endif
- ".show Show the current values for various settings\n"
- ".stats ?on|off? Show stats or turn stats on or off\n"
+ ".show Show the current values for various settings",
+ ".stats ?on|off? Show stats or turn stats on or off",
#ifndef SQLITE_NOHAVE_SYSTEM
- ".system CMD ARGS... Run CMD ARGS... in a system shell\n"
-#endif
- ".tables ?TABLE? List names of tables\n"
- " If TABLE specified, only list tables matching\n"
- " LIKE pattern TABLE.\n"
- ".testcase NAME Begin redirecting output to 'testcase-out.txt'\n"
- ".timeout MS Try opening locked tables for MS milliseconds\n"
- ".timer on|off Turn SQL timer on or off\n"
- ".trace FILE|off Output each SQL statement as it is run\n"
- ".vfsinfo ?AUX? Information about the top-level VFS\n"
- ".vfslist List all available VFSes\n"
- ".vfsname ?AUX? Print the name of the VFS stack\n"
- ".width NUM1 NUM2 ... Set column widths for \"column\" mode\n"
- " Negative values right-justify\n"
-;
+ ".system CMD ARGS... Run CMD ARGS... in a system shell",
+#endif
+ ".tables ?TABLE? List names of tables matching LIKE pattern TABLE",
+ ".testcase NAME Begin redirecting output to 'testcase-out.txt'",
+ ".timeout MS Try opening locked tables for MS milliseconds",
+ ".timer on|off Turn SQL timer on or off",
+ ".trace FILE|off Output each SQL statement as it is run",
+ ".vfsinfo ?AUX? Information about the top-level VFS",
+ ".vfslist List all available VFSes",
+ ".vfsname ?AUX? Print the name of the VFS stack",
+ ".width NUM1 NUM2 ... Set column widths for \"column\" mode",
+ " Negative values right-justify",
+};
-#if defined(SQLITE_ENABLE_SESSION)
/*
-** Print help information for the ".sessions" command
-*/
-void session_help(ShellState *p){
- raw_printf(p->out,
- ".session ?NAME? SUBCOMMAND ?ARGS...?\n"
- "If ?NAME? is omitted, the first defined session is used.\n"
- "Subcommands:\n"
- " attach TABLE Attach TABLE\n"
- " changeset FILE Write a changeset into FILE\n"
- " close Close one session\n"
- " enable ?BOOLEAN? Set or query the enable bit\n"
- " filter GLOB... Reject tables matching GLOBs\n"
- " indirect ?BOOLEAN? Mark or query the indirect status\n"
- " isempty Query whether the session is empty\n"
- " list List currently open session names\n"
- " open DB NAME Open a new session on DB\n"
- " patchset FILE Write a patchset into FILE\n"
- );
+** Output help text.
+**
+** zPattern describes the set of commands for which help text is provided.
+** If zPattern is NULL, then show all commands, but only give a one-line
+** description of each.
+**
+** Return the number of matches.
+*/
+static int showHelp(FILE *out, const char *zPattern){
+ int i = 0;
+ int j = 0;
+ int n = 0;
+ char *zPat;
+ if( zPattern==0
+ || zPattern[0]=='0'
+ || strcmp(zPattern,"-a")==0
+ || strcmp(zPattern,"-all")==0
+ ){
+ /* Show all commands, but only one line per command */
+ if( zPattern==0 ) zPattern = "";
+ for(i=0; i<ArraySize(azHelp); i++){
+ if( azHelp[i][0]=='.' || zPattern[0] ){
+ utf8_printf(out, "%s\n", azHelp[i]);
+ n++;
+ }
+ }
+ }else{
+ /* Look for commands that for which zPattern is an exact prefix */
+ zPat = sqlite3_mprintf(".%s*", zPattern);
+ for(i=0; i<ArraySize(azHelp); i++){
+ if( sqlite3_strglob(zPat, azHelp[i])==0 ){
+ utf8_printf(out, "%s\n", azHelp[i]);
+ j = i+1;
+ n++;
+ }
+ }
+ sqlite3_free(zPat);
+ if( n ){
+ if( n==1 ){
+ /* when zPattern is a prefix of exactly one command, then include the
+ ** details of that command, which should begin at offset j */
+ while( j<ArraySize(azHelp)-1 && azHelp[j][0]!='.' ){
+ utf8_printf(out, "%s\n", azHelp[j]);
+ j++;
+ }
+ }
+ return n;
+ }
+ /* Look for commands that contain zPattern anywhere. Show the complete
+ ** text of all commands that match. */
+ zPat = sqlite3_mprintf("%%%s%%", zPattern);
+ for(i=0; i<ArraySize(azHelp); i++){
+ if( azHelp[i][0]=='.' ) j = i;
+ if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){
+ utf8_printf(out, "%s\n", azHelp[j]);
+ while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]!='.' ){
+ j++;
+ utf8_printf(out, "%s\n", azHelp[j]);
+ }
+ i = j;
+ n++;
+ }
+ }
+ sqlite3_free(zPat);
+ }
+ return n;
}
-#endif
-
/* Forward reference */
static int process_input(ShellState *p, FILE *in);
@@ -10996,7 +11145,7 @@ static char *readFile(const char *zName, int *pnByte){
nIn = ftell(in);
rewind(in);
pBuf = sqlite3_malloc64( nIn+1 );
- if( pBuf==0 ) return 0;
+ if( pBuf==0 ){ fclose(in); return 0; }
nRead = fread(pBuf, nIn, 1, in);
fclose(in);
if( nRead!=1 ){
@@ -11076,6 +11225,11 @@ int deduceDatabaseType(const char *zName, int dfltZip){
return SHELL_OPEN_NORMAL;
}
}
+ n = fread(zBuf, 16, 1, f);
+ if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){
+ fclose(f);
+ return SHELL_OPEN_NORMAL;
+ }
fseek(f, -25, SEEK_END);
n = fread(zBuf, 25, 1, f);
if( n==1 && memcmp(zBuf, "Start-Of-SQLite3-", 17)==0 ){
@@ -11127,6 +11281,10 @@ static void open_db(ShellState *p, int openFlags){
SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, "apndvfs");
break;
}
+ case SHELL_OPEN_DESERIALIZE: {
+ sqlite3_open(0, &p->db);
+ break;
+ }
case SHELL_OPEN_ZIPFILE: {
sqlite3_open(":memory:", &p->db);
break;
@@ -11176,6 +11334,18 @@ static void open_db(ShellState *p, int openFlags){
sqlite3_exec(p->db, zSql, 0, 0, 0);
sqlite3_free(zSql);
}
+#ifdef SQLITE_ENABLE_DESERIALIZE
+ else if( p->openMode==SHELL_OPEN_DESERIALIZE ){
+ int nData = 0;
+ unsigned char *aData = (unsigned char*)readFile(p->zDbFilename, &nData);
+ int rc = sqlite3_deserialize(p->db, "main", aData, nData, nData,
+ SQLITE_DESERIALIZE_RESIZEABLE |
+ SQLITE_DESERIALIZE_FREEONCLOSE);
+ if( rc ){
+ utf8_printf(stderr, "Error: sqlite3_deserialize() returns %d\n", rc);
+ }
+ }
+#endif
}
}
@@ -12380,6 +12550,7 @@ static void shellPreparePrintf(
char *z;
va_start(ap, zFmt);
z = sqlite3_vmprintf(zFmt, ap);
+ va_end(ap);
if( z==0 ){
*pRc = SQLITE_NOMEM;
}else{
@@ -12442,32 +12613,7 @@ struct ArCommand {
** Print a usage message for the .ar command to stderr and return SQLITE_ERROR.
*/
static int arUsage(FILE *f){
- raw_printf(f,
-"\n"
-"Usage: .ar [OPTION...] [FILE...]\n"
-"The .ar command manages sqlar archives.\n"
-"\n"
-"Examples:\n"
-" .ar -cf archive.sar foo bar # Create archive.sar from files foo and bar\n"
-" .ar -tf archive.sar # List members of archive.sar\n"
-" .ar -xvf archive.sar # Verbosely extract files from archive.sar\n"
-"\n"
-"Each command line must feature exactly one command option:\n"
-" -c, --create Create a new archive\n"
-" -u, --update Update or add files to an existing archive\n"
-" -t, --list List contents of archive\n"
-" -x, --extract Extract files from archive\n"
-"\n"
-"And zero or more optional options:\n"
-" -v, --verbose Print each filename as it is processed\n"
-" -f FILE, --file FILE Operate on archive FILE (default is current db)\n"
-" -a FILE, --append FILE Operate on FILE opened using the apndvfs VFS\n"
-" -C DIR, --directory DIR Change to directory DIR to read/extract files\n"
-" -n, --dryrun Show the SQL that would have occurred\n"
-"\n"
-"See also: http://sqlite.org/cli.html#sqlar_archive_support\n"
-"\n"
-);
+ showHelp(f,"archive");
return SQLITE_ERROR;
}
@@ -12574,6 +12720,7 @@ static int arParseCommand(
struct ArSwitch *pEnd = &aSwitch[nSwitch];
if( nArg<=1 ){
+ utf8_printf(stderr, "Wrong number of arguments. Usage:\n");
return arUsage(stderr);
}else{
char *z = azArg[1];
@@ -13345,7 +13492,10 @@ static int do_meta_command(char *zLine, ShellState *p){
}else
if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){
- static const struct DbConfigChoices {const char *zName; int op;} aDbConfig[] = {
+ static const struct DbConfigChoices {
+ const char *zName;
+ int op;
+ } aDbConfig[] = {
{ "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY },
{ "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER },
{ "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
@@ -13354,6 +13504,7 @@ static int do_meta_command(char *zLine, ShellState *p){
{ "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG },
{ "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP },
{ "reset_database", SQLITE_DBCONFIG_RESET_DATABASE },
+ { "defensive", SQLITE_DBCONFIG_DEFENSIVE },
};
int ii, v;
open_db(p, 0);
@@ -13592,7 +13743,14 @@ static int do_meta_command(char *zLine, ShellState *p){
}else
if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
- utf8_printf(p->out, "%s", zHelp);
+ if( nArg>=2 ){
+ n = showHelp(p->out, azArg[1]);
+ if( n==0 ){
+ utf8_printf(p->out, "Nothing matches '%s'\n", azArg[1]);
+ }
+ }else{
+ showHelp(p->out, 0);
+ }
}else
if( c=='i' && strncmp(azArg[0], "import", n)==0 ){
@@ -14069,6 +14227,10 @@ static int do_meta_command(char *zLine, ShellState *p){
p->openMode = SHELL_OPEN_APPENDVFS;
}else if( optionMatch(z, "readonly") ){
p->openMode = SHELL_OPEN_READONLY;
+#ifdef SQLITE_ENABLE_DESERIALIZE
+ }else if( optionMatch(z, "deserialize") ){
+ p->openMode = SHELL_OPEN_DESERIALIZE;
+#endif
}else if( z[0]=='-' ){
utf8_printf(stderr, "unknown option: %s\n", z);
rc = 1;
@@ -14596,7 +14758,7 @@ static int do_meta_command(char *zLine, ShellState *p){
}else
/* If no command name matches, show a syntax error */
session_syntax_error:
- session_help(p);
+ showHelp(p->out, "session");
}else
#endif
@@ -15063,6 +15225,7 @@ static int do_meta_command(char *zLine, ShellState *p){
{ "byteorder", SQLITE_TESTCTRL_BYTEORDER, "" },
/*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, "" }, */
{ "imposter", SQLITE_TESTCTRL_IMPOSTER, "SCHEMA ON/OFF ROOTPAGE"},
+ { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, "BOOLEAN" },
{ "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN" },
{ "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN" },
{ "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK" },
@@ -15157,6 +15320,7 @@ static int do_meta_command(char *zLine, ShellState *p){
/* sqlite3_test_control(int, int) */
case SQLITE_TESTCTRL_ASSERT:
case SQLITE_TESTCTRL_ALWAYS:
+ case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS:
if( nArg==3 ){
int opt = booleanValue(azArg[2]);
rc2 = sqlite3_test_control(testctrl, opt);
@@ -15451,7 +15615,7 @@ static int line_is_command_terminator(const char *zLine){
** user-friendly, but it does seem to work.
*/
#ifdef SQLITE_OMIT_COMPLETE
-int sqlite3_complete(const char *zSql){ return 1; }
+#define sqlite3_complete(x) 1
#endif
/*
@@ -16047,6 +16211,10 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
#endif
}else if( strcmp(z,"-append")==0 ){
data.openMode = SHELL_OPEN_APPENDVFS;
+#ifdef SQLITE_ENABLE_DESERIALIZE
+ }else if( strcmp(z,"-deserialize")==0 ){
+ data.openMode = SHELL_OPEN_DESERIALIZE;
+#endif
}else if( strcmp(z,"-readonly")==0 ){
data.openMode = SHELL_OPEN_READONLY;
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
@@ -16142,6 +16310,10 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
#endif
}else if( strcmp(z,"-append")==0 ){
data.openMode = SHELL_OPEN_APPENDVFS;
+#ifdef SQLITE_ENABLE_DESERIALIZE
+ }else if( strcmp(z,"-deserialize")==0 ){
+ data.openMode = SHELL_OPEN_DESERIALIZE;
+#endif
}else if( strcmp(z,"-readonly")==0 ){
data.openMode = SHELL_OPEN_READONLY;
}else if( strcmp(z,"-ascii")==0 ){
@@ -16286,7 +16458,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
*/
if( stdin_is_interactive ){
char *zHome;
- char *zHistory = 0;
+ char *zHistory;
int nHistory;
printf(
"SQLite version %s %.19s\n" /*extra-version-info*/
@@ -16299,8 +16471,10 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
printf(".\nUse \".open FILENAME\" to reopen on a "
"persistent database.\n");
}
- zHome = find_home_dir(0);
- if( zHome ){
+ zHistory = getenv("SQLITE_HISTORY");
+ if( zHistory ){
+ zHistory = strdup(zHistory);
+ }else if( (zHome = find_home_dir(0))!=0 ){
nHistory = strlen30(zHome) + 20;
if( (zHistory = malloc(nHistory))!=0 ){
sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome);
diff --git a/chromium/third_party/sqlite/amalgamation/sqlite3.c b/chromium/third_party/sqlite/amalgamation/sqlite3.c
index 554c4708fe5..9f03a9c121b 100644
--- a/chromium/third_party/sqlite/amalgamation/sqlite3.c
+++ b/chromium/third_party/sqlite/amalgamation/sqlite3.c
@@ -1,6 +1,6 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-** version 3.25.3. By combining all the individual C code files into this
+** version 3.26.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
@@ -260,6 +260,9 @@ static const char * const sqlite3azCompileOpt[] = {
#if SQLITE_ENABLE_FTS5
"ENABLE_FTS5",
#endif
+#if SQLITE_ENABLE_GEOPOLY
+ "ENABLE_GEOPOLY",
+#endif
#if SQLITE_ENABLE_HIDDEN_COLUMNS
"ENABLE_HIDDEN_COLUMNS",
#endif
@@ -290,6 +293,9 @@ static const char * const sqlite3azCompileOpt[] = {
#if SQLITE_ENABLE_MULTIPLEX
"ENABLE_MULTIPLEX",
#endif
+#if SQLITE_ENABLE_NORMALIZE
+ "ENABLE_NORMALIZE",
+#endif
#if SQLITE_ENABLE_NULL_TRIM
"ENABLE_NULL_TRIM",
#endif
@@ -1156,9 +1162,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.25.3"
-#define SQLITE_VERSION_NUMBER 3025003
-#define SQLITE_SOURCE_ID "2018-11-05 20:37:38 89e099fbe5e13c33e683bef07361231ca525b88f7907be7092058007b750alt1"
+#define SQLITE_VERSION "3.26.0"
+#define SQLITE_VERSION_NUMBER 3026000
+#define SQLITE_SOURCE_ID "2018-12-01 12:34:55 bf8c1b2b7a5960c282e543b9c293686dccff272512d08865f4600fb58238alt1"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -3050,6 +3056,7 @@ struct sqlite3_mem_methods {
** is invoked.
**
** <dl>
+** [[SQLITE_DBCONFIG_LOOKASIDE]]
** <dt>SQLITE_DBCONFIG_LOOKASIDE</dt>
** <dd> ^This option takes three additional arguments that determine the
** [lookaside memory allocator] configuration for the [database connection].
@@ -3072,6 +3079,7 @@ struct sqlite3_mem_methods {
** memory is in use leaves the configuration unchanged and returns
** [SQLITE_BUSY].)^</dd>
**
+** [[SQLITE_DBCONFIG_ENABLE_FKEY]]
** <dt>SQLITE_DBCONFIG_ENABLE_FKEY</dt>
** <dd> ^This option is used to enable or disable the enforcement of
** [foreign key constraints]. There should be two additional arguments.
@@ -3082,6 +3090,7 @@ struct sqlite3_mem_methods {
** following this call. The second parameter may be a NULL pointer, in
** which case the FK enforcement setting is not reported back. </dd>
**
+** [[SQLITE_DBCONFIG_ENABLE_TRIGGER]]
** <dt>SQLITE_DBCONFIG_ENABLE_TRIGGER</dt>
** <dd> ^This option is used to enable or disable [CREATE TRIGGER | triggers].
** There should be two additional arguments.
@@ -3092,6 +3101,7 @@ struct sqlite3_mem_methods {
** following this call. The second parameter may be a NULL pointer, in
** which case the trigger setting is not reported back. </dd>
**
+** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]]
** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt>
** <dd> ^This option is used to enable or disable the two-argument
** version of the [fts3_tokenizer()] function which is part of the
@@ -3105,6 +3115,7 @@ struct sqlite3_mem_methods {
** following this call. The second parameter may be a NULL pointer, in
** which case the new setting is not reported back. </dd>
**
+** [[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION]]
** <dt>SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION</dt>
** <dd> ^This option is used to enable or disable the [sqlite3_load_extension()]
** interface independently of the [load_extension()] SQL function.
@@ -3122,7 +3133,7 @@ struct sqlite3_mem_methods {
** be a NULL pointer, in which case the new setting is not reported back.
** </dd>
**
-** <dt>SQLITE_DBCONFIG_MAINDBNAME</dt>
+** [[SQLITE_DBCONFIG_MAINDBNAME]] <dt>SQLITE_DBCONFIG_MAINDBNAME</dt>
** <dd> ^This option is used to change the name of the "main" database
** schema. ^The sole argument is a pointer to a constant UTF8 string
** which will become the new schema name in place of "main". ^SQLite
@@ -3131,6 +3142,7 @@ struct sqlite3_mem_methods {
** until after the database connection closes.
** </dd>
**
+** [[SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE]]
** <dt>SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE</dt>
** <dd> Usually, when a database in wal mode is closed or detached from a
** database handle, SQLite checks if this will mean that there are now no
@@ -3144,7 +3156,7 @@ struct sqlite3_mem_methods {
** have been disabled - 0 if they are not disabled, 1 if they are.
** </dd>
**
-** <dt>SQLITE_DBCONFIG_ENABLE_QPSG</dt>
+** [[SQLITE_DBCONFIG_ENABLE_QPSG]] <dt>SQLITE_DBCONFIG_ENABLE_QPSG</dt>
** <dd>^(The SQLITE_DBCONFIG_ENABLE_QPSG option activates or deactivates
** the [query planner stability guarantee] (QPSG). When the QPSG is active,
** a single SQL query statement will always use the same algorithm regardless
@@ -3160,7 +3172,7 @@ struct sqlite3_mem_methods {
** following this call.
** </dd>
**
-** <dt>SQLITE_DBCONFIG_TRIGGER_EQP</dt>
+** [[SQLITE_DBCONFIG_TRIGGER_EQP]] <dt>SQLITE_DBCONFIG_TRIGGER_EQP</dt>
** <dd> By default, the output of EXPLAIN QUERY PLAN commands does not
** include output for any operations performed by trigger programs. This
** option is used to set or clear (the default) a flag that governs this
@@ -3172,7 +3184,7 @@ struct sqlite3_mem_methods {
** it is not disabled, 1 if it is.
** </dd>
**
-** <dt>SQLITE_DBCONFIG_RESET_DATABASE</dt>
+** [[SQLITE_DBCONFIG_RESET_DATABASE]] <dt>SQLITE_DBCONFIG_RESET_DATABASE</dt>
** <dd> Set the SQLITE_DBCONFIG_RESET_DATABASE flag and then run
** [VACUUM] in order to reset a database back to an empty database
** with no schema and no content. The following process works even for
@@ -3191,6 +3203,18 @@ struct sqlite3_mem_methods {
** Because resetting a database is destructive and irreversible, the
** process requires the use of this obscure API and multiple steps to help
** ensure that it does not happen by accident.
+**
+** [[SQLITE_DBCONFIG_DEFENSIVE]] <dt>SQLITE_DBCONFIG_DEFENSIVE</dt>
+** <dd>The SQLITE_DBCONFIG_DEFENSIVE option activates or deactivates the
+** "defensive" flag for a database connection. When the defensive
+** flag is enabled, language features that allow ordinary SQL to
+** deliberately corrupt the database file are disabled. The disabled
+** features include but are not limited to the following:
+** <ul>
+** <li> The [PRAGMA writable_schema=ON] statement.
+** <li> Writes to the [sqlite_dbpage] virtual table.
+** <li> Direct writes to [shadow tables].
+** </ul>
** </dd>
** </dl>
*/
@@ -3204,7 +3228,8 @@ struct sqlite3_mem_methods {
#define SQLITE_DBCONFIG_ENABLE_QPSG 1007 /* int int* */
#define SQLITE_DBCONFIG_TRIGGER_EQP 1008 /* int int* */
#define SQLITE_DBCONFIG_RESET_DATABASE 1009 /* int int* */
-#define SQLITE_DBCONFIG_MAX 1009 /* Largest DBCONFIG */
+#define SQLITE_DBCONFIG_DEFENSIVE 1010 /* int int* */
+#define SQLITE_DBCONFIG_MAX 1010 /* Largest DBCONFIG */
/*
** CAPI3REF: Enable Or Disable Extended Result Codes
@@ -4642,9 +4667,19 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** on this hint by avoiding the use of [lookaside memory] so as not to
** deplete the limited store of lookaside memory. Future versions of
** SQLite may act on this hint differently.
+**
+** [[SQLITE_PREPARE_NORMALIZE]] ^(<dt>SQLITE_PREPARE_NORMALIZE</dt>
+** <dd>The SQLITE_PREPARE_NORMALIZE flag indicates that a normalized
+** representation of the SQL statement should be calculated and then
+** associated with the prepared statement, which can be obtained via
+** the [sqlite3_normalized_sql()] interface.)^ The semantics used to
+** normalize a SQL statement are unspecified and subject to change.
+** At a minimum, literal values will be replaced with suitable
+** placeholders.
** </dl>
*/
#define SQLITE_PREPARE_PERSISTENT 0x01
+#define SQLITE_PREPARE_NORMALIZE 0x02
/*
** CAPI3REF: Compiling An SQL Statement
@@ -4802,6 +4837,11 @@ SQLITE_API int sqlite3_prepare16_v3(
** ^The sqlite3_expanded_sql(P) interface returns a pointer to a UTF-8
** string containing the SQL text of prepared statement P with
** [bound parameters] expanded.
+** ^The sqlite3_normalized_sql(P) interface returns a pointer to a UTF-8
+** string containing the normalized SQL text of prepared statement P. The
+** semantics used to normalize a SQL statement are unspecified and subject
+** to change. At a minimum, literal values will be replaced with suitable
+** placeholders.
**
** ^(For example, if a prepared statement is created using the SQL
** text "SELECT $abc,:xyz" and if parameter $abc is bound to integer 2345
@@ -4817,14 +4857,16 @@ SQLITE_API int sqlite3_prepare16_v3(
** bound parameter expansions. ^The [SQLITE_OMIT_TRACE] compile-time
** option causes sqlite3_expanded_sql() to always return NULL.
**
-** ^The string returned by sqlite3_sql(P) is managed by SQLite and is
-** automatically freed when the prepared statement is finalized.
+** ^The strings returned by sqlite3_sql(P) and sqlite3_normalized_sql(P)
+** are managed by SQLite and are automatically freed when the prepared
+** statement is finalized.
** ^The string returned by sqlite3_expanded_sql(P), on the other hand,
** is obtained from [sqlite3_malloc()] and must be free by the application
** by passing it to [sqlite3_free()].
*/
SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt);
SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt);
+SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt);
/*
** CAPI3REF: Determine If An SQL Statement Writes The Database
@@ -7314,6 +7356,9 @@ struct sqlite3_module {
int (*xSavepoint)(sqlite3_vtab *pVTab, int);
int (*xRelease)(sqlite3_vtab *pVTab, int);
int (*xRollbackTo)(sqlite3_vtab *pVTab, int);
+ /* The methods above are in versions 1 and 2 of the sqlite_module object.
+ ** Those below are for version 3 and greater. */
+ int (*xShadowName)(const char*);
};
/*
@@ -8236,6 +8281,7 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_OPTIMIZATIONS 15
#define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */
#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */
+#define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 17
#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
#define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */
#define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19
@@ -9671,6 +9717,7 @@ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
** can use to customize and optimize their behavior.
**
** <dl>
+** [[SQLITE_VTAB_CONSTRAINT_SUPPORT]]
** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT
** <dd>Calls of the form
** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported,
@@ -10440,7 +10487,7 @@ struct sqlite3_rtree_query_info {
sqlite3_int64 iRowid; /* Rowid for current entry */
sqlite3_rtree_dbl rParentScore; /* Score of parent node */
int eParentWithin; /* Visibility of parent node */
- int eWithin; /* OUT: Visiblity */
+ int eWithin; /* OUT: Visibility */
sqlite3_rtree_dbl rScore; /* OUT: Write the score here */
/* The following fields are only available in 3.8.11 and later */
sqlite3_value **apSqlParam; /* Original SQL values of parameters */
@@ -10936,12 +10983,38 @@ SQLITE_API int sqlite3session_isempty(sqlite3_session *pSession);
** consecutively. There is no chance that the iterator will visit a change
** the applies to table X, then one for table Y, and then later on visit
** another change for table X.
+**
+** The behavior of sqlite3changeset_start_v2() and its streaming equivalent
+** may be modified by passing a combination of
+** [SQLITE_CHANGESETSTART_INVERT | supported flags] as the 4th parameter.
+**
+** Note that the sqlite3changeset_start_v2() API is still <b>experimental</b>
+** and therefore subject to change.
*/
SQLITE_API int sqlite3changeset_start(
sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */
int nChangeset, /* Size of changeset blob in bytes */
void *pChangeset /* Pointer to blob containing changeset */
);
+SQLITE_API int sqlite3changeset_start_v2(
+ sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */
+ int nChangeset, /* Size of changeset blob in bytes */
+ void *pChangeset, /* Pointer to blob containing changeset */
+ int flags /* SESSION_CHANGESETSTART_* flags */
+);
+
+/*
+** CAPI3REF: Flags for sqlite3changeset_start_v2
+**
+** The following flags may passed via the 4th parameter to
+** [sqlite3changeset_start_v2] and [sqlite3changeset_start_v2_strm]:
+**
+** <dt>SQLITE_CHANGESETAPPLY_INVERT <dd>
+** Invert the changeset while iterating through it. This is equivalent to
+** inverting a changeset using sqlite3changeset_invert() before applying it.
+** It is an error to specify this flag with a patchset.
+*/
+#define SQLITE_CHANGESETSTART_INVERT 0x0002
/*
@@ -11596,7 +11669,7 @@ SQLITE_API int sqlite3changeset_apply_v2(
),
void *pCtx, /* First argument passed to xConflict */
void **ppRebase, int *pnRebase, /* OUT: Rebase data */
- int flags /* Combination of SESSION_APPLY_* flags */
+ int flags /* SESSION_CHANGESETAPPLY_* flags */
);
/*
@@ -11614,8 +11687,14 @@ SQLITE_API int sqlite3changeset_apply_v2(
** causes the sessions module to omit this savepoint. In this case, if the
** caller has an open transaction or savepoint when apply_v2() is called,
** it may revert the partially applied changeset by rolling it back.
+**
+** <dt>SQLITE_CHANGESETAPPLY_INVERT <dd>
+** Invert the changeset before applying it. This is equivalent to inverting
+** a changeset using sqlite3changeset_invert() before applying it. It is
+** an error to specify this flag with a patchset.
*/
#define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001
+#define SQLITE_CHANGESETAPPLY_INVERT 0x0002
/*
** CAPI3REF: Constants Passed To The Conflict Handler
@@ -12009,6 +12088,12 @@ SQLITE_API int sqlite3changeset_start_strm(
int (*xInput)(void *pIn, void *pData, int *pnData),
void *pIn
);
+SQLITE_API int sqlite3changeset_start_v2_strm(
+ sqlite3_changeset_iter **pp,
+ int (*xInput)(void *pIn, void *pData, int *pnData),
+ void *pIn,
+ int flags
+);
SQLITE_API int sqlite3session_changeset_strm(
sqlite3_session *pSession,
int (*xOutput)(void *pOut, const void *pData, int nData),
@@ -12035,6 +12120,45 @@ SQLITE_API int sqlite3rebaser_rebase_strm(
void *pOut
);
+/*
+** CAPI3REF: Configure global parameters
+**
+** The sqlite3session_config() interface is used to make global configuration
+** changes to the sessions module in order to tune it to the specific needs
+** of the application.
+**
+** The sqlite3session_config() interface is not threadsafe. If it is invoked
+** while any other thread is inside any other sessions method then the
+** results are undefined. Furthermore, if it is invoked after any sessions
+** related objects have been created, the results are also undefined.
+**
+** The first argument to the sqlite3session_config() function must be one
+** of the SQLITE_SESSION_CONFIG_XXX constants defined below. The
+** interpretation of the (void*) value passed as the second parameter and
+** the effect of calling this function depends on the value of the first
+** parameter.
+**
+** <dl>
+** <dt>SQLITE_SESSION_CONFIG_STRMSIZE<dd>
+** By default, the sessions module streaming interfaces attempt to input
+** and output data in approximately 1 KiB chunks. This operand may be used
+** to set and query the value of this configuration setting. The pointer
+** passed as the second argument must point to a value of type (int).
+** If this value is greater than 0, it is used as the new streaming data
+** chunk size for both input and output. Before returning, the (int) value
+** pointed to by pArg is set to the final value of the streaming interface
+** chunk size.
+** </dl>
+**
+** This function returns SQLITE_OK if successful, or an SQLite error code
+** otherwise.
+*/
+SQLITE_API int sqlite3session_config(int op, void *pArg);
+
+/*
+** CAPI3REF: Values for sqlite3session_config().
+*/
+#define SQLITE_SESSION_CONFIG_STRMSIZE 1
/*
** Make sure we can call this stuff from C++.
@@ -15293,9 +15417,6 @@ SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager);
SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager);
SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3*);
-# ifdef SQLITE_DIRECT_OVERFLOW_READ
-SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager, Pgno);
-# endif
# ifdef SQLITE_ENABLE_SNAPSHOT
SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot);
SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot);
@@ -15303,8 +15424,10 @@ SQLITE_PRIVATE int sqlite3PagerSnapshotRecover(Pager *pPager);
SQLITE_PRIVATE int sqlite3PagerSnapshotCheck(Pager *pPager, sqlite3_snapshot *pSnapshot);
SQLITE_PRIVATE void sqlite3PagerSnapshotUnlock(Pager *pPager);
# endif
-#else
-# define sqlite3PagerUseWal(x,y) 0
+#endif
+
+#ifdef SQLITE_DIRECT_OVERFLOW_READ
+SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno);
#endif
#ifdef SQLITE_ENABLE_ZIPVFS
@@ -15549,6 +15672,10 @@ SQLITE_PRIVATE int sqlite3HeaderSizePcache1(void);
/* Number of dirty pages as a percentage of the configured cache size */
SQLITE_PRIVATE int sqlite3PCachePercentDirty(PCache*);
+#ifdef SQLITE_DIRECT_OVERFLOW_READ
+SQLITE_PRIVATE int sqlite3PCacheIsDirty(PCache *pCache);
+#endif
+
#endif /* _PCACHE_H_ */
/************** End of pcache.h **********************************************/
@@ -16054,12 +16181,14 @@ struct LookasideSlot {
** functions use a regular table table from hash.h.)
**
** Hash each FuncDef structure into one of the FuncDefHash.a[] slots.
-** Collisions are on the FuncDef.u.pHash chain.
+** Collisions are on the FuncDef.u.pHash chain. Use the SQLITE_FUNC_HASH()
+** macro to compute a hash on the function name.
*/
#define SQLITE_FUNC_HASH_SZ 23
struct FuncDefHash {
FuncDef *a[SQLITE_FUNC_HASH_SZ]; /* Hash table for functions */
};
+#define SQLITE_FUNC_HASH(C,L) (((C)+(L))%SQLITE_FUNC_HASH_SZ)
#ifdef SQLITE_USER_AUTHENTICATION
/*
@@ -16120,7 +16249,7 @@ struct sqlite3 {
Db *aDb; /* All backends */
int nDb; /* Number of backends currently in use */
u32 mDbFlags; /* flags recording internal state */
- u32 flags; /* flags settable by pragmas. See below */
+ u64 flags; /* flags settable by pragmas. See below */
i64 lastRowid; /* ROWID of most recent insert (see above) */
i64 szMmap; /* Default mmap_size setting */
u32 nSchemaLock; /* Do not reset the schema when non-zero */
@@ -16286,14 +16415,17 @@ struct sqlite3 {
#define SQLITE_TriggerEQP 0x01000000 /* Show trigger EXPLAIN QUERY PLAN */
#define SQLITE_ResetDatabase 0x02000000 /* Reset the database */
#define SQLITE_LegacyAlter 0x04000000 /* Legacy ALTER TABLE behaviour */
+#define SQLITE_NoSchemaError 0x08000000 /* Do not report schema parse errors*/
+#define SQLITE_Defensive 0x10000000 /* Input SQL is likely hostile */
/* Flags used only if debugging */
+#define HI(X) ((u64)(X)<<32)
#ifdef SQLITE_DEBUG
-#define SQLITE_SqlTrace 0x08000000 /* Debug print SQL as it executes */
-#define SQLITE_VdbeListing 0x10000000 /* Debug listings of VDBE programs */
-#define SQLITE_VdbeTrace 0x20000000 /* True to trace VDBE execution */
-#define SQLITE_VdbeAddopTrace 0x40000000 /* Trace sqlite3VdbeAddOp() calls */
-#define SQLITE_VdbeEQP 0x80000000 /* Debug EXPLAIN QUERY PLAN */
+#define SQLITE_SqlTrace HI(0x0001) /* Debug print SQL as it executes */
+#define SQLITE_VdbeListing HI(0x0002) /* Debug listings of VDBE progs */
+#define SQLITE_VdbeTrace HI(0x0004) /* True to trace VDBE execution */
+#define SQLITE_VdbeAddopTrace HI(0x0008) /* Trace sqlite3VdbeAddOp() calls */
+#define SQLITE_VdbeEQP HI(0x0010) /* Debug EXPLAIN QUERY PLAN */
#endif
/*
@@ -16427,8 +16559,9 @@ struct FuncDestructor {
** single query - might change over time */
#define SQLITE_FUNC_AFFINITY 0x4000 /* Built-in affinity() function */
#define SQLITE_FUNC_OFFSET 0x8000 /* Built-in sqlite_offset() function */
-#define SQLITE_FUNC_WINDOW 0x10000 /* Built-in window-only function */
-#define SQLITE_FUNC_WINDOW_SIZE 0x20000 /* Requires partition size as arg. */
+#define SQLITE_FUNC_WINDOW 0x00010000 /* Built-in window-only function */
+#define SQLITE_FUNC_WINDOW_SIZE 0x20000 /* Requires partition size as arg. */
+#define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */
/*
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
@@ -16504,10 +16637,13 @@ struct FuncDestructor {
#define AGGREGATE2(zName, nArg, arg, nc, xStep, xFinal, extraFlags) \
{nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|extraFlags, \
SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xFinal,0,#zName, {0}}
-
#define WAGGREGATE(zName, nArg, arg, nc, xStep, xFinal, xValue, xInverse, f) \
{nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|f, \
SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xValue,xInverse,#zName, {0}}
+#define INTERNAL_FUNCTION(zName, nArg, xFunc) \
+ {nArg, SQLITE_FUNC_INTERNAL|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \
+ 0, 0, xFunc, 0, 0, 0, #zName, {0} }
+
/*
** All current savepoints are stored in a linked list starting at
@@ -16692,6 +16828,9 @@ struct VTable {
struct Table {
char *zName; /* Name of the table or view */
Column *aCol; /* Information about each column */
+#ifdef SQLITE_ENABLE_NORMALIZE
+ Hash *pColHash; /* All columns indexed by name */
+#endif
Index *pIndex; /* List of SQL indexes on this table. */
Select *pSelect; /* NULL for tables. Points to definition if a view. */
FKey *pFKey; /* Linked list of all foreign keys in this table */
@@ -16742,6 +16881,7 @@ struct Table {
#define TF_StatsUsed 0x0100 /* Query planner decisions affected by
** Index.aiRowLogEst[] values */
#define TF_HasNotNull 0x0200 /* Contains NOT NULL constraints */
+#define TF_Shadow 0x0400 /* True for a shadow table */
/*
** Test to see whether or not a table is a virtual table. This is
@@ -17029,6 +17169,12 @@ struct IndexSample {
};
/*
+** Possible values to use within the flags argument to sqlite3GetToken().
+*/
+#define SQLITE_TOKEN_QUOTED 0x1 /* Token is a quoted identifier. */
+#define SQLITE_TOKEN_KEYWORD 0x2 /* Token is a keyword. */
+
+/*
** Each token coming out of the lexer is an instance of
** this structure. Tokens are also used as part of an expression.
**
@@ -17209,11 +17355,11 @@ struct Expr {
** TK_COLUMN: the value of p5 for OP_Column
** TK_AGG_FUNCTION: nesting depth */
AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
- Table *pTab; /* Table for TK_COLUMN expressions. Can be NULL
- ** for a column of an index on an expression */
-#ifndef SQLITE_OMIT_WINDOWFUNC
- Window *pWin; /* Window definition for window functions */
-#endif
+ union {
+ Table *pTab; /* TK_COLUMN: Table containing column. Can be NULL
+ ** for a column of an index on an expression */
+ Window *pWin; /* TK_FUNCTION: Window definition for the func */
+ } y;
};
/*
@@ -17243,6 +17389,7 @@ struct Expr {
#define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */
#define EP_Alias 0x400000 /* Is an alias for a result set column */
#define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */
+#define EP_WinFunc 0x1000000 /* TK_FUNCTION with Expr.y.pWin set */
/*
** The EP_Propagate mask is a set of properties that automatically propagate
@@ -18147,6 +18294,7 @@ struct Sqlite3Config {
int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */
#endif
int bLocaltimeFault; /* True to fail localtime() calls */
+ int bInternalFunctions; /* Internal SQL functions are visible */
int iOnceResetThreshold; /* When to reset OP_Once counters */
u32 szSorterRef; /* Min size in bytes to use sorter-refs */
};
@@ -18400,6 +18548,7 @@ SQLITE_PRIVATE int sqlite3IsIdChar(u8);
*/
SQLITE_PRIVATE int sqlite3StrICmp(const char*,const char*);
SQLITE_PRIVATE int sqlite3Strlen30(const char*);
+#define sqlite3Strlen30NN(C) (strlen(C)&0x3fffffff)
SQLITE_PRIVATE char *sqlite3ColumnType(Column*,char*);
#define sqlite3StrNICmp sqlite3_strnicmp
@@ -18516,6 +18665,7 @@ SQLITE_PRIVATE void *sqlite3TestTextToPtr(const char*);
SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView*, const Expr*, u8);
SQLITE_PRIVATE void sqlite3TreeViewBareExprList(TreeView*, const ExprList*, const char*);
SQLITE_PRIVATE void sqlite3TreeViewExprList(TreeView*, const ExprList*, u8, const char*);
+SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView*, const SrcList*);
SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView*, const Select*, u8);
SQLITE_PRIVATE void sqlite3TreeViewWith(TreeView*, const With*, u8);
#ifndef SQLITE_OMIT_WINDOWFUNC
@@ -18748,11 +18898,15 @@ SQLITE_PRIVATE int sqlite3ExprIsInteger(Expr*, int*);
SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*);
SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
SQLITE_PRIVATE int sqlite3IsRowid(const char*);
+#ifdef SQLITE_ENABLE_NORMALIZE
+SQLITE_PRIVATE int sqlite3IsRowidN(const char*, int);
+#endif
SQLITE_PRIVATE void sqlite3GenerateRowDelete(
Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8,int);
SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int);
SQLITE_PRIVATE int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int);
SQLITE_PRIVATE void sqlite3ResolvePartIdxLabel(Parse*,int);
+SQLITE_PRIVATE int sqlite3ExprReferencesUpdatedColumn(Expr*,int*,int);
SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int,
u8,u8,int,int*,int*,Upsert*);
#ifdef SQLITE_ENABLE_NULL_TRIM
@@ -18773,6 +18927,9 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int);
SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int);
SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3*,IdList*);
SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3*,Select*,int);
+#ifdef SQLITE_ENABLE_NORMALIZE
+SQLITE_PRIVATE FuncDef *sqlite3FunctionSearchN(int,const char*,int);
+#endif
SQLITE_PRIVATE void sqlite3InsertBuiltinFuncs(FuncDef*,int);
SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,u8,u8);
SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void);
@@ -18930,6 +19087,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Toke
SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*);
SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *);
+SQLITE_PRIVATE int sqlite3WritableSchema(sqlite3*);
SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *, const char *);
SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, int);
SQLITE_PRIVATE int sqlite3AddInt64(i64*,i64);
@@ -18976,6 +19134,9 @@ SQLITE_PRIVATE void sqlite3AlterFunctions(void);
SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
SQLITE_PRIVATE void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*);
SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *);
+#ifdef SQLITE_ENABLE_NORMALIZE
+SQLITE_PRIVATE int sqlite3GetTokenNormalized(const unsigned char *, int *, int *);
+#endif
SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...);
SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*, int);
SQLITE_PRIVATE int sqlite3CodeSubselect(Parse*, Expr *, int, int);
@@ -19133,6 +19294,9 @@ SQLITE_PRIVATE sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*);
SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe*, const char*, int);
SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
SQLITE_PRIVATE void sqlite3ParserReset(Parse*);
+#ifdef SQLITE_ENABLE_NORMALIZE
+SQLITE_PRIVATE void sqlite3Normalize(Vdbe*, const char*, int, u8);
+#endif
SQLITE_PRIVATE int sqlite3Reprepare(Vdbe*);
SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
@@ -19594,6 +19758,7 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
0, /* xTestCallback */
#endif
0, /* bLocaltimeFault */
+ 0, /* bInternalFunctions */
0x7ffffffe, /* iOnceResetThreshold */
SQLITE_DEFAULT_SORTERREF_SIZE /* szSorterRef */
};
@@ -20085,6 +20250,9 @@ struct Vdbe {
yDbMask lockMask; /* Subset of btreeMask that requires a lock */
u32 aCounter[7]; /* Counters used by sqlite3_stmt_status() */
char *zSql; /* Text of the SQL statement that generated this */
+#ifdef SQLITE_ENABLE_NORMALIZE
+ char *zNormSql; /* Normalization of the associated SQL statement */
+#endif
void *pFree; /* Free this when deleting the vdbe */
VdbeFrame *pFrame; /* Parent frame */
VdbeFrame *pDelFrame; /* List of frame objects to free on VM reset */
@@ -20147,7 +20315,9 @@ int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(sqlite3*,VdbeCursor*,UnpackedRecord*,int*);
SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3*, BtCursor*, i64*);
SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*);
+#ifndef SQLITE_OMIT_EXPLAIN
SQLITE_PRIVATE int sqlite3VdbeList(Vdbe*);
+#endif
SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe*);
SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *, int);
SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem*);
@@ -20186,7 +20356,9 @@ SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
#ifndef SQLITE_OMIT_WINDOWFUNC
SQLITE_PRIVATE int sqlite3VdbeMemAggValue(Mem*, Mem*, FuncDef*);
#endif
+#ifndef SQLITE_OMIT_EXPLAIN
SQLITE_PRIVATE const char *sqlite3OpcodeName(int);
+#endif
SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int n);
SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int);
@@ -28313,6 +28485,42 @@ SQLITE_PRIVATE void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 m
}
}
+/*
+** Generate a human-readable description of a SrcList object.
+*/
+SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc){
+ int i;
+ for(i=0; i<pSrc->nSrc; i++){
+ const struct SrcList_item *pItem = &pSrc->a[i];
+ StrAccum x;
+ char zLine[100];
+ sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
+ sqlite3_str_appendf(&x, "{%d,*}", pItem->iCursor);
+ if( pItem->zDatabase ){
+ sqlite3_str_appendf(&x, " %s.%s", pItem->zDatabase, pItem->zName);
+ }else if( pItem->zName ){
+ sqlite3_str_appendf(&x, " %s", pItem->zName);
+ }
+ if( pItem->pTab ){
+ sqlite3_str_appendf(&x, " tabname=%Q", pItem->pTab->zName);
+ }
+ if( pItem->zAlias ){
+ sqlite3_str_appendf(&x, " (AS %s)", pItem->zAlias);
+ }
+ if( pItem->fg.jointype & JT_LEFT ){
+ sqlite3_str_appendf(&x, " LEFT-JOIN");
+ }
+ sqlite3StrAccumFinish(&x);
+ sqlite3TreeViewItem(pView, zLine, i<pSrc->nSrc-1);
+ if( pItem->pSelect ){
+ sqlite3TreeViewSelect(pView, pItem->pSelect, 0);
+ }
+ if( pItem->fg.isTabFunc ){
+ sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:");
+ }
+ sqlite3TreeViewPop(pView);
+ }
+}
/*
** Generate a human-readable description of a Select object.
@@ -28367,39 +28575,9 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m
}
#endif
if( p->pSrc && p->pSrc->nSrc ){
- int i;
pView = sqlite3TreeViewPush(pView, (n--)>0);
sqlite3TreeViewLine(pView, "FROM");
- for(i=0; i<p->pSrc->nSrc; i++){
- struct SrcList_item *pItem = &p->pSrc->a[i];
- StrAccum x;
- char zLine[100];
- sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
- sqlite3_str_appendf(&x, "{%d,*}", pItem->iCursor);
- if( pItem->zDatabase ){
- sqlite3_str_appendf(&x, " %s.%s", pItem->zDatabase, pItem->zName);
- }else if( pItem->zName ){
- sqlite3_str_appendf(&x, " %s", pItem->zName);
- }
- if( pItem->pTab ){
- sqlite3_str_appendf(&x, " tabname=%Q", pItem->pTab->zName);
- }
- if( pItem->zAlias ){
- sqlite3_str_appendf(&x, " (AS %s)", pItem->zAlias);
- }
- if( pItem->fg.jointype & JT_LEFT ){
- sqlite3_str_appendf(&x, " LEFT-JOIN");
- }
- sqlite3StrAccumFinish(&x);
- sqlite3TreeViewItem(pView, zLine, i<p->pSrc->nSrc-1);
- if( pItem->pSelect ){
- sqlite3TreeViewSelect(pView, pItem->pSelect, 0);
- }
- if( pItem->fg.isTabFunc ){
- sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:");
- }
- sqlite3TreeViewPop(pView);
- }
+ sqlite3TreeViewSrcList(pView, p->pSrc);
sqlite3TreeViewPop(pView);
}
if( p->pWhere ){
@@ -28689,7 +28867,7 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
}else{
pFarg = pExpr->x.pList;
#ifndef SQLITE_OMIT_WINDOWFUNC
- pWin = pExpr->pWin;
+ pWin = pExpr->y.pWin;
#else
pWin = 0;
#endif
@@ -31517,6 +31695,20 @@ static unsigned int strHash(const char *z){
}
return h;
}
+#ifdef SQLITE_ENABLE_NORMALIZE
+static unsigned int strHashN(const char *z, int n){
+ unsigned int h = 0;
+ int i;
+ for(i=0; i<n; i++){
+ /* Knuth multiplicative hashing. (Sorting & Searching, p. 510).
+ ** 0x9e3779b1 is 2654435761 which is the closest prime number to
+ ** (2**32)*golden_ratio, where golden_ratio = (sqrt(5) - 1)/2. */
+ h += sqlite3UpperToLower[z[i]];
+ h *= 0x9e3779b1;
+ }
+ return h;
+}
+#endif /* SQLITE_ENABLE_NORMALIZE */
/* Link pNew element into the hash table pH. If pEntry!=0 then also
@@ -31628,6 +31820,40 @@ static HashElem *findElementWithHash(
}
return &nullElement;
}
+#ifdef SQLITE_ENABLE_NORMALIZE
+static HashElem *findElementWithHashN(
+ const Hash *pH, /* The pH to be searched */
+ const char *pKey, /* The key we are searching for */
+ int nKey, /* Number of key bytes to use */
+ unsigned int *pHash /* Write the hash value here */
+){
+ HashElem *elem; /* Used to loop thru the element list */
+ int count; /* Number of elements left to test */
+ unsigned int h; /* The computed hash */
+ static HashElem nullElement = { 0, 0, 0, 0 };
+
+ if( pH->ht ){ /*OPTIMIZATION-IF-TRUE*/
+ struct _ht *pEntry;
+ h = strHashN(pKey, nKey) % pH->htsize;
+ pEntry = &pH->ht[h];
+ elem = pEntry->chain;
+ count = pEntry->count;
+ }else{
+ h = 0;
+ elem = pH->first;
+ count = pH->count;
+ }
+ if( pHash ) *pHash = h;
+ while( count-- ){
+ assert( elem!=0 );
+ if( sqlite3StrNICmp(elem->pKey,pKey,nKey)==0 ){
+ return elem;
+ }
+ elem = elem->next;
+ }
+ return &nullElement;
+}
+#endif /* SQLITE_ENABLE_NORMALIZE */
/* Remove a single entry from the hash table given a pointer to that
** element and a hash on the element's key.
@@ -31672,6 +31898,14 @@ SQLITE_PRIVATE void *sqlite3HashFind(const Hash *pH, const char *pKey){
assert( pKey!=0 );
return findElementWithHash(pH, pKey, 0)->data;
}
+#ifdef SQLITE_ENABLE_NORMALIZE
+SQLITE_PRIVATE void *sqlite3HashFindN(const Hash *pH, const char *pKey, int nKey){
+ assert( pH!=0 );
+ assert( pKey!=0 );
+ assert( nKey>=0 );
+ return findElementWithHashN(pH, pKey, nKey, 0)->data;
+}
+#endif /* SQLITE_ENABLE_NORMALIZE */
/* Insert an element into the hash table pH. The key is pKey
** and the data is "data".
@@ -32054,12 +32288,10 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
#define SQLITE_FSFLAGS_IS_MSDOS 0x1
/*
-** If we are to be thread-safe, include the pthreads header and define
-** the SQLITE_UNIX_THREADS macro.
+** If we are to be thread-safe, include the pthreads header.
*/
#if SQLITE_THREADSAFE
/* # include <pthread.h> */
-# define SQLITE_UNIX_THREADS 1
#endif
/*
@@ -33235,8 +33467,7 @@ struct unixFileId {
/*
** An instance of the following structure is allocated for each open
-** inode. Or, on LinuxThreads, there is one of these structures for
-** each inode opened by each thread.
+** inode.
**
** A single inode can have multiple file descriptors, so each unixFile
** structure contains a pointer to an instance of this object and this
@@ -33282,13 +33513,16 @@ struct unixInodeInfo {
/*
** A lists of all unixInodeInfo objects.
+**
+** Must hold unixBigLock in order to read or write this variable.
*/
static unixInodeInfo *inodeList = 0; /* All unixInodeInfo objects */
#ifdef SQLITE_DEBUG
/*
-** True if the inode mutex is held, or not. Used only within assert()
-** to help verify correct mutex usage.
+** True if the inode mutex (on the unixFile.pFileMutex field) is held, or not.
+** This routine is used only within assert() to help verify correct mutex
+** usage.
*/
int unixFileMutexHeld(unixFile *pFile){
assert( pFile->pInode );
@@ -33416,8 +33650,8 @@ static void closePendingFds(unixFile *pFile){
/*
** Release a unixInodeInfo structure previously allocated by findInodeInfo().
**
-** The mutex entered using the unixEnterMutex() function must be held
-** when this function is called.
+** The global mutex must be held when this routine is called, but the mutex
+** on the inode being deleted must NOT be held.
*/
static void releaseInodeInfo(unixFile *pFile){
unixInodeInfo *pInode = pFile->pInode;
@@ -33452,8 +33686,7 @@ static void releaseInodeInfo(unixFile *pFile){
** describes that file descriptor. Create a new one if necessary. The
** return value might be uninitialized if an error occurs.
**
-** The mutex entered using the unixEnterMutex() function must be held
-** when this function is called.
+** The global mutex must held when calling this routine.
**
** Return an appropriate error code.
*/
@@ -33514,6 +33747,7 @@ static int findInodeInfo(
#else
fileId.ino = (u64)statbuf.st_ino;
#endif
+ assert( unixMutexHeld() );
pInode = inodeList;
while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){
pInode = pInode->pNext;
@@ -33533,6 +33767,7 @@ static int findInodeInfo(
}
}
pInode->nRef = 1;
+ assert( unixMutexHeld() );
pInode->pNext = inodeList;
pInode->pPrev = 0;
if( inodeList ) inodeList->pPrev = pInode;
@@ -36336,18 +36571,18 @@ static int unixGetpagesize(void){
**
** The following fields are read-only after the object is created:
**
-** fid
+** hShm
** zFilename
**
-** Either unixShmNode.mutex must be held or unixShmNode.nRef==0 and
+** Either unixShmNode.pShmMutex must be held or unixShmNode.nRef==0 and
** unixMutexHeld() is true when reading or writing any other field
** in this structure.
*/
struct unixShmNode {
unixInodeInfo *pInode; /* unixInodeInfo that owns this SHM node */
- sqlite3_mutex *mutex; /* Mutex to access this object */
+ sqlite3_mutex *pShmMutex; /* Mutex to access this object */
char *zFilename; /* Name of the mmapped file */
- int h; /* Open file descriptor */
+ int hShm; /* Open file descriptor */
int szRegion; /* Size of shared-memory regions */
u16 nRegion; /* Size of array apRegion */
u8 isReadonly; /* True if read-only */
@@ -36369,16 +36604,16 @@ struct unixShmNode {
** The following fields are initialized when this object is created and
** are read-only thereafter:
**
-** unixShm.pFile
+** unixShm.pShmNode
** unixShm.id
**
-** All other fields are read/write. The unixShm.pFile->mutex must be held
-** while accessing any read/write fields.
+** All other fields are read/write. The unixShm.pShmNode->pShmMutex must
+** be held while accessing any read/write fields.
*/
struct unixShm {
unixShmNode *pShmNode; /* The underlying unixShmNode object */
unixShm *pNext; /* Next unixShm with the same unixShmNode */
- u8 hasMutex; /* True if holding the unixShmNode mutex */
+ u8 hasMutex; /* True if holding the unixShmNode->pShmMutex */
u8 id; /* Id of this connection within its unixShmNode */
u16 sharedMask; /* Mask of shared locks held */
u16 exclMask; /* Mask of exclusive locks held */
@@ -36408,7 +36643,8 @@ static int unixShmSystemLock(
/* Access to the unixShmNode object is serialized by the caller */
pShmNode = pFile->pInode->pShmNode;
- assert( pShmNode->nRef==0 || sqlite3_mutex_held(pShmNode->mutex) );
+ assert( pShmNode->nRef==0 || sqlite3_mutex_held(pShmNode->pShmMutex) );
+ assert( pShmNode->nRef>0 || unixMutexHeld() );
/* Shared locks never span more than one byte */
assert( n==1 || lockType!=F_RDLCK );
@@ -36416,13 +36652,13 @@ static int unixShmSystemLock(
/* Locks are within range */
assert( n>=1 && n<=SQLITE_SHM_NLOCK );
- if( pShmNode->h>=0 ){
+ if( pShmNode->hShm>=0 ){
/* Initialize the locking parameters */
f.l_type = lockType;
f.l_whence = SEEK_SET;
f.l_start = ofst;
f.l_len = n;
- rc = osSetPosixAdvisoryLock(pShmNode->h, &f, pFile);
+ rc = osSetPosixAdvisoryLock(pShmNode->hShm, &f, pFile);
rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
}
@@ -36494,18 +36730,18 @@ static void unixShmPurge(unixFile *pFd){
int nShmPerMap = unixShmRegionPerMap();
int i;
assert( p->pInode==pFd->pInode );
- sqlite3_mutex_free(p->mutex);
+ sqlite3_mutex_free(p->pShmMutex);
for(i=0; i<p->nRegion; i+=nShmPerMap){
- if( p->h>=0 ){
+ if( p->hShm>=0 ){
osMunmap(p->apRegion[i], p->szRegion);
}else{
sqlite3_free(p->apRegion[i]);
}
}
sqlite3_free(p->apRegion);
- if( p->h>=0 ){
- robust_close(pFd, p->h, __LINE__);
- p->h = -1;
+ if( p->hShm>=0 ){
+ robust_close(pFd, p->hShm, __LINE__);
+ p->hShm = -1;
}
p->pInode->pShmNode = 0;
sqlite3_free(p);
@@ -36547,7 +36783,7 @@ static int unixLockSharedMemory(unixFile *pDbFd, unixShmNode *pShmNode){
lock.l_start = UNIX_SHM_DMS;
lock.l_len = 1;
lock.l_type = F_WRLCK;
- if( osFcntl(pShmNode->h, F_GETLK, &lock)!=0 ) {
+ if( osFcntl(pShmNode->hShm, F_GETLK, &lock)!=0 ) {
rc = SQLITE_IOERR_LOCK;
}else if( lock.l_type==F_UNLCK ){
if( pShmNode->isReadonly ){
@@ -36555,7 +36791,12 @@ static int unixLockSharedMemory(unixFile *pDbFd, unixShmNode *pShmNode){
rc = SQLITE_READONLY_CANTINIT;
}else{
rc = unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1);
- if( rc==SQLITE_OK && robust_ftruncate(pShmNode->h, 0) ){
+ /* The first connection to attach must truncate the -shm file. We
+ ** truncate to 3 bytes (an arbitrary small number, less than the
+ ** -shm header size) rather than 0 as a system debugging aid, to
+ ** help detect if a -shm file truncation is legitimate or is the work
+ ** or a rogue process. */
+ if( rc==SQLITE_OK && robust_ftruncate(pShmNode->hShm, 3) ){
rc = unixLogError(SQLITE_IOERR_SHMOPEN,"ftruncate",pShmNode->zFilename);
}
}
@@ -36661,12 +36902,12 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
sqlite3_snprintf(nShmFilename, zShm, "%s-shm", zBasePath);
sqlite3FileSuffix3(pDbFd->zPath, zShm);
#endif
- pShmNode->h = -1;
+ pShmNode->hShm = -1;
pDbFd->pInode->pShmNode = pShmNode;
pShmNode->pInode = pDbFd->pInode;
if( sqlite3GlobalConfig.bCoreMutex ){
- pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
- if( pShmNode->mutex==0 ){
+ pShmNode->pShmMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
+ if( pShmNode->pShmMutex==0 ){
rc = SQLITE_NOMEM_BKPT;
goto shm_open_err;
}
@@ -36674,11 +36915,11 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
if( pInode->bProcessLock==0 ){
if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){
- pShmNode->h = robust_open(zShm, O_RDWR|O_CREAT, (sStat.st_mode&0777));
+ pShmNode->hShm = robust_open(zShm, O_RDWR|O_CREAT,(sStat.st_mode&0777));
}
- if( pShmNode->h<0 ){
- pShmNode->h = robust_open(zShm, O_RDONLY, (sStat.st_mode&0777));
- if( pShmNode->h<0 ){
+ if( pShmNode->hShm<0 ){
+ pShmNode->hShm = robust_open(zShm, O_RDONLY, (sStat.st_mode&0777));
+ if( pShmNode->hShm<0 ){
rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShm);
goto shm_open_err;
}
@@ -36689,7 +36930,7 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
** is owned by the same user that owns the original database. Otherwise,
** the original owner will not be able to connect.
*/
- robustFchown(pShmNode->h, sStat.st_uid, sStat.st_gid);
+ robustFchown(pShmNode->hShm, sStat.st_uid, sStat.st_gid);
rc = unixLockSharedMemory(pDbFd, pShmNode);
if( rc!=SQLITE_OK && rc!=SQLITE_READONLY_CANTINIT ) goto shm_open_err;
@@ -36709,13 +36950,13 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
** the cover of the unixEnterMutex() mutex and the pointer from the
** new (struct unixShm) object to the pShmNode has been set. All that is
** left to do is to link the new object into the linked list starting
- ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex
- ** mutex.
+ ** at pShmNode->pFirst. This must be done while holding the
+ ** pShmNode->pShmMutex.
*/
- sqlite3_mutex_enter(pShmNode->mutex);
+ sqlite3_mutex_enter(pShmNode->pShmMutex);
p->pNext = pShmNode->pFirst;
pShmNode->pFirst = p;
- sqlite3_mutex_leave(pShmNode->mutex);
+ sqlite3_mutex_leave(pShmNode->pShmMutex);
return rc;
/* Jump here on any error */
@@ -36767,7 +37008,7 @@ static int unixShmMap(
p = pDbFd->pShm;
pShmNode = p->pShmNode;
- sqlite3_mutex_enter(pShmNode->mutex);
+ sqlite3_mutex_enter(pShmNode->pShmMutex);
if( pShmNode->isUnlocked ){
rc = unixLockSharedMemory(pDbFd, pShmNode);
if( rc!=SQLITE_OK ) goto shmpage_out;
@@ -36775,8 +37016,8 @@ static int unixShmMap(
}
assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
assert( pShmNode->pInode==pDbFd->pInode );
- assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 );
- assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 );
+ assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 );
+ assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 );
/* Minimum number of regions required to be mapped. */
nReqRegion = ((iRegion+nShmPerMap) / nShmPerMap) * nShmPerMap;
@@ -36788,12 +37029,12 @@ static int unixShmMap(
pShmNode->szRegion = szRegion;
- if( pShmNode->h>=0 ){
+ if( pShmNode->hShm>=0 ){
/* The requested region is not mapped into this processes address space.
** Check to see if it has been allocated (i.e. if the wal-index file is
** large enough to contain the requested region).
*/
- if( osFstat(pShmNode->h, &sStat) ){
+ if( osFstat(pShmNode->hShm, &sStat) ){
rc = SQLITE_IOERR_SHMSIZE;
goto shmpage_out;
}
@@ -36821,7 +37062,7 @@ static int unixShmMap(
assert( (nByte % pgsz)==0 );
for(iPg=(sStat.st_size/pgsz); iPg<(nByte/pgsz); iPg++){
int x = 0;
- if( seekAndWriteFd(pShmNode->h, iPg*pgsz + pgsz-1, "", 1, &x)!=1 ){
+ if( seekAndWriteFd(pShmNode->hShm, iPg*pgsz + pgsz-1,"",1,&x)!=1 ){
const char *zFile = pShmNode->zFilename;
rc = unixLogError(SQLITE_IOERR_SHMSIZE, "write", zFile);
goto shmpage_out;
@@ -36844,22 +37085,22 @@ static int unixShmMap(
int nMap = szRegion*nShmPerMap;
int i;
void *pMem;
- if( pShmNode->h>=0 ){
+ if( pShmNode->hShm>=0 ){
pMem = osMmap(0, nMap,
pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE,
- MAP_SHARED, pShmNode->h, szRegion*(i64)pShmNode->nRegion
+ MAP_SHARED, pShmNode->hShm, szRegion*(i64)pShmNode->nRegion
);
if( pMem==MAP_FAILED ){
rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename);
goto shmpage_out;
}
}else{
- pMem = sqlite3_malloc64(szRegion);
+ pMem = sqlite3_malloc64(nMap);
if( pMem==0 ){
rc = SQLITE_NOMEM_BKPT;
goto shmpage_out;
}
- memset(pMem, 0, szRegion);
+ memset(pMem, 0, nMap);
}
for(i=0; i<nShmPerMap; i++){
@@ -36876,7 +37117,7 @@ shmpage_out:
*pp = 0;
}
if( pShmNode->isReadonly && rc==SQLITE_OK ) rc = SQLITE_READONLY;
- sqlite3_mutex_leave(pShmNode->mutex);
+ sqlite3_mutex_leave(pShmNode->pShmMutex);
return rc;
}
@@ -36910,12 +37151,12 @@ static int unixShmLock(
|| flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED)
|| flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
- assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 );
- assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 );
+ assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 );
+ assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 );
mask = (1<<(ofst+n)) - (1<<ofst);
assert( n>1 || mask==(1<<ofst) );
- sqlite3_mutex_enter(pShmNode->mutex);
+ sqlite3_mutex_enter(pShmNode->pShmMutex);
if( flags & SQLITE_SHM_UNLOCK ){
u16 allMask = 0; /* Mask of locks held by siblings */
@@ -36988,7 +37229,7 @@ static int unixShmLock(
}
}
}
- sqlite3_mutex_leave(pShmNode->mutex);
+ sqlite3_mutex_leave(pShmNode->pShmMutex);
OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n",
p->id, osGetpid(0), p->sharedMask, p->exclMask));
return rc;
@@ -37038,14 +37279,14 @@ static int unixShmUnmap(
/* Remove connection p from the set of connections associated
** with pShmNode */
- sqlite3_mutex_enter(pShmNode->mutex);
+ sqlite3_mutex_enter(pShmNode->pShmMutex);
for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
*pp = p->pNext;
/* Free the connection p */
sqlite3_free(p);
pDbFd->pShm = 0;
- sqlite3_mutex_leave(pShmNode->mutex);
+ sqlite3_mutex_leave(pShmNode->pShmMutex);
/* If pShmNode->nRef has reached 0, then close the underlying
** shared-memory file, too */
@@ -37054,7 +37295,7 @@ static int unixShmUnmap(
assert( pShmNode->nRef>0 );
pShmNode->nRef--;
if( pShmNode->nRef==0 ){
- if( deleteFlag && pShmNode->h>=0 ){
+ if( deleteFlag && pShmNode->hShm>=0 ){
osUnlink(pShmNode->zFilename);
}
unixShmPurge(pDbFd);
@@ -40521,8 +40762,7 @@ struct winFile {
int nFetchOut; /* Number of outstanding xFetch references */
HANDLE hMap; /* Handle for accessing memory mapping */
void *pMapRegion; /* Area memory mapped */
- sqlite3_int64 mmapSize; /* Usable size of mapped region */
- sqlite3_int64 mmapSizeActual; /* Actual size of mapped region */
+ sqlite3_int64 mmapSize; /* Size of mapped region */
sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */
#endif
};
@@ -43143,7 +43383,26 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
DWORD lastErrno;
#if SQLITE_MAX_MMAP_SIZE>0
sqlite3_int64 oldMmapSize;
- if( pFile->nFetchOut>0 ) return SQLITE_OK;
+ if( pFile->nFetchOut>0 ){
+ /* File truncation is a no-op if there are outstanding memory mapped
+ ** pages. This is because truncating the file means temporarily unmapping
+ ** the file, and that might delete memory out from under existing cursors.
+ **
+ ** This can result in incremental vacuum not truncating the file,
+ ** if there is an active read cursor when the incremental vacuum occurs.
+ ** No real harm comes of this - the database file is not corrupted,
+ ** though some folks might complain that the file is bigger than it
+ ** needs to be.
+ **
+ ** The only feasible work-around is to defer the truncation until after
+ ** all references to memory-mapped content are closed. That is doable,
+ ** but involves adding a few branches in the common write code path which
+ ** could slow down normal operations slightly. Hence, we have decided for
+ ** now to simply make trancations a no-op if there are pending reads. We
+ ** can maybe revisit this decision in the future.
+ */
+ return SQLITE_OK;
+ }
#endif
assert( pFile );
@@ -44572,9 +44831,9 @@ shmpage_out:
static int winUnmapfile(winFile *pFile){
assert( pFile!=0 );
OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, hMap=%p, pMapRegion=%p, "
- "mmapSize=%lld, mmapSizeActual=%lld, mmapSizeMax=%lld\n",
+ "mmapSize=%lld, mmapSizeMax=%lld\n",
osGetCurrentProcessId(), pFile, pFile->hMap, pFile->pMapRegion,
- pFile->mmapSize, pFile->mmapSizeActual, pFile->mmapSizeMax));
+ pFile->mmapSize, pFile->mmapSizeMax));
if( pFile->pMapRegion ){
if( !osUnmapViewOfFile(pFile->pMapRegion) ){
pFile->lastErrno = osGetLastError();
@@ -44586,7 +44845,6 @@ static int winUnmapfile(winFile *pFile){
}
pFile->pMapRegion = 0;
pFile->mmapSize = 0;
- pFile->mmapSizeActual = 0;
}
if( pFile->hMap!=NULL ){
if( !osCloseHandle(pFile->hMap) ){
@@ -44697,7 +44955,6 @@ static int winMapfile(winFile *pFd, sqlite3_int64 nByte){
}
pFd->pMapRegion = pNew;
pFd->mmapSize = nMap;
- pFd->mmapSizeActual = nMap;
}
OSTRACE(("MAP-FILE pid=%lu, pFile=%p, rc=SQLITE_OK\n",
@@ -45499,7 +45756,6 @@ static int winOpen(
pFile->hMap = NULL;
pFile->pMapRegion = 0;
pFile->mmapSize = 0;
- pFile->mmapSizeActual = 0;
pFile->mmapSizeMax = sqlite3GlobalConfig.szMmap;
#endif
@@ -47404,7 +47660,7 @@ bitvec_end:
** The PCache.pSynced variable is used to optimize searching for a dirty
** page to eject from the cache mid-transaction. It is better to eject
** a page that does not require a journal sync than one that does.
-** Therefore, pSynced is maintained to that it *almost* always points
+** Therefore, pSynced is maintained so that it *almost* always points
** to either the oldest page in the pDirty/pDirtyTail list that has a
** clear PGHDR_NEED_SYNC flag or to a page that is older than this one
** (so that the right page to eject can be found by following pDirtyPrev
@@ -48228,6 +48484,15 @@ SQLITE_PRIVATE int sqlite3PCachePercentDirty(PCache *pCache){
return nCache ? (int)(((i64)nDirty * 100) / nCache) : 0;
}
+#ifdef SQLITE_DIRECT_OVERFLOW_READ
+/*
+** Return true if there are one or more dirty pages in the cache. Else false.
+*/
+SQLITE_PRIVATE int sqlite3PCacheIsDirty(PCache *pCache){
+ return (pCache->pDirty!=0);
+}
+#endif
+
#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG)
/*
** For all dirty pages currently in the cache, invoke the specified
@@ -48351,7 +48616,8 @@ struct PgHdr1 {
};
/*
-** A page is pinned if it is no on the LRU list
+** A page is pinned if it is not on the LRU list. To be "pinned" means
+** that the page is in active use and must not be deallocated.
*/
#define PAGE_IS_PINNED(p) ((p)->pLruNext==0)
#define PAGE_IS_UNPINNED(p) ((p)->pLruNext!=0)
@@ -48412,6 +48678,7 @@ struct PCache1 {
unsigned int nMax; /* Configured "cache_size" value */
unsigned int n90pct; /* nMax*9/10 */
unsigned int iMaxKey; /* Largest key seen since xTruncate() */
+ unsigned int nPurgeableDummy; /* pnPurgeable points here when not used*/
/* Hash table of all pages. The following variables may only be accessed
** when the accessor is holding the PGroup mutex.
@@ -49025,8 +49292,7 @@ static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){
pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
pCache->pnPurgeable = &pGroup->nPurgeable;
}else{
- static unsigned int dummyCurrentPage;
- pCache->pnPurgeable = &dummyCurrentPage;
+ pCache->pnPurgeable = &pCache->nPurgeableDummy;
}
pcache1LeaveMutex(pGroup);
if( pCache->nHash==0 ){
@@ -50991,19 +51257,30 @@ static const unsigned char aJournalMagic[] = {
*/
#define isOpen(pFd) ((pFd)->pMethods!=0)
+#ifdef SQLITE_DIRECT_OVERFLOW_READ
/*
-** Return true if this pager uses a write-ahead log to read page pgno.
-** Return false if the pager reads pgno directly from the database.
+** Return true if page pgno can be read directly from the database file
+** by the b-tree layer. This is the case if:
+**
+** * the database file is open,
+** * there are no dirty pages in the cache, and
+** * the desired page is not currently in the wal file.
*/
-#if !defined(SQLITE_OMIT_WAL) && defined(SQLITE_DIRECT_OVERFLOW_READ)
-SQLITE_PRIVATE int sqlite3PagerUseWal(Pager *pPager, Pgno pgno){
- u32 iRead = 0;
- int rc;
- if( pPager->pWal==0 ) return 0;
- rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iRead);
- return rc || iRead;
+SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){
+ if( pPager->fd->pMethods==0 ) return 0;
+ if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0;
+#ifndef SQLITE_OMIT_WAL
+ if( pPager->pWal ){
+ u32 iRead = 0;
+ int rc;
+ rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iRead);
+ return (rc==SQLITE_OK && iRead==0);
+ }
+#endif
+ return 1;
}
#endif
+
#ifndef SQLITE_OMIT_WAL
# define pagerUseWal(x) ((x)->pWal!=0)
#else
@@ -57187,7 +57464,11 @@ SQLITE_PRIVATE void sqlite3PagerSetCodec(
void (*xCodecFree)(void*),
void *pCodec
){
- if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec);
+ if( pPager->xCodecFree ){
+ pPager->xCodecFree(pPager->pCodec);
+ }else{
+ pager_reset(pPager);
+ }
pPager->xCodec = pPager->memDb ? 0 : xCodec;
pPager->xCodecSizeChng = xCodecSizeChng;
pPager->xCodecFree = xCodecFree;
@@ -63728,6 +64009,13 @@ static void ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent, int *pRC){
*pRC = rc;
return;
}
+ if( ((char*)sqlite3PagerGetExtra(pDbPage))[0]!=0 ){
+ /* The first byte of the extra data is the MemPage.isInit byte.
+ ** If that byte is set, it means this page is also being used
+ ** as a btree page. */
+ *pRC = SQLITE_CORRUPT_BKPT;
+ goto ptrmap_exit;
+ }
offset = PTRMAP_PTROFFSET(iPtrmap, key);
if( offset<0 ){
*pRC = SQLITE_CORRUPT_BKPT;
@@ -64093,7 +64381,12 @@ static void ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell, int *pRC){
assert( pCell!=0 );
pPage->xParseCell(pPage, pCell, &info);
if( info.nLocal<info.nPayload ){
- Pgno ovfl = get4byte(&pCell[info.nSize-4]);
+ Pgno ovfl;
+ if( SQLITE_WITHIN(pPage->aDataEnd, pCell, pCell+info.nLocal) ){
+ *pRC = SQLITE_CORRUPT_BKPT;
+ return;
+ }
+ ovfl = get4byte(&pCell[info.nSize-4]);
ptrmapPut(pPage->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno, pRC);
}
}
@@ -65888,7 +66181,7 @@ static int lockBtree(BtShared *pBt){
pageSize-usableSize);
return rc;
}
- if( (pBt->db->flags & SQLITE_WriteSchema)==0 && nPage>nPageFile ){
+ if( sqlite3WritableSchema(pBt->db)==0 && nPage>nPageFile ){
rc = SQLITE_CORRUPT_BKPT;
goto page1_init_failed;
}
@@ -66362,6 +66655,7 @@ static int relocatePage(
eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE );
assert( sqlite3_mutex_held(pBt->mutex) );
assert( pDbPage->pBt==pBt );
+ if( iDbPage<3 ) return SQLITE_CORRUPT_BKPT;
/* Move page iDbPage from its current location to page number iFreePage */
TRACE(("AUTOVACUUM: Moving %d to free page %d (ptr page %d type %d)\n",
@@ -67547,9 +67841,6 @@ static int accessPayload(
/* Need to read this page properly. It contains some of the
** range of data that is being read (eOp==0) or written (eOp!=0).
*/
-#ifdef SQLITE_DIRECT_OVERFLOW_READ
- sqlite3_file *fd; /* File from which to do direct overflow read */
-#endif
int a = amt;
if( a + offset > ovflSize ){
a = ovflSize - offset;
@@ -67560,7 +67851,7 @@ static int accessPayload(
**
** 1) this is a read operation, and
** 2) data is required from the start of this overflow page, and
- ** 3) there is no open write-transaction, and
+ ** 3) there are no dirty pages in the page-cache
** 4) the database is file-backed, and
** 5) the page is not in the WAL file
** 6) at least 4 bytes have already been read into the output buffer
@@ -67571,11 +67862,10 @@ static int accessPayload(
*/
if( eOp==0 /* (1) */
&& offset==0 /* (2) */
- && pBt->inTransaction==TRANS_READ /* (3) */
- && (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (4) */
- && 0==sqlite3PagerUseWal(pBt->pPager, nextPage) /* (5) */
+ && sqlite3PagerDirectReadOk(pBt->pPager, nextPage) /* (3,4,5) */
&& &pBuf[-4]>=pBufStart /* (6) */
){
+ sqlite3_file *fd = sqlite3PagerFile(pBt->pPager);
u8 aSave[4];
u8 *aWrite = &pBuf[-4];
assert( aWrite>=pBufStart ); /* due to (6) */
@@ -74171,7 +74461,8 @@ SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem *pMem, u8 enc, u8 bForce){
assert( fg & MEM_Real );
sqlite3_snprintf(nByte, pMem->z, "%!.15g", pMem->u.r);
}
- pMem->n = sqlite3Strlen30(pMem->z);
+ assert( pMem->z!=0 );
+ pMem->n = sqlite3Strlen30NN(pMem->z);
pMem->enc = SQLITE_UTF8;
pMem->flags |= MEM_Str|MEM_Term;
if( bForce ) pMem->flags &= ~(MEM_Int|MEM_Real);
@@ -75746,6 +76037,13 @@ SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, u8 prepFlag
}
assert( p->zSql==0 );
p->zSql = sqlite3DbStrNDup(p->db, z, n);
+#ifdef SQLITE_ENABLE_NORMALIZE
+ assert( p->zNormSql==0 );
+ if( p->zSql && (prepFlags & SQLITE_PREPARE_NORMALIZE)!=0 ){
+ sqlite3Normalize(p, p->zSql, n, prepFlags);
+ assert( p->zNormSql!=0 || p->db->mallocFailed );
+ }
+#endif
}
/*
@@ -75767,6 +76065,11 @@ SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){
zTmp = pA->zSql;
pA->zSql = pB->zSql;
pB->zSql = zTmp;
+#ifdef SQLITE_ENABLE_NORMALIZE
+ zTmp = pA->zNormSql;
+ pA->zNormSql = pB->zNormSql;
+ pB->zNormSql = zTmp;
+#endif
pB->expmask = pA->expmask;
pB->prepFlags = pA->prepFlags;
memcpy(pB->aCounter, pA->aCounter, sizeof(pB->aCounter));
@@ -78838,6 +79141,9 @@ SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
vdbeFreeOpArray(db, p->aOp, p->nOp);
sqlite3DbFree(db, p->aColName);
sqlite3DbFree(db, p->zSql);
+#ifdef SQLITE_ENABLE_NORMALIZE
+ sqlite3DbFree(db, p->zNormSql);
+#endif
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
{
int i;
@@ -79834,12 +80140,12 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
}else{
idx1 = getVarint32(aKey1, szHdr1);
d1 = szHdr1;
- if( d1>(unsigned)nKey1 ){
- pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
- return 0; /* Corruption */
- }
i = 0;
}
+ if( d1>(unsigned)nKey1 ){
+ pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
+ return 0; /* Corruption */
+ }
VVA_ONLY( mem1.szMalloc = 0; ) /* Only needed by assert() statements */
assert( pPKey2->pKeyInfo->nAllField>=pPKey2->nField
@@ -82252,6 +82558,16 @@ SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt){
#endif
}
+#ifdef SQLITE_ENABLE_NORMALIZE
+/*
+** Return the normalized SQL associated with a prepared statement.
+*/
+SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt){
+ Vdbe *p = (Vdbe *)pStmt;
+ return p ? p->zNormSql : 0;
+}
+#endif /* SQLITE_ENABLE_NORMALIZE */
+
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
/*
** Allocate and populate an UnpackedRecord structure based on the serialized
@@ -85691,17 +86007,25 @@ case OP_MakeRecord: {
if( nVarint<sqlite3VarintLen(nHdr) ) nHdr++;
}
nByte = nHdr+nData;
- if( nByte+nZero>db->aLimit[SQLITE_LIMIT_LENGTH] ){
- goto too_big;
- }
/* Make sure the output register has a buffer large enough to store
** the new record. The output register (pOp->p3) is not allowed to
** be one of the input registers (because the following call to
** sqlite3VdbeMemClearAndResize() could clobber the value before it is used).
*/
- if( sqlite3VdbeMemClearAndResize(pOut, (int)nByte) ){
- goto no_mem;
+ if( nByte+nZero<=pOut->szMalloc ){
+ /* The output register is already large enough to hold the record.
+ ** No error checks or buffer enlargement is required */
+ pOut->z = pOut->zMalloc;
+ }else{
+ /* Need to make sure that the output is not too big and then enlarge
+ ** the output register to hold the full result */
+ if( nByte+nZero>db->aLimit[SQLITE_LIMIT_LENGTH] ){
+ goto too_big;
+ }
+ if( sqlite3VdbeMemClearAndResize(pOut, (int)nByte) ){
+ goto no_mem;
+ }
}
zNewRecord = (u8 *)pOut->z;
@@ -88557,7 +88881,7 @@ case OP_ParseSchema: {
{
zMaster = MASTER_NAME;
initData.db = db;
- initData.iDb = pOp->p1;
+ initData.iDb = iDb;
initData.pzErrMsg = &p->zErrMsg;
initData.mInitFlags = 0;
zSql = sqlite3MPrintf(db,
@@ -94140,8 +94464,8 @@ static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){
if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
}
#ifndef SQLITE_OMIT_WINDOWFUNC
- if( !ExprHasProperty(pExpr, EP_Reduced) && pExpr->pWin ){
- Window *pWin = pExpr->pWin;
+ if( ExprHasProperty(pExpr, EP_WinFunc) ){
+ Window *pWin = pExpr->y.pWin;
if( sqlite3WalkExprList(pWalker, pWin->pPartition) ) return WRC_Abort;
if( sqlite3WalkExprList(pWalker, pWin->pOrderBy) ) return WRC_Abort;
if( sqlite3WalkExpr(pWalker, pWin->pFilter) ) return WRC_Abort;
@@ -94414,7 +94738,7 @@ SQLITE_PRIVATE int sqlite3MatchSpanName(
** (even if X is implied).
** pExpr->iTable Set to the cursor number for the table obtained
** from pSrcList.
-** pExpr->pTab Points to the Table structure of X.Y (even if
+** pExpr->y.pTab Points to the Table structure of X.Y (even if
** X and/or Y are implied.)
** pExpr->iColumn Set to the column number within the table.
** pExpr->op Set to TK_COLUMN.
@@ -94458,7 +94782,6 @@ static int lookupName(
/* Initialize the node to no-match */
pExpr->iTable = -1;
- pExpr->pTab = 0;
ExprSetVVAProperty(pExpr, EP_NoReduce);
/* Translate the schema name in zDb into a pointer to the corresponding
@@ -94520,7 +94843,7 @@ static int lookupName(
continue;
}
if( IN_RENAME_OBJECT && pItem->zAlias ){
- sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->pTab);
+ sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->y.pTab);
}
}
if( 0==(cntTab++) ){
@@ -94546,13 +94869,13 @@ static int lookupName(
}
if( pMatch ){
pExpr->iTable = pMatch->iCursor;
- pExpr->pTab = pMatch->pTab;
+ pExpr->y.pTab = pMatch->pTab;
/* RIGHT JOIN not (yet) supported */
assert( (pMatch->fg.jointype & JT_RIGHT)==0 );
if( (pMatch->fg.jointype & JT_LEFT)!=0 ){
ExprSetProperty(pExpr, EP_CanBeNull);
}
- pSchema = pExpr->pTab->pSchema;
+ pSchema = pExpr->y.pTab->pSchema;
}
} /* if( pSrcList ) */
@@ -94609,7 +94932,7 @@ static int lookupName(
testcase( iCol==(-1) );
if( IN_RENAME_OBJECT ){
pExpr->iColumn = iCol;
- pExpr->pTab = pTab;
+ pExpr->y.pTab = pTab;
eNewExprOp = TK_COLUMN;
}else{
pExpr->iTable = pNC->uNC.pUpsert->regData + iCol;
@@ -94631,7 +94954,7 @@ static int lookupName(
testcase( iCol==32 );
pParse->newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol));
}
- pExpr->pTab = pTab;
+ pExpr->y.pTab = pTab;
pExpr->iColumn = (i16)iCol;
eNewExprOp = TK_TRIGGER;
#endif /* SQLITE_OMIT_TRIGGER */
@@ -94731,7 +95054,7 @@ static int lookupName(
assert( pExpr->op==TK_ID );
if( ExprHasProperty(pExpr,EP_DblQuoted) ){
pExpr->op = TK_STRING;
- pExpr->pTab = 0;
+ pExpr->y.pTab = 0;
return WRC_Prune;
}
if( sqlite3ExprIdToTrueFalse(pExpr) ){
@@ -94809,9 +95132,9 @@ SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSr
Expr *p = sqlite3ExprAlloc(db, TK_COLUMN, 0, 0);
if( p ){
struct SrcList_item *pItem = &pSrc->a[iSrc];
- p->pTab = pItem->pTab;
+ p->y.pTab = pItem->pTab;
p->iTable = pItem->iCursor;
- if( p->pTab->iPKey==iCol ){
+ if( p->y.pTab->iPKey==iCol ){
p->iColumn = -1;
}else{
p->iColumn = (ynVar)iCol;
@@ -94901,7 +95224,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
pItem = pSrcList->a;
assert( HasRowid(pItem->pTab) && pItem->pTab->pSelect==0 );
pExpr->op = TK_COLUMN;
- pExpr->pTab = pItem->pTab;
+ pExpr->y.pTab = pItem->pTab;
pExpr->iTable = pItem->iCursor;
pExpr->iColumn = -1;
pExpr->affinity = SQLITE_AFF_INTEGER;
@@ -94945,9 +95268,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
zColumn = pRight->u.zToken;
if( IN_RENAME_OBJECT ){
sqlite3RenameTokenRemap(pParse, (void*)pExpr, (void*)pRight);
- }
- if( IN_RENAME_OBJECT ){
- sqlite3RenameTokenRemap(pParse, (void*)&pExpr->pTab, (void*)pLeft);
+ sqlite3RenameTokenRemap(pParse, (void*)&pExpr->y.pTab, (void*)pLeft);
}
}
return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr);
@@ -95029,6 +95350,15 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
notValid(pParse, pNC, "non-deterministic functions",
NC_IdxExpr|NC_PartIdx);
}
+ if( (pDef->funcFlags & SQLITE_FUNC_INTERNAL)!=0
+ && pParse->nested==0
+ && sqlite3Config.bInternalFunctions==0
+ ){
+ /* Internal-use-only functions are disallowed unless the
+ ** SQL is being compiled using sqlite3NestedParse() */
+ no_such_func = 1;
+ pDef = 0;
+ }
}
if( 0==IN_RENAME_OBJECT ){
@@ -95037,18 +95367,18 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|| (pDef->xValue==0 && pDef->xInverse==0)
|| (pDef->xValue && pDef->xInverse && pDef->xSFunc && pDef->xFinalize)
);
- if( pDef && pDef->xValue==0 && pExpr->pWin ){
+ if( pDef && pDef->xValue==0 && ExprHasProperty(pExpr, EP_WinFunc) ){
sqlite3ErrorMsg(pParse,
"%.*s() may not be used as a window function", nId, zId
);
pNC->nErr++;
}else if(
(is_agg && (pNC->ncFlags & NC_AllowAgg)==0)
- || (is_agg && (pDef->funcFlags & SQLITE_FUNC_WINDOW) && !pExpr->pWin)
- || (is_agg && pExpr->pWin && (pNC->ncFlags & NC_AllowWin)==0)
+ || (is_agg && (pDef->funcFlags&SQLITE_FUNC_WINDOW) && !pExpr->y.pWin)
+ || (is_agg && pExpr->y.pWin && (pNC->ncFlags & NC_AllowWin)==0)
){
const char *zType;
- if( (pDef->funcFlags & SQLITE_FUNC_WINDOW) || pExpr->pWin ){
+ if( (pDef->funcFlags & SQLITE_FUNC_WINDOW) || pExpr->y.pWin ){
zType = "window";
}else{
zType = "aggregate";
@@ -95078,7 +95408,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
}
if( is_agg ){
#ifndef SQLITE_OMIT_WINDOWFUNC
- pNC->ncFlags &= ~(pExpr->pWin ? NC_AllowWin : NC_AllowAgg);
+ pNC->ncFlags &= ~(pExpr->y.pWin ? NC_AllowWin : NC_AllowAgg);
#else
pNC->ncFlags &= ~NC_AllowAgg;
#endif
@@ -95087,17 +95417,17 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
sqlite3WalkExprList(pWalker, pList);
if( is_agg ){
#ifndef SQLITE_OMIT_WINDOWFUNC
- if( pExpr->pWin ){
+ if( pExpr->y.pWin ){
Select *pSel = pNC->pWinSelect;
- sqlite3WalkExprList(pWalker, pExpr->pWin->pPartition);
- sqlite3WalkExprList(pWalker, pExpr->pWin->pOrderBy);
- sqlite3WalkExpr(pWalker, pExpr->pWin->pFilter);
- sqlite3WindowUpdate(pParse, pSel->pWinDefn, pExpr->pWin, pDef);
+ sqlite3WalkExprList(pWalker, pExpr->y.pWin->pPartition);
+ sqlite3WalkExprList(pWalker, pExpr->y.pWin->pOrderBy);
+ sqlite3WalkExpr(pWalker, pExpr->y.pWin->pFilter);
+ sqlite3WindowUpdate(pParse, pSel->pWinDefn, pExpr->y.pWin, pDef);
if( 0==pSel->pWin
- || 0==sqlite3WindowCompare(pParse, pSel->pWin, pExpr->pWin)
+ || 0==sqlite3WindowCompare(pParse, pSel->pWin, pExpr->y.pWin)
){
- pExpr->pWin->pNextWin = pSel->pWin;
- pSel->pWin = pExpr->pWin;
+ pExpr->y.pWin->pNextWin = pSel->pWin;
+ pSel->pWin = pExpr->y.pWin;
}
pNC->ncFlags |= NC_AllowWin;
}else
@@ -95520,13 +95850,13 @@ static int resolveOrderGroupBy(
for(j=0; j<pSelect->pEList->nExpr; j++){
if( sqlite3ExprCompare(0, pE, pSelect->pEList->a[j].pExpr, -1)==0 ){
#ifndef SQLITE_OMIT_WINDOWFUNC
- if( pE->pWin ){
+ if( ExprHasProperty(pE, EP_WinFunc) ){
/* Since this window function is being changed into a reference
** to the same window function the result set, remove the instance
** of this window function from the Select.pWin list. */
Window **pp;
for(pp=&pSelect->pWin; *pp; pp=&(*pp)->pNextWin){
- if( *pp==pE->pWin ){
+ if( *pp==pE->y.pWin ){
*pp = (*pp)->pNextWin;
}
}
@@ -95989,8 +96319,8 @@ SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){
return sqlite3AffinityType(pExpr->u.zToken, 0);
}
#endif
- if( (op==TK_AGG_COLUMN || op==TK_COLUMN) && pExpr->pTab ){
- return sqlite3TableColumnAffinity(pExpr->pTab, pExpr->iColumn);
+ if( (op==TK_AGG_COLUMN || op==TK_COLUMN) && pExpr->y.pTab ){
+ return sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
}
if( op==TK_SELECT_COLUMN ){
assert( pExpr->pLeft->flags&EP_xIsSelect );
@@ -96072,15 +96402,15 @@ SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
while( p ){
int op = p->op;
if( p->flags & EP_Generic ) break;
- if( (op==TK_AGG_COLUMN || op==TK_COLUMN
- || op==TK_REGISTER || op==TK_TRIGGER)
- && p->pTab!=0
+ if( op==TK_REGISTER ) op = p->op2;
+ if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_TRIGGER)
+ && p->y.pTab!=0
){
- /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally
+ /* op==TK_REGISTER && p->y.pTab!=0 happens when pExpr was originally
** a TK_COLUMN but was previously evaluated and cached in a register */
int j = p->iColumn;
if( j>=0 ){
- const char *zColl = p->pTab->aCol[j].zColl;
+ const char *zColl = p->y.pTab->aCol[j].zColl;
pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
}
break;
@@ -96089,7 +96419,7 @@ SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
p = p->pLeft;
continue;
}
- if( op==TK_COLLATE || (op==TK_REGISTER && p->op2==TK_COLLATE) ){
+ if( op==TK_COLLATE ){
pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
break;
}
@@ -96983,6 +97313,10 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
assert( p!=0 );
/* Sanity check: Assert that the IntValue is non-negative if it exists */
assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 );
+
+ assert( !ExprHasProperty(p, EP_WinFunc) || p->y.pWin!=0 || db->mallocFailed );
+ assert( p->op!=TK_FUNCTION || ExprHasProperty(p, EP_TokenOnly|EP_Reduced)
+ || p->y.pWin==0 || ExprHasProperty(p, EP_WinFunc) );
#ifdef SQLITE_DEBUG
if( ExprHasProperty(p, EP_Leaf) && !ExprHasProperty(p, EP_TokenOnly) ){
assert( p->pLeft==0 );
@@ -97001,8 +97335,9 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
}else{
sqlite3ExprListDelete(db, p->x.pList);
}
- if( !ExprHasProperty(p, EP_Reduced) ){
- sqlite3WindowDelete(db, p->pWin);
+ if( ExprHasProperty(p, EP_WinFunc) ){
+ assert( p->op==TK_FUNCTION );
+ sqlite3WindowDelete(db, p->y.pWin);
}
}
if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken);
@@ -97066,7 +97401,7 @@ static int dupedExprStructSize(Expr *p, int flags){
assert( (0xfff & (EP_Reduced|EP_TokenOnly))==0 );
if( 0==flags || p->op==TK_SELECT_COLUMN
#ifndef SQLITE_OMIT_WINDOWFUNC
- || p->pWin
+ || ExprHasProperty(p, EP_WinFunc)
#endif
){
nSize = EXPR_FULLSIZE;
@@ -97093,7 +97428,7 @@ static int dupedExprStructSize(Expr *p, int flags){
static int dupedExprNodeSize(Expr *p, int flags){
int nByte = dupedExprStructSize(p, flags) & 0xfff;
if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){
- nByte += sqlite3Strlen30(p->u.zToken)+1;
+ nByte += sqlite3Strlen30NN(p->u.zToken)+1;
}
return ROUND8(nByte);
}
@@ -97196,22 +97531,24 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
}
/* Fill in pNew->pLeft and pNew->pRight. */
- zAlloc += dupedExprNodeSize(p, dupFlags);
- if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly) ){
+ if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly|EP_WinFunc) ){
+ zAlloc += dupedExprNodeSize(p, dupFlags);
if( !ExprHasProperty(pNew, EP_TokenOnly|EP_Leaf) ){
pNew->pLeft = p->pLeft ?
exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc) : 0;
pNew->pRight = p->pRight ?
exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc) : 0;
}
- }else{
#ifndef SQLITE_OMIT_WINDOWFUNC
- if( ExprHasProperty(p, EP_Reduced|EP_TokenOnly) ){
- pNew->pWin = 0;
- }else{
- pNew->pWin = sqlite3WindowDup(db, pNew, p->pWin);
+ if( ExprHasProperty(p, EP_WinFunc) ){
+ pNew->y.pWin = sqlite3WindowDup(db, pNew, p->y.pWin);
+ assert( ExprHasProperty(pNew, EP_WinFunc) );
}
#endif /* SQLITE_OMIT_WINDOWFUNC */
+ if( pzBuffer ){
+ *pzBuffer = zAlloc;
+ }
+ }else{
if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){
if( pNew->op==TK_SELECT_COLUMN ){
pNew->pLeft = p->pLeft;
@@ -97223,9 +97560,6 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
pNew->pRight = sqlite3ExprDup(db, p->pRight, 0);
}
}
- if( pzBuffer ){
- *pzBuffer = zAlloc;
- }
}
return pNew;
}
@@ -98020,8 +98354,8 @@ SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr *p){
return 0;
case TK_COLUMN:
return ExprHasProperty(p, EP_CanBeNull) ||
- p->pTab==0 || /* Reference to column of index on expression */
- (p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0);
+ p->y.pTab==0 || /* Reference to column of index on expression */
+ (p->iColumn>=0 && p->y.pTab->aCol[p->iColumn].notNull==0);
default:
return 1;
}
@@ -98076,6 +98410,14 @@ SQLITE_PRIVATE int sqlite3IsRowid(const char *z){
if( sqlite3StrICmp(z, "OID")==0 ) return 1;
return 0;
}
+#ifdef SQLITE_ENABLE_NORMALIZE
+SQLITE_PRIVATE int sqlite3IsRowidN(const char *z, int n){
+ if( sqlite3StrNICmp(z, "_ROWID_", n)==0 ) return 1;
+ if( sqlite3StrNICmp(z, "ROWID", n)==0 ) return 1;
+ if( sqlite3StrNICmp(z, "OID", n)==0 ) return 1;
+ return 0;
+}
+#endif
/*
** pX is the RHS of an IN operator. If pX is a SELECT statement
@@ -99309,7 +99651,7 @@ expr_code_doover:
** constant.
*/
int iReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft,target);
- int aff = sqlite3TableColumnAffinity(pExpr->pTab, pExpr->iColumn);
+ int aff = sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
if( aff!=SQLITE_AFF_BLOB ){
static const char zAff[] = "B\000C\000D\000E";
assert( SQLITE_AFF_BLOB=='A' );
@@ -99333,7 +99675,7 @@ expr_code_doover:
iTab = pParse->iSelfTab - 1;
}
}
- return sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,
+ return sqlite3ExprCodeGetColumn(pParse, pExpr->y.pTab,
pExpr->iColumn, iTab, target,
pExpr->op2);
}
@@ -99547,8 +99889,8 @@ expr_code_doover:
CollSeq *pColl = 0; /* A collating sequence */
#ifndef SQLITE_OMIT_WINDOWFUNC
- if( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) && pExpr->pWin ){
- return pExpr->pWin->regResult;
+ if( ExprHasProperty(pExpr, EP_WinFunc) ){
+ return pExpr->y.pWin->regResult;
}
#endif
@@ -99791,7 +100133,7 @@ expr_code_doover:
** p1==1 -> old.a p1==4 -> new.a
** p1==2 -> old.b p1==5 -> new.b
*/
- Table *pTab = pExpr->pTab;
+ Table *pTab = pExpr->y.pTab;
int p1 = pExpr->iTable * (pTab->nCol+1) + 1 + pExpr->iColumn;
assert( pExpr->iTable==0 || pExpr->iTable==1 );
@@ -99802,7 +100144,7 @@ expr_code_doover:
sqlite3VdbeAddOp2(v, OP_Param, p1, target);
VdbeComment((v, "r[%d]=%s.%s", target,
(pExpr->iTable ? "new" : "old"),
- (pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName)
+ (pExpr->iColumn<0 ? "rowid" : pExpr->y.pTab->aCol[pExpr->iColumn].zName)
));
#ifndef SQLITE_OMIT_FLOATING_POINT
@@ -100641,7 +100983,7 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTa
}
return 2;
}
- if( pA->op!=pB->op ){
+ if( pA->op!=pB->op || pA->op==TK_RAISE ){
if( pA->op==TK_COLLATE && sqlite3ExprCompare(pParse, pA->pLeft,pB,iTab)<2 ){
return 1;
}
@@ -100653,6 +100995,20 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTa
if( pA->op!=TK_COLUMN && pA->op!=TK_AGG_COLUMN && pA->u.zToken ){
if( pA->op==TK_FUNCTION ){
if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2;
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ /* Justification for the assert():
+ ** window functions have p->op==TK_FUNCTION but aggregate functions
+ ** have p->op==TK_AGG_FUNCTION. So any comparison between an aggregate
+ ** function and a window function should have failed before reaching
+ ** this point. And, it is not possible to have a window function and
+ ** a scalar function with the same name and number of arguments. So
+ ** if we reach this point, either A and B both window functions or
+ ** neither are a window functions. */
+ assert( ExprHasProperty(pA,EP_WinFunc)==ExprHasProperty(pB,EP_WinFunc) );
+ if( ExprHasProperty(pA,EP_WinFunc) ){
+ if( sqlite3WindowCompare(pParse,pA->y.pWin,pB->y.pWin)!=0 ) return 2;
+ }
+#endif
}else if( pA->op==TK_COLLATE ){
if( sqlite3_stricmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2;
}else if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){
@@ -100660,33 +101016,20 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTa
}
}
if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
- if( ALWAYS((combinedFlags & EP_TokenOnly)==0) ){
+ if( (combinedFlags & EP_TokenOnly)==0 ){
if( combinedFlags & EP_xIsSelect ) return 2;
if( (combinedFlags & EP_FixedCol)==0
&& sqlite3ExprCompare(pParse, pA->pLeft, pB->pLeft, iTab) ) return 2;
if( sqlite3ExprCompare(pParse, pA->pRight, pB->pRight, iTab) ) return 2;
if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2;
- assert( (combinedFlags & EP_Reduced)==0 );
- if( pA->op!=TK_STRING && pA->op!=TK_TRUEFALSE ){
+ if( pA->op!=TK_STRING
+ && pA->op!=TK_TRUEFALSE
+ && (combinedFlags & EP_Reduced)==0
+ ){
if( pA->iColumn!=pB->iColumn ) return 2;
if( pA->iTable!=pB->iTable
&& (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2;
}
-#ifndef SQLITE_OMIT_WINDOWFUNC
- /* Justification for the assert():
- ** window functions have p->op==TK_FUNCTION but aggregate functions
- ** have p->op==TK_AGG_FUNCTION. So any comparison between an aggregate
- ** function and a window function should have failed before reaching
- ** this point. And, it is not possible to have a window function and
- ** a scalar function with the same name and number of arguments. So
- ** if we reach this point, either A and B both window functions or
- ** neither are a window functions. */
- assert( (pA->pWin==0)==(pB->pWin==0) );
-
- if( pA->pWin!=0 ){
- if( sqlite3WindowCompare(pParse,pA->pWin,pB->pWin)!=0 ) return 2;
- }
-#endif
}
return 0;
}
@@ -100827,8 +101170,8 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
testcase( pExpr->op==TK_LE );
testcase( pExpr->op==TK_GT );
testcase( pExpr->op==TK_GE );
- if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->pTab))
- || (pExpr->pRight->op==TK_COLUMN && IsVirtual(pExpr->pRight->pTab))
+ if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->y.pTab))
+ || (pExpr->pRight->op==TK_COLUMN && IsVirtual(pExpr->pRight->y.pTab))
){
return WRC_Prune;
}
@@ -101059,7 +101402,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
&& (k = addAggInfoColumn(pParse->db, pAggInfo))>=0
){
pCol = &pAggInfo->aCol[k];
- pCol->pTab = pExpr->pTab;
+ pCol->pTab = pExpr->y.pTab;
pCol->iTable = pExpr->iTable;
pCol->iColumn = pExpr->iColumn;
pCol->iMem = ++pParse->nMem;
@@ -101942,10 +102285,16 @@ static void renameTokenCheckAll(Parse *pParse, void *pPtr){
#endif
/*
-** Add a new RenameToken object mapping parse tree element pPtr into
-** token *pToken to the Parse object currently under construction.
+** Remember that the parser tree element pPtr was created using
+** the token pToken.
**
-** Return a copy of pPtr.
+** In other words, construct a new RenameToken object and add it
+** to the list of RenameToken objects currently being built up
+** in pParse->pRename.
+**
+** The pPtr argument is returned so that this routine can be used
+** with tail recursion in tokenExpr() routine, for a small performance
+** improvement.
*/
SQLITE_PRIVATE void *sqlite3RenameTokenMap(Parse *pParse, void *pPtr, Token *pToken){
RenameToken *pNew;
@@ -102078,7 +102427,7 @@ static int renameColumnExprCb(Walker *pWalker, Expr *pExpr){
renameTokenFind(pWalker->pParse, p, (void*)pExpr);
}else if( pExpr->op==TK_COLUMN
&& pExpr->iColumn==p->iCol
- && p->pTab==pExpr->pTab
+ && p->pTab==pExpr->y.pTab
){
renameTokenFind(pWalker->pParse, p, (void*)pExpr);
}
@@ -102336,9 +102685,14 @@ static int renameResolveTrigger(Parse *pParse, const char *zDb){
db->aDb[sqlite3SchemaToIndex(db, pNew->pTabSchema)].zDbSName
);
pParse->eTriggerOp = pNew->op;
+ /* ALWAYS() because if the table of the trigger does not exist, the
+ ** error would have been hit before this point */
+ if( ALWAYS(pParse->pTriggerTab) ){
+ rc = sqlite3ViewGetColumnNames(pParse, pParse->pTriggerTab);
+ }
/* Resolve symbols in WHEN clause */
- if( pNew->pWhen ){
+ if( rc==SQLITE_OK && pNew->pWhen ){
rc = sqlite3ResolveExprNames(&sNC, pNew->pWhen);
}
@@ -102452,15 +102806,8 @@ static void renameParseCleanup(Parse *pParse){
** into zNew. The name should be quoted if bQuote is true.
**
** This function is used internally by the ALTER TABLE RENAME COLUMN command.
-** Though accessible to application code, it is not intended for use by
-** applications. The existance of this function, and the way it works,
-** is subject to change without notice.
-**
-** If any of the parameters are out-of-bounds, then simply return NULL.
-** An out-of-bounds parameter can only occur when the application calls
-** this function directly. The parameters will always be well-formed when
-** this routine is invoked by the bytecode for a legitimate ALTER TABLE
-** statement.
+** It is only accessible to SQL created using sqlite3NestedParse(). It is
+** not reachable from ordinary SQL passed into sqlite3_prepare().
*/
static void renameColumnFunc(
sqlite3_context *context,
@@ -102616,8 +102963,8 @@ renameColumnFunc_done:
*/
static int renameTableExprCb(Walker *pWalker, Expr *pExpr){
RenameCtx *p = pWalker->u.pRename;
- if( pExpr->op==TK_COLUMN && p->pTab==pExpr->pTab ){
- renameTokenFind(pWalker->pParse, p, (void*)&pExpr->pTab);
+ if( pExpr->op==TK_COLUMN && p->pTab==pExpr->y.pTab ){
+ renameTokenFind(pWalker->pParse, p, (void*)&pExpr->y.pTab);
}
return WRC_Continue;
}
@@ -102714,7 +103061,7 @@ static void renameTableFunc(
}else{
/* Modify any FK definitions to point to the new table. */
#ifndef SQLITE_OMIT_FOREIGN_KEY
- if( db->flags & SQLITE_ForeignKeys ){
+ if( isLegacy==0 || (db->flags & SQLITE_ForeignKeys) ){
FKey *pFKey;
for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){
if( sqlite3_stricmp(pFKey->zTo, zOld)==0 ){
@@ -102868,9 +103215,9 @@ static void renameTableTest(
*/
SQLITE_PRIVATE void sqlite3AlterFunctions(void){
static FuncDef aAlterTableFuncs[] = {
- FUNCTION(sqlite_rename_column, 9, 0, 0, renameColumnFunc),
- FUNCTION(sqlite_rename_table, 7, 0, 0, renameTableFunc),
- FUNCTION(sqlite_rename_test, 5, 0, 0, renameTableTest),
+ INTERNAL_FUNCTION(sqlite_rename_column, 9, renameColumnFunc),
+ INTERNAL_FUNCTION(sqlite_rename_table, 7, renameTableFunc),
+ INTERNAL_FUNCTION(sqlite_rename_test, 5, renameTableTest),
};
sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs));
}
@@ -104919,7 +105266,7 @@ static void attachFunc(
if( pNew->pBt ) sqlite3BtreeClose(pNew->pBt);
pNew->pBt = 0;
pNew->pSchema = 0;
- rc = sqlite3BtreeOpen(pVfs, "x", db, &pNew->pBt, 0, SQLITE_OPEN_MAIN_DB);
+ rc = sqlite3BtreeOpen(pVfs, "x\0", db, &pNew->pBt, 0, SQLITE_OPEN_MAIN_DB);
}else{
/* This is a real ATTACH
**
@@ -105599,6 +105946,7 @@ SQLITE_PRIVATE void sqlite3AuthRead(
int iCol; /* Index of column in table */
assert( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER );
+ assert( !IN_RENAME_OBJECT || db->xAuth==0 );
if( db->xAuth==0 ) return;
iDb = sqlite3SchemaToIndex(pParse->db, pSchema);
if( iDb<0 ){
@@ -105655,6 +106003,7 @@ SQLITE_PRIVATE int sqlite3AuthCheck(
/* Don't do any authorization checks if the database is initialising
** or if the parser is being invoked from within sqlite3_declare_vtab.
*/
+ assert( !IN_RENAME_OBJECT || db->xAuth==0 );
if( db->init.busy || IN_SPECIAL_PARSE ){
return SQLITE_OK;
}
@@ -106078,17 +106427,15 @@ SQLITE_PRIVATE Table *sqlite3LocateTable(
if( p==0 ){
const char *zMsg = flags & LOCATE_VIEW ? "no such view" : "no such table";
#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( sqlite3FindDbName(db, zDbase)<1 ){
- /* If zName is the not the name of a table in the schema created using
- ** CREATE, then check to see if it is the name of an virtual table that
- ** can be an eponymous virtual table. */
- Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName);
- if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
- pMod = sqlite3PragmaVtabRegister(db, zName);
- }
- if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){
- return pMod->pEpoTab;
- }
+ /* If zName is the not the name of a table in the schema created using
+ ** CREATE, then check to see if it is the name of an virtual table that
+ ** can be an eponymous virtual table. */
+ Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName);
+ if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
+ pMod = sqlite3PragmaVtabRegister(db, zName);
+ }
+ if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){
+ return pMod->pEpoTab;
}
#endif
if( (flags & LOCATE_NOERR)==0 ){
@@ -106268,17 +106615,22 @@ SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3 *db, int iDb){
SQLITE_PRIVATE void sqlite3ResetAllSchemasOfConnection(sqlite3 *db){
int i;
sqlite3BtreeEnterAll(db);
- assert( db->nSchemaLock==0 );
for(i=0; i<db->nDb; i++){
Db *pDb = &db->aDb[i];
if( pDb->pSchema ){
- sqlite3SchemaClear(pDb->pSchema);
+ if( db->nSchemaLock==0 ){
+ sqlite3SchemaClear(pDb->pSchema);
+ }else{
+ DbSetProperty(db, i, DB_ResetWanted);
+ }
}
}
db->mDbFlags &= ~(DBFLAG_SchemaChange|DBFLAG_SchemaKnownOk);
sqlite3VtabUnlockList(db);
sqlite3BtreeLeaveAll(db);
- sqlite3CollapseDatabaseArray(db);
+ if( db->nSchemaLock==0 ){
+ sqlite3CollapseDatabaseArray(db);
+ }
}
/*
@@ -106355,6 +106707,12 @@ static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){
/* Delete the Table structure itself.
*/
+#ifdef SQLITE_ENABLE_NORMALIZE
+ if( pTable->pColHash ){
+ sqlite3HashClear(pTable->pColHash);
+ sqlite3_free(pTable->pColHash);
+ }
+#endif
sqlite3DeleteColumnNames(db, pTable);
sqlite3DbFree(db, pTable->zName);
sqlite3DbFree(db, pTable->zColAff);
@@ -106514,6 +106872,20 @@ SQLITE_PRIVATE int sqlite3TwoPartName(
}
/*
+** True if PRAGMA writable_schema is ON
+*/
+SQLITE_PRIVATE int sqlite3WritableSchema(sqlite3 *db){
+ testcase( (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))==0 );
+ testcase( (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))==
+ SQLITE_WriteSchema );
+ testcase( (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))==
+ SQLITE_Defensive );
+ testcase( (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))==
+ (SQLITE_WriteSchema|SQLITE_Defensive) );
+ return (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))==SQLITE_WriteSchema;
+}
+
+/*
** This routine is used to check if the UTF-8 string zName is a legal
** unqualified name for a new schema object (table, index, view or
** trigger). All names are legal except those that begin with the string
@@ -106522,7 +106894,7 @@ SQLITE_PRIVATE int sqlite3TwoPartName(
*/
SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *pParse, const char *zName){
if( !pParse->db->init.busy && pParse->nested==0
- && (pParse->db->flags & SQLITE_WriteSchema)==0
+ && sqlite3WritableSchema(pParse->db)==0
&& 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", zName);
return SQLITE_ERROR;
@@ -107598,6 +107970,36 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
recomputeColumnsNotIndexed(pPk);
}
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/*
+** Return true if zName is a shadow table name in the current database
+** connection.
+**
+** zName is temporarily modified while this routine is running, but is
+** restored to its original value prior to this routine returning.
+*/
+static int isShadowTableName(sqlite3 *db, char *zName){
+ char *zTail; /* Pointer to the last "_" in zName */
+ Table *pTab; /* Table that zName is a shadow of */
+ Module *pMod; /* Module for the virtual table */
+
+ zTail = strrchr(zName, '_');
+ if( zTail==0 ) return 0;
+ *zTail = 0;
+ pTab = sqlite3FindTable(db, zName, 0);
+ *zTail = '_';
+ if( pTab==0 ) return 0;
+ if( !IsVirtual(pTab) ) return 0;
+ pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->azModuleArg[0]);
+ if( pMod==0 ) return 0;
+ if( pMod->pModule->iVersion<3 ) return 0;
+ if( pMod->pModule->xShadowName==0 ) return 0;
+ return pMod->pModule->xShadowName(zTail+1);
+}
+#else
+# define isShadowTableName(x,y) 0
+#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
+
/*
** This routine is called to report the final ")" that terminates
** a CREATE TABLE statement.
@@ -107637,6 +108039,10 @@ SQLITE_PRIVATE void sqlite3EndTable(
p = pParse->pNewTable;
if( p==0 ) return;
+ if( pSelect==0 && isShadowTableName(db, p->zName) ){
+ p->tabFlags |= TF_Shadow;
+ }
+
/* If the db->init.busy is 1 it means we are reading the SQL off the
** "sqlite_master" or "sqlite_temp_master" table on the disk.
** So do not write to the disk again. Extract the root page number
@@ -108144,7 +108550,7 @@ SQLITE_PRIVATE void sqlite3RootPageMoved(sqlite3 *db, int iDb, int iFrom, int iT
static void destroyRootPage(Parse *pParse, int iTable, int iDb){
Vdbe *v = sqlite3GetVdbe(pParse);
int r1 = sqlite3GetTempReg(pParse);
- assert( iTable>1 );
+ if( iTable<2 ) sqlite3ErrorMsg(pParse, "corrupt schema");
sqlite3VdbeAddOp3(v, OP_Destroy, iTable, r1, iDb);
sqlite3MayAbort(pParse);
#ifndef SQLITE_OMIT_AUTOVACUUM
@@ -110599,6 +111005,21 @@ static FuncDef *functionSearch(
}
return 0;
}
+#ifdef SQLITE_ENABLE_NORMALIZE
+SQLITE_PRIVATE FuncDef *sqlite3FunctionSearchN(
+ int h, /* Hash of the name */
+ const char *zFunc, /* Name of function */
+ int nFunc /* Length of the name */
+){
+ FuncDef *p;
+ for(p=sqlite3BuiltinFunctions.a[h]; p; p=p->u.pHash){
+ if( sqlite3StrNICmp(p->zName, zFunc, nFunc)==0 ){
+ return p;
+ }
+ }
+ return 0;
+}
+#endif /* SQLITE_ENABLE_NORMALIZE */
/*
** Insert a new FuncDef into a FuncDefHash hash table.
@@ -110612,7 +111033,7 @@ SQLITE_PRIVATE void sqlite3InsertBuiltinFuncs(
FuncDef *pOther;
const char *zName = aDef[i].zName;
int nName = sqlite3Strlen30(zName);
- int h = (zName[0] + nName) % SQLITE_FUNC_HASH_SZ;
+ int h = SQLITE_FUNC_HASH(zName[0], nName);
assert( zName[0]>='a' && zName[0]<='z' );
pOther = functionSearch(h, zName);
if( pOther ){
@@ -110691,7 +111112,7 @@ SQLITE_PRIVATE FuncDef *sqlite3FindFunction(
*/
if( !createFlag && (pBest==0 || (db->mDbFlags & DBFLAG_PreferBuiltin)!=0) ){
bestScore = 0;
- h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % SQLITE_FUNC_HASH_SZ;
+ h = SQLITE_FUNC_HASH(sqlite3UpperToLower[(u8)zName[0]], nName);
p = functionSearch(h, zName);
while( p ){
int score = matchQuality(p, nArg, enc);
@@ -110839,32 +111260,49 @@ SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
return pTab;
}
+/* Return true if table pTab is read-only.
+**
+** A table is read-only if any of the following are true:
+**
+** 1) It is a virtual table and no implementation of the xUpdate method
+** has been provided
+**
+** 2) It is a system table (i.e. sqlite_master), this call is not
+** part of a nested parse and writable_schema pragma has not
+** been specified
+**
+** 3) The table is a shadow table, the database connection is in
+** defensive mode, and the current sqlite3_prepare()
+** is for a top-level SQL statement.
+*/
+static int tabIsReadOnly(Parse *pParse, Table *pTab){
+ sqlite3 *db;
+ if( IsVirtual(pTab) ){
+ return sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0;
+ }
+ if( (pTab->tabFlags & (TF_Readonly|TF_Shadow))==0 ) return 0;
+ db = pParse->db;
+ if( (pTab->tabFlags & TF_Readonly)!=0 ){
+ return sqlite3WritableSchema(db)==0 && pParse->nested==0;
+ }
+ assert( pTab->tabFlags & TF_Shadow );
+ return (db->flags & SQLITE_Defensive)!=0
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ && db->pVtabCtx==0
+#endif
+ && db->nVdbeExec==0;
+}
+
/*
** Check to make sure the given table is writable. If it is not
** writable, generate an error message and return 1. If it is
** writable return 0;
*/
SQLITE_PRIVATE int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
- /* A table is not writable under the following circumstances:
- **
- ** 1) It is a virtual table and no implementation of the xUpdate method
- ** has been provided, or
- ** 2) It is a system table (i.e. sqlite_master), this call is not
- ** part of a nested parse and writable_schema pragma has not
- ** been specified.
- **
- ** In either case leave an error message in pParse and return non-zero.
- */
- if( ( IsVirtual(pTab)
- && sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0 )
- || ( (pTab->tabFlags & TF_Readonly)!=0
- && (pParse->db->flags & SQLITE_WriteSchema)==0
- && pParse->nested==0 )
- ){
+ if( tabIsReadOnly(pParse, pTab) ){
sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName);
return 1;
}
-
#ifndef SQLITE_OMIT_VIEW
if( !viewOk && pTab->pSelect ){
sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName);
@@ -114268,7 +114706,7 @@ static Expr *exprTableColumn(
){
Expr *pExpr = sqlite3Expr(db, TK_COLUMN, 0);
if( pExpr ){
- pExpr->pTab = pTab;
+ pExpr->y.pTab = pTab;
pExpr->iTable = iCursor;
pExpr->iColumn = iCol;
}
@@ -114368,8 +114806,11 @@ static void fkScanChildren(
** NOT( $current_a==a AND $current_b==b AND ... )
**
** The first form is used for rowid tables. The second form is used
- ** for WITHOUT ROWID tables. In the second form, the primary key is
- ** (a,b,...)
+ ** for WITHOUT ROWID tables. In the second form, the *parent* key is
+ ** (a,b,...). Either the parent or primary key could be used to
+ ** uniquely identify the current row, but the parent key is more convenient
+ ** as the required values have already been loaded into registers
+ ** by the caller.
*/
if( pTab==pFKey->pFrom && nIncr>0 ){
Expr *pNe; /* Expression (pLeft != pRight) */
@@ -114383,12 +114824,12 @@ static void fkScanChildren(
Expr *pEq, *pAll = 0;
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
assert( pIdx!=0 );
- for(i=0; i<pPk->nKeyCol; i++){
+ for(i=0; i<pIdx->nKeyCol; i++){
i16 iCol = pIdx->aiColumn[i];
assert( iCol>=0 );
pLeft = exprTableRegister(pParse, pTab, regData, iCol);
- pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, iCol);
- pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight);
+ pRight = sqlite3Expr(db, TK_ID, pTab->aCol[iCol].zName);
+ pEq = sqlite3PExpr(pParse, TK_IS, pLeft, pRight);
pAll = sqlite3ExprAnd(db, pAll, pEq);
}
pNe = sqlite3PExpr(pParse, TK_NOT, pAll, 0);
@@ -115344,7 +115785,8 @@ SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){
}while( i>=0 && zColAff[i]==SQLITE_AFF_BLOB );
pTab->zColAff = zColAff;
}
- i = sqlite3Strlen30(zColAff);
+ assert( zColAff!=0 );
+ i = sqlite3Strlen30NN(zColAff);
if( i ){
if( iReg ){
sqlite3VdbeAddOp4(v, OP_Affinity, iReg, i, 0, zColAff, i);
@@ -116324,14 +116766,15 @@ insert_cleanup:
#endif
/*
-** Meanings of bits in of pWalker->eCode for checkConstraintUnchanged()
+** Meanings of bits in of pWalker->eCode for
+** sqlite3ExprReferencesUpdatedColumn()
*/
#define CKCNSTRNT_COLUMN 0x01 /* CHECK constraint uses a changing column */
#define CKCNSTRNT_ROWID 0x02 /* CHECK constraint references the ROWID */
-/* This is the Walker callback from checkConstraintUnchanged(). Set
-** bit 0x01 of pWalker->eCode if
-** pWalker->eCode to 0 if this expression node references any of the
+/* This is the Walker callback from sqlite3ExprReferencesUpdatedColumn().
+* Set bit 0x01 of pWalker->eCode if pWalker->eCode to 0 and if this
+** expression node references any of the
** columns that are being modifed by an UPDATE statement.
*/
static int checkConstraintExprNode(Walker *pWalker, Expr *pExpr){
@@ -116353,12 +116796,21 @@ static int checkConstraintExprNode(Walker *pWalker, Expr *pExpr){
** only columns that are modified by the UPDATE are those for which
** aiChng[i]>=0, and also the ROWID is modified if chngRowid is true.
**
-** Return true if CHECK constraint pExpr does not use any of the
+** Return true if CHECK constraint pExpr uses any of the
** changing columns (or the rowid if it is changing). In other words,
-** return true if this CHECK constraint can be skipped when validating
+** return true if this CHECK constraint must be validated for
** the new row in the UPDATE statement.
+**
+** 2018-09-15: pExpr might also be an expression for an index-on-expressions.
+** The operation of this routine is the same - return true if an only if
+** the expression uses one or more of columns identified by the second and
+** third arguments.
*/
-static int checkConstraintUnchanged(Expr *pExpr, int *aiChng, int chngRowid){
+SQLITE_PRIVATE int sqlite3ExprReferencesUpdatedColumn(
+ Expr *pExpr, /* The expression to be checked */
+ int *aiChng, /* aiChng[x]>=0 if column x changed by the UPDATE */
+ int chngRowid /* True if UPDATE changes the rowid */
+){
Walker w;
memset(&w, 0, sizeof(w));
w.eCode = 0;
@@ -116373,7 +116825,7 @@ static int checkConstraintUnchanged(Expr *pExpr, int *aiChng, int chngRowid){
testcase( w.eCode==CKCNSTRNT_COLUMN );
testcase( w.eCode==CKCNSTRNT_ROWID );
testcase( w.eCode==(CKCNSTRNT_ROWID|CKCNSTRNT_COLUMN) );
- return !w.eCode;
+ return w.eCode!=0;
}
/*
@@ -116579,7 +117031,13 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
for(i=0; i<pCheck->nExpr; i++){
int allOk;
Expr *pExpr = pCheck->a[i].pExpr;
- if( aiChng && checkConstraintUnchanged(pExpr, aiChng, pkChng) ) continue;
+ if( aiChng
+ && !sqlite3ExprReferencesUpdatedColumn(pExpr, aiChng, pkChng)
+ ){
+ /* The check constraints do not reference any of the columns being
+ ** updated so there is no point it verifying the check constraint */
+ continue;
+ }
allOk = sqlite3VdbeMakeLabel(v);
sqlite3VdbeVerifyAbortable(v, onError);
sqlite3ExprIfTrue(pParse, pExpr, allOk, SQLITE_JUMPIFNULL);
@@ -118080,12 +118538,15 @@ struct sqlite3_api_routines {
int (*str_errcode)(sqlite3_str*);
int (*str_length)(sqlite3_str*);
char *(*str_value)(sqlite3_str*);
+ /* Version 3.25.0 and later */
int (*create_window_function)(sqlite3*,const char*,int,int,void*,
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*),
void (*xValue)(sqlite3_context*),
void (*xInv)(sqlite3_context*,int,sqlite3_value**),
void(*xDestroy)(void*));
+ /* Version 3.26.0 and later */
+ const char *(*normalized_sql)(sqlite3_stmt*);
};
/*
@@ -118373,6 +118834,8 @@ typedef int (*sqlite3_loadext_entry)(
#define sqlite3_str_value sqlite3_api->str_value
/* Version 3.25.0 and later */
#define sqlite3_create_window_function sqlite3_api->create_window_function
+/* Version 3.26.0 and later */
+#define sqlite3_normalized_sql sqlite3_api->normalized_sql
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
@@ -118461,6 +118924,7 @@ typedef int (*sqlite3_loadext_entry)(
# define sqlite3_declare_vtab 0
# define sqlite3_vtab_config 0
# define sqlite3_vtab_on_conflict 0
+# define sqlite3_vtab_collation 0
#endif
#ifdef SQLITE_OMIT_SHARED_CACHE
@@ -118828,7 +119292,13 @@ static const sqlite3_api_routines sqlite3Apis = {
sqlite3_str_length,
sqlite3_str_value,
/* Version 3.25.0 and later */
- sqlite3_create_window_function
+ sqlite3_create_window_function,
+ /* Version 3.26.0 and later */
+#ifdef SQLITE_ENABLE_NORMALIZE
+ sqlite3_normalized_sql
+#else
+ 0
+#endif
};
/*
@@ -119279,10 +119749,9 @@ SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3 *db){
#define PragTyp_ACTIVATE_EXTENSIONS 41
#define PragTyp_HEXKEY 42
#define PragTyp_KEY 43
-#define PragTyp_REKEY 44
-#define PragTyp_LOCK_STATUS 45
-#define PragTyp_PARSER_TRACE 46
-#define PragTyp_STATS 47
+#define PragTyp_LOCK_STATUS 44
+#define PragTyp_PARSER_TRACE 45
+#define PragTyp_STATS 46
/* Property flags associated with various pragma. */
#define PragFlg_NeedSchema 0x01 /* Force schema load before running */
@@ -119299,58 +119768,57 @@ SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3 *db){
** result column is different from the name of the pragma
*/
static const char *const pragCName[] = {
- /* 0 */ "cache_size", /* Used by: default_cache_size */
- /* 1 */ "cid", /* Used by: table_info */
- /* 2 */ "name",
- /* 3 */ "type",
- /* 4 */ "notnull",
- /* 5 */ "dflt_value",
- /* 6 */ "pk",
- /* 7 */ "tbl", /* Used by: stats */
- /* 8 */ "idx",
- /* 9 */ "wdth",
- /* 10 */ "hght",
- /* 11 */ "flgs",
- /* 12 */ "seqno", /* Used by: index_info */
- /* 13 */ "cid",
- /* 14 */ "name",
+ /* 0 */ "id", /* Used by: foreign_key_list */
+ /* 1 */ "seq",
+ /* 2 */ "table",
+ /* 3 */ "from",
+ /* 4 */ "to",
+ /* 5 */ "on_update",
+ /* 6 */ "on_delete",
+ /* 7 */ "match",
+ /* 8 */ "cid", /* Used by: table_xinfo */
+ /* 9 */ "name",
+ /* 10 */ "type",
+ /* 11 */ "notnull",
+ /* 12 */ "dflt_value",
+ /* 13 */ "pk",
+ /* 14 */ "hidden",
+ /* table_info reuses 8 */
/* 15 */ "seqno", /* Used by: index_xinfo */
- /* 16 */ "cid",
- /* 17 */ "name",
- /* 18 */ "desc",
- /* 19 */ "coll",
- /* 20 */ "key",
- /* 21 */ "seq", /* Used by: index_list */
- /* 22 */ "name",
- /* 23 */ "unique",
- /* 24 */ "origin",
- /* 25 */ "partial",
- /* 26 */ "seq", /* Used by: database_list */
- /* 27 */ "name",
- /* 28 */ "file",
- /* 29 */ "name", /* Used by: function_list */
- /* 30 */ "builtin",
- /* 31 */ "name", /* Used by: module_list pragma_list */
- /* 32 */ "seq", /* Used by: collation_list */
- /* 33 */ "name",
- /* 34 */ "id", /* Used by: foreign_key_list */
- /* 35 */ "seq",
- /* 36 */ "table",
- /* 37 */ "from",
- /* 38 */ "to",
- /* 39 */ "on_update",
- /* 40 */ "on_delete",
- /* 41 */ "match",
- /* 42 */ "table", /* Used by: foreign_key_check */
- /* 43 */ "rowid",
- /* 44 */ "parent",
- /* 45 */ "fkid",
- /* 46 */ "busy", /* Used by: wal_checkpoint */
- /* 47 */ "log",
- /* 48 */ "checkpointed",
- /* 49 */ "timeout", /* Used by: busy_timeout */
- /* 50 */ "database", /* Used by: lock_status */
- /* 51 */ "status",
+ /* 16 */ "cid",
+ /* 17 */ "name",
+ /* 18 */ "desc",
+ /* 19 */ "coll",
+ /* 20 */ "key",
+ /* 21 */ "tbl", /* Used by: stats */
+ /* 22 */ "idx",
+ /* 23 */ "wdth",
+ /* 24 */ "hght",
+ /* 25 */ "flgs",
+ /* 26 */ "seq", /* Used by: index_list */
+ /* 27 */ "name",
+ /* 28 */ "unique",
+ /* 29 */ "origin",
+ /* 30 */ "partial",
+ /* 31 */ "table", /* Used by: foreign_key_check */
+ /* 32 */ "rowid",
+ /* 33 */ "parent",
+ /* 34 */ "fkid",
+ /* index_info reuses 15 */
+ /* 35 */ "seq", /* Used by: database_list */
+ /* 36 */ "name",
+ /* 37 */ "file",
+ /* 38 */ "busy", /* Used by: wal_checkpoint */
+ /* 39 */ "log",
+ /* 40 */ "checkpointed",
+ /* 41 */ "name", /* Used by: function_list */
+ /* 42 */ "builtin",
+ /* collation_list reuses 26 */
+ /* 43 */ "database", /* Used by: lock_status */
+ /* 44 */ "status",
+ /* 45 */ "cache_size", /* Used by: default_cache_size */
+ /* module_list pragma_list reuses 9 */
+ /* 46 */ "timeout", /* Used by: busy_timeout */
};
/* Definitions of all built-in pragmas */
@@ -119360,7 +119828,7 @@ typedef struct PragmaName {
u8 mPragFlg; /* Zero or more PragFlg_XXX values */
u8 iPragCName; /* Start of column names in pragCName[] */
u8 nPragCName; /* Num of col names. 0 means use pragma name */
- u32 iArg; /* Extra argument */
+ u64 iArg; /* Extra argument */
} PragmaName;
static const PragmaName aPragmaName[] = {
#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
@@ -119401,7 +119869,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "busy_timeout",
/* ePragTyp: */ PragTyp_BUSY_TIMEOUT,
/* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 49, 1,
+ /* ColNames: */ 46, 1,
/* iArg: */ 0 },
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
{/* zName: */ "cache_size",
@@ -119438,7 +119906,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "collation_list",
/* ePragTyp: */ PragTyp_COLLATION_LIST,
/* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 32, 2,
+ /* ColNames: */ 26, 2,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS)
@@ -119473,14 +119941,14 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "database_list",
/* ePragTyp: */ PragTyp_DATABASE_LIST,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0,
- /* ColNames: */ 26, 3,
+ /* ColNames: */ 35, 3,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
{/* zName: */ "default_cache_size",
/* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
- /* ColNames: */ 0, 1,
+ /* ColNames: */ 45, 1,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
@@ -119510,14 +119978,14 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "foreign_key_check",
/* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0,
- /* ColNames: */ 42, 4,
+ /* ColNames: */ 31, 4,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FOREIGN_KEY)
{/* zName: */ "foreign_key_list",
/* ePragTyp: */ PragTyp_FOREIGN_KEY_LIST,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
- /* ColNames: */ 34, 8,
+ /* ColNames: */ 0, 8,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
@@ -119553,7 +120021,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "function_list",
/* ePragTyp: */ PragTyp_FUNCTION_LIST,
/* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 29, 2,
+ /* ColNames: */ 41, 2,
/* iArg: */ 0 },
#endif
#endif
@@ -119562,12 +120030,12 @@ static const PragmaName aPragmaName[] = {
/* ePragTyp: */ PragTyp_HEXKEY,
/* ePragFlg: */ 0,
/* ColNames: */ 0, 0,
- /* iArg: */ 0 },
+ /* iArg: */ 2 },
{/* zName: */ "hexrekey",
/* ePragTyp: */ PragTyp_HEXKEY,
/* ePragFlg: */ 0,
/* ColNames: */ 0, 0,
- /* iArg: */ 0 },
+ /* iArg: */ 3 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
#if !defined(SQLITE_OMIT_CHECK)
@@ -119589,12 +120057,12 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "index_info",
/* ePragTyp: */ PragTyp_INDEX_INFO,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
- /* ColNames: */ 12, 3,
+ /* ColNames: */ 15, 3,
/* iArg: */ 0 },
{/* zName: */ "index_list",
/* ePragTyp: */ PragTyp_INDEX_LIST,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
- /* ColNames: */ 21, 5,
+ /* ColNames: */ 26, 5,
/* iArg: */ 0 },
{/* zName: */ "index_xinfo",
/* ePragTyp: */ PragTyp_INDEX_INFO,
@@ -119651,7 +120119,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "lock_status",
/* ePragTyp: */ PragTyp_LOCK_STATUS,
/* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 50, 2,
+ /* ColNames: */ 43, 2,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
@@ -119677,7 +120145,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "module_list",
/* ePragTyp: */ PragTyp_MODULE_LIST,
/* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 31, 1,
+ /* ColNames: */ 9, 1,
/* iArg: */ 0 },
#endif
#endif
@@ -119710,7 +120178,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "pragma_list",
/* ePragTyp: */ PragTyp_PRAGMA_LIST,
/* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 31, 1,
+ /* ColNames: */ 9, 1,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
@@ -119741,10 +120209,10 @@ static const PragmaName aPragmaName[] = {
#endif
#if defined(SQLITE_HAS_CODEC)
{/* zName: */ "rekey",
- /* ePragTyp: */ PragTyp_REKEY,
+ /* ePragTyp: */ PragTyp_KEY,
/* ePragFlg: */ 0,
/* ColNames: */ 0, 0,
- /* iArg: */ 0 },
+ /* iArg: */ 1 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
{/* zName: */ "reverse_unordered_selects",
@@ -119797,7 +120265,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "stats",
/* ePragTyp: */ PragTyp_STATS,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
- /* ColNames: */ 7, 5,
+ /* ColNames: */ 21, 5,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
@@ -119811,8 +120279,13 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "table_info",
/* ePragTyp: */ PragTyp_TABLE_INFO,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
- /* ColNames: */ 1, 6,
+ /* ColNames: */ 8, 6,
/* iArg: */ 0 },
+ {/* zName: */ "table_xinfo",
+ /* ePragTyp: */ PragTyp_TABLE_INFO,
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
+ /* ColNames: */ 8, 7,
+ /* iArg: */ 1 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
{/* zName: */ "temp_store",
@@ -119826,6 +120299,18 @@ static const PragmaName aPragmaName[] = {
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
#endif
+#if defined(SQLITE_HAS_CODEC)
+ {/* zName: */ "textkey",
+ /* ePragTyp: */ PragTyp_KEY,
+ /* ePragFlg: */ 0,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 4 },
+ {/* zName: */ "textrekey",
+ /* ePragTyp: */ PragTyp_KEY,
+ /* ePragFlg: */ 0,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 5 },
+#endif
{/* zName: */ "threads",
/* ePragTyp: */ PragTyp_THREADS,
/* ePragFlg: */ PragFlg_Result0,
@@ -119876,7 +120361,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "wal_checkpoint",
/* ePragTyp: */ PragTyp_WAL_CHECKPOINT,
/* ePragFlg: */ PragFlg_NeedSchema,
- /* ColNames: */ 46, 3,
+ /* ColNames: */ 38, 3,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
@@ -119884,10 +120369,10 @@ static const PragmaName aPragmaName[] = {
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
- /* iArg: */ SQLITE_WriteSchema },
+ /* iArg: */ SQLITE_WriteSchema|SQLITE_NoSchemaError },
#endif
};
-/* Number of pragmas: 61 on by default, 78 total. */
+/* Number of pragmas: 63 on by default, 82 total. */
/************** End of pragma.h **********************************************/
/************** Continuing where we left off in pragma.c *********************/
@@ -120920,7 +121405,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
setPragmaResultColumnNames(v, pPragma);
returnSingleInt(v, (db->flags & pPragma->iArg)!=0 );
}else{
- int mask = pPragma->iArg; /* Mask of bits to set or clear. */
+ u64 mask = pPragma->iArg; /* Mask of bits to set or clear. */
if( db->autoCommit==0 ){
/* Foreign key support may not be enabled or disabled while not
** in auto-commit mode. */
@@ -120969,15 +121454,17 @@ SQLITE_PRIVATE void sqlite3Pragma(
Table *pTab;
pTab = sqlite3LocateTable(pParse, LOCATE_NOERR, zRight, zDb);
if( pTab ){
+ int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
int i, k;
int nHidden = 0;
Column *pCol;
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
- pParse->nMem = 6;
- sqlite3CodeVerifySchema(pParse, iDb);
+ pParse->nMem = 7;
+ sqlite3CodeVerifySchema(pParse, iTabDb);
sqlite3ViewGetColumnNames(pParse, pTab);
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
- if( IsHiddenColumn(pCol) ){
+ int isHidden = IsHiddenColumn(pCol);
+ if( isHidden && pPragma->iArg==0 ){
nHidden++;
continue;
}
@@ -120989,13 +121476,14 @@ SQLITE_PRIVATE void sqlite3Pragma(
for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){}
}
assert( pCol->pDflt==0 || pCol->pDflt->op==TK_SPAN );
- sqlite3VdbeMultiLoad(v, 1, "issisi",
+ sqlite3VdbeMultiLoad(v, 1, pPragma->iArg ? "issisii" : "issisi",
i-nHidden,
pCol->zName,
sqlite3ColumnType(pCol,""),
pCol->notNull ? 1 : 0,
pCol->pDflt ? pCol->pDflt->u.zToken : 0,
- k);
+ k,
+ isHidden);
}
}
}
@@ -121033,6 +121521,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
Table *pTab;
pIdx = sqlite3FindIndex(db, zRight, zDb);
if( pIdx ){
+ int iIdxDb = sqlite3SchemaToIndex(db, pIdx->pSchema);
int i;
int mx;
if( pPragma->iArg ){
@@ -121045,7 +121534,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
pParse->nMem = 3;
}
pTab = pIdx->pTable;
- sqlite3CodeVerifySchema(pParse, iDb);
+ sqlite3CodeVerifySchema(pParse, iIdxDb);
assert( pParse->nMem<=pPragma->nPragCName );
for(i=0; i<mx; i++){
i16 cnum = pIdx->aiColumn[i];
@@ -121069,8 +121558,9 @@ SQLITE_PRIVATE void sqlite3Pragma(
int i;
pTab = sqlite3FindTable(db, zRight, zDb);
if( pTab ){
+ int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
pParse->nMem = 5;
- sqlite3CodeVerifySchema(pParse, iDb);
+ sqlite3CodeVerifySchema(pParse, iTabDb);
for(pIdx=pTab->pIndex, i=0; pIdx; pIdx=pIdx->pNext, i++){
const char *azOrigin[] = { "c", "u", "pk" };
sqlite3VdbeMultiLoad(v, 1, "isisi",
@@ -121117,6 +121607,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
pParse->nMem = 2;
for(i=0; i<SQLITE_FUNC_HASH_SZ; i++){
for(p=sqlite3BuiltinFunctions.a[i]; p; p=p->u.pHash ){
+ if( p->funcFlags & SQLITE_FUNC_INTERNAL ) continue;
sqlite3VdbeMultiLoad(v, 1, "si", p->zName, 1);
}
}
@@ -121158,9 +121649,10 @@ SQLITE_PRIVATE void sqlite3Pragma(
if( pTab ){
pFK = pTab->pFKey;
if( pFK ){
+ int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
int i = 0;
pParse->nMem = 8;
- sqlite3CodeVerifySchema(pParse, iDb);
+ sqlite3CodeVerifySchema(pParse, iTabDb);
while(pFK){
int j;
for(j=0; j<pFK->nCol; j++){
@@ -121205,9 +121697,9 @@ SQLITE_PRIVATE void sqlite3Pragma(
pParse->nMem += 4;
regKey = ++pParse->nMem;
regRow = ++pParse->nMem;
- sqlite3CodeVerifySchema(pParse, iDb);
k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash);
while( k ){
+ int iTabDb;
if( zRight ){
pTab = sqlite3LocateTable(pParse, 0, zRight, zDb);
k = 0;
@@ -121216,21 +121708,23 @@ SQLITE_PRIVATE void sqlite3Pragma(
k = sqliteHashNext(k);
}
if( pTab==0 || pTab->pFKey==0 ) continue;
- sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
+ iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+ sqlite3CodeVerifySchema(pParse, iTabDb);
+ sqlite3TableLock(pParse, iTabDb, pTab->tnum, 0, pTab->zName);
if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow;
- sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead);
+ sqlite3OpenTable(pParse, 0, iTabDb, pTab, OP_OpenRead);
sqlite3VdbeLoadString(v, regResult, pTab->zName);
for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
pParent = sqlite3FindTable(db, pFK->zTo, zDb);
if( pParent==0 ) continue;
pIdx = 0;
- sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName);
+ sqlite3TableLock(pParse, iTabDb, pParent->tnum, 0, pParent->zName);
x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0);
if( x==0 ){
if( pIdx==0 ){
- sqlite3OpenTable(pParse, i, iDb, pParent, OP_OpenRead);
+ sqlite3OpenTable(pParse, i, iTabDb, pParent, OP_OpenRead);
}else{
- sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iDb);
+ sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iTabDb);
sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
}
}else{
@@ -121999,12 +122493,24 @@ SQLITE_PRIVATE void sqlite3Pragma(
#endif
#ifdef SQLITE_HAS_CODEC
+ /* Pragma iArg
+ ** ---------- ------
+ ** key 0
+ ** rekey 1
+ ** hexkey 2
+ ** hexrekey 3
+ ** textkey 4
+ ** textrekey 5
+ */
case PragTyp_KEY: {
- if( zRight ) sqlite3_key_v2(db, zDb, zRight, sqlite3Strlen30(zRight));
- break;
- }
- case PragTyp_REKEY: {
- if( zRight ) sqlite3_rekey_v2(db, zDb, zRight, sqlite3Strlen30(zRight));
+ if( zRight ){
+ int n = pPragma->iArg<4 ? sqlite3Strlen30(zRight) : -1;
+ if( (pPragma->iArg & 1)==0 ){
+ sqlite3_key_v2(db, zDb, zRight, n);
+ }else{
+ sqlite3_rekey_v2(db, zDb, zRight, n);
+ }
+ }
break;
}
case PragTyp_HEXKEY: {
@@ -122016,7 +122522,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
iByte = (iByte<<4) + sqlite3HexToInt(zRight[i]);
if( (i&1)!=0 ) zKey[i/2] = iByte;
}
- if( (zLeft[3] & 0xf)==0xb ){
+ if( (pPragma->iArg & 1)==0 ){
sqlite3_key_v2(db, zDb, zKey, i/2);
}else{
sqlite3_rekey_v2(db, zDb, zKey, i/2);
@@ -122346,7 +122852,8 @@ static const sqlite3_module pragmaVtabModule = {
0, /* xRename - rename the table */
0, /* xSavepoint */
0, /* xRelease */
- 0 /* xRollbackTo */
+ 0, /* xRollbackTo */
+ 0 /* xShadowName */
};
/*
@@ -122699,8 +123206,8 @@ SQLITE_PRIVATE int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFl
rc = SQLITE_NOMEM_BKPT;
sqlite3ResetAllSchemasOfConnection(db);
}
- if( rc==SQLITE_OK || (db->flags&SQLITE_WriteSchema)){
- /* Black magic: If the SQLITE_WriteSchema flag is set, then consider
+ if( rc==SQLITE_OK || (db->flags&SQLITE_NoSchemaError)){
+ /* Black magic: If the SQLITE_NoSchemaError flag is set, then consider
** the schema loaded, even if errors occurred. In this situation the
** current sqlite3_prepare() operation will fail, but the following one
** will attempt to compile the supplied statement against whatever subset
@@ -123081,6 +123588,294 @@ static int sqlite3LockAndPrepare(
return rc;
}
+#ifdef SQLITE_ENABLE_NORMALIZE
+/*
+** Checks if the specified token is a table, column, or function name,
+** based on the databases associated with the statement being prepared.
+** If the function fails, zero is returned and pRc is filled with the
+** error code.
+*/
+static int shouldTreatAsIdentifier(
+ sqlite3 *db, /* Database handle. */
+ const char *zToken, /* Pointer to start of token to be checked */
+ int nToken, /* Length of token to be checked */
+ int *pRc /* Pointer to error code upon failure */
+){
+ int bFound = 0; /* Non-zero if token is an identifier name. */
+ int i, j; /* Database and column loop indexes. */
+ Schema *pSchema; /* Schema for current database. */
+ Hash *pHash; /* Hash table of tables for current database. */
+ HashElem *e; /* Hash element for hash table iteration. */
+ Table *pTab; /* Database table for columns being checked. */
+
+ if( sqlite3IsRowidN(zToken, nToken) ){
+ return 1;
+ }
+ if( nToken>0 ){
+ int hash = SQLITE_FUNC_HASH(sqlite3UpperToLower[(u8)zToken[0]], nToken);
+ if( sqlite3FunctionSearchN(hash, zToken, nToken) ) return 1;
+ }
+ assert( db!=0 );
+ sqlite3_mutex_enter(db->mutex);
+ sqlite3BtreeEnterAll(db);
+ for(i=0; i<db->nDb; i++){
+ pHash = &db->aFunc;
+ if( sqlite3HashFindN(pHash, zToken, nToken) ){
+ bFound = 1;
+ break;
+ }
+ pSchema = db->aDb[i].pSchema;
+ if( pSchema==0 ) continue;
+ pHash = &pSchema->tblHash;
+ if( sqlite3HashFindN(pHash, zToken, nToken) ){
+ bFound = 1;
+ break;
+ }
+ for(e=sqliteHashFirst(pHash); e; e=sqliteHashNext(e)){
+ pTab = sqliteHashData(e);
+ if( pTab==0 ) continue;
+ pHash = pTab->pColHash;
+ if( pHash==0 ){
+ pTab->pColHash = pHash = sqlite3_malloc(sizeof(Hash));
+ if( pHash ){
+ sqlite3HashInit(pHash);
+ for(j=0; j<pTab->nCol; j++){
+ Column *pCol = &pTab->aCol[j];
+ sqlite3HashInsert(pHash, pCol->zName, pCol);
+ }
+ }else{
+ *pRc = SQLITE_NOMEM_BKPT;
+ bFound = 0;
+ goto done;
+ }
+ }
+ if( pHash && sqlite3HashFindN(pHash, zToken, nToken) ){
+ bFound = 1;
+ goto done;
+ }
+ }
+ }
+done:
+ sqlite3BtreeLeaveAll(db);
+ sqlite3_mutex_leave(db->mutex);
+ return bFound;
+}
+
+/*
+** Attempt to estimate the final output buffer size needed for the fully
+** normalized version of the specified SQL string. This should take into
+** account any potential expansion that could occur (e.g. via IN clauses
+** being expanded, etc). This size returned is the total number of bytes
+** including the NUL terminator.
+*/
+static int estimateNormalizedSize(
+ const char *zSql, /* The original SQL string */
+ int nSql, /* Length of original SQL string */
+ u8 prepFlags /* The flags passed to sqlite3_prepare_v3() */
+){
+ int nOut = nSql + 4;
+ const char *z = zSql;
+ while( nOut<nSql*5 ){
+ while( z[0]!=0 && z[0]!='I' && z[0]!='i' ){ z++; }
+ if( z[0]==0 ) break;
+ z++;
+ if( z[0]!='N' && z[0]!='n' ) break;
+ z++;
+ while( sqlite3Isspace(z[0]) ){ z++; }
+ if( z[0]!='(' ) break;
+ z++;
+ nOut += 5; /* ?,?,? */
+ }
+ return nOut;
+}
+
+/*
+** Copy the current token into the output buffer while dealing with quoted
+** identifiers. By default, all letters will be converted into lowercase.
+** If the bUpper flag is set, uppercase will be used. The piOut argument
+** will be used to update the target index into the output string.
+*/
+static void copyNormalizedToken(
+ const char *zSql, /* The original SQL string */
+ int iIn, /* Current index into the original SQL string */
+ int nToken, /* Number of bytes in the current token */
+ int tokenFlags, /* Flags returned by the tokenizer */
+ char *zOut, /* The output string */
+ int *piOut /* Pointer to target index into the output string */
+){
+ int bQuoted = tokenFlags & SQLITE_TOKEN_QUOTED;
+ int bKeyword = tokenFlags & SQLITE_TOKEN_KEYWORD;
+ int j = *piOut, k = 0;
+ for(; k<nToken; k++){
+ if( bQuoted ){
+ if( k==0 && iIn>0 ){
+ zOut[j++] = '"';
+ continue;
+ }else if( k==nToken-1 ){
+ zOut[j++] = '"';
+ continue;
+ }
+ }
+ if( bKeyword ){
+ zOut[j++] = sqlite3Toupper(zSql[iIn+k]);
+ }else{
+ zOut[j++] = sqlite3Tolower(zSql[iIn+k]);
+ }
+ }
+ *piOut = j;
+}
+
+/*
+** Perform normalization of the SQL contained in the prepared statement and
+** store the result in the zNormSql field. The schema for the associated
+** databases are consulted while performing the normalization in order to
+** determine if a token appears to be an identifier. All identifiers are
+** left intact in the normalized SQL and all literals are replaced with a
+** single '?'.
+*/
+SQLITE_PRIVATE void sqlite3Normalize(
+ Vdbe *pVdbe, /* VM being reprepared */
+ const char *zSql, /* The original SQL string */
+ int nSql, /* Size of the input string in bytes */
+ u8 prepFlags /* The flags passed to sqlite3_prepare_v3() */
+){
+ sqlite3 *db; /* Database handle. */
+ char *z; /* The output string */
+ int nZ; /* Size of the output string in bytes */
+ int i; /* Next character to read from zSql[] */
+ int j; /* Next character to fill in on z[] */
+ int tokenType = 0; /* Type of the next token */
+ int prevTokenType = 0; /* Type of the previous token, except spaces */
+ int n; /* Size of the next token */
+ int nParen = 0; /* Nesting level of parenthesis */
+ Hash inHash; /* Table of parenthesis levels to output index. */
+
+ db = sqlite3VdbeDb(pVdbe);
+ assert( db!=0 );
+ assert( pVdbe->zNormSql==0 );
+ if( zSql==0 ) return;
+ nZ = estimateNormalizedSize(zSql, nSql, prepFlags);
+ z = sqlite3DbMallocRawNN(db, nZ);
+ if( z==0 ) return;
+ sqlite3HashInit(&inHash);
+ for(i=j=0; i<nSql && zSql[i]; i+=n){
+ int flags = 0;
+ if( tokenType!=TK_SPACE ) prevTokenType = tokenType;
+ n = sqlite3GetTokenNormalized((unsigned char*)zSql+i, &tokenType, &flags);
+ switch( tokenType ){
+ case TK_SPACE: {
+ break;
+ }
+ case TK_ILLEGAL: {
+ sqlite3DbFree(db, z);
+ sqlite3HashClear(&inHash);
+ return;
+ }
+ case TK_STRING:
+ case TK_INTEGER:
+ case TK_FLOAT:
+ case TK_VARIABLE:
+ case TK_BLOB: {
+ z[j++] = '?';
+ break;
+ }
+ case TK_LP:
+ case TK_RP: {
+ if( tokenType==TK_LP ){
+ nParen++;
+ if( prevTokenType==TK_IN ){
+ assert( nParen<nSql );
+ sqlite3HashInsert(&inHash, zSql+nParen, SQLITE_INT_TO_PTR(j));
+ }
+ }else{
+ int jj;
+ assert( nParen<nSql );
+ jj = SQLITE_PTR_TO_INT(sqlite3HashFind(&inHash, zSql+nParen));
+ if( jj>0 ){
+ sqlite3HashInsert(&inHash, zSql+nParen, 0);
+ assert( jj+6<nZ );
+ memcpy(z+jj+1, "?,?,?", 5);
+ j = jj+6;
+ assert( nZ-1-j>=0 );
+ assert( nZ-1-j<nZ );
+ memset(z+j, 0, nZ-1-j);
+ }
+ nParen--;
+ }
+ assert( nParen>=0 );
+ /* Fall through */
+ }
+ case TK_MINUS:
+ case TK_SEMI:
+ case TK_PLUS:
+ case TK_STAR:
+ case TK_SLASH:
+ case TK_REM:
+ case TK_EQ:
+ case TK_LE:
+ case TK_NE:
+ case TK_LSHIFT:
+ case TK_LT:
+ case TK_RSHIFT:
+ case TK_GT:
+ case TK_GE:
+ case TK_BITOR:
+ case TK_CONCAT:
+ case TK_COMMA:
+ case TK_BITAND:
+ case TK_BITNOT:
+ case TK_DOT:
+ case TK_IN:
+ case TK_IS:
+ case TK_NOT:
+ case TK_NULL:
+ case TK_ID: {
+ if( tokenType==TK_NULL ){
+ if( prevTokenType==TK_IS || prevTokenType==TK_NOT ){
+ /* NULL is a keyword in this case, not a literal value */
+ }else{
+ /* Here the NULL is a literal value */
+ z[j++] = '?';
+ break;
+ }
+ }
+ if( j>0 && sqlite3IsIdChar(z[j-1]) && sqlite3IsIdChar(zSql[i]) ){
+ z[j++] = ' ';
+ }
+ if( tokenType==TK_ID ){
+ int i2 = i, n2 = n, rc = SQLITE_OK;
+ if( nParen>0 ){
+ assert( nParen<nSql );
+ sqlite3HashInsert(&inHash, zSql+nParen, 0);
+ }
+ if( flags&SQLITE_TOKEN_QUOTED ){ i2++; n2-=2; }
+ if( shouldTreatAsIdentifier(db, zSql+i2, n2, &rc)==0 ){
+ if( rc!=SQLITE_OK ){
+ sqlite3DbFree(db, z);
+ sqlite3HashClear(&inHash);
+ return;
+ }
+ if( sqlite3_keyword_check(zSql+i2, n2)==0 ){
+ z[j++] = '?';
+ break;
+ }
+ }
+ }
+ copyNormalizedToken(zSql, i, n, flags, z, &j);
+ break;
+ }
+ }
+ }
+ assert( j<nZ && "one" );
+ while( j>0 && z[j-1]==' ' ){ j--; }
+ if( j>0 && z[j-1]!=';' ){ z[j++] = ';'; }
+ z[j] = 0;
+ assert( j<nZ && "two" );
+ pVdbe->zNormSql = z;
+ sqlite3HashClear(&inHash);
+}
+#endif /* SQLITE_ENABLE_NORMALIZE */
+
/*
** Rerun the compilation of a statement after a schema change.
**
@@ -124093,7 +124888,7 @@ static void selectExprDefer(
struct ExprList_item *pItem = &pEList->a[i];
if( pItem->u.x.iOrderByCol==0 ){
Expr *pExpr = pItem->pExpr;
- Table *pTab = pExpr->pTab;
+ Table *pTab = pExpr->y.pTab;
if( pExpr->op==TK_COLUMN && pExpr->iColumn>=0 && pTab && !IsVirtual(pTab)
&& (pTab->aCol[pExpr->iColumn].colFlags & COLFLAG_SORTERREF)
){
@@ -124116,12 +124911,12 @@ static void selectExprDefer(
Expr *pNew = sqlite3PExpr(pParse, TK_COLUMN, 0, 0);
if( pNew ){
pNew->iTable = pExpr->iTable;
- pNew->pTab = pExpr->pTab;
+ pNew->y.pTab = pExpr->y.pTab;
pNew->iColumn = pPk ? pPk->aiColumn[k] : -1;
pExtra = sqlite3ExprListAppend(pParse, pExtra, pNew);
}
}
- pSort->aDefer[nDefer].pTab = pExpr->pTab;
+ pSort->aDefer[nDefer].pTab = pExpr->y.pTab;
pSort->aDefer[nDefer].iCsr = pExpr->iTable;
pSort->aDefer[nDefer].nKey = nKey;
nDefer++;
@@ -124970,7 +125765,7 @@ static const char *columnTypeImpl(
break;
}
- assert( pTab && pExpr->pTab==pTab );
+ assert( pTab && pExpr->y.pTab==pTab );
if( pS ){
/* The "table" is actually a sub-select or a view in the FROM clause
** of the SELECT statement. Return the declaration type and origin
@@ -125155,7 +125950,7 @@ static void generateColumnNames(
assert( p!=0 );
assert( p->op!=TK_AGG_COLUMN ); /* Agg processing has not run yet */
- assert( p->op!=TK_COLUMN || p->pTab!=0 ); /* Covering idx not yet coded */
+ assert( p->op!=TK_COLUMN || p->y.pTab!=0 ); /* Covering idx not yet coded */
if( pEList->a[i].zName ){
/* An AS clause always takes first priority */
char *zName = pEList->a[i].zName;
@@ -125163,7 +125958,7 @@ static void generateColumnNames(
}else if( srcName && p->op==TK_COLUMN ){
char *zCol;
int iCol = p->iColumn;
- pTab = p->pTab;
+ pTab = p->y.pTab;
assert( pTab!=0 );
if( iCol<0 ) iCol = pTab->iPKey;
assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
@@ -125254,7 +126049,7 @@ SQLITE_PRIVATE int sqlite3ColumnsFromExprList(
if( pColExpr->op==TK_COLUMN ){
/* For columns use the column name name */
int iCol = pColExpr->iColumn;
- Table *pTab = pColExpr->pTab;
+ Table *pTab = pColExpr->y.pTab;
assert( pTab!=0 );
if( iCol<0 ) iCol = pTab->iPKey;
zName = iCol>=0 ? pTab->aCol[iCol].zName : "rowid";
@@ -128754,14 +129549,19 @@ static struct SrcList_item *isSelfJoinView(
){
struct SrcList_item *pItem;
for(pItem = pTabList->a; pItem<pThis; pItem++){
+ Select *pS1;
if( pItem->pSelect==0 ) continue;
if( pItem->fg.viaCoroutine ) continue;
if( pItem->zName==0 ) continue;
if( sqlite3_stricmp(pItem->zDatabase, pThis->zDatabase)!=0 ) continue;
if( sqlite3_stricmp(pItem->zName, pThis->zName)!=0 ) continue;
- if( sqlite3ExprCompare(0,
- pThis->pSelect->pWhere, pItem->pSelect->pWhere, -1)
- ){
+ pS1 = pItem->pSelect;
+ if( pThis->pSelect->selId!=pS1->selId ){
+ /* The query flattener left two different CTE tables with identical
+ ** names in the same FROM clause. */
+ continue;
+ }
+ if( sqlite3ExprCompare(0, pThis->pSelect->pWhere, pS1->pWhere, -1) ){
/* The view was modified by some other optimization such as
** pushDownWhereTerms() */
continue;
@@ -131380,6 +132180,57 @@ SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
}
/*
+** Check to see if column iCol of index pIdx references any of the
+** columns defined by aXRef and chngRowid. Return true if it does
+** and false if not. This is an optimization. False-positives are a
+** performance degradation, but false-negatives can result in a corrupt
+** index and incorrect answers.
+**
+** aXRef[j] will be non-negative if column j of the original table is
+** being updated. chngRowid will be true if the rowid of the table is
+** being updated.
+*/
+static int indexColumnIsBeingUpdated(
+ Index *pIdx, /* The index to check */
+ int iCol, /* Which column of the index to check */
+ int *aXRef, /* aXRef[j]>=0 if column j is being updated */
+ int chngRowid /* true if the rowid is being updated */
+){
+ i16 iIdxCol = pIdx->aiColumn[iCol];
+ assert( iIdxCol!=XN_ROWID ); /* Cannot index rowid */
+ if( iIdxCol>=0 ){
+ return aXRef[iIdxCol]>=0;
+ }
+ assert( iIdxCol==XN_EXPR );
+ assert( pIdx->aColExpr!=0 );
+ assert( pIdx->aColExpr->a[iCol].pExpr!=0 );
+ return sqlite3ExprReferencesUpdatedColumn(pIdx->aColExpr->a[iCol].pExpr,
+ aXRef,chngRowid);
+}
+
+/*
+** Check to see if index pIdx is a partial index whose conditional
+** expression might change values due to an UPDATE. Return true if
+** the index is subject to change and false if the index is guaranteed
+** to be unchanged. This is an optimization. False-positives are a
+** performance degradation, but false-negatives can result in a corrupt
+** index and incorrect answers.
+**
+** aXRef[j] will be non-negative if column j of the original table is
+** being updated. chngRowid will be true if the rowid of the table is
+** being updated.
+*/
+static int indexWhereClauseMightChange(
+ Index *pIdx, /* The index to check */
+ int *aXRef, /* aXRef[j]>=0 if column j is being updated */
+ int chngRowid /* true if the rowid is being updated */
+){
+ if( pIdx->pPartIdxWhere==0 ) return 0;
+ return sqlite3ExprReferencesUpdatedColumn(pIdx->pPartIdxWhere,
+ aXRef, chngRowid);
+}
+
+/*
** Process an UPDATE statement.
**
** UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL;
@@ -131602,19 +132453,18 @@ SQLITE_PRIVATE void sqlite3Update(
/* There is one entry in the aRegIdx[] array for each index on the table
** being updated. Fill in aRegIdx[] with a register number that will hold
** the key for accessing each index.
- **
- ** FIXME: Be smarter about omitting indexes that use expressions.
*/
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
int reg;
- if( chngKey || hasFK>1 || pIdx->pPartIdxWhere || pIdx==pPk ){
+ if( chngKey || hasFK>1 || pIdx==pPk
+ || indexWhereClauseMightChange(pIdx,aXRef,chngRowid)
+ ){
reg = ++pParse->nMem;
pParse->nMem += pIdx->nColumn;
}else{
reg = 0;
for(i=0; i<pIdx->nKeyCol; i++){
- i16 iIdxCol = pIdx->aiColumn[i];
- if( iIdxCol<0 || aXRef[iIdxCol]>=0 ){
+ if( indexColumnIsBeingUpdated(pIdx, i, aXRef, chngRowid) ){
reg = ++pParse->nMem;
pParse->nMem += pIdx->nColumn;
if( (onError==OE_Replace)
@@ -132664,7 +133514,8 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
saved_mTrace = db->mTrace;
db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks;
db->mDbFlags |= DBFLAG_PreferBuiltin | DBFLAG_Vacuum;
- db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder | SQLITE_CountRows);
+ db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder
+ | SQLITE_Defensive | SQLITE_CountRows);
db->mTrace = 0;
zDbMain = db->aDb[iDb].zDbSName;
@@ -133206,7 +134057,6 @@ SQLITE_PRIVATE void sqlite3VtabBeginParse(
Token *pModuleName, /* Name of the module for the virtual table */
int ifNotExists /* No error if the table already exists */
){
- int iDb; /* The database the table is being created in */
Table *pTable; /* The new virtual table */
sqlite3 *db; /* Database connection */
@@ -133216,8 +134066,6 @@ SQLITE_PRIVATE void sqlite3VtabBeginParse(
assert( 0==pTable->pIndex );
db = pParse->db;
- iDb = sqlite3SchemaToIndex(db, pTable->pSchema);
- assert( iDb>=0 );
assert( pTable->nModuleArg==0 );
addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName));
@@ -133237,6 +134085,8 @@ SQLITE_PRIVATE void sqlite3VtabBeginParse(
** The second call, to obtain permission to create the table, is made now.
*/
if( pTable->azModuleArg ){
+ int iDb = sqlite3SchemaToIndex(db, pTable->pSchema);
+ assert( iDb>=0 ); /* The database the table is being created in */
sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName,
pTable->azModuleArg[0], pParse->db->aDb[iDb].zDbSName);
}
@@ -133931,7 +134781,7 @@ SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(
/* Check to see the left operand is a column in a virtual table */
if( NEVER(pExpr==0) ) return pDef;
if( pExpr->op!=TK_COLUMN ) return pDef;
- pTab = pExpr->pTab;
+ pTab = pExpr->y.pTab;
if( pTab==0 ) return pDef;
if( !IsVirtual(pTab) ) return pDef;
pVtab = sqlite3GetVTable(db, pTab)->pVtab;
@@ -134551,12 +135401,33 @@ struct WhereLoopBuilder {
int nRecValid; /* Number of valid fields currently in pRec */
#endif
unsigned int bldFlags; /* SQLITE_BLDF_* flags */
+ unsigned int iPlanLimit; /* Search limiter */
};
/* Allowed values for WhereLoopBuider.bldFlags */
#define SQLITE_BLDF_INDEXED 0x0001 /* An index is used */
#define SQLITE_BLDF_UNIQUE 0x0002 /* All keys of a UNIQUE index used */
+/* The WhereLoopBuilder.iPlanLimit is used to limit the number of
+** index+constraint combinations the query planner will consider for a
+** particular query. If this parameter is unlimited, then certain
+** pathological queries can spend excess time in the sqlite3WhereBegin()
+** routine. The limit is high enough that is should not impact real-world
+** queries.
+**
+** SQLITE_QUERY_PLANNER_LIMIT is the baseline limit. The limit is
+** increased by SQLITE_QUERY_PLANNER_LIMIT_INCR before each term of the FROM
+** clause is processed, so that every table in a join is guaranteed to be
+** able to propose a some index+constraint combinations even if the initial
+** baseline limit was exhausted by prior tables of the join.
+*/
+#ifndef SQLITE_QUERY_PLANNER_LIMIT
+# define SQLITE_QUERY_PLANNER_LIMIT 20000
+#endif
+#ifndef SQLITE_QUERY_PLANNER_LIMIT_INCR
+# define SQLITE_QUERY_PLANNER_LIMIT_INCR 1000
+#endif
+
/*
** The WHERE clause processing routine has two halves. The
** first part does the start of the WHERE loop and the second
@@ -135810,7 +136681,7 @@ static int whereIndexExprTransNode(Walker *p, Expr *pExpr){
pExpr->op = TK_COLUMN;
pExpr->iTable = pX->iIdxCur;
pExpr->iColumn = pX->iIdxCol;
- pExpr->pTab = 0;
+ pExpr->y.pTab = 0;
return WRC_Prune;
}else{
return WRC_Continue;
@@ -137210,7 +138081,7 @@ static int isLikeOrGlob(
){
if( pLeft->op!=TK_COLUMN
|| sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT
- || IsVirtual(pLeft->pTab) /* Value might be numeric */
+ || IsVirtual(pLeft->y.pTab) /* Value might be numeric */
){
sqlite3ExprDelete(db, pPrefix);
sqlite3ValueFree(pVal);
@@ -137311,7 +138182,7 @@ static int isAuxiliaryVtabOperator(
** MATCH(expression,vtab_column)
*/
pCol = pList->a[1].pExpr;
- if( pCol->op==TK_COLUMN && IsVirtual(pCol->pTab) ){
+ if( pCol->op==TK_COLUMN && IsVirtual(pCol->y.pTab) ){
for(i=0; i<ArraySize(aOp); i++){
if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){
*peOp2 = aOp[i].eOp2;
@@ -137333,12 +138204,12 @@ static int isAuxiliaryVtabOperator(
** with function names in an arbitrary case.
*/
pCol = pList->a[0].pExpr;
- if( pCol->op==TK_COLUMN && IsVirtual(pCol->pTab) ){
+ if( pCol->op==TK_COLUMN && IsVirtual(pCol->y.pTab) ){
sqlite3_vtab *pVtab;
sqlite3_module *pMod;
void (*xNotUsed)(sqlite3_context*,int,sqlite3_value**);
void *pNotUsed;
- pVtab = sqlite3GetVTable(db, pCol->pTab)->pVtab;
+ pVtab = sqlite3GetVTable(db, pCol->y.pTab)->pVtab;
assert( pVtab!=0 );
assert( pVtab->pModule!=0 );
pMod = (sqlite3_module *)pVtab->pModule;
@@ -137356,10 +138227,10 @@ static int isAuxiliaryVtabOperator(
int res = 0;
Expr *pLeft = pExpr->pLeft;
Expr *pRight = pExpr->pRight;
- if( pLeft->op==TK_COLUMN && IsVirtual(pLeft->pTab) ){
+ if( pLeft->op==TK_COLUMN && IsVirtual(pLeft->y.pTab) ){
res++;
}
- if( pRight && pRight->op==TK_COLUMN && IsVirtual(pRight->pTab) ){
+ if( pRight && pRight->op==TK_COLUMN && IsVirtual(pRight->y.pTab) ){
res++;
SWAP(Expr*, pLeft, pRight);
}
@@ -138503,6 +139374,7 @@ SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(
pArgs = pItem->u1.pFuncArg;
if( pArgs==0 ) return;
for(j=k=0; j<pArgs->nExpr; j++){
+ Expr *pRhs;
while( k<pTab->nCol && (pTab->aCol[k].colFlags & COLFLAG_HIDDEN)==0 ){k++;}
if( k>=pTab->nCol ){
sqlite3ErrorMsg(pParse, "too many arguments on %s() - max %d",
@@ -138513,9 +139385,10 @@ SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(
if( pColRef==0 ) return;
pColRef->iTable = pItem->iCursor;
pColRef->iColumn = k++;
- pColRef->pTab = pTab;
- pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef,
- sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0));
+ pColRef->y.pTab = pTab;
+ pRhs = sqlite3PExpr(pParse, TK_UPLUS,
+ sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0), 0);
+ pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, pRhs);
whereClauseInsert(pWC, pTerm, TERM_DYNAMIC);
}
}
@@ -139378,7 +140251,6 @@ static void constructAutomaticIndex(
translateColumnToCopy(pParse, addrTop, pLevel->iTabCur,
pTabItem->regResult, 1);
sqlite3VdbeGoto(v, addrTop);
- pTabItem->fg.viaCoroutine = 0;
}else{
sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); VdbeCoverage(v);
}
@@ -139556,9 +140428,11 @@ static sqlite3_index_info *allocateIndexInfo(
** method of the virtual table with the sqlite3_index_info object that
** comes in as the 3rd argument to this function.
**
-** If an error occurs, pParse is populated with an error message and a
-** non-zero value is returned. Otherwise, 0 is returned and the output
-** part of the sqlite3_index_info structure is left populated.
+** If an error occurs, pParse is populated with an error message and an
+** appropriate error code is returned. A return of SQLITE_CONSTRAINT from
+** xBestIndex is not considered an error. SQLITE_CONSTRAINT indicates that
+** the current configuration of "unusable" flags in sqlite3_index_info can
+** not result in a valid plan.
**
** Whether or not an error is returned, it is the responsibility of the
** caller to eventually free p->idxStr if p->needToFreeIdxStr indicates
@@ -139572,7 +140446,7 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
rc = pVtab->pModule->xBestIndex(pVtab, p);
TRACE_IDX_OUTPUTS(p);
- if( rc!=SQLITE_OK ){
+ if( rc!=SQLITE_OK && rc!=SQLITE_CONSTRAINT ){
if( rc==SQLITE_NOMEM ){
sqlite3OomFault(pParse->db);
}else if( !pVtab->zErrMsg ){
@@ -139583,19 +140457,7 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
}
sqlite3_free(pVtab->zErrMsg);
pVtab->zErrMsg = 0;
-
-#if 0
- /* This error is now caught by the caller.
- ** Search for "xBestIndex malfunction" below */
- for(i=0; i<p->nConstraint; i++){
- if( !p->aConstraint[i].usable && p->aConstraintUsage[i].argvIndex>0 ){
- sqlite3ErrorMsg(pParse,
- "table %s: xBestIndex returned an invalid plan", pTab->zName);
- }
- }
-#endif
-
- return pParse->nErr;
+ return rc;
}
#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */
@@ -140650,6 +141512,14 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
sqlite3 *db = pWInfo->pParse->db;
int rc;
+ /* Stop the search once we hit the query planner search limit */
+ if( pBuilder->iPlanLimit==0 ){
+ WHERETRACE(0xffffffff,("=== query planner search limit reached ===\n"));
+ if( pBuilder->pOrSet ) pBuilder->pOrSet->n = 0;
+ return SQLITE_DONE;
+ }
+ pBuilder->iPlanLimit--;
+
/* If pBuilder->pOrSet is defined, then only keep track of the costs
** and prereqs.
*/
@@ -141660,7 +142530,17 @@ static int whereLoopAddVirtualOne(
/* Invoke the virtual table xBestIndex() method */
rc = vtabBestIndex(pParse, pSrc->pTab, pIdxInfo);
- if( rc ) return rc;
+ if( rc ){
+ if( rc==SQLITE_CONSTRAINT ){
+ /* If the xBestIndex method returns SQLITE_CONSTRAINT, that means
+ ** that the particular combination of parameters provided is unusable.
+ ** Make no entries in the loop table.
+ */
+ WHERETRACE(0xffff, (" ^^^^--- non-viable plan rejected!\n"));
+ return SQLITE_OK;
+ }
+ return rc;
+ }
mxTerm = -1;
assert( pNew->nLSlot>=nConstraint );
@@ -142056,9 +142936,11 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
/* Loop over the tables in the join, from left to right */
pNew = pBuilder->pNew;
whereLoopInit(pNew);
+ pBuilder->iPlanLimit = SQLITE_QUERY_PLANNER_LIMIT;
for(iTab=0, pItem=pTabList->a; pItem<pEnd; iTab++, pItem++){
Bitmask mUnusable = 0;
pNew->iTab = iTab;
+ pBuilder->iPlanLimit += SQLITE_QUERY_PLANNER_LIMIT_INCR;
pNew->maskSelf = sqlite3WhereGetMask(&pWInfo->sMaskSet, pItem->iCursor);
if( ((pItem->fg.jointype|priorJointype) & (JT_LEFT|JT_CROSS))!=0 ){
/* This condition is true when pItem is the FROM clause term on the
@@ -142084,7 +142966,15 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
rc = whereLoopAddOr(pBuilder, mPrereq, mUnusable);
}
mPrior |= pNew->maskSelf;
- if( rc || db->mallocFailed ) break;
+ if( rc || db->mallocFailed ){
+ if( rc==SQLITE_DONE ){
+ /* We hit the query planner search limit set by iPlanLimit */
+ sqlite3_log(SQLITE_WARNING, "abbreviated query algorithm search");
+ rc = SQLITE_OK;
+ }else{
+ break;
+ }
+ }
}
whereLoopClear(db, pNew);
@@ -144466,12 +145356,12 @@ static int selectWindowRewriteExprCb(Walker *pWalker, Expr *pExpr){
switch( pExpr->op ){
case TK_FUNCTION:
- if( pExpr->pWin==0 ){
+ if( !ExprHasProperty(pExpr, EP_WinFunc) ){
break;
}else{
Window *pWin;
for(pWin=p->pWin; pWin; pWin=pWin->pNextWin){
- if( pExpr->pWin==pWin ){
+ if( pExpr->y.pWin==pWin ){
assert( pWin->pOwner==pExpr );
return WRC_Prune;
}
@@ -144588,7 +145478,7 @@ static ExprList *exprListAppendList(
*/
SQLITE_PRIVATE int sqlite3WindowRewrite(Parse *pParse, Select *p){
int rc = SQLITE_OK;
- if( p->pWin ){
+ if( p->pWin && p->pPrior==0 ){
Vdbe *v = sqlite3GetVdbe(pParse);
sqlite3 *db = pParse->db;
Select *pSub = 0; /* The subquery */
@@ -144801,11 +145691,13 @@ windowAllocErr:
*/
SQLITE_PRIVATE void sqlite3WindowAttach(Parse *pParse, Expr *p, Window *pWin){
if( p ){
+ assert( p->op==TK_FUNCTION );
/* This routine is only called for the parser. If pWin was not
** allocated due to an OOM, then the parser would fail before ever
** invoking this routine */
if( ALWAYS(pWin) ){
- p->pWin = pWin;
+ p->y.pWin = pWin;
+ ExprSetProperty(p, EP_WinFunc);
pWin->pOwner = p;
if( p->flags & EP_Distinct ){
sqlite3ErrorMsg(pParse,
@@ -145968,7 +146860,7 @@ static void windowCodeDefaultStep(
*/
SQLITE_PRIVATE Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p){
Window *pNew = 0;
- if( p ){
+ if( ALWAYS(p) ){
pNew = sqlite3DbMallocZero(db, sizeof(Window));
if( pNew ){
pNew->zName = sqlite3DbStrDup(db, p->zName);
@@ -146120,6 +147012,7 @@ SQLITE_PRIVATE void sqlite3WindowCodeStep(
** input grammar file:
*/
/* #include <stdio.h> */
+/* #include <assert.h> */
/************ Begin %include sections from the grammar ************************/
/* #include "sqliteInt.h" */
@@ -146221,13 +147114,10 @@ static void disableLookaside(Parse *pParse){
p->pLeft = p->pRight = 0;
p->x.pList = 0;
p->pAggInfo = 0;
- p->pTab = 0;
+ p->y.pTab = 0;
p->op2 = 0;
p->iTable = 0;
p->iColumn = 0;
-#ifndef SQLITE_OMIT_WINDOWFUNC
- p->pWin = 0;
-#endif
p->u.zToken = (char*)&p[1];
memcpy(p->u.zToken, t.z, t.n);
p->u.zToken[t.n] = 0;
@@ -150122,10 +151012,9 @@ SQLITE_PRIVATE void sqlite3Parser(
yymajor = YYNOCODE;
}else{
while( yypParser->yytos >= yypParser->yystack
- && yymx != YYERRORSYMBOL
&& (yyact = yy_find_reduce_action(
yypParser->yytos->stateno,
- YYERRORSYMBOL)) >= YY_MIN_REDUCE
+ YYERRORSYMBOL)) > YY_MAX_SHIFTREDUCE
){
yy_pop_parser_stack(yypParser);
}
@@ -151070,6 +151959,73 @@ SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){
return i;
}
+#ifdef SQLITE_ENABLE_NORMALIZE
+/*
+** Return the length (in bytes) of the token that begins at z[0].
+** Store the token type in *tokenType before returning. If flags has
+** SQLITE_TOKEN_NORMALIZE flag enabled, use the identifier token type
+** for keywords. Add SQLITE_TOKEN_QUOTED to flags if the token was
+** actually a quoted identifier. Add SQLITE_TOKEN_KEYWORD to flags
+** if the token was recognized as a keyword; this is useful when the
+** SQLITE_TOKEN_NORMALIZE flag is used, because it enables the caller
+** to differentiate between a keyword being treated as an identifier
+** (for normalization purposes) and an actual identifier.
+*/
+SQLITE_PRIVATE int sqlite3GetTokenNormalized(
+ const unsigned char *z,
+ int *tokenType,
+ int *flags
+){
+ int n;
+ unsigned char iClass = aiClass[*z];
+ if( iClass==CC_KYWD ){
+ int i;
+ for(i=1; aiClass[z[i]]<=CC_KYWD; i++){}
+ if( IdChar(z[i]) ){
+ /* This token started out using characters that can appear in keywords,
+ ** but z[i] is a character not allowed within keywords, so this must
+ ** be an identifier instead */
+ i++;
+ while( IdChar(z[i]) ){ i++; }
+ *tokenType = TK_ID;
+ return i;
+ }
+ *tokenType = TK_ID;
+ n = keywordCode((char*)z, i, tokenType);
+ /* If the token is no longer considered to be an identifier, then it is a
+ ** keyword of some kind. Make the token back into an identifier and then
+ ** set the SQLITE_TOKEN_KEYWORD flag. Several non-identifier tokens are
+ ** used verbatim, including IN, IS, NOT, and NULL. */
+ switch( *tokenType ){
+ case TK_ID: {
+ /* do nothing, handled by caller */
+ break;
+ }
+ case TK_IN:
+ case TK_IS:
+ case TK_NOT:
+ case TK_NULL: {
+ *flags |= SQLITE_TOKEN_KEYWORD;
+ break;
+ }
+ default: {
+ *tokenType = TK_ID;
+ *flags |= SQLITE_TOKEN_KEYWORD;
+ break;
+ }
+ }
+ }else{
+ n = sqlite3GetToken(z, tokenType);
+ /* If the token is considered to be an identifier and the character class
+ ** of the first character is a quote, set the SQLITE_TOKEN_QUOTED flag. */
+ if( *tokenType==TK_ID && (iClass==CC_QUOTE || iClass==CC_QUOTE2) ){
+ *flags |= SQLITE_TOKEN_QUOTED;
+ }
+ }
+ return n;
+}
+#endif /* SQLITE_ENABLE_NORMALIZE */
+
/*
** Run the parser on the given SQL string. The parser structure is
** passed in. An SQLITE_ status code is returned. If an error occurs
@@ -152467,6 +153423,7 @@ SQLITE_API int sqlite3_db_config(sqlite3 *db, int op, ...){
{ SQLITE_DBCONFIG_ENABLE_QPSG, SQLITE_EnableQPSG },
{ SQLITE_DBCONFIG_TRIGGER_EQP, SQLITE_TriggerEQP },
{ SQLITE_DBCONFIG_RESET_DATABASE, SQLITE_ResetDatabase },
+ { SQLITE_DBCONFIG_DEFENSIVE, SQLITE_Defensive },
};
unsigned int i;
rc = SQLITE_ERROR; /* IMP: R-42790-23372 */
@@ -154694,6 +155651,9 @@ static int openDatabase(
#if defined(SQLITE_ENABLE_QPSG)
| SQLITE_EnableQPSG
#endif
+#if defined(SQLITE_DEFAULT_DEFENSIVE)
+ | SQLITE_Defensive
+#endif
;
sqlite3HashInit(&db->aCollSeq);
#ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -155589,15 +156549,26 @@ SQLITE_API int sqlite3_test_control(int op, ...){
/* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, int onoff);
**
- ** If parameter onoff is non-zero, configure the wrappers so that all
- ** subsequent calls to localtime() and variants fail. If onoff is zero,
- ** undo this setting.
+ ** If parameter onoff is non-zero, subsequent calls to localtime()
+ ** and its variants fail. If onoff is zero, undo this setting.
*/
case SQLITE_TESTCTRL_LOCALTIME_FAULT: {
sqlite3GlobalConfig.bLocaltimeFault = va_arg(ap, int);
break;
}
+ /* sqlite3_test_control(SQLITE_TESTCTRL_INTERNAL_FUNCS, int onoff);
+ **
+ ** If parameter onoff is non-zero, internal-use-only SQL functions
+ ** are visible to ordinary SQL. This is useful for testing but is
+ ** unsafe because invalid parameters to those internal-use-only functions
+ ** can result in crashes or segfaults.
+ */
+ case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS: {
+ sqlite3GlobalConfig.bInternalFunctions = va_arg(ap, int);
+ break;
+ }
+
/* sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, int);
**
** Set or clear a flag that indicates that the database file is always well-
@@ -157376,7 +158347,7 @@ SQLITE_PRIVATE int sqlite3Fts3DeferredTokenList(Fts3DeferredToken *, char **, in
# define sqlite3Fts3DeferToken(x,y,z) SQLITE_OK
# define sqlite3Fts3CacheDeferredDoclists(x) SQLITE_OK
# define sqlite3Fts3FreeDeferredDoclists(x)
-# define sqlite3Fts3DeferredTokenList(x,y,z) ((*(y)=0),(*(z)=0),SQLITE_OK)
+# define sqlite3Fts3DeferredTokenList(x,y,z) SQLITE_OK
#endif
SQLITE_PRIVATE void sqlite3Fts3SegmentsClose(Fts3Table *);
@@ -161066,8 +162037,23 @@ static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
return SQLITE_OK;
}
+/*
+** Return true if zName is the extension on one of the shadow tables used
+** by this module.
+*/
+static int fts3ShadowName(const char *zName){
+ static const char *azName[] = {
+ "content", "docsize", "segdir", "segments", "stat",
+ };
+ unsigned int i;
+ for(i=0; i<sizeof(azName)/sizeof(azName[0]); i++){
+ if( sqlite3_stricmp(zName, azName[i])==0 ) return 1;
+ }
+ return 0;
+}
+
static const sqlite3_module fts3Module = {
- /* iVersion */ 2,
+ /* iVersion */ 3,
/* xCreate */ fts3CreateMethod,
/* xConnect */ fts3ConnectMethod,
/* xBestIndex */ fts3BestIndexMethod,
@@ -161090,6 +162076,7 @@ static const sqlite3_module fts3Module = {
/* xSavepoint */ fts3SavepointMethod,
/* xRelease */ fts3ReleaseMethod,
/* xRollbackTo */ fts3RollbackToMethod,
+ /* xShadowName */ fts3ShadowName,
};
/*
@@ -161378,6 +162365,7 @@ static int fts3EvalPhraseLoad(
return rc;
}
+#ifndef SQLITE_DISABLE_FTS4_DEFERRED
/*
** This function is called on each phrase after the position lists for
** any deferred tokens have been loaded into memory. It updates the phrases
@@ -161481,6 +162469,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
return SQLITE_OK;
}
+#endif /* SQLITE_DISABLE_FTS4_DEFERRED */
/*
** Maximum number of tokens a phrase may have to be considered for the
@@ -163729,7 +164718,8 @@ SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db){
0, /* xRename */
0, /* xSavepoint */
0, /* xRelease */
- 0 /* xRollbackTo */
+ 0, /* xRollbackTo */
+ 0 /* xShadowName */
};
int rc; /* Return code */
@@ -167288,7 +168278,8 @@ SQLITE_PRIVATE int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash){
0, /* xRename */
0, /* xSavepoint */
0, /* xRelease */
- 0 /* xRollbackTo */
+ 0, /* xRollbackTo */
+ 0 /* xShadowName */
};
int rc; /* Return code */
@@ -177465,6 +178456,9 @@ static int jsonEachConnect(
#define JEACH_PARENT 5
#define JEACH_FULLKEY 6
#define JEACH_PATH 7
+/* The xBestIndex method assumes that the JSON and ROOT columns are
+** the last two columns in the table. Should this ever changes, be
+** sure to update the xBestIndex method. */
#define JEACH_JSON 8
#define JEACH_ROOT 9
@@ -177722,35 +178716,54 @@ static int jsonEachBestIndex(
sqlite3_vtab *tab,
sqlite3_index_info *pIdxInfo
){
- int i;
- int jsonIdx = -1;
- int rootIdx = -1;
+ int i; /* Loop counter or computed array index */
+ int aIdx[2]; /* Index of constraints for JSON and ROOT */
+ int unusableMask = 0; /* Mask of unusable JSON and ROOT constraints */
+ int idxMask = 0; /* Mask of usable == constraints JSON and ROOT */
const struct sqlite3_index_constraint *pConstraint;
+ /* This implementation assumes that JSON and ROOT are the last two
+ ** columns in the table */
+ assert( JEACH_ROOT == JEACH_JSON+1 );
UNUSED_PARAM(tab);
+ aIdx[0] = aIdx[1] = -1;
pConstraint = pIdxInfo->aConstraint;
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
- if( pConstraint->usable==0 ) continue;
- if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
- switch( pConstraint->iColumn ){
- case JEACH_JSON: jsonIdx = i; break;
- case JEACH_ROOT: rootIdx = i; break;
- default: /* no-op */ break;
- }
- }
- if( jsonIdx<0 ){
+ int iCol;
+ int iMask;
+ if( pConstraint->iColumn < JEACH_JSON ) continue;
+ iCol = pConstraint->iColumn - JEACH_JSON;
+ assert( iCol==0 || iCol==1 );
+ iMask = 1 << iCol;
+ if( pConstraint->usable==0 ){
+ unusableMask |= iMask;
+ }else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
+ aIdx[iCol] = i;
+ idxMask |= iMask;
+ }
+ }
+ if( (unusableMask & ~idxMask)!=0 ){
+ /* If there are any unusable constraints on JSON or ROOT, then reject
+ ** this entire plan */
+ return SQLITE_CONSTRAINT;
+ }
+ if( aIdx[0]<0 ){
+ /* No JSON input. Leave estimatedCost at the huge value that it was
+ ** initialized to to discourage the query planner from selecting this
+ ** plan. */
pIdxInfo->idxNum = 0;
- pIdxInfo->estimatedCost = 1e99;
}else{
pIdxInfo->estimatedCost = 1.0;
- pIdxInfo->aConstraintUsage[jsonIdx].argvIndex = 1;
- pIdxInfo->aConstraintUsage[jsonIdx].omit = 1;
- if( rootIdx<0 ){
- pIdxInfo->idxNum = 1;
+ i = aIdx[0];
+ pIdxInfo->aConstraintUsage[i].argvIndex = 1;
+ pIdxInfo->aConstraintUsage[i].omit = 1;
+ if( aIdx[1]<0 ){
+ pIdxInfo->idxNum = 1; /* Only JSON supplied. Plan 1 */
}else{
- pIdxInfo->aConstraintUsage[rootIdx].argvIndex = 2;
- pIdxInfo->aConstraintUsage[rootIdx].omit = 1;
- pIdxInfo->idxNum = 3;
+ i = aIdx[1];
+ pIdxInfo->aConstraintUsage[i].argvIndex = 2;
+ pIdxInfo->aConstraintUsage[i].omit = 1;
+ pIdxInfo->idxNum = 3; /* Both JSON and ROOT are supplied. Plan 3 */
}
}
return SQLITE_OK;
@@ -177859,7 +178872,8 @@ static sqlite3_module jsonEachModule = {
0, /* xRename */
0, /* xSavepoint */
0, /* xRelease */
- 0 /* xRollbackTo */
+ 0, /* xRollbackTo */
+ 0 /* xShadowName */
};
/* The methods of the json_tree virtual table. */
@@ -177886,7 +178900,8 @@ static sqlite3_module jsonTreeModule = {
0, /* xRename */
0, /* xSavepoint */
0, /* xRelease */
- 0 /* xRollbackTo */
+ 0, /* xRollbackTo */
+ 0 /* xShadowName */
};
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -181316,8 +182331,24 @@ static int rtreeQueryStat1(sqlite3 *db, Rtree *pRtree){
return rc;
}
+
+/*
+** Return true if zName is the extension on one of the shadow tables used
+** by this module.
+*/
+static int rtreeShadowName(const char *zName){
+ static const char *azName[] = {
+ "node", "parent", "rowid"
+ };
+ unsigned int i;
+ for(i=0; i<sizeof(azName)/sizeof(azName[0]); i++){
+ if( sqlite3_stricmp(zName, azName[i])==0 ) return 1;
+ }
+ return 0;
+}
+
static sqlite3_module rtreeModule = {
- 2, /* iVersion */
+ 3, /* iVersion */
rtreeCreate, /* xCreate - create a table */
rtreeConnect, /* xConnect - connect to an existing table */
rtreeBestIndex, /* xBestIndex - Determine search strategy */
@@ -181340,6 +182371,7 @@ static sqlite3_module rtreeModule = {
rtreeSavepoint, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
+ rtreeShadowName /* xShadowName */
};
static int rtreeSqlInit(
@@ -182330,14 +183362,24 @@ typedef float GeoCoord;
**
** encoding (1 byte) 0=big-endian, 1=little-endian
** nvertex (3 bytes) Number of vertexes as a big-endian integer
+**
+** Enough space is allocated for 4 coordinates, to work around over-zealous
+** warnings coming from some compiler (notably, clang). In reality, the size
+** of each GeoPoly memory allocate is adjusted as necessary so that the
+** GeoPoly.a[] array at the end is the appropriate size.
*/
typedef struct GeoPoly GeoPoly;
struct GeoPoly {
int nVertex; /* Number of vertexes */
unsigned char hdr[4]; /* Header for on-disk representation */
- GeoCoord a[2]; /* 2*nVertex values. X (longitude) first, then Y */
+ GeoCoord a[8]; /* 2*nVertex values. X (longitude) first, then Y */
};
+/* The size of a memory allocation needed for a GeoPoly object sufficient
+** to hold N coordinate pairs.
+*/
+#define GEOPOLY_SZ(N) (sizeof(GeoPoly) + sizeof(GeoCoord)*2*((N)-4))
+
/*
** State of a parse of a GeoJSON input.
*/
@@ -182362,7 +183404,7 @@ static void geopolySwab32(unsigned char *a){
/* Skip whitespace. Return the next non-whitespace character. */
static char geopolySkipSpace(GeoParse *p){
- while( p->z[0] && safe_isspace(p->z[0]) ) p->z++;
+ while( safe_isspace(p->z[0]) ) p->z++;
return p->z[0];
}
@@ -182382,7 +183424,7 @@ static int geopolyParseNumber(GeoParse *p, GeoCoord *pVal){
if( c=='0' && z[j+1]>='0' && z[j+1]<='9' ) return 0;
for(;; j++){
c = z[j];
- if( c>='0' && c<='9' ) continue;
+ if( safe_isdigit(c) ) continue;
if( c=='.' ){
if( z[j-1]=='-' ) return 0;
if( seenDP ) return 0;
@@ -182404,7 +183446,17 @@ static int geopolyParseNumber(GeoParse *p, GeoCoord *pVal){
break;
}
if( z[j-1]<'0' ) return 0;
- if( pVal ) *pVal = (GeoCoord)atof((const char*)p->z);
+ if( pVal ){
+#ifdef SQLITE_AMALGAMATION
+ /* The sqlite3AtoF() routine is much much faster than atof(), if it
+ ** is available */
+ double r;
+ (void)sqlite3AtoF((const char*)p->z, &r, j, SQLITE_UTF8);
+ *pVal = r;
+#else
+ *pVal = (GeoCoord)atof((const char*)p->z);
+#endif
+ }
p->z += j;
return 1;
}
@@ -182462,12 +183514,10 @@ static GeoPoly *geopolyParseJson(const unsigned char *z, int *pRc){
&& s.a[1]==s.a[s.nVertex*2-1]
&& (s.z++, geopolySkipSpace(&s)==0)
){
- int nByte;
GeoPoly *pOut;
int x = 1;
s.nVertex--; /* Remove the redundant vertex at the end */
- nByte = sizeof(GeoPoly) * s.nVertex*2*sizeof(GeoCoord);
- pOut = sqlite3_malloc64( nByte );
+ pOut = sqlite3_malloc64( GEOPOLY_SZ(s.nVertex) );
x = 1;
if( pOut==0 ) goto parse_json_err;
pOut->nVertex = s.nVertex;
@@ -182671,6 +183721,27 @@ static void geopolyXformFunc(
}
/*
+** Compute the area enclosed by the polygon.
+**
+** This routine can also be used to detect polygons that rotate in
+** the wrong direction. Polygons are suppose to be counter-clockwise (CCW).
+** This routine returns a negative value for clockwise (CW) polygons.
+*/
+static double geopolyArea(GeoPoly *p){
+ double rArea = 0.0;
+ int ii;
+ for(ii=0; ii<p->nVertex-1; ii++){
+ rArea += (p->a[ii*2] - p->a[ii*2+2]) /* (x0 - x1) */
+ * (p->a[ii*2+1] + p->a[ii*2+3]) /* (y0 + y1) */
+ * 0.5;
+ }
+ rArea += (p->a[ii*2] - p->a[0]) /* (xN - x0) */
+ * (p->a[ii*2+1] + p->a[1]) /* (yN + y0) */
+ * 0.5;
+ return rArea;
+}
+
+/*
** Implementation of the geopoly_area(X) function.
**
** If the input is a well-formed Geopoly BLOB then return the area
@@ -182685,22 +183756,107 @@ static void geopolyAreaFunc(
){
GeoPoly *p = geopolyFuncParam(context, argv[0], 0);
if( p ){
- double rArea = 0.0;
- int ii;
- for(ii=0; ii<p->nVertex-1; ii++){
- rArea += (p->a[ii*2] - p->a[ii*2+2]) /* (x0 - x1) */
- * (p->a[ii*2+1] + p->a[ii*2+3]) /* (y0 + y1) */
- * 0.5;
- }
- rArea += (p->a[ii*2] - p->a[0]) /* (xN - x0) */
- * (p->a[ii*2+1] + p->a[1]) /* (yN + y0) */
- * 0.5;
- sqlite3_result_double(context, rArea);
+ sqlite3_result_double(context, geopolyArea(p));
sqlite3_free(p);
}
}
/*
+** Implementation of the geopoly_ccw(X) function.
+**
+** If the rotation of polygon X is clockwise (incorrect) instead of
+** counter-clockwise (the correct winding order according to RFC7946)
+** then reverse the order of the vertexes in polygon X.
+**
+** In other words, this routine returns a CCW polygon regardless of the
+** winding order of its input.
+**
+** Use this routine to sanitize historical inputs that that sometimes
+** contain polygons that wind in the wrong direction.
+*/
+static void geopolyCcwFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ GeoPoly *p = geopolyFuncParam(context, argv[0], 0);
+ if( p ){
+ if( geopolyArea(p)<0.0 ){
+ int ii, jj;
+ for(ii=2, jj=p->nVertex*2 - 2; ii<jj; ii+=2, jj-=2){
+ GeoCoord t = p->a[ii];
+ p->a[ii] = p->a[jj];
+ p->a[jj] = t;
+ t = p->a[ii+1];
+ p->a[ii+1] = p->a[jj+1];
+ p->a[jj+1] = t;
+ }
+ }
+ sqlite3_result_blob(context, p->hdr,
+ 4+8*p->nVertex, SQLITE_TRANSIENT);
+ sqlite3_free(p);
+ }
+}
+
+#define GEOPOLY_PI 3.1415926535897932385
+
+/* Fast approximation for sine(X) for X between -0.5*pi and 2*pi
+*/
+static double geopolySine(double r){
+ assert( r>=-0.5*GEOPOLY_PI && r<=2.0*GEOPOLY_PI );
+ if( r>=1.5*GEOPOLY_PI ){
+ r -= 2.0*GEOPOLY_PI;
+ }
+ if( r>=0.5*GEOPOLY_PI ){
+ return -geopolySine(r-GEOPOLY_PI);
+ }else{
+ double r2 = r*r;
+ double r3 = r2*r;
+ double r5 = r3*r2;
+ return 0.9996949*r - 0.1656700*r3 + 0.0075134*r5;
+ }
+}
+
+/*
+** Function: geopoly_regular(X,Y,R,N)
+**
+** Construct a simple, convex, regular polygon centered at X, Y
+** with circumradius R and with N sides.
+*/
+static void geopolyRegularFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ double x = sqlite3_value_double(argv[0]);
+ double y = sqlite3_value_double(argv[1]);
+ double r = sqlite3_value_double(argv[2]);
+ int n = sqlite3_value_int(argv[3]);
+ int i;
+ GeoPoly *p;
+
+ if( n<3 || r<=0.0 ) return;
+ if( n>1000 ) n = 1000;
+ p = sqlite3_malloc64( sizeof(*p) + (n-1)*2*sizeof(GeoCoord) );
+ if( p==0 ){
+ sqlite3_result_error_nomem(context);
+ return;
+ }
+ i = 1;
+ p->hdr[0] = *(unsigned char*)&i;
+ p->hdr[1] = 0;
+ p->hdr[2] = (n>>8)&0xff;
+ p->hdr[3] = n&0xff;
+ for(i=0; i<n; i++){
+ double rAngle = 2.0*GEOPOLY_PI*i/n;
+ p->a[i*2] = x - r*geopolySine(rAngle-0.5*GEOPOLY_PI);
+ p->a[i*2+1] = y + r*geopolySine(rAngle);
+ }
+ sqlite3_result_blob(context, p->hdr, 4+8*n, SQLITE_TRANSIENT);
+ sqlite3_free(p);
+}
+
+/*
** If pPoly is a polygon, compute its bounding box. Then:
**
** (1) if aCoord!=0 store the bounding box in aCoord, returning NULL
@@ -182744,7 +183900,7 @@ static GeoPoly *geopolyBBox(
if( pRc ) *pRc = SQLITE_OK;
if( aCoord==0 ){
geopolyBboxFill:
- pOut = sqlite3_realloc(p, sizeof(GeoPoly)+sizeof(GeoCoord)*6);
+ pOut = sqlite3_realloc(p, GEOPOLY_SZ(4));
if( pOut==0 ){
sqlite3_free(p);
if( context ) sqlite3_result_error_nomem(context);
@@ -183772,7 +184928,16 @@ static int geopolyUpdate(
if( sqlite3_value_nochange(aData[2]) ){
sqlite3_bind_null(pUp, 2);
}else{
- sqlite3_bind_value(pUp, 2, aData[2]);
+ GeoPoly *p = 0;
+ if( sqlite3_value_type(aData[2])==SQLITE_TEXT
+ && (p = geopolyFuncParam(0, aData[2], &rc))!=0
+ && rc==SQLITE_OK
+ ){
+ sqlite3_bind_blob(pUp, 2, p->hdr, 4+8*p->nVertex, SQLITE_TRANSIENT);
+ }else{
+ sqlite3_bind_value(pUp, 2, aData[2]);
+ }
+ sqlite3_free(p);
nChange = 1;
}
for(jj=1; jj<pRtree->nAux; jj++){
@@ -183816,7 +184981,7 @@ static int geopolyFindFunction(
static sqlite3_module geopolyModule = {
- 2, /* iVersion */
+ 3, /* iVersion */
geopolyCreate, /* xCreate - create a table */
geopolyConnect, /* xConnect - connect to an existing table */
geopolyBestIndex, /* xBestIndex - Determine search strategy */
@@ -183839,25 +185004,29 @@ static sqlite3_module geopolyModule = {
rtreeSavepoint, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
+ rtreeShadowName /* xShadowName */
};
static int sqlite3_geopoly_init(sqlite3 *db){
int rc = SQLITE_OK;
static const struct {
void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
- int nArg;
+ signed char nArg;
+ unsigned char bPure;
const char *zName;
} aFunc[] = {
- { geopolyAreaFunc, 1, "geopoly_area" },
- { geopolyBlobFunc, 1, "geopoly_blob" },
- { geopolyJsonFunc, 1, "geopoly_json" },
- { geopolySvgFunc, -1, "geopoly_svg" },
- { geopolyWithinFunc, 2, "geopoly_within" },
- { geopolyContainsPointFunc, 3, "geopoly_contains_point" },
- { geopolyOverlapFunc, 2, "geopoly_overlap" },
- { geopolyDebugFunc, 1, "geopoly_debug" },
- { geopolyBBoxFunc, 1, "geopoly_bbox" },
- { geopolyXformFunc, 7, "geopoly_xform" },
+ { geopolyAreaFunc, 1, 1, "geopoly_area" },
+ { geopolyBlobFunc, 1, 1, "geopoly_blob" },
+ { geopolyJsonFunc, 1, 1, "geopoly_json" },
+ { geopolySvgFunc, -1, 1, "geopoly_svg" },
+ { geopolyWithinFunc, 2, 1, "geopoly_within" },
+ { geopolyContainsPointFunc, 3, 1, "geopoly_contains_point" },
+ { geopolyOverlapFunc, 2, 1, "geopoly_overlap" },
+ { geopolyDebugFunc, 1, 0, "geopoly_debug" },
+ { geopolyBBoxFunc, 1, 1, "geopoly_bbox" },
+ { geopolyXformFunc, 7, 1, "geopoly_xform" },
+ { geopolyRegularFunc, 4, 1, "geopoly_regular" },
+ { geopolyCcwFunc, 1, 1, "geopoly_ccw" },
};
static const struct {
void (*xStep)(sqlite3_context*,int,sqlite3_value**);
@@ -183868,8 +185037,9 @@ static int sqlite3_geopoly_init(sqlite3 *db){
};
int i;
for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
+ int enc = aFunc[i].bPure ? SQLITE_UTF8|SQLITE_DETERMINISTIC : SQLITE_UTF8;
rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg,
- SQLITE_UTF8, 0,
+ enc, 0,
aFunc[i].xFunc, 0, 0);
}
for(i=0; i<sizeof(aAgg)/sizeof(aAgg[0]) && rc==SQLITE_OK; i++){
@@ -185896,7 +187066,8 @@ struct rbu_vfs {
sqlite3_vfs *pRealVfs; /* Underlying VFS */
sqlite3_mutex *mutex; /* Mutex to protect pMain */
sqlite3rbu *pRbu; /* Owner RBU object */
- rbu_file *pMain; /* Linked list of main db files */
+ rbu_file *pMain; /* List of main db files */
+ rbu_file *pMainRbu; /* List of main db files with pRbu!=0 */
};
/*
@@ -185925,6 +187096,7 @@ struct rbu_file {
const char *zWal; /* Wal filename for this main db file */
rbu_file *pWalFd; /* Wal file descriptor for this main db */
rbu_file *pMainNext; /* Next MAIN_DB file */
+ rbu_file *pMainRbuNext; /* Next MAIN_DB file with pRbu!=0 */
};
/*
@@ -189522,6 +190694,69 @@ static int rbuUpdateTempSize(rbu_file *pFd, sqlite3_int64 nNew){
}
/*
+** Add an item to the main-db lists, if it is not already present.
+**
+** There are two main-db lists. One for all file descriptors, and one
+** for all file descriptors with rbu_file.pDb!=0. If the argument has
+** rbu_file.pDb!=0, then it is assumed to already be present on the
+** main list and is only added to the pDb!=0 list.
+*/
+static void rbuMainlistAdd(rbu_file *p){
+ rbu_vfs *pRbuVfs = p->pRbuVfs;
+ rbu_file *pIter;
+ assert( (p->openFlags & SQLITE_OPEN_MAIN_DB) );
+ sqlite3_mutex_enter(pRbuVfs->mutex);
+ if( p->pRbu==0 ){
+ for(pIter=pRbuVfs->pMain; pIter; pIter=pIter->pMainNext);
+ p->pMainNext = pRbuVfs->pMain;
+ pRbuVfs->pMain = p;
+ }else{
+ for(pIter=pRbuVfs->pMainRbu; pIter && pIter!=p; pIter=pIter->pMainRbuNext){}
+ if( pIter==0 ){
+ p->pMainRbuNext = pRbuVfs->pMainRbu;
+ pRbuVfs->pMainRbu = p;
+ }
+ }
+ sqlite3_mutex_leave(pRbuVfs->mutex);
+}
+
+/*
+** Remove an item from the main-db lists.
+*/
+static void rbuMainlistRemove(rbu_file *p){
+ rbu_file **pp;
+ sqlite3_mutex_enter(p->pRbuVfs->mutex);
+ for(pp=&p->pRbuVfs->pMain; *pp && *pp!=p; pp=&((*pp)->pMainNext)){}
+ if( *pp ) *pp = p->pMainNext;
+ p->pMainNext = 0;
+ for(pp=&p->pRbuVfs->pMainRbu; *pp && *pp!=p; pp=&((*pp)->pMainRbuNext)){}
+ if( *pp ) *pp = p->pMainRbuNext;
+ p->pMainRbuNext = 0;
+ sqlite3_mutex_leave(p->pRbuVfs->mutex);
+}
+
+/*
+** Given that zWal points to a buffer containing a wal file name passed to
+** either the xOpen() or xAccess() VFS method, search the main-db list for
+** a file-handle opened by the same database connection on the corresponding
+** database file.
+**
+** If parameter bRbu is true, only search for file-descriptors with
+** rbu_file.pDb!=0.
+*/
+static rbu_file *rbuFindMaindb(rbu_vfs *pRbuVfs, const char *zWal, int bRbu){
+ rbu_file *pDb;
+ sqlite3_mutex_enter(pRbuVfs->mutex);
+ if( bRbu ){
+ for(pDb=pRbuVfs->pMainRbu; pDb && pDb->zWal!=zWal; pDb=pDb->pMainRbuNext){}
+ }else{
+ for(pDb=pRbuVfs->pMain; pDb && pDb->zWal!=zWal; pDb=pDb->pMainNext){}
+ }
+ sqlite3_mutex_leave(pRbuVfs->mutex);
+ return pDb;
+}
+
+/*
** Close an rbu file.
*/
static int rbuVfsClose(sqlite3_file *pFile){
@@ -189538,17 +190773,14 @@ static int rbuVfsClose(sqlite3_file *pFile){
sqlite3_free(p->zDel);
if( p->openFlags & SQLITE_OPEN_MAIN_DB ){
- rbu_file **pp;
- sqlite3_mutex_enter(p->pRbuVfs->mutex);
- for(pp=&p->pRbuVfs->pMain; *pp!=p; pp=&((*pp)->pMainNext));
- *pp = p->pMainNext;
- sqlite3_mutex_leave(p->pRbuVfs->mutex);
+ rbuMainlistRemove(p);
rbuUnlockShm(p);
p->pReal->pMethods->xShmUnmap(p->pReal, 0);
}
else if( (p->openFlags & SQLITE_OPEN_DELETEONCLOSE) && p->pRbu ){
rbuUpdateTempSize(p, 0);
}
+ assert( p->pMainNext==0 && p->pRbuVfs->pMain!=p );
/* Close the underlying file handle */
rc = p->pReal->pMethods->xClose(p->pReal);
@@ -189807,6 +191039,9 @@ static int rbuVfsFileControl(sqlite3_file *pFile, int op, void *pArg){
}else if( rc==SQLITE_NOTFOUND ){
pRbu->pTargetFd = p;
p->pRbu = pRbu;
+ if( p->openFlags & SQLITE_OPEN_MAIN_DB ){
+ rbuMainlistAdd(p);
+ }
if( p->pWalFd ) p->pWalFd->pRbu = pRbu;
rc = SQLITE_OK;
}
@@ -189969,20 +191204,6 @@ static int rbuVfsShmUnmap(sqlite3_file *pFile, int delFlag){
}
/*
-** Given that zWal points to a buffer containing a wal file name passed to
-** either the xOpen() or xAccess() VFS method, return a pointer to the
-** file-handle opened by the same database connection on the corresponding
-** database file.
-*/
-static rbu_file *rbuFindMaindb(rbu_vfs *pRbuVfs, const char *zWal){
- rbu_file *pDb;
- sqlite3_mutex_enter(pRbuVfs->mutex);
- for(pDb=pRbuVfs->pMain; pDb && pDb->zWal!=zWal; pDb=pDb->pMainNext){}
- sqlite3_mutex_leave(pRbuVfs->mutex);
- return pDb;
-}
-
-/*
** A main database named zName has just been opened. The following
** function returns a pointer to a buffer owned by SQLite that contains
** the name of the *-wal file this db connection will use. SQLite
@@ -190060,7 +191281,7 @@ static int rbuVfsOpen(
pFd->zWal = rbuMainToWal(zName, flags);
}
else if( flags & SQLITE_OPEN_WAL ){
- rbu_file *pDb = rbuFindMaindb(pRbuVfs, zName);
+ rbu_file *pDb = rbuFindMaindb(pRbuVfs, zName, 0);
if( pDb ){
if( pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){
/* This call is to open a *-wal file. Intead, open the *-oal. This
@@ -190112,10 +191333,7 @@ static int rbuVfsOpen(
** mutex protected linked list of all such files. */
pFile->pMethods = &rbuvfs_io_methods;
if( flags & SQLITE_OPEN_MAIN_DB ){
- sqlite3_mutex_enter(pRbuVfs->mutex);
- pFd->pMainNext = pRbuVfs->pMain;
- pRbuVfs->pMain = pFd;
- sqlite3_mutex_leave(pRbuVfs->mutex);
+ rbuMainlistAdd(pFd);
}
}else{
sqlite3_free(pFd->zDel);
@@ -190163,7 +191381,7 @@ static int rbuVfsAccess(
** file opened instead.
*/
if( rc==SQLITE_OK && flags==SQLITE_ACCESS_EXISTS ){
- rbu_file *pDb = rbuFindMaindb(pRbuVfs, zPath);
+ rbu_file *pDb = rbuFindMaindb(pRbuVfs, zPath, 1);
if( pDb && pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){
if( *pResOut ){
rc = SQLITE_CANTOPEN;
@@ -190576,17 +191794,15 @@ static int statDisconnect(sqlite3_vtab *pVtab){
static int statBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
int i;
- pIdxInfo->estimatedCost = 1.0e6; /* Initial cost estimate */
-
/* Look for a valid schema=? constraint. If found, change the idxNum to
** 1 and request the value of that constraint be sent to xFilter. And
** lower the cost estimate to encourage the constrained version to be
** used.
*/
for(i=0; i<pIdxInfo->nConstraint; i++){
- if( pIdxInfo->aConstraint[i].usable==0 ) continue;
- if( pIdxInfo->aConstraint[i].op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
if( pIdxInfo->aConstraint[i].iColumn!=10 ) continue;
+ if( pIdxInfo->aConstraint[i].usable==0 ) return SQLITE_CONSTRAINT;
+ if( pIdxInfo->aConstraint[i].op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
pIdxInfo->idxNum = 1;
pIdxInfo->estimatedCost = 1.0;
pIdxInfo->aConstraintUsage[i].argvIndex = 1;
@@ -190636,7 +191852,7 @@ static int statOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
return SQLITE_OK;
}
-static void statClearPage(StatPage *p){
+static void statClearCells(StatPage *p){
int i;
if( p->aCell ){
for(i=0; i<p->nCell; i++){
@@ -190644,6 +191860,12 @@ static void statClearPage(StatPage *p){
}
sqlite3_free(p->aCell);
}
+ p->nCell = 0;
+ p->aCell = 0;
+}
+
+static void statClearPage(StatPage *p){
+ statClearCells(p);
sqlite3PagerUnref(p->pPg);
sqlite3_free(p->zPath);
memset(p, 0, sizeof(StatPage));
@@ -190706,22 +191928,33 @@ static int statDecodePage(Btree *pBt, StatPage *p){
u8 *aHdr = &aData[p->iPgno==1 ? 100 : 0];
p->flags = aHdr[0];
+ if( p->flags==0x0A || p->flags==0x0D ){
+ isLeaf = 1;
+ nHdr = 8;
+ }else if( p->flags==0x05 || p->flags==0x02 ){
+ isLeaf = 0;
+ nHdr = 12;
+ }else{
+ goto statPageIsCorrupt;
+ }
+ if( p->iPgno==1 ) nHdr += 100;
p->nCell = get2byte(&aHdr[3]);
p->nMxPayload = 0;
-
- isLeaf = (p->flags==0x0A || p->flags==0x0D);
- nHdr = 12 - isLeaf*4 + (p->iPgno==1)*100;
+ szPage = sqlite3BtreeGetPageSize(pBt);
nUnused = get2byte(&aHdr[5]) - nHdr - 2*p->nCell;
nUnused += (int)aHdr[7];
iOff = get2byte(&aHdr[1]);
while( iOff ){
+ int iNext;
+ if( iOff>=szPage ) goto statPageIsCorrupt;
nUnused += get2byte(&aData[iOff+2]);
- iOff = get2byte(&aData[iOff]);
+ iNext = get2byte(&aData[iOff]);
+ if( iNext<iOff+4 && iNext>0 ) goto statPageIsCorrupt;
+ iOff = iNext;
}
p->nUnused = nUnused;
p->iRightChildPg = isLeaf ? 0 : sqlite3Get4byte(&aHdr[8]);
- szPage = sqlite3BtreeGetPageSize(pBt);
if( p->nCell ){
int i; /* Used to iterate through cells */
@@ -190738,6 +191971,7 @@ static int statDecodePage(Btree *pBt, StatPage *p){
StatCell *pCell = &p->aCell[i];
iOff = get2byte(&aData[nHdr+i*2]);
+ if( iOff<nHdr || iOff>=szPage ) goto statPageIsCorrupt;
if( !isLeaf ){
pCell->iChildPg = sqlite3Get4byte(&aData[iOff]);
iOff += 4;
@@ -190754,13 +191988,14 @@ static int statDecodePage(Btree *pBt, StatPage *p){
}
if( nPayload>(u32)p->nMxPayload ) p->nMxPayload = nPayload;
getLocalPayload(nUsable, p->flags, nPayload, &nLocal);
+ if( nLocal<0 ) goto statPageIsCorrupt;
pCell->nLocal = nLocal;
- assert( nLocal>=0 );
assert( nPayload>=(u32)nLocal );
assert( nLocal<=(nUsable-35) );
if( nPayload>(u32)nLocal ){
int j;
int nOvfl = ((nPayload - nLocal) + nUsable-4 - 1) / (nUsable - 4);
+ if( iOff+nLocal>nUsable ) goto statPageIsCorrupt;
pCell->nLastOvfl = (nPayload-nLocal) - (nOvfl-1) * (nUsable-4);
pCell->nOvfl = nOvfl;
pCell->aOvfl = sqlite3_malloc64(sizeof(u32)*nOvfl);
@@ -190784,6 +192019,11 @@ static int statDecodePage(Btree *pBt, StatPage *p){
}
return SQLITE_OK;
+
+statPageIsCorrupt:
+ p->flags = 0;
+ statClearCells(p);
+ return SQLITE_OK;
}
/*
@@ -191079,6 +192319,7 @@ SQLITE_PRIVATE int sqlite3DbstatRegister(sqlite3 *db){
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
+ 0 /* xShadowName */
};
return sqlite3_create_module(db, "dbstat", &dbstat_module, 0);
}
@@ -191209,9 +192450,8 @@ static int dbpageBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
if( p->iColumn!=DBPAGE_COLUMN_SCHEMA ) continue;
if( p->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
if( !p->usable ){
- /* No solution. Use the default SQLITE_BIG_DBL cost */
- pIdxInfo->estimatedRows = 0x7fffffff;
- return SQLITE_OK;
+ /* No solution. */
+ return SQLITE_CONSTRAINT;
}
iPlan = 2;
pIdxInfo->aConstraintUsage[i].argvIndex = 1;
@@ -191403,6 +192643,10 @@ static int dbpageUpdate(
Pager *pPager;
int szPage;
+ if( pTab->db->flags & SQLITE_Defensive ){
+ zErr = "read-only";
+ goto update_fail;
+ }
if( argc==1 ){
zErr = "cannot delete";
goto update_fail;
@@ -191493,6 +192737,7 @@ SQLITE_PRIVATE int sqlite3DbpageRegister(sqlite3 *db){
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
+ 0 /* xShadowName */
};
return sqlite3_create_module(db, "sqlite_dbpage", &dbpage_module, 0);
}
@@ -191529,6 +192774,8 @@ typedef struct SessionInput SessionInput;
# endif
#endif
+static int sessions_strm_chunk_size = SESSIONS_STRM_CHUNK_SIZE;
+
typedef struct SessionHook SessionHook;
struct SessionHook {
void *pCtx;
@@ -191591,6 +192838,7 @@ struct sqlite3_changeset_iter {
SessionInput in; /* Input buffer or stream */
SessionBuffer tblhdr; /* Buffer to hold apValue/zTab/abPK/ */
int bPatchset; /* True if this is a patchset */
+ int bInvert; /* True to invert changeset */
int rc; /* Iterator error code */
sqlite3_stmt *pConflict; /* Points to conflicting row, if any */
char *zTab; /* Current table */
@@ -191747,6 +192995,42 @@ struct SessionTable {
** The records associated with INSERT changes are in the same format as for
** changesets. It is not possible for a record associated with an INSERT
** change to contain a field set to "undefined".
+**
+** REBASE BLOB FORMAT:
+**
+** A rebase blob may be output by sqlite3changeset_apply_v2() and its
+** streaming equivalent for use with the sqlite3_rebaser APIs to rebase
+** existing changesets. A rebase blob contains one entry for each conflict
+** resolved using either the OMIT or REPLACE strategies within the apply_v2()
+** call.
+**
+** The format used for a rebase blob is very similar to that used for
+** changesets. All entries related to a single table are grouped together.
+**
+** Each group of entries begins with a table header in changeset format:
+**
+** 1 byte: Constant 0x54 (capital 'T')
+** Varint: Number of columns in the table.
+** nCol bytes: 0x01 for PK columns, 0x00 otherwise.
+** N bytes: Unqualified table name (encoded using UTF-8). Nul-terminated.
+**
+** Followed by one or more entries associated with the table.
+**
+** 1 byte: Either SQLITE_INSERT (0x12), DELETE (0x09).
+** 1 byte: Flag. 0x01 for REPLACE, 0x00 for OMIT.
+** record: (in the record format defined above).
+**
+** In a rebase blob, the first field is set to SQLITE_INSERT if the change
+** that caused the conflict was an INSERT or UPDATE, or to SQLITE_DELETE if
+** it was a DELETE. The second field is set to 0x01 if the conflict
+** resolution strategy was REPLACE, or 0x00 if it was OMIT.
+**
+** If the change that caused the conflict was a DELETE, then the single
+** record is a copy of the old.* record from the original changeset. If it
+** was an INSERT, then the single record is a copy of the new.* record. If
+** the conflicting change was an UPDATE, then the single record is a copy
+** of the new.* record with the PK fields filled in based on the original
+** old.* record.
*/
/*
@@ -193297,12 +194581,12 @@ SQLITE_API int sqlite3session_attach(
static int sessionBufferGrow(SessionBuffer *p, int nByte, int *pRc){
if( *pRc==SQLITE_OK && p->nAlloc-p->nBuf<nByte ){
u8 *aNew;
- int nNew = p->nAlloc ? p->nAlloc : 128;
+ i64 nNew = p->nAlloc ? p->nAlloc : 128;
do {
nNew = nNew*2;
- }while( nNew<(p->nBuf+nByte) );
+ }while( (nNew-p->nBuf)<nByte );
- aNew = (u8 *)sqlite3_realloc(p->aBuf, nNew);
+ aNew = (u8 *)sqlite3_realloc64(p->aBuf, nNew);
if( 0==aNew ){
*pRc = SQLITE_NOMEM;
}else{
@@ -193900,12 +195184,12 @@ static int sessionGenerateChangeset(
rc = sqlite3_reset(pSel);
}
- /* If the buffer is now larger than SESSIONS_STRM_CHUNK_SIZE, pass
+ /* If the buffer is now larger than sessions_strm_chunk_size, pass
** its contents to the xOutput() callback. */
if( xOutput
&& rc==SQLITE_OK
&& buf.nBuf>nNoop
- && buf.nBuf>SESSIONS_STRM_CHUNK_SIZE
+ && buf.nBuf>sessions_strm_chunk_size
){
rc = xOutput(pOut, (void*)buf.aBuf, buf.nBuf);
nNoop = -1;
@@ -194044,7 +195328,8 @@ static int sessionChangesetStart(
int (*xInput)(void *pIn, void *pData, int *pnData),
void *pIn,
int nChangeset, /* Size of buffer pChangeset in bytes */
- void *pChangeset /* Pointer to buffer containing changeset */
+ void *pChangeset, /* Pointer to buffer containing changeset */
+ int bInvert /* True to invert changeset */
){
sqlite3_changeset_iter *pRet; /* Iterator to return */
int nByte; /* Number of bytes to allocate for iterator */
@@ -194064,6 +195349,7 @@ static int sessionChangesetStart(
pRet->in.xInput = xInput;
pRet->in.pIn = pIn;
pRet->in.bEof = (xInput ? 0 : 1);
+ pRet->bInvert = bInvert;
/* Populate the output variable and return success. */
*pp = pRet;
@@ -194078,7 +195364,16 @@ SQLITE_API int sqlite3changeset_start(
int nChangeset, /* Size of buffer pChangeset in bytes */
void *pChangeset /* Pointer to buffer containing changeset */
){
- return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset);
+ return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset, 0);
+}
+SQLITE_API int sqlite3changeset_start_v2(
+ sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */
+ int nChangeset, /* Size of buffer pChangeset in bytes */
+ void *pChangeset, /* Pointer to buffer containing changeset */
+ int flags
+){
+ int bInvert = !!(flags & SQLITE_CHANGESETSTART_INVERT);
+ return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset, bInvert);
}
/*
@@ -194089,7 +195384,16 @@ SQLITE_API int sqlite3changeset_start_strm(
int (*xInput)(void *pIn, void *pData, int *pnData),
void *pIn
){
- return sessionChangesetStart(pp, xInput, pIn, 0, 0);
+ return sessionChangesetStart(pp, xInput, pIn, 0, 0, 0);
+}
+SQLITE_API int sqlite3changeset_start_v2_strm(
+ sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */
+ int (*xInput)(void *pIn, void *pData, int *pnData),
+ void *pIn,
+ int flags
+){
+ int bInvert = !!(flags & SQLITE_CHANGESETSTART_INVERT);
+ return sessionChangesetStart(pp, xInput, pIn, 0, 0, bInvert);
}
/*
@@ -194097,7 +195401,7 @@ SQLITE_API int sqlite3changeset_start_strm(
** object and the buffer is full, discard some data to free up space.
*/
static void sessionDiscardData(SessionInput *pIn){
- if( pIn->xInput && pIn->iNext>=SESSIONS_STRM_CHUNK_SIZE ){
+ if( pIn->xInput && pIn->iNext>=sessions_strm_chunk_size ){
int nMove = pIn->buf.nBuf - pIn->iNext;
assert( nMove>=0 );
if( nMove>0 ){
@@ -194120,7 +195424,7 @@ static int sessionInputBuffer(SessionInput *pIn, int nByte){
int rc = SQLITE_OK;
if( pIn->xInput ){
while( !pIn->bEof && (pIn->iNext+nByte)>=pIn->nData && rc==SQLITE_OK ){
- int nNew = SESSIONS_STRM_CHUNK_SIZE;
+ int nNew = sessions_strm_chunk_size;
if( pIn->bNoDiscard==0 ) sessionDiscardData(pIn);
if( SQLITE_OK==sessionBufferGrow(&pIn->buf, nNew, &rc) ){
@@ -194468,10 +195772,10 @@ static int sessionChangesetNext(
op = p->in.aData[p->in.iNext++];
}
- if( p->zTab==0 ){
+ if( p->zTab==0 || (p->bPatchset && p->bInvert) ){
/* The first record in the changeset is not a table header. Must be a
** corrupt changeset. */
- assert( p->in.iNext==1 );
+ assert( p->in.iNext==1 || p->zTab );
return (p->rc = SQLITE_CORRUPT_BKPT);
}
@@ -194496,33 +195800,39 @@ static int sessionChangesetNext(
*paRec = &p->in.aData[p->in.iNext];
p->in.iNext += *pnRec;
}else{
+ sqlite3_value **apOld = (p->bInvert ? &p->apValue[p->nCol] : p->apValue);
+ sqlite3_value **apNew = (p->bInvert ? p->apValue : &p->apValue[p->nCol]);
/* If this is an UPDATE or DELETE, read the old.* record. */
if( p->op!=SQLITE_INSERT && (p->bPatchset==0 || p->op==SQLITE_DELETE) ){
u8 *abPK = p->bPatchset ? p->abPK : 0;
- p->rc = sessionReadRecord(&p->in, p->nCol, abPK, p->apValue);
+ p->rc = sessionReadRecord(&p->in, p->nCol, abPK, apOld);
if( p->rc!=SQLITE_OK ) return p->rc;
}
/* If this is an INSERT or UPDATE, read the new.* record. */
if( p->op!=SQLITE_DELETE ){
- p->rc = sessionReadRecord(&p->in, p->nCol, 0, &p->apValue[p->nCol]);
+ p->rc = sessionReadRecord(&p->in, p->nCol, 0, apNew);
if( p->rc!=SQLITE_OK ) return p->rc;
}
- if( p->bPatchset && p->op==SQLITE_UPDATE ){
+ if( (p->bPatchset || p->bInvert) && p->op==SQLITE_UPDATE ){
/* If this is an UPDATE that is part of a patchset, then all PK and
** modified fields are present in the new.* record. The old.* record
** is currently completely empty. This block shifts the PK fields from
** new.* to old.*, to accommodate the code that reads these arrays. */
for(i=0; i<p->nCol; i++){
- assert( p->apValue[i]==0 );
+ assert( p->bPatchset==0 || p->apValue[i]==0 );
if( p->abPK[i] ){
+ assert( p->apValue[i]==0 );
p->apValue[i] = p->apValue[i+p->nCol];
if( p->apValue[i]==0 ) return (p->rc = SQLITE_CORRUPT_BKPT);
p->apValue[i+p->nCol] = 0;
}
}
+ }else if( p->bInvert ){
+ if( p->op==SQLITE_INSERT ) p->op = SQLITE_DELETE;
+ else if( p->op==SQLITE_DELETE ) p->op = SQLITE_INSERT;
}
}
@@ -194839,7 +196149,7 @@ static int sessionChangesetInvert(
}
assert( rc==SQLITE_OK );
- if( xOutput && sOut.nBuf>=SESSIONS_STRM_CHUNK_SIZE ){
+ if( xOutput && sOut.nBuf>=sessions_strm_chunk_size ){
rc = xOutput(pOut, sOut.aBuf, sOut.nBuf);
sOut.nBuf = 0;
if( rc!=SQLITE_OK ) goto finished_invert;
@@ -194918,7 +196228,8 @@ struct SessionApplyCtx {
int bDeferConstraints; /* True to defer constraints */
SessionBuffer constraints; /* Deferred constraints are stored here */
SessionBuffer rebase; /* Rebase information (if any) here */
- int bRebaseStarted; /* If table header is already in rebase */
+ u8 bRebaseStarted; /* If table header is already in rebase */
+ u8 bRebase; /* True to collect rebase information */
};
/*
@@ -195315,35 +196626,36 @@ static int sessionRebaseAdd(
sqlite3_changeset_iter *pIter /* Iterator pointing at current change */
){
int rc = SQLITE_OK;
- int i;
- int eOp = pIter->op;
- if( p->bRebaseStarted==0 ){
- /* Append a table-header to the rebase buffer */
- const char *zTab = pIter->zTab;
- sessionAppendByte(&p->rebase, 'T', &rc);
- sessionAppendVarint(&p->rebase, p->nCol, &rc);
- sessionAppendBlob(&p->rebase, p->abPK, p->nCol, &rc);
- sessionAppendBlob(&p->rebase, (u8*)zTab, (int)strlen(zTab)+1, &rc);
- p->bRebaseStarted = 1;
- }
-
- assert( eType==SQLITE_CHANGESET_REPLACE||eType==SQLITE_CHANGESET_OMIT );
- assert( eOp==SQLITE_DELETE || eOp==SQLITE_INSERT || eOp==SQLITE_UPDATE );
-
- sessionAppendByte(&p->rebase,
- (eOp==SQLITE_DELETE ? SQLITE_DELETE : SQLITE_INSERT), &rc
- );
- sessionAppendByte(&p->rebase, (eType==SQLITE_CHANGESET_REPLACE), &rc);
- for(i=0; i<p->nCol; i++){
- sqlite3_value *pVal = 0;
- if( eOp==SQLITE_DELETE || (eOp==SQLITE_UPDATE && p->abPK[i]) ){
- sqlite3changeset_old(pIter, i, &pVal);
- }else{
- sqlite3changeset_new(pIter, i, &pVal);
+ if( p->bRebase ){
+ int i;
+ int eOp = pIter->op;
+ if( p->bRebaseStarted==0 ){
+ /* Append a table-header to the rebase buffer */
+ const char *zTab = pIter->zTab;
+ sessionAppendByte(&p->rebase, 'T', &rc);
+ sessionAppendVarint(&p->rebase, p->nCol, &rc);
+ sessionAppendBlob(&p->rebase, p->abPK, p->nCol, &rc);
+ sessionAppendBlob(&p->rebase, (u8*)zTab, (int)strlen(zTab)+1, &rc);
+ p->bRebaseStarted = 1;
}
- sessionAppendValue(&p->rebase, pVal, &rc);
- }
+ assert( eType==SQLITE_CHANGESET_REPLACE||eType==SQLITE_CHANGESET_OMIT );
+ assert( eOp==SQLITE_DELETE || eOp==SQLITE_INSERT || eOp==SQLITE_UPDATE );
+
+ sessionAppendByte(&p->rebase,
+ (eOp==SQLITE_DELETE ? SQLITE_DELETE : SQLITE_INSERT), &rc
+ );
+ sessionAppendByte(&p->rebase, (eType==SQLITE_CHANGESET_REPLACE), &rc);
+ for(i=0; i<p->nCol; i++){
+ sqlite3_value *pVal = 0;
+ if( eOp==SQLITE_DELETE || (eOp==SQLITE_UPDATE && p->abPK[i]) ){
+ sqlite3changeset_old(pIter, i, &pVal);
+ }else{
+ sqlite3changeset_new(pIter, i, &pVal);
+ }
+ sessionAppendValue(&p->rebase, pVal, &rc);
+ }
+ }
return rc;
}
@@ -195686,7 +196998,7 @@ static int sessionRetryConstraints(
SessionBuffer cons = pApply->constraints;
memset(&pApply->constraints, 0, sizeof(SessionBuffer));
- rc = sessionChangesetStart(&pIter2, 0, 0, cons.nBuf, cons.aBuf);
+ rc = sessionChangesetStart(&pIter2, 0, 0, cons.nBuf, cons.aBuf, 0);
if( rc==SQLITE_OK ){
int nByte = 2*pApply->nCol*sizeof(sqlite3_value*);
int rc2;
@@ -195752,6 +197064,7 @@ static int sessionChangesetApply(
pIter->in.bNoDiscard = 1;
memset(&sApply, 0, sizeof(sApply));
+ sApply.bRebase = (ppRebase && pnRebase);
sqlite3_mutex_enter(sqlite3_db_mutex(db));
if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){
rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0);
@@ -195902,7 +197215,8 @@ static int sessionChangesetApply(
}
}
- if( rc==SQLITE_OK && bPatchset==0 && ppRebase && pnRebase ){
+ assert( sApply.bRebase || sApply.rebase.nBuf==0 );
+ if( rc==SQLITE_OK && bPatchset==0 && sApply.bRebase ){
*ppRebase = (void*)sApply.rebase.aBuf;
*pnRebase = sApply.rebase.nBuf;
sApply.rebase.aBuf = 0;
@@ -195940,7 +197254,8 @@ SQLITE_API int sqlite3changeset_apply_v2(
int flags
){
sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */
- int rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset);
+ int bInverse = !!(flags & SQLITE_CHANGESETAPPLY_INVERT);
+ int rc = sessionChangesetStart(&pIter, 0, 0, nChangeset, pChangeset,bInverse);
if( rc==SQLITE_OK ){
rc = sessionChangesetApply(
db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags
@@ -195997,7 +197312,8 @@ SQLITE_API int sqlite3changeset_apply_v2_strm(
int flags
){
sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */
- int rc = sqlite3changeset_start_strm(&pIter, xInput, pIn);
+ int bInverse = !!(flags & SQLITE_CHANGESETAPPLY_INVERT);
+ int rc = sessionChangesetStart(&pIter, xInput, pIn, 0, 0, bInverse);
if( rc==SQLITE_OK ){
rc = sessionChangesetApply(
db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags
@@ -196370,13 +197686,12 @@ static int sessionChangegroupOutput(
sessionAppendByte(&buf, p->op, &rc);
sessionAppendByte(&buf, p->bIndirect, &rc);
sessionAppendBlob(&buf, p->aRecord, p->nRecord, &rc);
+ if( rc==SQLITE_OK && xOutput && buf.nBuf>=sessions_strm_chunk_size ){
+ rc = xOutput(pOut, buf.aBuf, buf.nBuf);
+ buf.nBuf = 0;
+ }
}
}
-
- if( rc==SQLITE_OK && xOutput && buf.nBuf>=SESSIONS_STRM_CHUNK_SIZE ){
- rc = xOutput(pOut, buf.aBuf, buf.nBuf);
- buf.nBuf = 0;
- }
}
if( rc==SQLITE_OK ){
@@ -196767,7 +198082,7 @@ static int sessionRebase(
sessionAppendByte(&sOut, pIter->bIndirect, &rc);
sessionAppendBlob(&sOut, aRec, nRec, &rc);
}
- if( rc==SQLITE_OK && xOutput && sOut.nBuf>SESSIONS_STRM_CHUNK_SIZE ){
+ if( rc==SQLITE_OK && xOutput && sOut.nBuf>sessions_strm_chunk_size ){
rc = xOutput(pOut, sOut.aBuf, sOut.nBuf);
sOut.nBuf = 0;
}
@@ -196878,6 +198193,27 @@ SQLITE_API void sqlite3rebaser_delete(sqlite3_rebaser *p){
}
}
+/*
+** Global configuration
+*/
+SQLITE_API int sqlite3session_config(int op, void *pArg){
+ int rc = SQLITE_OK;
+ switch( op ){
+ case SQLITE_SESSION_CONFIG_STRMSIZE: {
+ int *pInt = (int*)pArg;
+ if( *pInt>0 ){
+ sessions_strm_chunk_size = *pInt;
+ }
+ *pInt = sessions_strm_chunk_size;
+ break;
+ }
+ default:
+ rc = SQLITE_MISUSE;
+ break;
+ }
+ return rc;
+}
+
#endif /* SQLITE_ENABLE_SESSION && SQLITE_ENABLE_PREUPDATE_HOOK */
/************** End of sqlite3session.c **************************************/
@@ -198312,6 +199648,7 @@ static void sqlite3Fts5UnicodeAscii(u8*, u8*);
** input grammar file:
*/
/* #include <stdio.h> */
+/* #include <assert.h> */
/************ Begin %include sections from the grammar ************************/
/* #include "fts5Int.h" */
@@ -199634,10 +200971,9 @@ static void sqlite3Fts5Parser(
fts5yymajor = fts5YYNOCODE;
}else{
while( fts5yypParser->fts5yytos >= fts5yypParser->fts5yystack
- && fts5yymx != fts5YYERRORSYMBOL
&& (fts5yyact = fts5yy_find_reduce_action(
fts5yypParser->fts5yytos->stateno,
- fts5YYERRORSYMBOL)) >= fts5YY_MIN_REDUCE
+ fts5YYERRORSYMBOL)) > fts5YY_MAX_SHIFTREDUCE
){
fts5yy_pop_parser_stack(fts5yypParser);
}
@@ -210587,7 +211923,7 @@ static int sqlite3Fts5IndexQuery(
fts5CloseReader(p);
}
- *ppIter = &pRet->base;
+ *ppIter = (Fts5IndexIter*)pRet;
sqlite3Fts5BufferFree(&buf);
}
return fts5IndexReturn(p);
@@ -214336,12 +215672,27 @@ static void fts5SourceIdFunc(
){
assert( nArg==0 );
UNUSED_PARAM2(nArg, apUnused);
- sqlite3_result_text(pCtx, "fts5: 2018-11-05 20:37:38 89e099fbe5e13c33e683bef07361231ca525b88f7907be7092058007b75036f2", -1, SQLITE_TRANSIENT);
+ sqlite3_result_text(pCtx, "fts5: 2018-12-01 12:34:55 bf8c1b2b7a5960c282e543b9c293686dccff272512d08865f4600fb58238b4f9", -1, SQLITE_TRANSIENT);
+}
+
+/*
+** Return true if zName is the extension on one of the shadow tables used
+** by this module.
+*/
+static int fts5ShadowName(const char *zName){
+ static const char *azName[] = {
+ "config", "content", "data", "docsize", "idx"
+ };
+ unsigned int i;
+ for(i=0; i<sizeof(azName)/sizeof(azName[0]); i++){
+ if( sqlite3_stricmp(zName, azName[i])==0 ) return 1;
+ }
+ return 0;
}
static int fts5Init(sqlite3 *db){
static const sqlite3_module fts5Mod = {
- /* iVersion */ 2,
+ /* iVersion */ 3,
/* xCreate */ fts5CreateMethod,
/* xConnect */ fts5ConnectMethod,
/* xBestIndex */ fts5BestIndexMethod,
@@ -214364,6 +215715,7 @@ static int fts5Init(sqlite3 *db){
/* xSavepoint */ fts5SavepointMethod,
/* xRelease */ fts5ReleaseMethod,
/* xRollbackTo */ fts5RollbackToMethod,
+ /* xShadowName */ fts5ShadowName
};
int rc;
@@ -218408,6 +219760,8 @@ static int fts5VocabInstanceNext(Fts5VocabCursor *pCsr){
i64 *pp = &pCsr->iInstPos;
int *po = &pCsr->iInstOff;
+ assert( sqlite3Fts5IterEof(pIter)==0 );
+ assert( pCsr->bEof==0 );
while( eDetail==FTS5_DETAIL_NONE
|| sqlite3Fts5PoslistNext64(pIter->pData, pIter->nData, po, pp)
){
@@ -218417,7 +219771,7 @@ static int fts5VocabInstanceNext(Fts5VocabCursor *pCsr){
rc = sqlite3Fts5IterNextScan(pCsr->pIter);
if( rc==SQLITE_OK ){
rc = fts5VocabInstanceNewTerm(pCsr);
- if( eDetail==FTS5_DETAIL_NONE ) break;
+ if( pCsr->bEof || eDetail==FTS5_DETAIL_NONE ) break;
}
if( rc ){
pCsr->bEof = 1;
@@ -218732,6 +220086,7 @@ static int sqlite3Fts5VocabInit(Fts5Global *pGlobal, sqlite3 *db){
/* xSavepoint */ 0,
/* xRelease */ 0,
/* xRollbackTo */ 0,
+ /* xShadowName */ 0
};
void *p = (void*)pGlobal;
@@ -218740,8 +220095,6 @@ static int sqlite3Fts5VocabInit(Fts5Global *pGlobal, sqlite3 *db){
-
-
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS5) */
/************** End of fts5.c ************************************************/
@@ -219014,6 +220367,7 @@ static sqlite3_module stmtModule = {
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
+ 0, /* xShadowName */
};
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -219046,9 +220400,9 @@ SQLITE_API int sqlite3_stmt_init(
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
/************** End of stmt.c ************************************************/
-#if __LINE__!=219049
+#if __LINE__!=220403
#undef SQLITE_SOURCE_ID
-#define SQLITE_SOURCE_ID "2018-11-05 20:37:38 89e099fbe5e13c33e683bef07361231ca525b88f7907be7092058007b750alt2"
+#define SQLITE_SOURCE_ID "2018-12-01 12:34:55 bf8c1b2b7a5960c282e543b9c293686dccff272512d08865f4600fb58238alt2"
#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/amalgamation/sqlite3.h b/chromium/third_party/sqlite/amalgamation/sqlite3.h
index 165bd8a218a..fe538430428 100644
--- a/chromium/third_party/sqlite/amalgamation/sqlite3.h
+++ b/chromium/third_party/sqlite/amalgamation/sqlite3.h
@@ -123,9 +123,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.25.3"
-#define SQLITE_VERSION_NUMBER 3025003
-#define SQLITE_SOURCE_ID "2018-11-05 20:37:38 89e099fbe5e13c33e683bef07361231ca525b88f7907be7092058007b750alt1"
+#define SQLITE_VERSION "3.26.0"
+#define SQLITE_VERSION_NUMBER 3026000
+#define SQLITE_SOURCE_ID "2018-12-01 12:34:55 bf8c1b2b7a5960c282e543b9c293686dccff272512d08865f4600fb58238alt1"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -2017,6 +2017,7 @@ struct sqlite3_mem_methods {
** is invoked.
**
** <dl>
+** [[SQLITE_DBCONFIG_LOOKASIDE]]
** <dt>SQLITE_DBCONFIG_LOOKASIDE</dt>
** <dd> ^This option takes three additional arguments that determine the
** [lookaside memory allocator] configuration for the [database connection].
@@ -2039,6 +2040,7 @@ struct sqlite3_mem_methods {
** memory is in use leaves the configuration unchanged and returns
** [SQLITE_BUSY].)^</dd>
**
+** [[SQLITE_DBCONFIG_ENABLE_FKEY]]
** <dt>SQLITE_DBCONFIG_ENABLE_FKEY</dt>
** <dd> ^This option is used to enable or disable the enforcement of
** [foreign key constraints]. There should be two additional arguments.
@@ -2049,6 +2051,7 @@ struct sqlite3_mem_methods {
** following this call. The second parameter may be a NULL pointer, in
** which case the FK enforcement setting is not reported back. </dd>
**
+** [[SQLITE_DBCONFIG_ENABLE_TRIGGER]]
** <dt>SQLITE_DBCONFIG_ENABLE_TRIGGER</dt>
** <dd> ^This option is used to enable or disable [CREATE TRIGGER | triggers].
** There should be two additional arguments.
@@ -2059,6 +2062,7 @@ struct sqlite3_mem_methods {
** following this call. The second parameter may be a NULL pointer, in
** which case the trigger setting is not reported back. </dd>
**
+** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]]
** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt>
** <dd> ^This option is used to enable or disable the two-argument
** version of the [fts3_tokenizer()] function which is part of the
@@ -2072,6 +2076,7 @@ struct sqlite3_mem_methods {
** following this call. The second parameter may be a NULL pointer, in
** which case the new setting is not reported back. </dd>
**
+** [[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION]]
** <dt>SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION</dt>
** <dd> ^This option is used to enable or disable the [sqlite3_load_extension()]
** interface independently of the [load_extension()] SQL function.
@@ -2089,7 +2094,7 @@ struct sqlite3_mem_methods {
** be a NULL pointer, in which case the new setting is not reported back.
** </dd>
**
-** <dt>SQLITE_DBCONFIG_MAINDBNAME</dt>
+** [[SQLITE_DBCONFIG_MAINDBNAME]] <dt>SQLITE_DBCONFIG_MAINDBNAME</dt>
** <dd> ^This option is used to change the name of the "main" database
** schema. ^The sole argument is a pointer to a constant UTF8 string
** which will become the new schema name in place of "main". ^SQLite
@@ -2098,6 +2103,7 @@ struct sqlite3_mem_methods {
** until after the database connection closes.
** </dd>
**
+** [[SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE]]
** <dt>SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE</dt>
** <dd> Usually, when a database in wal mode is closed or detached from a
** database handle, SQLite checks if this will mean that there are now no
@@ -2111,7 +2117,7 @@ struct sqlite3_mem_methods {
** have been disabled - 0 if they are not disabled, 1 if they are.
** </dd>
**
-** <dt>SQLITE_DBCONFIG_ENABLE_QPSG</dt>
+** [[SQLITE_DBCONFIG_ENABLE_QPSG]] <dt>SQLITE_DBCONFIG_ENABLE_QPSG</dt>
** <dd>^(The SQLITE_DBCONFIG_ENABLE_QPSG option activates or deactivates
** the [query planner stability guarantee] (QPSG). When the QPSG is active,
** a single SQL query statement will always use the same algorithm regardless
@@ -2127,7 +2133,7 @@ struct sqlite3_mem_methods {
** following this call.
** </dd>
**
-** <dt>SQLITE_DBCONFIG_TRIGGER_EQP</dt>
+** [[SQLITE_DBCONFIG_TRIGGER_EQP]] <dt>SQLITE_DBCONFIG_TRIGGER_EQP</dt>
** <dd> By default, the output of EXPLAIN QUERY PLAN commands does not
** include output for any operations performed by trigger programs. This
** option is used to set or clear (the default) a flag that governs this
@@ -2139,7 +2145,7 @@ struct sqlite3_mem_methods {
** it is not disabled, 1 if it is.
** </dd>
**
-** <dt>SQLITE_DBCONFIG_RESET_DATABASE</dt>
+** [[SQLITE_DBCONFIG_RESET_DATABASE]] <dt>SQLITE_DBCONFIG_RESET_DATABASE</dt>
** <dd> Set the SQLITE_DBCONFIG_RESET_DATABASE flag and then run
** [VACUUM] in order to reset a database back to an empty database
** with no schema and no content. The following process works even for
@@ -2158,6 +2164,18 @@ struct sqlite3_mem_methods {
** Because resetting a database is destructive and irreversible, the
** process requires the use of this obscure API and multiple steps to help
** ensure that it does not happen by accident.
+**
+** [[SQLITE_DBCONFIG_DEFENSIVE]] <dt>SQLITE_DBCONFIG_DEFENSIVE</dt>
+** <dd>The SQLITE_DBCONFIG_DEFENSIVE option activates or deactivates the
+** "defensive" flag for a database connection. When the defensive
+** flag is enabled, language features that allow ordinary SQL to
+** deliberately corrupt the database file are disabled. The disabled
+** features include but are not limited to the following:
+** <ul>
+** <li> The [PRAGMA writable_schema=ON] statement.
+** <li> Writes to the [sqlite_dbpage] virtual table.
+** <li> Direct writes to [shadow tables].
+** </ul>
** </dd>
** </dl>
*/
@@ -2171,7 +2189,8 @@ struct sqlite3_mem_methods {
#define SQLITE_DBCONFIG_ENABLE_QPSG 1007 /* int int* */
#define SQLITE_DBCONFIG_TRIGGER_EQP 1008 /* int int* */
#define SQLITE_DBCONFIG_RESET_DATABASE 1009 /* int int* */
-#define SQLITE_DBCONFIG_MAX 1009 /* Largest DBCONFIG */
+#define SQLITE_DBCONFIG_DEFENSIVE 1010 /* int int* */
+#define SQLITE_DBCONFIG_MAX 1010 /* Largest DBCONFIG */
/*
** CAPI3REF: Enable Or Disable Extended Result Codes
@@ -3609,9 +3628,19 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** on this hint by avoiding the use of [lookaside memory] so as not to
** deplete the limited store of lookaside memory. Future versions of
** SQLite may act on this hint differently.
+**
+** [[SQLITE_PREPARE_NORMALIZE]] ^(<dt>SQLITE_PREPARE_NORMALIZE</dt>
+** <dd>The SQLITE_PREPARE_NORMALIZE flag indicates that a normalized
+** representation of the SQL statement should be calculated and then
+** associated with the prepared statement, which can be obtained via
+** the [sqlite3_normalized_sql()] interface.)^ The semantics used to
+** normalize a SQL statement are unspecified and subject to change.
+** At a minimum, literal values will be replaced with suitable
+** placeholders.
** </dl>
*/
#define SQLITE_PREPARE_PERSISTENT 0x01
+#define SQLITE_PREPARE_NORMALIZE 0x02
/*
** CAPI3REF: Compiling An SQL Statement
@@ -3769,6 +3798,11 @@ SQLITE_API int sqlite3_prepare16_v3(
** ^The sqlite3_expanded_sql(P) interface returns a pointer to a UTF-8
** string containing the SQL text of prepared statement P with
** [bound parameters] expanded.
+** ^The sqlite3_normalized_sql(P) interface returns a pointer to a UTF-8
+** string containing the normalized SQL text of prepared statement P. The
+** semantics used to normalize a SQL statement are unspecified and subject
+** to change. At a minimum, literal values will be replaced with suitable
+** placeholders.
**
** ^(For example, if a prepared statement is created using the SQL
** text "SELECT $abc,:xyz" and if parameter $abc is bound to integer 2345
@@ -3784,14 +3818,16 @@ SQLITE_API int sqlite3_prepare16_v3(
** bound parameter expansions. ^The [SQLITE_OMIT_TRACE] compile-time
** option causes sqlite3_expanded_sql() to always return NULL.
**
-** ^The string returned by sqlite3_sql(P) is managed by SQLite and is
-** automatically freed when the prepared statement is finalized.
+** ^The strings returned by sqlite3_sql(P) and sqlite3_normalized_sql(P)
+** are managed by SQLite and are automatically freed when the prepared
+** statement is finalized.
** ^The string returned by sqlite3_expanded_sql(P), on the other hand,
** is obtained from [sqlite3_malloc()] and must be free by the application
** by passing it to [sqlite3_free()].
*/
SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt);
SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt);
+SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt);
/*
** CAPI3REF: Determine If An SQL Statement Writes The Database
@@ -6281,6 +6317,9 @@ struct sqlite3_module {
int (*xSavepoint)(sqlite3_vtab *pVTab, int);
int (*xRelease)(sqlite3_vtab *pVTab, int);
int (*xRollbackTo)(sqlite3_vtab *pVTab, int);
+ /* The methods above are in versions 1 and 2 of the sqlite_module object.
+ ** Those below are for version 3 and greater. */
+ int (*xShadowName)(const char*);
};
/*
@@ -7203,6 +7242,7 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_OPTIMIZATIONS 15
#define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */
#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */
+#define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 17
#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
#define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */
#define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19
@@ -8638,6 +8678,7 @@ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
** can use to customize and optimize their behavior.
**
** <dl>
+** [[SQLITE_VTAB_CONSTRAINT_SUPPORT]]
** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT
** <dd>Calls of the form
** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported,
@@ -9407,7 +9448,7 @@ struct sqlite3_rtree_query_info {
sqlite3_int64 iRowid; /* Rowid for current entry */
sqlite3_rtree_dbl rParentScore; /* Score of parent node */
int eParentWithin; /* Visibility of parent node */
- int eWithin; /* OUT: Visiblity */
+ int eWithin; /* OUT: Visibility */
sqlite3_rtree_dbl rScore; /* OUT: Write the score here */
/* The following fields are only available in 3.8.11 and later */
sqlite3_value **apSqlParam; /* Original SQL values of parameters */
@@ -9903,12 +9944,38 @@ SQLITE_API int sqlite3session_isempty(sqlite3_session *pSession);
** consecutively. There is no chance that the iterator will visit a change
** the applies to table X, then one for table Y, and then later on visit
** another change for table X.
+**
+** The behavior of sqlite3changeset_start_v2() and its streaming equivalent
+** may be modified by passing a combination of
+** [SQLITE_CHANGESETSTART_INVERT | supported flags] as the 4th parameter.
+**
+** Note that the sqlite3changeset_start_v2() API is still <b>experimental</b>
+** and therefore subject to change.
*/
SQLITE_API int sqlite3changeset_start(
sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */
int nChangeset, /* Size of changeset blob in bytes */
void *pChangeset /* Pointer to blob containing changeset */
);
+SQLITE_API int sqlite3changeset_start_v2(
+ sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */
+ int nChangeset, /* Size of changeset blob in bytes */
+ void *pChangeset, /* Pointer to blob containing changeset */
+ int flags /* SESSION_CHANGESETSTART_* flags */
+);
+
+/*
+** CAPI3REF: Flags for sqlite3changeset_start_v2
+**
+** The following flags may passed via the 4th parameter to
+** [sqlite3changeset_start_v2] and [sqlite3changeset_start_v2_strm]:
+**
+** <dt>SQLITE_CHANGESETAPPLY_INVERT <dd>
+** Invert the changeset while iterating through it. This is equivalent to
+** inverting a changeset using sqlite3changeset_invert() before applying it.
+** It is an error to specify this flag with a patchset.
+*/
+#define SQLITE_CHANGESETSTART_INVERT 0x0002
/*
@@ -10563,7 +10630,7 @@ SQLITE_API int sqlite3changeset_apply_v2(
),
void *pCtx, /* First argument passed to xConflict */
void **ppRebase, int *pnRebase, /* OUT: Rebase data */
- int flags /* Combination of SESSION_APPLY_* flags */
+ int flags /* SESSION_CHANGESETAPPLY_* flags */
);
/*
@@ -10581,8 +10648,14 @@ SQLITE_API int sqlite3changeset_apply_v2(
** causes the sessions module to omit this savepoint. In this case, if the
** caller has an open transaction or savepoint when apply_v2() is called,
** it may revert the partially applied changeset by rolling it back.
+**
+** <dt>SQLITE_CHANGESETAPPLY_INVERT <dd>
+** Invert the changeset before applying it. This is equivalent to inverting
+** a changeset using sqlite3changeset_invert() before applying it. It is
+** an error to specify this flag with a patchset.
*/
#define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001
+#define SQLITE_CHANGESETAPPLY_INVERT 0x0002
/*
** CAPI3REF: Constants Passed To The Conflict Handler
@@ -10976,6 +11049,12 @@ SQLITE_API int sqlite3changeset_start_strm(
int (*xInput)(void *pIn, void *pData, int *pnData),
void *pIn
);
+SQLITE_API int sqlite3changeset_start_v2_strm(
+ sqlite3_changeset_iter **pp,
+ int (*xInput)(void *pIn, void *pData, int *pnData),
+ void *pIn,
+ int flags
+);
SQLITE_API int sqlite3session_changeset_strm(
sqlite3_session *pSession,
int (*xOutput)(void *pOut, const void *pData, int nData),
@@ -11002,6 +11081,45 @@ SQLITE_API int sqlite3rebaser_rebase_strm(
void *pOut
);
+/*
+** CAPI3REF: Configure global parameters
+**
+** The sqlite3session_config() interface is used to make global configuration
+** changes to the sessions module in order to tune it to the specific needs
+** of the application.
+**
+** The sqlite3session_config() interface is not threadsafe. If it is invoked
+** while any other thread is inside any other sessions method then the
+** results are undefined. Furthermore, if it is invoked after any sessions
+** related objects have been created, the results are also undefined.
+**
+** The first argument to the sqlite3session_config() function must be one
+** of the SQLITE_SESSION_CONFIG_XXX constants defined below. The
+** interpretation of the (void*) value passed as the second parameter and
+** the effect of calling this function depends on the value of the first
+** parameter.
+**
+** <dl>
+** <dt>SQLITE_SESSION_CONFIG_STRMSIZE<dd>
+** By default, the sessions module streaming interfaces attempt to input
+** and output data in approximately 1 KiB chunks. This operand may be used
+** to set and query the value of this configuration setting. The pointer
+** passed as the second argument must point to a value of type (int).
+** If this value is greater than 0, it is used as the new streaming data
+** chunk size for both input and output. Before returning, the (int) value
+** pointed to by pArg is set to the final value of the streaming interface
+** chunk size.
+** </dl>
+**
+** This function returns SQLITE_OK if successful, or an SQLite error code
+** otherwise.
+*/
+SQLITE_API int sqlite3session_config(int op, void *pArg);
+
+/*
+** CAPI3REF: Values for sqlite3session_config().
+*/
+#define SQLITE_SESSION_CONFIG_STRMSIZE 1
/*
** Make sure we can call this stuff from C++.
diff --git a/chromium/third_party/sqlite/fuzz/sqlite3_prepare_v2_fuzzer.cc b/chromium/third_party/sqlite/fuzz/sqlite3_prepare_v2_fuzzer.cc
deleted file mode 100644
index cc5c8f18a3a..00000000000
--- a/chromium/third_party/sqlite/fuzz/sqlite3_prepare_v2_fuzzer.cc
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <algorithm>
-#include <array>
-#include <string>
-#include <vector>
-
-#include "third_party/sqlite/sqlite3.h"
-
-
-static const std::array<uint8_t, 6> kBadKeyword{{'R', 'E', 'G', 'E', 'X', 'P'}};
-
-
-bool checkForBadKeyword(const uint8_t* data, size_t size) {
- auto it = std::search(
- data, data + size, kBadKeyword.begin(), kBadKeyword.end(),
- [](char c1, char c2) { return std::toupper(c1) == std::toupper(c2); });
-
- if (it != data + size)
- return true;
-
- return false;
-}
-
-
-#if !defined(SQLITE_OMIT_PROGRESS_CALLBACK)
-
-static int Progress(void *not_used_ptr) {
- return 1;
-}
-
-#endif // !defined(SQLITE_OMIT_PROGRESS_CALLBACK)
-
-
-// Entry point for LibFuzzer.
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- if (size < 2)
- return 0;
-
- if (checkForBadKeyword(data, size))
- return 0;
-
- sqlite3* db;
- int return_code = sqlite3_open_v2(
- "db.db",
- &db,
- SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY, 0);
-
- if (SQLITE_OK != return_code)
- return 0;
-
- // Use first byte as random selector for other parameters.
- int selector = data[0];
-
-#if !defined(SQLITE_OMIT_PROGRESS_CALLBACK)
- // To cover both cases when progress_handler is used and isn't used.
- if (selector & 1)
- sqlite3_progress_handler(db, 4, &Progress, NULL);
- else
- sqlite3_progress_handler(db, 0, NULL, NULL);
-
- // Remove least significant bit to make further usage of selector independent.
- selector >>= 1;
-#endif // !defined(SQLITE_OMIT_PROGRESS_CALLBACK)
-
- sqlite3_stmt* statement = NULL;
- int result = sqlite3_prepare_v2(db, reinterpret_cast<const char*>(data + 1),
- static_cast<int>(size - 1), &statement, NULL);
- if (result == SQLITE_OK) {
- // Use selector value to randomize number of iterations.
- for (int i = 0; i < selector; i++) {
- if (sqlite3_step(statement) != SQLITE_ROW)
- break;
- }
-
- sqlite3_finalize(statement);
- }
-
- sqlite3_close(db);
- return 0;
-}
diff --git a/chromium/third_party/sqlite/patches/0001-Modify-default-VFS-to-support-WebDatabase.patch b/chromium/third_party/sqlite/patches/0001-Modify-default-VFS-to-support-WebDatabase.patch
new file mode 100644
index 00000000000..6d8ff9f0399
--- /dev/null
+++ b/chromium/third_party/sqlite/patches/0001-Modify-default-VFS-to-support-WebDatabase.patch
@@ -0,0 +1,179 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: dumi <dumi@chromium.org>
+Date: Mon, 20 Jul 2009 23:40:51 +0000
+Subject: [PATCH 01/17] Modify default VFS to support WebDatabase.
+
+The renderer WebDatabase implementation needs to broker certain requests
+to the browser. This modifies SQLite to allow monkey-patching the VFS
+to support this.
+
+NOTE(shess): This patch relies on core SQLite implementation details
+remaining unchanged. When importing a new version of SQLite, pay very
+close attention to whether the change is still doing what is intended.
+
+Original review URLs:
+https://codereview.chromium.org/159044
+https://codereview.chromium.org/384075
+https://codereview.chromium.org/377039
+[Possibly not a complete list.]
+---
+ third_party/sqlite/src/src/os_unix.c | 51 ++++++++++++++++++++++++++
+ third_party/sqlite/src/src/os_win.c | 8 ++++
+ third_party/sqlite/src/src/sqlite.h.in | 23 ++++++++++++
+ 3 files changed, 82 insertions(+)
+
+diff --git a/third_party/sqlite/src/src/os_unix.c b/third_party/sqlite/src/src/os_unix.c
+index 52ef64116444..d0e1c39bc4b8 100644
+--- a/third_party/sqlite/src/src/os_unix.c
++++ b/third_party/sqlite/src/src/os_unix.c
+@@ -1437,6 +1437,12 @@ static int fileHasMoved(unixFile *pFile){
+ return pFile->pInode!=0 && pFile->pId!=pFile->pInode->fileId.pId;
+ #else
+ struct stat buf;
++
++ /* TODO(shess): This check doesn't work when the Chromium's WebDB code is
++ ** running in the sandbox.
++ */
++ return 0;
++
+ return pFile->pInode!=0 &&
+ (osStat(pFile->zPath, &buf)!=0
+ || (u64)buf.st_ino!=pFile->pInode->fileId.ino);
+@@ -5879,6 +5885,45 @@ static int findCreateFileMode(
+ return rc;
+ }
+
++/*
++** Initialize |unixFile| internals of |file| on behalf of chromiumOpen() in
++** WebDatabase SQLiteFileSystemPosix.cpp. Function is a subset of unixOpen(),
++** each duplicated piece is marked by "Duplicated in" comment in unixOpen().
++*/
++CHROMIUM_SQLITE_API
++int chromium_sqlite3_fill_in_unix_sqlite3_file(sqlite3_vfs* pVfs,
++ int fd,
++ sqlite3_file* pFile,
++ const char* zPath,
++ int noLock,
++ int flags) {
++ unixFile *p = (unixFile *)pFile;
++ const int eType = flags&0xFFFFFF00; /* Type of file to open */
++ const int ctrlFlags = (noLock ? UNIXFILE_NOLOCK : 0);
++ int rc;
++
++ memset(p, 0, sizeof(unixFile));
++
++ /* osStat() will not work in the sandbox, so findReusableFd() will always
++ ** fail, so directly include the failure-case setup then initialize
++ ** pPreallocatedUnused.
++ */
++ if( eType==SQLITE_OPEN_MAIN_DB ){
++ p->pPreallocatedUnused = sqlite3_malloc(sizeof(*p->pPreallocatedUnused));
++ if (!p->pPreallocatedUnused) {
++ return SQLITE_NOMEM_BKPT;
++ }
++ p->pPreallocatedUnused->fd = fd;
++ p->pPreallocatedUnused->flags = flags;
++ }
++
++ rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);
++ if( rc!=SQLITE_OK ){
++ sqlite3_free(p->pPreallocatedUnused);
++ }
++ return rc;
++}
++
+ /*
+ ** Open the file zPath.
+ **
+@@ -5979,6 +6024,8 @@ static int unixOpen(
+ randomnessPid = osGetpid(0);
+ sqlite3_randomness(0,0);
+ }
++
++ /* Duplicated in chromium_sqlite3_fill_in_unix_sqlite3_file(). */
+ memset(p, 0, sizeof(unixFile));
+
+ if( eType==SQLITE_OPEN_MAIN_DB ){
+@@ -5987,6 +6034,7 @@ static int unixOpen(
+ if( pUnused ){
+ fd = pUnused->fd;
+ }else{
++ /* Duplicated in chromium_sqlite3_fill_in_unix_sqlite3_file(). */
+ pUnused = sqlite3_malloc64(sizeof(*pUnused));
+ if( !pUnused ){
+ return SQLITE_NOMEM_BKPT;
+@@ -6071,6 +6119,7 @@ static int unixOpen(
+ }
+
+ if( p->pPreallocatedUnused ){
++ /* Duplicated in chromium_sqlite3_fill_in_unix_sqlite3_file(). */
+ p->pPreallocatedUnused->fd = fd;
+ p->pPreallocatedUnused->flags = flags;
+ }
+@@ -6152,10 +6201,12 @@ static int unixOpen(
+ assert( zPath==0 || zPath[0]=='/'
+ || eType==SQLITE_OPEN_MASTER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL
+ );
++ /* Duplicated in chromium_sqlite3_fill_in_unix_sqlite3_file(). */
+ rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);
+
+ open_finished:
+ if( rc!=SQLITE_OK ){
++ /* Duplicated in chromium_sqlite3_fill_in_unix_sqlite3_file(). */
+ sqlite3_free(p->pPreallocatedUnused);
+ }
+ return rc;
+diff --git a/third_party/sqlite/src/src/os_win.c b/third_party/sqlite/src/src/os_win.c
+index aafc89f7d2d5..76743781a019 100644
+--- a/third_party/sqlite/src/src/os_win.c
++++ b/third_party/sqlite/src/src/os_win.c
+@@ -6130,4 +6130,12 @@ int sqlite3_os_end(void){
+ return SQLITE_OK;
+ }
+
++CHROMIUM_SQLITE_API
++void chromium_sqlite3_initialize_win_sqlite3_file(sqlite3_file* file, HANDLE handle) {
++ winFile* winSQLite3File = (winFile*)file;
++ memset(file, 0, sizeof(*file));
++ winSQLite3File->pMethod = &winIoMethod;
++ winSQLite3File->h = handle;
++}
++
+ #endif /* SQLITE_OS_WIN */
+diff --git a/third_party/sqlite/src/src/sqlite.h.in b/third_party/sqlite/src/src/sqlite.h.in
+index cf17bc015fa7..11622a49697f 100644
+--- a/third_party/sqlite/src/src/sqlite.h.in
++++ b/third_party/sqlite/src/src/sqlite.h.in
+@@ -8378,6 +8378,29 @@ int sqlite3_strnicmp(const char *, const char *, int);
+ */
+ int sqlite3_strglob(const char *zGlob, const char *zStr);
+
++/* Begin WebDatabase patch for Chromium */
++/* Expose some SQLite internals for the WebDatabase vfs.
++** DO NOT EXTEND THE USE OF THIS.
++*/
++#ifndef CHROMIUM_SQLITE_API
++#define CHROMIUM_SQLITE_API SQLITE_API
++#endif
++#if defined(CHROMIUM_SQLITE_INTERNALS)
++#ifdef _WIN32
++CHROMIUM_SQLITE_API
++void chromium_sqlite3_initialize_win_sqlite3_file(sqlite3_file* file, HANDLE handle);
++#else /* _WIN32 */
++CHROMIUM_SQLITE_API
++int chromium_sqlite3_fill_in_unix_sqlite3_file(sqlite3_vfs* pVfs,
++ int fd,
++ sqlite3_file* pFile,
++ const char* zPath,
++ int noLock,
++ int flags);
++#endif /* _WIN32 */
++#endif /* CHROMIUM_SQLITE_INTERNALS */
++/* End WebDatabase patch for Chromium */
++
+ /*
+ ** CAPI3REF: String LIKE Matching
+ *
+--
+2.18.0
+
diff --git a/chromium/third_party/sqlite/patches/0001-test-SQLite-tests-compiling-on-Linux.patch b/chromium/third_party/sqlite/patches/0001-test-SQLite-tests-compiling-on-Linux.patch
index 0e4706c2e8b..97cd2bd4fa2 100644
--- a/chromium/third_party/sqlite/patches/0001-test-SQLite-tests-compiling-on-Linux.patch
+++ b/chromium/third_party/sqlite/patches/0001-test-SQLite-tests-compiling-on-Linux.patch
@@ -1,7 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Scott Hess <shess@chromium.org>
Date: Fri, 16 Jan 2015 10:24:30 -0800
-Subject: [PATCH 01/10] [test] SQLite tests compiling on Linux.
+Subject: [PATCH 1/6] [test] SQLite tests compiling on Linux.
---
third_party/sqlite/src/Makefile.linux-gcc | 41 ++++++++++++++++-------
@@ -103,10 +103,10 @@ index b838b844a312..62d029430803 100644
#LIBTCL = /home/drh/tcltk/8.3hpux/libtcl8.3.a -ldld -lm -lc
diff --git a/third_party/sqlite/src/main.mk b/third_party/sqlite/src/main.mk
-index 051257e532a2..ef2b67bd5116 100644
+index d18313bdc79a..05c8f83b4212 100644
--- a/third_party/sqlite/src/main.mk
+++ b/third_party/sqlite/src/main.mk
-@@ -833,7 +833,7 @@ sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl $
+@@ -836,7 +836,7 @@ sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl $
tclsh $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in >sqlite3_analyzer.c
sqlite3_analyzer$(EXE): sqlite3_analyzer.c
diff --git a/chromium/third_party/sqlite/patches/0002-Modify-default-VFS-to-support-WebDatabase.patch b/chromium/third_party/sqlite/patches/0002-Modify-default-VFS-to-support-WebDatabase.patch
index 62200059a11..1dd942c5921 100644
--- a/chromium/third_party/sqlite/patches/0002-Modify-default-VFS-to-support-WebDatabase.patch
+++ b/chromium/third_party/sqlite/patches/0002-Modify-default-VFS-to-support-WebDatabase.patch
@@ -1,7 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: dumi <dumi@chromium.org>
Date: Mon, 20 Jul 2009 23:40:51 +0000
-Subject: [PATCH 02/10] Modify default VFS to support WebDatabase.
+Subject: [PATCH 2/6] Modify default VFS to support WebDatabase.
The renderer WebDatabase implementation needs to broker certain requests
to the browser. This modifies SQLite to allow monkey-patching the VFS
@@ -23,10 +23,10 @@ https://codereview.chromium.org/377039
3 files changed, 82 insertions(+)
diff --git a/third_party/sqlite/src/src/os_unix.c b/third_party/sqlite/src/src/os_unix.c
-index 745573fa84b1..ebae2eb47043 100644
+index 52ef64116444..d0e1c39bc4b8 100644
--- a/third_party/sqlite/src/src/os_unix.c
+++ b/third_party/sqlite/src/src/os_unix.c
-@@ -1436,6 +1436,12 @@ static int fileHasMoved(unixFile *pFile){
+@@ -1437,6 +1437,12 @@ static int fileHasMoved(unixFile *pFile){
return pFile->pInode!=0 && pFile->pId!=pFile->pInode->fileId.pId;
#else
struct stat buf;
@@ -39,7 +39,7 @@ index 745573fa84b1..ebae2eb47043 100644
return pFile->pInode!=0 &&
(osStat(pFile->zPath, &buf)!=0
|| (u64)buf.st_ino!=pFile->pInode->fileId.ino);
-@@ -5872,6 +5878,45 @@ static int findCreateFileMode(
+@@ -5879,6 +5885,45 @@ static int findCreateFileMode(
return rc;
}
@@ -85,7 +85,7 @@ index 745573fa84b1..ebae2eb47043 100644
/*
** Open the file zPath.
**
-@@ -5972,6 +6017,8 @@ static int unixOpen(
+@@ -5979,6 +6024,8 @@ static int unixOpen(
randomnessPid = osGetpid(0);
sqlite3_randomness(0,0);
}
@@ -94,7 +94,7 @@ index 745573fa84b1..ebae2eb47043 100644
memset(p, 0, sizeof(unixFile));
if( eType==SQLITE_OPEN_MAIN_DB ){
-@@ -5980,6 +6027,7 @@ static int unixOpen(
+@@ -5987,6 +6034,7 @@ static int unixOpen(
if( pUnused ){
fd = pUnused->fd;
}else{
@@ -102,7 +102,7 @@ index 745573fa84b1..ebae2eb47043 100644
pUnused = sqlite3_malloc64(sizeof(*pUnused));
if( !pUnused ){
return SQLITE_NOMEM_BKPT;
-@@ -6064,6 +6112,7 @@ static int unixOpen(
+@@ -6071,6 +6119,7 @@ static int unixOpen(
}
if( p->pPreallocatedUnused ){
@@ -110,7 +110,7 @@ index 745573fa84b1..ebae2eb47043 100644
p->pPreallocatedUnused->fd = fd;
p->pPreallocatedUnused->flags = flags;
}
-@@ -6145,10 +6194,12 @@ static int unixOpen(
+@@ -6152,10 +6201,12 @@ static int unixOpen(
assert( zPath==0 || zPath[0]=='/'
|| eType==SQLITE_OPEN_MASTER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL
);
@@ -124,10 +124,10 @@ index 745573fa84b1..ebae2eb47043 100644
}
return rc;
diff --git a/third_party/sqlite/src/src/os_win.c b/third_party/sqlite/src/src/os_win.c
-index 2a4b613ff869..dfefc4452f02 100644
+index aafc89f7d2d5..76743781a019 100644
--- a/third_party/sqlite/src/src/os_win.c
+++ b/third_party/sqlite/src/src/os_win.c
-@@ -6114,4 +6114,12 @@ int sqlite3_os_end(void){
+@@ -6130,4 +6130,12 @@ int sqlite3_os_end(void){
return SQLITE_OK;
}
@@ -141,10 +141,10 @@ index 2a4b613ff869..dfefc4452f02 100644
+
#endif /* SQLITE_OS_WIN */
diff --git a/third_party/sqlite/src/src/sqlite.h.in b/third_party/sqlite/src/src/sqlite.h.in
-index 6749aa0082d4..620f10e631cc 100644
+index cf17bc015fa7..11622a49697f 100644
--- a/third_party/sqlite/src/src/sqlite.h.in
+++ b/third_party/sqlite/src/src/sqlite.h.in
-@@ -8338,6 +8338,29 @@ int sqlite3_strnicmp(const char *, const char *, int);
+@@ -8378,6 +8378,29 @@ int sqlite3_strnicmp(const char *, const char *, int);
*/
int sqlite3_strglob(const char *zGlob, const char *zStr);
diff --git a/chromium/third_party/sqlite/patches/0002-Virtual-table-supporting-recovery-of-corrupted-datab.patch b/chromium/third_party/sqlite/patches/0002-Virtual-table-supporting-recovery-of-corrupted-datab.patch
new file mode 100644
index 00000000000..ff5175af8b8
--- /dev/null
+++ b/chromium/third_party/sqlite/patches/0002-Virtual-table-supporting-recovery-of-corrupted-datab.patch
@@ -0,0 +1,3905 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Scott Hess <shess@chromium.org>
+Date: Sat, 20 Jul 2013 11:42:21 -0700
+Subject: [PATCH 02/17] Virtual table supporting recovery of corrupted
+ databases.
+
+"recover" implements a virtual table which uses the SQLite pager layer
+to read table pages and pull out the data which is structurally sound
+(at least at the storage layer).
+
+BUG=109482
+
+Since this implements a new feature for SQLite, the review URLs aren't
+listed. This patch and the top of recover.c should be considered
+authoritative. The history is mostly under
+third_party/sqlite/src/src/{recover,recover-alt}.c .
+---
+ third_party/sqlite/src/main.mk | 5 +
+ third_party/sqlite/src/src/main.c | 8 +
+ third_party/sqlite/src/src/recover.c | 2270 +++++++++++++++++++
+ third_party/sqlite/src/src/recover.h | 23 +
+ third_party/sqlite/src/src/recover_varint.c | 201 ++
+ third_party/sqlite/src/test/recover.test | 164 ++
+ third_party/sqlite/src/test/recover0.test | 532 +++++
+ third_party/sqlite/src/test/recover1.test | 429 ++++
+ third_party/sqlite/src/test/recover2.test | 157 ++
+ 9 files changed, 3789 insertions(+)
+ create mode 100644 third_party/sqlite/src/src/recover.c
+ create mode 100644 third_party/sqlite/src/src/recover.h
+ create mode 100644 third_party/sqlite/src/src/recover_varint.c
+ create mode 100644 third_party/sqlite/src/test/recover.test
+ create mode 100644 third_party/sqlite/src/test/recover0.test
+ create mode 100644 third_party/sqlite/src/test/recover1.test
+ create mode 100644 third_party/sqlite/src/test/recover2.test
+
+diff --git a/third_party/sqlite/src/main.mk b/third_party/sqlite/src/main.mk
+index d18313bdc79a..81774f9b100f 100644
+--- a/third_party/sqlite/src/main.mk
++++ b/third_party/sqlite/src/main.mk
+@@ -77,6 +77,8 @@ LIBOBJ+= vdbe.o parse.o \
+ vdbetrace.o wal.o walker.o where.o wherecode.o whereexpr.o \
+ utf.o vtab.o window.o
+
++LIBOBJ += recover.o recover_varint.o
++
+ LIBOBJ += sqlite3session.o
+
+ # All of the source code files.
+@@ -409,6 +411,8 @@ TESTSRC2 = \
+ $(TOP)/src/prepare.c \
+ $(TOP)/src/printf.c \
+ $(TOP)/src/random.c \
++ $(TOP)/src/recover.c \
++ $(TOP)/src/recover_varint.c \
+ $(TOP)/src/pcache.c \
+ $(TOP)/src/pcache1.c \
+ $(TOP)/src/select.c \
+@@ -876,6 +880,7 @@ TESTFIXTURE_FLAGS += -DSQLITE_DEFAULT_PAGE_SIZE=1024
+ TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_STMTVTAB
+ TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_DBPAGE_VTAB
+ TESTFIXTURE_FLAGS += -DTCLSH_INIT_PROC=sqlite3TestInit
++TESTFIXTURE_FLAGS += -DDEFAULT_ENABLE_RECOVER=1
+
+ testfixture$(EXE): $(TESTSRC2) libsqlite3.a $(TESTSRC) $(TOP)/src/tclsqlite.c
+ $(TCCX) $(TCL_FLAGS) $(TESTFIXTURE_FLAGS) \
+diff --git a/third_party/sqlite/src/src/main.c b/third_party/sqlite/src/src/main.c
+index d994c7176ea4..478428ac27c8 100644
+--- a/third_party/sqlite/src/src/main.c
++++ b/third_party/sqlite/src/src/main.c
+@@ -3201,6 +3201,14 @@ static int openDatabase(
+ }
+ #endif
+
++#ifdef DEFAULT_ENABLE_RECOVER
++ /* Initialize recover virtual table for testing. */
++ extern int chrome_sqlite3_recoverVtableInit(sqlite3 *db);
++ if( !db->mallocFailed && rc==SQLITE_OK ){
++ rc = chrome_sqlite3_recoverVtableInit(db);
++ }
++#endif
++
+ #if defined(SQLITE_ENABLE_ICU) || defined(SQLITE_ENABLE_ICU_COLLATIONS)
+ if( !db->mallocFailed && rc==SQLITE_OK ){
+ rc = sqlite3IcuInit(db);
+diff --git a/third_party/sqlite/src/src/recover.c b/third_party/sqlite/src/src/recover.c
+new file mode 100644
+index 000000000000..ba239a507f9c
+--- /dev/null
++++ b/third_party/sqlite/src/src/recover.c
+@@ -0,0 +1,2270 @@
++/*
++** 2012 Jan 11
++**
++** The author disclaims copyright to this source code. In place of
++** a legal notice, here is a blessing:
++**
++** May you do good and not evil.
++** May you find forgiveness for yourself and forgive others.
++** May you share freely, never taking more than you give.
++*/
++/* TODO(shess): THIS MODULE IS STILL EXPERIMENTAL. DO NOT USE IT. */
++/* Implements a virtual table "recover" which can be used to recover
++ * data from a corrupt table. The table is walked manually, with
++ * corrupt items skipped. Additionally, any errors while reading will
++ * be skipped.
++ *
++ * Given a table with this definition:
++ *
++ * CREATE TABLE Stuff (
++ * name TEXT PRIMARY KEY,
++ * value TEXT NOT NULL
++ * );
++ *
++ * to recover the data from teh table, you could do something like:
++ *
++ * -- Attach another database, the original is not trustworthy.
++ * ATTACH DATABASE '/tmp/db.db' AS rdb;
++ * -- Create a new version of the table.
++ * CREATE TABLE rdb.Stuff (
++ * name TEXT PRIMARY KEY,
++ * value TEXT NOT NULL
++ * );
++ * -- This will read the original table's data.
++ * CREATE VIRTUAL TABLE temp.recover_Stuff using recover(
++ * main.Stuff,
++ * name TEXT STRICT NOT NULL, -- only real TEXT data allowed
++ * value TEXT STRICT NOT NULL
++ * );
++ * -- Corruption means the UNIQUE constraint may no longer hold for
++ * -- Stuff, so either OR REPLACE or OR IGNORE must be used.
++ * INSERT OR REPLACE INTO rdb.Stuff (rowid, name, value )
++ * SELECT rowid, name, value FROM temp.recover_Stuff;
++ * DROP TABLE temp.recover_Stuff;
++ * DETACH DATABASE rdb;
++ * -- Move db.db to replace original db in filesystem.
++ *
++ *
++ * Usage
++ *
++ * Given the goal of dealing with corruption, it would not be safe to
++ * create a recovery table in the database being recovered. So
++ * recovery tables must be created in the temp database. They are not
++ * appropriate to persist, in any case. [As a bonus, sqlite_master
++ * tables can be recovered. Perhaps more cute than useful, though.]
++ *
++ * The parameters are a specifier for the table to read, and a column
++ * definition for each bit of data stored in that table. The named
++ * table must be convertable to a root page number by reading the
++ * sqlite_master table. Bare table names are assumed to be in
++ * database 0 ("main"), other databases can be specified in db.table
++ * fashion.
++ *
++ * Column definitions are similar to BUT NOT THE SAME AS those
++ * provided to CREATE statements:
++ * column-def: column-name [type-name [STRICT] [NOT NULL]]
++ * type-name: (ANY|ROWID|INTEGER|FLOAT|NUMERIC|TEXT|BLOB)
++ *
++ * Only those exact type names are accepted, there is no type
++ * intuition. The only constraints accepted are STRICT (see below)
++ * and NOT NULL. Anything unexpected will cause the create to fail.
++ *
++ * ANY is a convenience to indicate that manifest typing is desired.
++ * It is equivalent to not specifying a type at all. The results for
++ * such columns will have the type of the data's storage. The exposed
++ * schema will contain no type for that column.
++ *
++ * ROWID is used for columns representing aliases to the rowid
++ * (INTEGER PRIMARY KEY, with or without AUTOINCREMENT), to make the
++ * concept explicit. Such columns are actually stored as NULL, so
++ * they cannot be simply ignored. The exposed schema will be INTEGER
++ * for that column.
++ *
++ * NOT NULL causes rows with a NULL in that column to be skipped. It
++ * also adds NOT NULL to the column in the exposed schema. If the
++ * table has ever had columns added using ALTER TABLE, then those
++ * columns implicitly contain NULL for rows which have not been
++ * updated. [Workaround using COALESCE() in your SELECT statement.]
++ *
++ * The created table is read-only, with no indices. Any SELECT will
++ * be a full-table scan, returning each valid row read from the
++ * storage of the backing table. The rowid will be the rowid of the
++ * row from the backing table. "Valid" means:
++ * - The cell metadata for the row is well-formed. Mainly this means that
++ * the cell header info describes a payload of the size indicated by
++ * the cell's payload size.
++ * - The cell does not run off the page.
++ * - The cell does not overlap any other cell on the page.
++ * - The cell contains doesn't contain too many columns.
++ * - The types of the serialized data match the indicated types (see below).
++ *
++ *
++ * Type affinity versus type storage.
++ *
++ * http://www.sqlite.org/datatype3.html describes SQLite's type
++ * affinity system. The system provides for automated coercion of
++ * types in certain cases, transparently enough that many developers
++ * do not realize that it is happening. Importantly, it implies that
++ * the raw data stored in the database may not have the obvious type.
++ *
++ * Differences between the stored data types and the expected data
++ * types may be a signal of corruption. This module makes some
++ * allowances for automatic coercion. It is important to be concious
++ * of the difference between the schema exposed by the module, and the
++ * data types read from storage. The following table describes how
++ * the module interprets things:
++ *
++ * type schema data STRICT
++ * ---- ------ ---- ------
++ * ANY <none> any any
++ * ROWID INTEGER n/a n/a
++ * INTEGER INTEGER integer integer
++ * FLOAT FLOAT integer or float float
++ * NUMERIC NUMERIC integer, float, or text integer or float
++ * TEXT TEXT text or blob text
++ * BLOB BLOB blob blob
++ *
++ * type is the type provided to the recover module, schema is the
++ * schema exposed by the module, data is the acceptable types of data
++ * decoded from storage, and STRICT is a modification of that.
++ *
++ * A very loose recovery system might use ANY for all columns, then
++ * use the appropriate sqlite3_column_*() calls to coerce to expected
++ * types. This doesn't provide much protection if a page from a
++ * different table with the same column count is linked into an
++ * inappropriate btree.
++ *
++ * A very tight recovery system might use STRICT to enforce typing on
++ * all columns, preferring to skip rows which are valid at the storage
++ * level but don't contain the right types. Note that FLOAT STRICT is
++ * almost certainly not appropriate, since integral values are
++ * transparently stored as integers, when that is more efficient.
++ *
++ * Another option is to use ANY for all columns and inspect each
++ * result manually (using sqlite3_column_*). This should only be
++ * necessary in cases where developers have used manifest typing (test
++ * to make sure before you decide that you aren't using manifest
++ * typing!).
++ *
++ *
++ * Caveats
++ *
++ * Leaf pages not referenced by interior nodes will not be found.
++ *
++ * Leaf pages referenced from interior nodes of other tables will not
++ * be resolved.
++ *
++ * Rows referencing invalid overflow pages will be skipped.
++ *
++ * SQlite rows have a header which describes how to interpret the rest
++ * of the payload. The header can be valid in cases where the rest of
++ * the record is actually corrupt (in the sense that the data is not
++ * the intended data). This can especially happen WRT overflow pages,
++ * as lack of atomic updates between pages is the primary form of
++ * corruption I have seen in the wild.
++ */
++/* The implementation is via a series of cursors. The cursor
++ * implementations follow the pattern:
++ *
++ * // Creates the cursor using various initialization info.
++ * int cursorCreate(...);
++ *
++ * // Returns 1 if there is no more data, 0 otherwise.
++ * int cursorEOF(Cursor *pCursor);
++ *
++ * // Various accessors can be used if not at EOF.
++ *
++ * // Move to the next item.
++ * int cursorNext(Cursor *pCursor);
++ *
++ * // Destroy the memory associated with the cursor.
++ * void cursorDestroy(Cursor *pCursor);
++ *
++ * References in the following are to sections at
++ * http://www.sqlite.org/fileformat2.html .
++ *
++ * RecoverLeafCursor iterates the records in a leaf table node
++ * described in section 1.5 "B-tree Pages". When the node is
++ * exhausted, an interior cursor is used to get the next leaf node,
++ * and iteration continues there.
++ *
++ * RecoverInteriorCursor iterates the child pages in an interior table
++ * node described in section 1.5 "B-tree Pages". When the node is
++ * exhausted, a parent interior cursor is used to get the next
++ * interior node at the same level, and iteration continues there.
++ *
++ * Together these record the path from the leaf level to the root of
++ * the tree. Iteration happens from the leaves rather than the root
++ * both for efficiency and putting the special case at the front of
++ * the list is easier to implement.
++ *
++ * RecoverCursor uses a RecoverLeafCursor to iterate the rows of a
++ * table, returning results via the SQLite virtual table interface.
++ */
++/* TODO(shess): It might be useful to allow DEFAULT in types to
++ * specify what to do for NULL when an ALTER TABLE case comes up.
++ * Unfortunately, simply adding it to the exposed schema and using
++ * sqlite3_result_null() does not cause the default to be generate.
++ * Handling it ourselves seems hard, unfortunately.
++ */
++
++#include <assert.h>
++#include <ctype.h>
++#include <stdint.h>
++#include <stdio.h>
++#include <string.h>
++
++#include "sqlite3.h"
++
++/* Some SQLite internals use, cribbed from fts5int.h. */
++#ifndef SQLITE_AMALGAMATION
++typedef uint8_t u8;
++typedef uint32_t u32;
++typedef sqlite3_int64 i64;
++typedef sqlite3_uint64 u64;
++
++#define ArraySize(x) (sizeof(x) / sizeof(x[0]))
++#endif
++
++/* From recover_varint.c. */
++u8 recoverGetVarint(const unsigned char *p, u64 *v);
++
++/* For debugging. */
++#if 0
++#define FNENTRY() fprintf(stderr, "In %s\n", __FUNCTION__)
++#else
++#define FNENTRY()
++#endif
++
++/* Generic constants and helper functions. */
++
++static const unsigned char kTableLeafPage = 0x0D;
++static const unsigned char kTableInteriorPage = 0x05;
++
++/* From section 1.2. */
++static const unsigned kiHeaderPageSizeOffset = 16;
++static const unsigned kiHeaderReservedSizeOffset = 20;
++static const unsigned kiHeaderEncodingOffset = 56;
++/* TODO(shess) |static const unsigned| fails creating the header in GetPager()
++** because |knHeaderSize| isn't |constexpr|. But this isn't C++, either.
++*/
++enum { knHeaderSize = 100};
++
++/* From section 1.5. */
++static const unsigned kiPageTypeOffset = 0;
++/* static const unsigned kiPageFreeBlockOffset = 1; */
++static const unsigned kiPageCellCountOffset = 3;
++/* static const unsigned kiPageCellContentOffset = 5; */
++/* static const unsigned kiPageFragmentedBytesOffset = 7; */
++static const unsigned knPageLeafHeaderBytes = 8;
++/* Interior pages contain an additional field. */
++static const unsigned kiPageRightChildOffset = 8;
++static const unsigned kiPageInteriorHeaderBytes = 12;
++
++/* Accepted types are specified by a mask. */
++#define MASK_ROWID (1<<0)
++#define MASK_INTEGER (1<<1)
++#define MASK_FLOAT (1<<2)
++#define MASK_TEXT (1<<3)
++#define MASK_BLOB (1<<4)
++#define MASK_NULL (1<<5)
++
++/* Helpers to decode fixed-size fields. */
++static u32 decodeUnsigned16(const unsigned char *pData){
++ return (pData[0]<<8) + pData[1];
++}
++static u32 decodeUnsigned32(const unsigned char *pData){
++ return (decodeUnsigned16(pData)<<16) + decodeUnsigned16(pData+2);
++}
++static i64 decodeSigned(const unsigned char *pData, unsigned nBytes){
++ i64 r = (char)(*pData);
++ while( --nBytes ){
++ r <<= 8;
++ r += *(++pData);
++ }
++ return r;
++}
++/* Derived from vdbeaux.c, sqlite3VdbeSerialGet(), case 7. */
++/* TODO(shess): Determine if swapMixedEndianFloat() applies. */
++static double decodeFloat64(const unsigned char *pData){
++#if !defined(NDEBUG)
++ static const u64 t1 = ((u64)0x3ff00000)<<32;
++ static const double r1 = 1.0;
++ u64 t2 = t1;
++ assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 );
++#endif
++ i64 x = decodeSigned(pData, 8);
++ double d;
++ memcpy(&d, &x, sizeof(x));
++ return d;
++}
++
++/* Return true if a varint can safely be read from pData/nData. */
++/* TODO(shess): DbPage points into the middle of a buffer which
++ * contains the page data before DbPage. So code should always be
++ * able to read a small number of varints safely. Consider whether to
++ * trust that or not.
++ */
++static int checkVarint(const unsigned char *pData, unsigned nData){
++ unsigned i;
++
++ /* In the worst case the decoder takes all 8 bits of the 9th byte. */
++ if( nData>=9 ){
++ return 1;
++ }
++
++ /* Look for a high-bit-clear byte in what's left. */
++ for( i=0; i<nData; ++i ){
++ if( !(pData[i]&0x80) ){
++ return 1;
++ }
++ }
++
++ /* Cannot decode in the space given. */
++ return 0;
++}
++
++/* Return 1 if n varints can be read from pData/nData. */
++static int checkVarints(const unsigned char *pData, unsigned nData,
++ unsigned n){
++ unsigned nCur = 0; /* Byte offset within current varint. */
++ unsigned nFound = 0; /* Number of varints found. */
++ unsigned i;
++
++ /* In the worst case the decoder takes all 8 bits of the 9th byte. */
++ if( nData>=9*n ){
++ return 1;
++ }
++
++ for( i=0; nFound<n && i<nData; ++i ){
++ nCur++;
++ if( nCur==9 || !(pData[i]&0x80) ){
++ nFound++;
++ nCur = 0;
++ }
++ }
++
++ return nFound==n;
++}
++
++/* ctype and str[n]casecmp() can be affected by locale (eg, tr_TR).
++ * These versions consider only the ASCII space.
++ */
++/* TODO(shess): It may be reasonable to just remove the need for these
++ * entirely. The module could require "TEXT STRICT NOT NULL", not
++ * "Text Strict Not Null" or whatever the developer felt like typing
++ * that day. Handling corrupt data is a PERFECT place to be pedantic.
++ */
++static int ascii_isspace(char c){
++ /* From fts3_expr.c */
++ return c==' ' || c=='\t' || c=='\n' || c=='\r' || c=='\v' || c=='\f';
++}
++static int ascii_isalnum(int x){
++ /* From fts3_tokenizer1.c */
++ return (x>='0' && x<='9') || (x>='A' && x<='Z') || (x>='a' && x<='z');
++}
++static int ascii_tolower(int x){
++ /* From fts3_tokenizer1.c */
++ return (x>='A' && x<='Z') ? x-'A'+'a' : x;
++}
++/* TODO(shess): Consider sqlite3_strnicmp() */
++static int ascii_strncasecmp(const char *s1, const char *s2, size_t n){
++ const unsigned char *us1 = (const unsigned char *)s1;
++ const unsigned char *us2 = (const unsigned char *)s2;
++ while( *us1 && *us2 && n && ascii_tolower(*us1)==ascii_tolower(*us2) ){
++ us1++, us2++, n--;
++ }
++ return n ? ascii_tolower(*us1)-ascii_tolower(*us2) : 0;
++}
++static int ascii_strcasecmp(const char *s1, const char *s2){
++ /* If s2 is equal through strlen(s1), will exit while() due to s1's
++ * trailing NUL, and return NUL-s2[strlen(s1)].
++ */
++ return ascii_strncasecmp(s1, s2, strlen(s1)+1);
++}
++
++/* Provide access to the pages of a SQLite database in a way similar to SQLite's
++** Pager.
++*/
++typedef struct RecoverPager RecoverPager;
++struct RecoverPager {
++ sqlite3_file *pSqliteFile; /* Reference to database's file handle */
++ u32 nPageSize; /* Size of pages in pSqliteFile */
++};
++
++static void pagerDestroy(RecoverPager *pPager){
++ pPager->pSqliteFile->pMethods->xUnlock(pPager->pSqliteFile, SQLITE_LOCK_NONE);
++ memset(pPager, 0xA5, sizeof(*pPager));
++ sqlite3_free(pPager);
++}
++
++/* pSqliteFile should already have a SHARED lock. */
++static int pagerCreate(sqlite3_file *pSqliteFile, u32 nPageSize,
++ RecoverPager **ppPager){
++ RecoverPager *pPager = sqlite3_malloc(sizeof(RecoverPager));
++ if( !pPager ){
++ return SQLITE_NOMEM;
++ }
++
++ memset(pPager, 0, sizeof(*pPager));
++ pPager->pSqliteFile = pSqliteFile;
++ pPager->nPageSize = nPageSize;
++ *ppPager = pPager;
++ return SQLITE_OK;
++}
++
++/* Matches DbPage (aka PgHdr) from SQLite internals. */
++/* TODO(shess): SQLite by default allocates page metadata in a single allocation
++** such that the page's data and metadata are contiguous, see pcache1AllocPage
++** in pcache1.c. I believe this was intended to reduce malloc churn. It means
++** that Chromium's automated tooling would be unlikely to see page-buffer
++** overruns. I believe that this code is safe, but for now replicate SQLite's
++** approach with kExcessSpace.
++*/
++const int kExcessSpace = 128;
++typedef struct RecoverPage RecoverPage;
++struct RecoverPage {
++ u32 pgno; /* Page number for this page */
++ void *pData; /* Page data for pgno */
++ RecoverPager *pPager; /* The pager this page is part of */
++};
++
++static void pageDestroy(RecoverPage *pPage){
++ sqlite3_free(pPage->pData);
++ memset(pPage, 0xA5, sizeof(*pPage));
++ sqlite3_free(pPage);
++}
++
++static int pageCreate(RecoverPager *pPager, u32 pgno, RecoverPage **ppPage){
++ RecoverPage *pPage = sqlite3_malloc(sizeof(RecoverPage));
++ if( !pPage ){
++ return SQLITE_NOMEM;
++ }
++
++ memset(pPage, 0, sizeof(*pPage));
++ pPage->pPager = pPager;
++ pPage->pgno = pgno;
++ pPage->pData = sqlite3_malloc(pPager->nPageSize + kExcessSpace);
++ if( pPage->pData==NULL ){
++ pageDestroy(pPage);
++ return SQLITE_NOMEM;
++ }
++ memset((u8 *)pPage->pData + pPager->nPageSize, 0, kExcessSpace);
++
++ *ppPage = pPage;
++ return SQLITE_OK;
++}
++
++static int pagerGetPage(RecoverPager *pPager, u32 iPage, RecoverPage **ppPage) {
++ sqlite3_int64 iOfst;
++ sqlite3_file *pFile = pPager->pSqliteFile;
++ RecoverPage *pPage;
++ int rc = pageCreate(pPager, iPage, &pPage);
++ if( rc!=SQLITE_OK ){
++ return rc;
++ }
++
++ /* xRead() can return SQLITE_IOERR_SHORT_READ, which should be treated as
++ ** SQLITE_OK plus an EOF indicator. The excess space is zero-filled.
++ */
++ iOfst = ((sqlite3_int64)iPage - 1) * pPager->nPageSize;
++ rc = pFile->pMethods->xRead(pFile, pPage->pData, pPager->nPageSize, iOfst);
++ if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){
++ pageDestroy(pPage);
++ return rc;
++ }
++
++ *ppPage = pPage;
++ return SQLITE_OK;
++}
++
++/* For some reason I kept making mistakes with offset calculations. */
++static const unsigned char *PageData(RecoverPage *pPage, unsigned iOffset){
++ assert( iOffset<=pPage->pPager->nPageSize );
++ return (unsigned char *)pPage->pData + iOffset;
++}
++
++/* The first page in the file contains a file header in the first 100
++ * bytes. The page's header information comes after that. Note that
++ * the offsets in the page's header information are relative to the
++ * beginning of the page, NOT the end of the page header.
++ */
++static const unsigned char *PageHeader(RecoverPage *pPage){
++ if( pPage->pgno==1 ){
++ return PageData(pPage, knHeaderSize);
++ }else{
++ return PageData(pPage, 0);
++ }
++}
++
++/* Helper to fetch the pager and page size for the named database. */
++static int GetPager(sqlite3 *db, const char *zName,
++ RecoverPager **ppPager, unsigned *pnPageSize,
++ int *piEncoding){
++ int rc, iEncoding;
++ unsigned nPageSize, nReservedSize;
++ unsigned char header[knHeaderSize];
++ sqlite3_file *pFile = NULL;
++ RecoverPager *pPager;
++
++ rc = sqlite3_file_control(db, zName, SQLITE_FCNTL_FILE_POINTER, &pFile);
++ if( rc!=SQLITE_OK ) {
++ return rc;
++ } else if( pFile==NULL ){
++ /* The documentation for sqlite3PagerFile() indicates it can return NULL if
++ ** the file has not yet been opened. That should not be possible here...
++ */
++ return SQLITE_MISUSE;
++ }
++
++ /* Get a shared lock to make sure the on-disk version of the file is truth. */
++ rc = pFile->pMethods->xLock(pFile, SQLITE_LOCK_SHARED);
++ if( rc != SQLITE_OK ){
++ return rc;
++ }
++
++ /* Read the Initial header information. In case of SQLITE_IOERR_SHORT_READ,
++ ** the header is incomplete, which means no data could be recovered anyhow.
++ */
++ rc = pFile->pMethods->xRead(pFile, header, sizeof(header), 0);
++ if( rc != SQLITE_OK ){
++ pFile->pMethods->xUnlock(pFile, SQLITE_LOCK_NONE);
++ if( rc==SQLITE_IOERR_SHORT_READ ){
++ return SQLITE_CORRUPT;
++ }
++ return rc;
++ }
++
++ /* Page size must be a power of two between 512 and 32768 inclusive. */
++ nPageSize = decodeUnsigned16(header + kiHeaderPageSizeOffset);
++ if( (nPageSize&(nPageSize-1)) || nPageSize>32768 || nPageSize<512 ){
++ pFile->pMethods->xUnlock(pFile, SQLITE_LOCK_NONE);
++ return rc;
++ }
++
++ /* Space reserved a the end of the page for extensions. Usually 0. */
++ nReservedSize = header[kiHeaderReservedSizeOffset];
++
++ /* 1 for UTF-8, 2 for UTF-16le, 3 for UTF-16be. */
++ iEncoding = decodeUnsigned32(header + kiHeaderEncodingOffset);
++ if( iEncoding==3 ){
++ *piEncoding = SQLITE_UTF16BE;
++ } else if( iEncoding==2 ){
++ *piEncoding = SQLITE_UTF16LE;
++ } else if( iEncoding==1 ){
++ *piEncoding = SQLITE_UTF8;
++ } else {
++ /* This case should not be possible. */
++ *piEncoding = SQLITE_UTF8;
++ }
++
++ rc = pagerCreate(pFile, nPageSize, &pPager);
++ if( rc!=SQLITE_OK ){
++ pFile->pMethods->xUnlock(pFile, SQLITE_LOCK_NONE);
++ return rc;
++ }
++
++ *ppPager = pPager;
++ *pnPageSize = nPageSize - nReservedSize;
++ *piEncoding = iEncoding;
++ return SQLITE_OK;
++}
++
++/* iSerialType is a type read from a record header. See "2.1 Record Format".
++ */
++
++/* Storage size of iSerialType in bytes. My interpretation of SQLite
++ * documentation is that text and blob fields can have 32-bit length.
++ * Values past 2^31-12 will need more than 32 bits to encode, which is
++ * why iSerialType is u64.
++ */
++static u32 SerialTypeLength(u64 iSerialType){
++ switch( iSerialType ){
++ case 0 : return 0; /* NULL */
++ case 1 : return 1; /* Various integers. */
++ case 2 : return 2;
++ case 3 : return 3;
++ case 4 : return 4;
++ case 5 : return 6;
++ case 6 : return 8;
++ case 7 : return 8; /* 64-bit float. */
++ case 8 : return 0; /* Constant 0. */
++ case 9 : return 0; /* Constant 1. */
++ case 10 : case 11 : assert( "RESERVED TYPE"==NULL ); return 0;
++ }
++ return (u32)((iSerialType>>1) - 6);
++}
++
++/* True if iSerialType refers to a blob. */
++static int SerialTypeIsBlob(u64 iSerialType){
++ assert( iSerialType>=12 );
++ return (iSerialType%2)==0;
++}
++
++/* Returns true if the serialized type represented by iSerialType is
++ * compatible with the given type mask.
++ */
++static int SerialTypeIsCompatible(u64 iSerialType, unsigned char mask){
++ switch( iSerialType ){
++ case 0 : return (mask&MASK_NULL)!=0;
++ case 1 : return (mask&MASK_INTEGER)!=0;
++ case 2 : return (mask&MASK_INTEGER)!=0;
++ case 3 : return (mask&MASK_INTEGER)!=0;
++ case 4 : return (mask&MASK_INTEGER)!=0;
++ case 5 : return (mask&MASK_INTEGER)!=0;
++ case 6 : return (mask&MASK_INTEGER)!=0;
++ case 7 : return (mask&MASK_FLOAT)!=0;
++ case 8 : return (mask&MASK_INTEGER)!=0;
++ case 9 : return (mask&MASK_INTEGER)!=0;
++ case 10 : assert( "RESERVED TYPE"==NULL ); return 0;
++ case 11 : assert( "RESERVED TYPE"==NULL ); return 0;
++ }
++ return (mask&(SerialTypeIsBlob(iSerialType) ? MASK_BLOB : MASK_TEXT));
++}
++
++/* Versions of strdup() with return values appropriate for
++ * sqlite3_free(). malloc.c has sqlite3DbStrDup()/NDup(), but those
++ * need sqlite3DbFree(), which seems intrusive.
++ */
++static char *sqlite3_strndup(const char *z, unsigned n){
++ char *zNew;
++
++ if( z==NULL ){
++ return NULL;
++ }
++
++ zNew = sqlite3_malloc(n+1);
++ if( zNew!=NULL ){
++ memcpy(zNew, z, n);
++ zNew[n] = '\0';
++ }
++ return zNew;
++}
++static char *sqlite3_strdup(const char *z){
++ if( z==NULL ){
++ return NULL;
++ }
++ return sqlite3_strndup(z, strlen(z));
++}
++
++/* Fetch the page number of zTable in zDb from sqlite_master in zDb,
++ * and put it in *piRootPage.
++ */
++static int getRootPage(sqlite3 *db, const char *zDb, const char *zTable,
++ u32 *piRootPage){
++ char *zSql; /* SQL selecting root page of named element. */
++ sqlite3_stmt *pStmt;
++ int rc;
++
++ if( strcmp(zTable, "sqlite_master")==0 ){
++ *piRootPage = 1;
++ return SQLITE_OK;
++ }
++
++ zSql = sqlite3_mprintf("SELECT rootpage FROM %s.sqlite_master "
++ "WHERE type = 'table' AND tbl_name = %Q",
++ zDb, zTable);
++ if( !zSql ){
++ return SQLITE_NOMEM;
++ }
++
++ rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
++ sqlite3_free(zSql);
++ if( rc!=SQLITE_OK ){
++ return rc;
++ }
++
++ /* Require a result. */
++ rc = sqlite3_step(pStmt);
++ if( rc==SQLITE_DONE ){
++ rc = SQLITE_CORRUPT;
++ }else if( rc==SQLITE_ROW ){
++ *piRootPage = sqlite3_column_int(pStmt, 0);
++
++ /* Require only one result. */
++ rc = sqlite3_step(pStmt);
++ if( rc==SQLITE_DONE ){
++ rc = SQLITE_OK;
++ }else if( rc==SQLITE_ROW ){
++ rc = SQLITE_CORRUPT;
++ }
++ }
++ sqlite3_finalize(pStmt);
++ return rc;
++}
++
++/* Cursor for iterating interior nodes. Interior page cells contain a
++ * child page number and a rowid. The child page contains items left
++ * of the rowid (less than). The rightmost page of the subtree is
++ * stored in the page header.
++ *
++ * interiorCursorDestroy - release all resources associated with the
++ * cursor and any parent cursors.
++ * interiorCursorCreate - create a cursor with the given parent and page.
++ * interiorCursorNextPage - fetch the next child page from the cursor.
++ *
++ * Logically, interiorCursorNextPage() returns the next child page
++ * number from the page the cursor is currently reading, calling the
++ * parent cursor as necessary to get new pages to read, until done.
++ * SQLITE_ROW if a page is returned, SQLITE_DONE if out of pages,
++ * error otherwise. Unfortunately, if the table is corrupted
++ * unexpected pages can be returned. If any unexpected page is found,
++ * leaf or otherwise, it is returned to the caller for processing,
++ * with the interior cursor left empty. The next call to
++ * interiorCursorNextPage() will recurse to the parent cursor until an
++ * interior page to iterate is returned.
++ *
++ * Note that while interiorCursorNextPage() will refuse to follow
++ * loops, it does not keep track of pages returned for purposes of
++ * preventing duplication.
++ */
++typedef struct RecoverInteriorCursor RecoverInteriorCursor;
++struct RecoverInteriorCursor {
++ RecoverInteriorCursor *pParent; /* Parent node to this node. */
++ RecoverPage *pPage; /* Reference to leaf page. */
++ unsigned nPageSize; /* Size of page. */
++ unsigned nChildren; /* Number of children on the page. */
++ unsigned iChild; /* Index of next child to return. */
++};
++
++static void interiorCursorDestroy(RecoverInteriorCursor *pCursor){
++ /* Destroy all the cursors to the root. */
++ while( pCursor ){
++ RecoverInteriorCursor *p = pCursor;
++ pCursor = pCursor->pParent;
++
++ if( p->pPage ){
++ pageDestroy(p->pPage);
++ p->pPage = NULL;
++ }
++
++ memset(p, 0xA5, sizeof(*p));
++ sqlite3_free(p);
++ }
++}
++
++/* Internal helper. Reset storage in preparation for iterating pPage. */
++static void interiorCursorSetPage(RecoverInteriorCursor *pCursor,
++ RecoverPage *pPage){
++ const unsigned knMinCellLength = 2 + 4 + 1;
++ unsigned nMaxChildren;
++ assert( PageHeader(pPage)[kiPageTypeOffset]==kTableInteriorPage );
++
++ if( pCursor->pPage ){
++ pageDestroy(pCursor->pPage);
++ pCursor->pPage = NULL;
++ }
++ pCursor->pPage = pPage;
++ pCursor->iChild = 0;
++
++ /* A child for each cell, plus one in the header. */
++ pCursor->nChildren = decodeUnsigned16(PageHeader(pPage) +
++ kiPageCellCountOffset) + 1;
++
++ /* Each child requires a 16-bit offset from an array after the header,
++ * and each child contains a 32-bit page number and at least a varint
++ * (min size of one byte). The final child page is in the header. So
++ * the maximum value for nChildren is:
++ * (nPageSize - kiPageInteriorHeaderBytes) /
++ * (sizeof(uint16) + sizeof(uint32) + 1) + 1
++ */
++ /* TODO(shess): This count is very unlikely to be corrupted in
++ * isolation, so seeing this could signal to skip the page. OTOH, I
++ * can't offhand think of how to get here unless this or the page-type
++ * byte is corrupted. Could be an overflow page, but it would require
++ * a very large database.
++ */
++ nMaxChildren =
++ (pCursor->nPageSize - kiPageInteriorHeaderBytes) / knMinCellLength + 1;
++ if (pCursor->nChildren > nMaxChildren) {
++ pCursor->nChildren = nMaxChildren;
++ }
++}
++
++static int interiorCursorCreate(RecoverInteriorCursor *pParent,
++ RecoverPage *pPage, int nPageSize,
++ RecoverInteriorCursor **ppCursor){
++ RecoverInteriorCursor *pCursor =
++ sqlite3_malloc(sizeof(RecoverInteriorCursor));
++ if( !pCursor ){
++ return SQLITE_NOMEM;
++ }
++
++ memset(pCursor, 0, sizeof(*pCursor));
++ pCursor->pParent = pParent;
++ pCursor->nPageSize = nPageSize;
++ interiorCursorSetPage(pCursor, pPage);
++ *ppCursor = pCursor;
++ return SQLITE_OK;
++}
++
++/* Internal helper. Return the child page number at iChild. */
++static unsigned interiorCursorChildPage(RecoverInteriorCursor *pCursor){
++ const unsigned char *pPageHeader; /* Header of the current page. */
++ const unsigned char *pCellOffsets; /* Offset to page's cell offsets. */
++ unsigned iCellOffset; /* Offset of target cell. */
++
++ assert( pCursor->iChild<pCursor->nChildren );
++
++ /* Rightmost child is in the header. */
++ pPageHeader = PageHeader(pCursor->pPage);
++ if( pCursor->iChild==pCursor->nChildren-1 ){
++ return decodeUnsigned32(pPageHeader + kiPageRightChildOffset);
++ }
++
++ /* Each cell is a 4-byte integer page number and a varint rowid
++ * which is greater than the rowid of items in that sub-tree (this
++ * module ignores ordering). The offset is from the beginning of the
++ * page, not from the page header.
++ */
++ pCellOffsets = pPageHeader + kiPageInteriorHeaderBytes;
++ iCellOffset = decodeUnsigned16(pCellOffsets + pCursor->iChild*2);
++ if( iCellOffset<=pCursor->nPageSize-4 ){
++ return decodeUnsigned32(PageData(pCursor->pPage, iCellOffset));
++ }
++
++ /* TODO(shess): Check for cell overlaps? Cells require 4 bytes plus
++ * a varint. Check could be identical to leaf check (or even a
++ * shared helper testing for "Cells starting in this range"?).
++ */
++
++ /* If the offset is broken, return an invalid page number. */
++ return 0;
++}
++
++/* Internal helper. Used to detect if iPage would cause a loop. */
++static int interiorCursorPageInUse(RecoverInteriorCursor *pCursor,
++ unsigned iPage){
++ /* Find any parent using the indicated page. */
++ while( pCursor && pCursor->pPage->pgno!=iPage ){
++ pCursor = pCursor->pParent;
++ }
++ return pCursor!=NULL;
++}
++
++/* Get the next page from the interior cursor at *ppCursor. Returns
++ * SQLITE_ROW with the page in *ppPage, or SQLITE_DONE if out of
++ * pages, or the error SQLite returned.
++ *
++ * If the tree is uneven, then when the cursor attempts to get a new
++ * interior page from the parent cursor, it may get a non-interior
++ * page. In that case, the new page is returned, and *ppCursor is
++ * updated to point to the parent cursor (this cursor is freed).
++ */
++/* TODO(shess): I've tried to avoid recursion in most of this code,
++ * but this case is more challenging because the recursive call is in
++ * the middle of operation. One option for converting it without
++ * adding memory management would be to retain the head pointer and
++ * use a helper to "back up" as needed. Another option would be to
++ * reverse the list during traversal.
++ */
++static int interiorCursorNextPage(RecoverInteriorCursor **ppCursor,
++ RecoverPage **ppPage){
++ RecoverInteriorCursor *pCursor = *ppCursor;
++ while( 1 ){
++ int rc;
++ const unsigned char *pPageHeader; /* Header of found page. */
++
++ /* Find a valid child page which isn't on the stack. */
++ while( pCursor->iChild<pCursor->nChildren ){
++ const unsigned iPage = interiorCursorChildPage(pCursor);
++ pCursor->iChild++;
++ if( interiorCursorPageInUse(pCursor, iPage) ){
++ fprintf(stderr, "Loop detected at %d\n", iPage);
++ }else{
++ int rc = pagerGetPage(pCursor->pPage->pPager, iPage, ppPage);
++ if( rc==SQLITE_OK ){
++ return SQLITE_ROW;
++ }
++ }
++ }
++
++ /* This page has no more children. Get next page from parent. */
++ if( !pCursor->pParent ){
++ return SQLITE_DONE;
++ }
++ rc = interiorCursorNextPage(&pCursor->pParent, ppPage);
++ if( rc!=SQLITE_ROW ){
++ return rc;
++ }
++
++ /* If a non-interior page is received, that either means that the
++ * tree is uneven, or that a child was re-used (say as an overflow
++ * page). Remove this cursor and let the caller handle the page.
++ */
++ pPageHeader = PageHeader(*ppPage);
++ if( pPageHeader[kiPageTypeOffset]!=kTableInteriorPage ){
++ *ppCursor = pCursor->pParent;
++ pCursor->pParent = NULL;
++ interiorCursorDestroy(pCursor);
++ return SQLITE_ROW;
++ }
++
++ /* Iterate the new page. */
++ interiorCursorSetPage(pCursor, *ppPage);
++ *ppPage = NULL;
++ }
++
++ assert(NULL); /* NOTREACHED() */
++ return SQLITE_CORRUPT;
++}
++
++/* Large rows are spilled to overflow pages. The row's main page
++ * stores the overflow page number after the local payload, with a
++ * linked list forward from there as necessary. overflowMaybeCreate()
++ * and overflowGetSegment() provide an abstraction for accessing such
++ * data while centralizing the code.
++ *
++ * overflowDestroy - releases all resources associated with the structure.
++ * overflowMaybeCreate - create the overflow structure if it is needed
++ * to represent the given record. See function comment.
++ * overflowGetSegment - fetch a segment from the record, accounting
++ * for overflow pages. Segments which are not
++ * entirely contained with a page are constructed
++ * into a buffer which is returned. See function comment.
++ */
++typedef struct RecoverOverflow RecoverOverflow;
++struct RecoverOverflow {
++ RecoverOverflow *pNextOverflow;
++ RecoverPage *pPage;
++ unsigned nPageSize;
++};
++
++static void overflowDestroy(RecoverOverflow *pOverflow){
++ while( pOverflow ){
++ RecoverOverflow *p = pOverflow;
++ pOverflow = p->pNextOverflow;
++
++ if( p->pPage ){
++ pageDestroy(p->pPage);
++ p->pPage = NULL;
++ }
++
++ memset(p, 0xA5, sizeof(*p));
++ sqlite3_free(p);
++ }
++}
++
++/* Internal helper. Used to detect if iPage would cause a loop. */
++static int overflowPageInUse(RecoverOverflow *pOverflow, unsigned iPage){
++ while( pOverflow && pOverflow->pPage->pgno!=iPage ){
++ pOverflow = pOverflow->pNextOverflow;
++ }
++ return pOverflow!=NULL;
++}
++
++/* Setup to access an nRecordBytes record beginning at iRecordOffset
++ * in pPage. If nRecordBytes can be satisfied entirely from pPage,
++ * then no overflow pages are needed an *pnLocalRecordBytes is set to
++ * nRecordBytes. Otherwise, *ppOverflow is set to the head of a list
++ * of overflow pages, and *pnLocalRecordBytes is set to the number of
++ * bytes local to pPage.
++ *
++ * overflowGetSegment() will do the right thing regardless of whether
++ * those values are set to be in-page or not.
++ */
++static int overflowMaybeCreate(RecoverPage *pPage, unsigned nPageSize,
++ unsigned iRecordOffset, unsigned nRecordBytes,
++ unsigned *pnLocalRecordBytes,
++ RecoverOverflow **ppOverflow){
++ unsigned nLocalRecordBytes; /* Record bytes in the leaf page. */
++ unsigned iNextPage; /* Next page number for record data. */
++ unsigned nBytes; /* Maximum record bytes as of current page. */
++ int rc;
++ RecoverOverflow *pFirstOverflow; /* First in linked list of pages. */
++ RecoverOverflow *pLastOverflow; /* End of linked list. */
++
++ /* Calculations from the "Table B-Tree Leaf Cell" part of section
++ * 1.5 of http://www.sqlite.org/fileformat2.html . maxLocal and
++ * minLocal to match naming in btree.c.
++ */
++ const unsigned maxLocal = nPageSize - 35;
++ const unsigned minLocal = ((nPageSize-12)*32/255)-23; /* m */
++
++ /* Always fit anything smaller than maxLocal. */
++ if( nRecordBytes<=maxLocal ){
++ *pnLocalRecordBytes = nRecordBytes;
++ *ppOverflow = NULL;
++ return SQLITE_OK;
++ }
++
++ /* Calculate the remainder after accounting for minLocal on the leaf
++ * page and what packs evenly into overflow pages. If the remainder
++ * does not fit into maxLocal, then a partially-full overflow page
++ * will be required in any case, so store as little as possible locally.
++ */
++ nLocalRecordBytes = minLocal+((nRecordBytes-minLocal)%(nPageSize-4));
++ if( maxLocal<nLocalRecordBytes ){
++ nLocalRecordBytes = minLocal;
++ }
++
++ /* Don't read off the end of the page. */
++ if( iRecordOffset+nLocalRecordBytes+4>nPageSize ){
++ return SQLITE_CORRUPT;
++ }
++
++ /* First overflow page number is after the local bytes. */
++ iNextPage =
++ decodeUnsigned32(PageData(pPage, iRecordOffset + nLocalRecordBytes));
++ nBytes = nLocalRecordBytes;
++
++ /* While there are more pages to read, and more bytes are needed,
++ * get another page.
++ */
++ pFirstOverflow = pLastOverflow = NULL;
++ rc = SQLITE_OK;
++ while( iNextPage && nBytes<nRecordBytes ){
++ RecoverOverflow *pOverflow; /* New overflow page for the list. */
++
++ rc = pagerGetPage(pPage->pPager, iNextPage, &pPage);
++ if( rc!=SQLITE_OK ){
++ break;
++ }
++
++ pOverflow = sqlite3_malloc(sizeof(RecoverOverflow));
++ if( !pOverflow ){
++ pageDestroy(pPage);
++ rc = SQLITE_NOMEM;
++ break;
++ }
++ memset(pOverflow, 0, sizeof(*pOverflow));
++ pOverflow->pPage = pPage;
++ pOverflow->nPageSize = nPageSize;
++
++ if( !pFirstOverflow ){
++ pFirstOverflow = pOverflow;
++ }else{
++ pLastOverflow->pNextOverflow = pOverflow;
++ }
++ pLastOverflow = pOverflow;
++
++ iNextPage = decodeUnsigned32(pPage->pData);
++ nBytes += nPageSize-4;
++
++ /* Avoid loops. */
++ if( overflowPageInUse(pFirstOverflow, iNextPage) ){
++ fprintf(stderr, "Overflow loop detected at %d\n", iNextPage);
++ rc = SQLITE_CORRUPT;
++ break;
++ }
++ }
++
++ /* If there were not enough pages, or too many, things are corrupt.
++ * Not having enough pages is an obvious problem, all the data
++ * cannot be read. Too many pages means that the contents of the
++ * row between the main page and the overflow page(s) is
++ * inconsistent (most likely one or more of the overflow pages does
++ * not really belong to this row).
++ */
++ if( rc==SQLITE_OK && (nBytes<nRecordBytes || iNextPage) ){
++ rc = SQLITE_CORRUPT;
++ }
++
++ if( rc==SQLITE_OK ){
++ *ppOverflow = pFirstOverflow;
++ *pnLocalRecordBytes = nLocalRecordBytes;
++ }else if( pFirstOverflow ){
++ overflowDestroy(pFirstOverflow);
++ }
++ return rc;
++}
++
++/* Use in concert with overflowMaybeCreate() to efficiently read parts
++ * of a potentially-overflowing record. pPage and iRecordOffset are
++ * the values passed into overflowMaybeCreate(), nLocalRecordBytes and
++ * pOverflow are the values returned by that call.
++ *
++ * On SQLITE_OK, *ppBase points to nRequestBytes of data at
++ * iRequestOffset within the record. If the data exists contiguously
++ * in a page, a direct pointer is returned, otherwise a buffer from
++ * sqlite3_malloc() is returned with the data. *pbFree is set true if
++ * sqlite3_free() should be called on *ppBase.
++ */
++/* Operation of this function is subtle. At any time, pPage is the
++ * current page, with iRecordOffset and nLocalRecordBytes being record
++ * data within pPage, and pOverflow being the overflow page after
++ * pPage. This allows the code to handle both the initial leaf page
++ * and overflow pages consistently by adjusting the values
++ * appropriately.
++ */
++static int overflowGetSegment(RecoverPage *pPage, unsigned iRecordOffset,
++ unsigned nLocalRecordBytes,
++ RecoverOverflow *pOverflow,
++ unsigned iRequestOffset, unsigned nRequestBytes,
++ unsigned char **ppBase, int *pbFree){
++ unsigned nBase; /* Amount of data currently collected. */
++ unsigned char *pBase; /* Buffer to collect record data into. */
++
++ /* Skip to the page containing the start of the data. */
++ while( iRequestOffset>=nLocalRecordBytes && pOverflow ){
++ /* Factor out current page's contribution. */
++ iRequestOffset -= nLocalRecordBytes;
++
++ /* Move forward to the next page in the list. */
++ pPage = pOverflow->pPage;
++ iRecordOffset = 4;
++ nLocalRecordBytes = pOverflow->nPageSize - iRecordOffset;
++ pOverflow = pOverflow->pNextOverflow;
++ }
++
++ /* If the requested data is entirely within this page, return a
++ * pointer into the page.
++ */
++ if( iRequestOffset+nRequestBytes<=nLocalRecordBytes ){
++ /* TODO(shess): "assignment discards qualifiers from pointer target type"
++ * Having ppBase be const makes sense, but sqlite3_free() takes non-const.
++ */
++ *ppBase = (unsigned char *)PageData(pPage, iRecordOffset + iRequestOffset);
++ *pbFree = 0;
++ return SQLITE_OK;
++ }
++
++ /* The data range would require additional pages. */
++ if( !pOverflow ){
++ /* Should never happen, the range is outside the nRecordBytes
++ * passed to overflowMaybeCreate().
++ */
++ assert(NULL); /* NOTREACHED */
++ return SQLITE_ERROR;
++ }
++
++ /* Get a buffer to construct into. */
++ nBase = 0;
++ pBase = sqlite3_malloc(nRequestBytes);
++ if( !pBase ){
++ return SQLITE_NOMEM;
++ }
++ while( nBase<nRequestBytes ){
++ /* Copy over data present on this page. */
++ unsigned nCopyBytes = nRequestBytes - nBase;
++ if( nLocalRecordBytes-iRequestOffset<nCopyBytes ){
++ nCopyBytes = nLocalRecordBytes - iRequestOffset;
++ }
++ memcpy(pBase + nBase, PageData(pPage, iRecordOffset + iRequestOffset),
++ nCopyBytes);
++ nBase += nCopyBytes;
++
++ if( pOverflow ){
++ /* Copy from start of record data in future pages. */
++ iRequestOffset = 0;
++
++ /* Move forward to the next page in the list. Should match
++ * first while() loop.
++ */
++ pPage = pOverflow->pPage;
++ iRecordOffset = 4;
++ nLocalRecordBytes = pOverflow->nPageSize - iRecordOffset;
++ pOverflow = pOverflow->pNextOverflow;
++ }else if( nBase<nRequestBytes ){
++ /* Ran out of overflow pages with data left to deliver. Not
++ * possible if the requested range fits within nRecordBytes
++ * passed to overflowMaybeCreate() when creating pOverflow.
++ */
++ assert(NULL); /* NOTREACHED */
++ sqlite3_free(pBase);
++ return SQLITE_ERROR;
++ }
++ }
++ assert( nBase==nRequestBytes );
++ *ppBase = pBase;
++ *pbFree = 1;
++ return SQLITE_OK;
++}
++
++/* Primary structure for iterating the contents of a table.
++ *
++ * leafCursorDestroy - release all resources associated with the cursor.
++ * leafCursorCreate - create a cursor to iterate items from tree at
++ * the provided root page.
++ * leafCursorNextValidCell - get the cursor ready to access data from
++ * the next valid cell in the table.
++ * leafCursorCellRowid - get the current cell's rowid.
++ * leafCursorCellColumns - get current cell's column count.
++ * leafCursorCellColInfo - get type and data for a column in current cell.
++ *
++ * leafCursorNextValidCell skips cells which fail simple integrity
++ * checks, such as overlapping other cells, or being located at
++ * impossible offsets, or where header data doesn't correctly describe
++ * payload data. Returns SQLITE_ROW if a valid cell is found,
++ * SQLITE_DONE if all pages in the tree were exhausted.
++ *
++ * leafCursorCellColInfo() accounts for overflow pages in the style of
++ * overflowGetSegment().
++ */
++typedef struct RecoverLeafCursor RecoverLeafCursor;
++struct RecoverLeafCursor {
++ RecoverInteriorCursor *pParent; /* Parent node to this node. */
++ RecoverPager *pPager; /* Page provider. */
++ RecoverPage *pPage; /* Current leaf page. */
++ unsigned nPageSize; /* Size of pPage. */
++ unsigned nCells; /* Number of cells in pPage. */
++ unsigned iCell; /* Current cell. */
++
++ /* Info parsed from data in iCell. */
++ i64 iRowid; /* rowid parsed. */
++ unsigned nRecordCols; /* how many items in the record. */
++ u64 iRecordOffset; /* offset to record data. */
++ /* TODO(shess): nRecordBytes and nRecordHeaderBytes are used in
++ * leafCursorCellColInfo() to prevent buffer overruns.
++ * leafCursorCellDecode() already verified that the cell is valid, so
++ * those checks should be redundant.
++ */
++ u64 nRecordBytes; /* Size of record data. */
++ unsigned nLocalRecordBytes; /* Amount of record data in-page. */
++ unsigned nRecordHeaderBytes; /* Size of record header data. */
++ unsigned char *pRecordHeader; /* Pointer to record header data. */
++ int bFreeRecordHeader; /* True if record header requires free. */
++ RecoverOverflow *pOverflow; /* Cell overflow info, if needed. */
++};
++
++/* Internal helper shared between next-page and create-cursor. If
++ * pPage is a leaf page, it will be stored in the cursor and state
++ * initialized for reading cells.
++ *
++ * If pPage is an interior page, a new parent cursor is created and
++ * injected on the stack. This is necessary to handle trees with
++ * uneven depth, but also is used during initial setup.
++ *
++ * If pPage is not a table page at all, it is discarded.
++ *
++ * If SQLITE_OK is returned, the caller no longer owns pPage,
++ * otherwise the caller is responsible for discarding it.
++ */
++static int leafCursorLoadPage(RecoverLeafCursor *pCursor, RecoverPage *pPage){
++ const unsigned char *pPageHeader; /* Header of *pPage */
++ unsigned nCells; /* Number of cells in the page */
++
++ /* Release the current page. */
++ if( pCursor->pPage ){
++ pageDestroy(pCursor->pPage);
++ pCursor->pPage = NULL;
++ pCursor->iCell = pCursor->nCells = 0;
++ }
++
++ /* If the page is an unexpected interior node, inject a new stack
++ * layer and try again from there.
++ */
++ pPageHeader = PageHeader(pPage);
++ if( pPageHeader[kiPageTypeOffset]==kTableInteriorPage ){
++ RecoverInteriorCursor *pParent;
++ int rc = interiorCursorCreate(pCursor->pParent, pPage, pCursor->nPageSize,
++ &pParent);
++ if( rc!=SQLITE_OK ){
++ return rc;
++ }
++ pCursor->pParent = pParent;
++ return SQLITE_OK;
++ }
++
++ /* Not a leaf page, skip it. */
++ if( pPageHeader[kiPageTypeOffset]!=kTableLeafPage ){
++ pageDestroy(pPage);
++ return SQLITE_OK;
++ }
++
++ /* Leaf contains no data, skip it. Empty tables, for instance. */
++ nCells = decodeUnsigned16(pPageHeader + kiPageCellCountOffset);;
++ if( nCells<1 ){
++ pageDestroy(pPage);
++ return SQLITE_OK;
++ }
++
++ /* Take ownership of the page and start decoding. */
++ pCursor->pPage = pPage;
++ pCursor->iCell = 0;
++ pCursor->nCells = nCells;
++ return SQLITE_OK;
++}
++
++/* Get the next leaf-level page in the tree. Returns SQLITE_ROW when
++ * a leaf page is found, SQLITE_DONE when no more leaves exist, or any
++ * error which occurred.
++ */
++static int leafCursorNextPage(RecoverLeafCursor *pCursor){
++ if( !pCursor->pParent ){
++ return SQLITE_DONE;
++ }
++
++ /* Repeatedly load the parent's next child page until a leaf is found. */
++ do {
++ RecoverPage *pNextPage;
++ int rc = interiorCursorNextPage(&pCursor->pParent, &pNextPage);
++ if( rc!=SQLITE_ROW ){
++ assert( rc==SQLITE_DONE );
++ return rc;
++ }
++
++ rc = leafCursorLoadPage(pCursor, pNextPage);
++ if( rc!=SQLITE_OK ){
++ pageDestroy(pNextPage);
++ return rc;
++ }
++ } while( !pCursor->pPage );
++
++ return SQLITE_ROW;
++}
++
++static void leafCursorDestroyCellData(RecoverLeafCursor *pCursor){
++ if( pCursor->bFreeRecordHeader ){
++ sqlite3_free(pCursor->pRecordHeader);
++ }
++ pCursor->bFreeRecordHeader = 0;
++ pCursor->pRecordHeader = NULL;
++
++ if( pCursor->pOverflow ){
++ overflowDestroy(pCursor->pOverflow);
++ pCursor->pOverflow = NULL;
++ }
++}
++
++static void leafCursorDestroy(RecoverLeafCursor *pCursor){
++ leafCursorDestroyCellData(pCursor);
++
++ if( pCursor->pParent ){
++ interiorCursorDestroy(pCursor->pParent);
++ pCursor->pParent = NULL;
++ }
++
++ if( pCursor->pPage ){
++ pageDestroy(pCursor->pPage);
++ pCursor->pPage = NULL;
++ }
++
++ if( pCursor->pPager ){
++ pagerDestroy(pCursor->pPager);
++ pCursor->pPager = NULL;
++ }
++
++ memset(pCursor, 0xA5, sizeof(*pCursor));
++ sqlite3_free(pCursor);
++}
++
++/* Create a cursor to iterate the rows from the leaf pages of a table
++ * rooted at iRootPage.
++ */
++/* TODO(shess): recoverOpen() calls this to setup the cursor, and I
++ * think that recoverFilter() may make a hard assumption that the
++ * cursor returned will turn up at least one valid cell.
++ *
++ * The cases I can think of which break this assumption are:
++ * - pPage is a valid leaf page with no valid cells.
++ * - pPage is a valid interior page with no valid leaves.
++ * - pPage is a valid interior page who's leaves contain no valid cells.
++ * - pPage is not a valid leaf or interior page.
++ */
++static int leafCursorCreate(RecoverPager *pPager, unsigned nPageSize,
++ u32 iRootPage, RecoverLeafCursor **ppCursor){
++ RecoverPage *pPage; /* Reference to page at iRootPage. */
++ RecoverLeafCursor *pCursor; /* Leaf cursor being constructed. */
++ int rc;
++
++ /* Start out with the root page. */
++ rc = pagerGetPage(pPager, iRootPage, &pPage);
++ if( rc!=SQLITE_OK ){
++ return rc;
++ }
++
++ pCursor = sqlite3_malloc(sizeof(RecoverLeafCursor));
++ if( !pCursor ){
++ pageDestroy(pPage);
++ return SQLITE_NOMEM;
++ }
++ memset(pCursor, 0, sizeof(*pCursor));
++
++ pCursor->nPageSize = nPageSize;
++ pCursor->pPager = pPager;
++
++ rc = leafCursorLoadPage(pCursor, pPage);
++ if( rc!=SQLITE_OK ){
++ pageDestroy(pPage);
++ leafCursorDestroy(pCursor);
++ return rc;
++ }
++
++ /* pPage wasn't a leaf page, find the next leaf page. */
++ if( !pCursor->pPage ){
++ rc = leafCursorNextPage(pCursor);
++ if( rc!=SQLITE_DONE && rc!=SQLITE_ROW ){
++ leafCursorDestroy(pCursor);
++ return rc;
++ }
++ }
++
++ *ppCursor = pCursor;
++ return SQLITE_OK;
++}
++
++/* Useful for setting breakpoints. */
++static int ValidateError(){
++ return SQLITE_ERROR;
++}
++
++/* Setup the cursor for reading the information from cell iCell. */
++static int leafCursorCellDecode(RecoverLeafCursor *pCursor){
++ const unsigned char *pPageHeader; /* Header of current page. */
++ const unsigned char *pPageEnd; /* Byte after end of current page. */
++ const unsigned char *pCellOffsets; /* Pointer to page's cell offsets. */
++ unsigned iCellOffset; /* Offset of current cell (iCell). */
++ const unsigned char *pCell; /* Pointer to data at iCellOffset. */
++ unsigned nCellMaxBytes; /* Maximum local size of iCell. */
++ unsigned iEndOffset; /* End of iCell's in-page data. */
++ u64 nRecordBytes; /* Expected size of cell, w/overflow. */
++ u64 iRowid; /* iCell's rowid (in table). */
++ unsigned nRead; /* Amount of cell read. */
++ unsigned nRecordHeaderRead; /* Header data read. */
++ u64 nRecordHeaderBytes; /* Header size expected. */
++ unsigned nRecordCols; /* Columns read from header. */
++ u64 nRecordColBytes; /* Bytes in payload for those columns. */
++ unsigned i;
++ int rc;
++
++ assert( pCursor->iCell<pCursor->nCells );
++
++ leafCursorDestroyCellData(pCursor);
++
++ /* Find the offset to the row. */
++ pPageHeader = PageHeader(pCursor->pPage);
++ pCellOffsets = pPageHeader + knPageLeafHeaderBytes;
++ pPageEnd = PageData(pCursor->pPage, pCursor->nPageSize);
++ if( pCellOffsets + pCursor->iCell*2 + 2 > pPageEnd ){
++ return ValidateError();
++ }
++ iCellOffset = decodeUnsigned16(pCellOffsets + pCursor->iCell*2);
++ if( iCellOffset>=pCursor->nPageSize ){
++ return ValidateError();
++ }
++
++ pCell = PageData(pCursor->pPage, iCellOffset);
++ nCellMaxBytes = pCursor->nPageSize - iCellOffset;
++
++ /* B-tree leaf cells lead with varint record size, varint rowid and
++ * varint header size.
++ */
++ /* TODO(shess): The smallest page size is 512 bytes, which has an m
++ * of 39. Three varints need at most 27 bytes to encode. I think.
++ */
++ if( !checkVarints(pCell, nCellMaxBytes, 3) ){
++ return ValidateError();
++ }
++
++ nRead = recoverGetVarint(pCell, &nRecordBytes);
++ assert( iCellOffset+nRead<=pCursor->nPageSize );
++ pCursor->nRecordBytes = nRecordBytes;
++
++ nRead += recoverGetVarint(pCell + nRead, &iRowid);
++ assert( iCellOffset+nRead<=pCursor->nPageSize );
++ pCursor->iRowid = (i64)iRowid;
++
++ pCursor->iRecordOffset = iCellOffset + nRead;
++
++ /* Start overflow setup here because nLocalRecordBytes is needed to
++ * check cell overlap.
++ */
++ rc = overflowMaybeCreate(pCursor->pPage, pCursor->nPageSize,
++ pCursor->iRecordOffset, pCursor->nRecordBytes,
++ &pCursor->nLocalRecordBytes,
++ &pCursor->pOverflow);
++ if( rc!=SQLITE_OK ){
++ return ValidateError();
++ }
++
++ /* Check that no other cell starts within this cell. */
++ iEndOffset = pCursor->iRecordOffset + pCursor->nLocalRecordBytes;
++ for( i=0; i<pCursor->nCells && pCellOffsets + i*2 + 2 <= pPageEnd; ++i ){
++ const unsigned iOtherOffset = decodeUnsigned16(pCellOffsets + i*2);
++ if( iOtherOffset>iCellOffset && iOtherOffset<iEndOffset ){
++ return ValidateError();
++ }
++ }
++
++ nRecordHeaderRead = recoverGetVarint(pCell + nRead, &nRecordHeaderBytes);
++ assert( nRecordHeaderBytes<=nRecordBytes );
++ pCursor->nRecordHeaderBytes = nRecordHeaderBytes;
++
++ /* Large headers could overflow if pages are small. */
++ rc = overflowGetSegment(pCursor->pPage,
++ pCursor->iRecordOffset, pCursor->nLocalRecordBytes,
++ pCursor->pOverflow, 0, nRecordHeaderBytes,
++ &pCursor->pRecordHeader, &pCursor->bFreeRecordHeader);
++ if( rc!=SQLITE_OK ){
++ return ValidateError();
++ }
++
++ /* Tally up the column count and size of data. */
++ nRecordCols = 0;
++ nRecordColBytes = 0;
++ while( nRecordHeaderRead<nRecordHeaderBytes ){
++ u64 iSerialType; /* Type descriptor for current column. */
++ if( !checkVarint(pCursor->pRecordHeader + nRecordHeaderRead,
++ nRecordHeaderBytes - nRecordHeaderRead) ){
++ return ValidateError();
++ }
++ nRecordHeaderRead += recoverGetVarint(
++ pCursor->pRecordHeader + nRecordHeaderRead, &iSerialType);
++ if( iSerialType==10 || iSerialType==11 ){
++ return ValidateError();
++ }
++ nRecordColBytes += SerialTypeLength(iSerialType);
++ nRecordCols++;
++ }
++ pCursor->nRecordCols = nRecordCols;
++
++ /* Parsing the header used as many bytes as expected. */
++ if( nRecordHeaderRead!=nRecordHeaderBytes ){
++ return ValidateError();
++ }
++
++ /* Calculated record is size of expected record. */
++ if( nRecordHeaderBytes+nRecordColBytes!=nRecordBytes ){
++ return ValidateError();
++ }
++
++ return SQLITE_OK;
++}
++
++static i64 leafCursorCellRowid(RecoverLeafCursor *pCursor){
++ return pCursor->iRowid;
++}
++
++static unsigned leafCursorCellColumns(RecoverLeafCursor *pCursor){
++ return pCursor->nRecordCols;
++}
++
++/* Get the column info for the cell. Pass NULL for ppBase to prevent
++ * retrieving the data segment. If *pbFree is true, *ppBase must be
++ * freed by the caller using sqlite3_free().
++ */
++static int leafCursorCellColInfo(RecoverLeafCursor *pCursor,
++ unsigned iCol, u64 *piColType,
++ unsigned char **ppBase, int *pbFree){
++ const unsigned char *pRecordHeader; /* Current cell's header. */
++ u64 nRecordHeaderBytes; /* Bytes in pRecordHeader. */
++ unsigned nRead; /* Bytes read from header. */
++ u64 iColEndOffset; /* Offset to end of column in cell. */
++ unsigned nColsSkipped; /* Count columns as procesed. */
++ u64 iSerialType; /* Type descriptor for current column. */
++
++ /* Implicit NULL for columns past the end. This case happens when
++ * rows have not been updated since an ALTER TABLE added columns.
++ * It is more convenient to address here than in callers.
++ */
++ if( iCol>=pCursor->nRecordCols ){
++ *piColType = 0;
++ if( ppBase ){
++ *ppBase = 0;
++ *pbFree = 0;
++ }
++ return SQLITE_OK;
++ }
++
++ /* Must be able to decode header size. */
++ pRecordHeader = pCursor->pRecordHeader;
++ if( !checkVarint(pRecordHeader, pCursor->nRecordHeaderBytes) ){
++ return SQLITE_CORRUPT;
++ }
++
++ /* Rather than caching the header size and how many bytes it took,
++ * decode it every time.
++ */
++ nRead = recoverGetVarint(pRecordHeader, &nRecordHeaderBytes);
++ assert( nRecordHeaderBytes==pCursor->nRecordHeaderBytes );
++
++ /* Scan forward to the indicated column. Scans to _after_ column
++ * for later range checking.
++ */
++ /* TODO(shess): This could get expensive for very wide tables. An
++ * array of iSerialType could be built in leafCursorCellDecode(), but
++ * the number of columns is dynamic per row, so it would add memory
++ * management complexity. Enough info to efficiently forward
++ * iterate could be kept, if all clients forward iterate
++ * (recoverColumn() may not).
++ */
++ iColEndOffset = 0;
++ nColsSkipped = 0;
++ while( nColsSkipped<=iCol && nRead<nRecordHeaderBytes ){
++ if( !checkVarint(pRecordHeader + nRead, nRecordHeaderBytes - nRead) ){
++ return SQLITE_CORRUPT;
++ }
++ nRead += recoverGetVarint(pRecordHeader + nRead, &iSerialType);
++ iColEndOffset += SerialTypeLength(iSerialType);
++ nColsSkipped++;
++ }
++
++ /* Column's data extends past record's end. */
++ if( nRecordHeaderBytes+iColEndOffset>pCursor->nRecordBytes ){
++ return SQLITE_CORRUPT;
++ }
++
++ *piColType = iSerialType;
++ if( ppBase ){
++ const u32 nColBytes = SerialTypeLength(iSerialType);
++
++ /* Offset from start of record to beginning of column. */
++ const unsigned iColOffset = nRecordHeaderBytes+iColEndOffset-nColBytes;
++
++ return overflowGetSegment(pCursor->pPage, pCursor->iRecordOffset,
++ pCursor->nLocalRecordBytes, pCursor->pOverflow,
++ iColOffset, nColBytes, ppBase, pbFree);
++ }
++ return SQLITE_OK;
++}
++
++static int leafCursorNextValidCell(RecoverLeafCursor *pCursor){
++ while( 1 ){
++ int rc;
++
++ /* Move to the next cell. */
++ pCursor->iCell++;
++
++ /* No more cells, get the next leaf. */
++ if( pCursor->iCell>=pCursor->nCells ){
++ rc = leafCursorNextPage(pCursor);
++ if( rc!=SQLITE_ROW ){
++ return rc;
++ }
++ assert( pCursor->iCell==0 );
++ }
++
++ /* If the cell is valid, indicate that a row is available. */
++ rc = leafCursorCellDecode(pCursor);
++ if( rc==SQLITE_OK ){
++ return SQLITE_ROW;
++ }
++
++ /* Iterate until done or a valid row is found. */
++ /* TODO(shess): Remove debugging output. */
++ fprintf(stderr, "Skipping invalid cell\n");
++ }
++ return SQLITE_ERROR;
++}
++
++typedef struct Recover Recover;
++struct Recover {
++ sqlite3_vtab base;
++ sqlite3 *db; /* Host database connection */
++ char *zDb; /* Database containing target table */
++ char *zTable; /* Target table */
++ unsigned nCols; /* Number of columns in target table */
++ unsigned char *pTypes; /* Types of columns in target table */
++};
++
++/* Internal helper for deleting the module. */
++static void recoverRelease(Recover *pRecover){
++ sqlite3_free(pRecover->zDb);
++ sqlite3_free(pRecover->zTable);
++ sqlite3_free(pRecover->pTypes);
++ memset(pRecover, 0xA5, sizeof(*pRecover));
++ sqlite3_free(pRecover);
++}
++
++/* Helper function for initializing the module. Forward-declared so
++ * recoverCreate() and recoverConnect() can see it.
++ */
++static int recoverInit(
++ sqlite3 *, void *, int, const char *const*, sqlite3_vtab **, char **
++);
++
++static int recoverCreate(
++ sqlite3 *db,
++ void *pAux,
++ int argc, const char *const*argv,
++ sqlite3_vtab **ppVtab,
++ char **pzErr
++){
++ FNENTRY();
++ return recoverInit(db, pAux, argc, argv, ppVtab, pzErr);
++}
++
++/* This should never be called. */
++static int recoverConnect(
++ sqlite3 *db,
++ void *pAux,
++ int argc, const char *const*argv,
++ sqlite3_vtab **ppVtab,
++ char **pzErr
++){
++ FNENTRY();
++ return recoverInit(db, pAux, argc, argv, ppVtab, pzErr);
++}
++
++/* No indices supported. */
++static int recoverBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
++ FNENTRY();
++ return SQLITE_OK;
++}
++
++/* Logically, this should never be called. */
++static int recoverDisconnect(sqlite3_vtab *pVtab){
++ FNENTRY();
++ recoverRelease((Recover*)pVtab);
++ return SQLITE_OK;
++}
++
++static int recoverDestroy(sqlite3_vtab *pVtab){
++ FNENTRY();
++ recoverRelease((Recover*)pVtab);
++ return SQLITE_OK;
++}
++
++typedef struct RecoverCursor RecoverCursor;
++struct RecoverCursor {
++ sqlite3_vtab_cursor base;
++ RecoverLeafCursor *pLeafCursor;
++ int iEncoding;
++ int bEOF;
++};
++
++static int recoverOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
++ Recover *pRecover = (Recover*)pVTab;
++ u32 iRootPage; /* Root page of the backing table. */
++ int iEncoding; /* UTF encoding for backing database. */
++ unsigned nPageSize; /* Size of pages in backing database. */
++ RecoverPager *pPager; /* Backing database pager. */
++ RecoverLeafCursor *pLeafCursor; /* Cursor to read table's leaf pages. */
++ RecoverCursor *pCursor; /* Cursor to read rows from leaves. */
++ int rc;
++
++ FNENTRY();
++
++ iRootPage = 0;
++ rc = getRootPage(pRecover->db, pRecover->zDb, pRecover->zTable,
++ &iRootPage);
++ if( rc!=SQLITE_OK ){
++ return rc;
++ }
++
++ rc = GetPager(pRecover->db, pRecover->zDb, &pPager, &nPageSize, &iEncoding);
++ if( rc!=SQLITE_OK ){
++ return rc;
++ }
++
++ rc = leafCursorCreate(pPager, nPageSize, iRootPage, &pLeafCursor);
++ if( rc!=SQLITE_OK ){
++ pagerDestroy(pPager);
++ return rc;
++ }
++
++ pCursor = sqlite3_malloc(sizeof(RecoverCursor));
++ if( !pCursor ){
++ leafCursorDestroy(pLeafCursor);
++ return SQLITE_NOMEM;
++ }
++ memset(pCursor, 0, sizeof(*pCursor));
++ pCursor->base.pVtab = pVTab;
++ pCursor->pLeafCursor = pLeafCursor;
++ pCursor->iEncoding = iEncoding;
++
++ /* If no leaf pages were found, empty result set. */
++ /* TODO(shess): leafCursorNextValidCell() would return SQLITE_ROW or
++ * SQLITE_DONE to indicate whether there is further data to consider.
++ */
++ pCursor->bEOF = (pLeafCursor->pPage==NULL);
++
++ *ppCursor = (sqlite3_vtab_cursor*)pCursor;
++ return SQLITE_OK;
++}
++
++static int recoverClose(sqlite3_vtab_cursor *cur){
++ RecoverCursor *pCursor = (RecoverCursor*)cur;
++ FNENTRY();
++ if( pCursor->pLeafCursor ){
++ leafCursorDestroy(pCursor->pLeafCursor);
++ pCursor->pLeafCursor = NULL;
++ }
++ memset(pCursor, 0xA5, sizeof(*pCursor));
++ sqlite3_free(cur);
++ return SQLITE_OK;
++}
++
++/* Helpful place to set a breakpoint. */
++static int RecoverInvalidCell(){
++ return SQLITE_ERROR;
++}
++
++/* Returns SQLITE_OK if the cell has an appropriate number of columns
++ * with the appropriate types of data.
++ */
++static int recoverValidateLeafCell(Recover *pRecover, RecoverCursor *pCursor){
++ unsigned i;
++
++ /* If the row's storage has too many columns, skip it. */
++ if( leafCursorCellColumns(pCursor->pLeafCursor)>pRecover->nCols ){
++ return RecoverInvalidCell();
++ }
++
++ /* Skip rows with unexpected types. */
++ for( i=0; i<pRecover->nCols; ++i ){
++ u64 iType; /* Storage type of column i. */
++ int rc;
++
++ /* ROWID alias. */
++ if( (pRecover->pTypes[i]&MASK_ROWID) ){
++ continue;
++ }
++
++ rc = leafCursorCellColInfo(pCursor->pLeafCursor, i, &iType, NULL, NULL);
++ assert( rc==SQLITE_OK );
++ if( rc!=SQLITE_OK || !SerialTypeIsCompatible(iType, pRecover->pTypes[i]) ){
++ return RecoverInvalidCell();
++ }
++ }
++
++ return SQLITE_OK;
++}
++
++static int recoverNext(sqlite3_vtab_cursor *pVtabCursor){
++ RecoverCursor *pCursor = (RecoverCursor*)pVtabCursor;
++ Recover *pRecover = (Recover*)pCursor->base.pVtab;
++ int rc;
++
++ FNENTRY();
++
++ /* Scan forward to the next cell with valid storage, then check that
++ * the stored data matches the schema.
++ */
++ while( (rc = leafCursorNextValidCell(pCursor->pLeafCursor))==SQLITE_ROW ){
++ if( recoverValidateLeafCell(pRecover, pCursor)==SQLITE_OK ){
++ return SQLITE_OK;
++ }
++ }
++
++ if( rc==SQLITE_DONE ){
++ pCursor->bEOF = 1;
++ return SQLITE_OK;
++ }
++
++ assert( rc!=SQLITE_OK );
++ return rc;
++}
++
++static int recoverFilter(
++ sqlite3_vtab_cursor *pVtabCursor,
++ int idxNum, const char *idxStr,
++ int argc, sqlite3_value **argv
++){
++ RecoverCursor *pCursor = (RecoverCursor*)pVtabCursor;
++ Recover *pRecover = (Recover*)pCursor->base.pVtab;
++ int rc;
++
++ FNENTRY();
++
++ /* There were no valid leaf pages in the table. */
++ if( pCursor->bEOF ){
++ return SQLITE_OK;
++ }
++
++ /* Load the first cell, and iterate forward if it's not valid. If no cells at
++ * all are valid, recoverNext() sets bEOF and returns appropriately.
++ */
++ rc = leafCursorCellDecode(pCursor->pLeafCursor);
++ if( rc!=SQLITE_OK || recoverValidateLeafCell(pRecover, pCursor)!=SQLITE_OK ){
++ return recoverNext(pVtabCursor);
++ }
++
++ return SQLITE_OK;
++}
++
++static int recoverEof(sqlite3_vtab_cursor *pVtabCursor){
++ RecoverCursor *pCursor = (RecoverCursor*)pVtabCursor;
++ FNENTRY();
++ return pCursor->bEOF;
++}
++
++static int recoverColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
++ RecoverCursor *pCursor = (RecoverCursor*)cur;
++ Recover *pRecover = (Recover*)pCursor->base.pVtab;
++ u64 iColType; /* Storage type of column i. */
++ unsigned char *pColData; /* Column i's data. */
++ int shouldFree; /* Non-zero if pColData should be freed. */
++ int rc;
++
++ FNENTRY();
++
++ if( (unsigned)i>=pRecover->nCols ){
++ return SQLITE_ERROR;
++ }
++
++ /* ROWID alias. */
++ if( (pRecover->pTypes[i]&MASK_ROWID) ){
++ sqlite3_result_int64(ctx, leafCursorCellRowid(pCursor->pLeafCursor));
++ return SQLITE_OK;
++ }
++
++ pColData = NULL;
++ shouldFree = 0;
++ rc = leafCursorCellColInfo(pCursor->pLeafCursor, i, &iColType,
++ &pColData, &shouldFree);
++ if( rc!=SQLITE_OK ){
++ return rc;
++ }
++ /* recoverValidateLeafCell() should guarantee that this will never
++ * occur.
++ */
++ if( !SerialTypeIsCompatible(iColType, pRecover->pTypes[i]) ){
++ if( shouldFree ){
++ sqlite3_free(pColData);
++ }
++ return SQLITE_ERROR;
++ }
++
++ switch( iColType ){
++ case 0 : sqlite3_result_null(ctx); break;
++ case 1 : sqlite3_result_int64(ctx, decodeSigned(pColData, 1)); break;
++ case 2 : sqlite3_result_int64(ctx, decodeSigned(pColData, 2)); break;
++ case 3 : sqlite3_result_int64(ctx, decodeSigned(pColData, 3)); break;
++ case 4 : sqlite3_result_int64(ctx, decodeSigned(pColData, 4)); break;
++ case 5 : sqlite3_result_int64(ctx, decodeSigned(pColData, 6)); break;
++ case 6 : sqlite3_result_int64(ctx, decodeSigned(pColData, 8)); break;
++ case 7 : sqlite3_result_double(ctx, decodeFloat64(pColData)); break;
++ case 8 : sqlite3_result_int(ctx, 0); break;
++ case 9 : sqlite3_result_int(ctx, 1); break;
++ case 10 : assert( iColType!=10 ); break;
++ case 11 : assert( iColType!=11 ); break;
++
++ default : {
++ u32 l = SerialTypeLength(iColType);
++
++ /* If pColData was already allocated, arrange to pass ownership. */
++ sqlite3_destructor_type pFn = SQLITE_TRANSIENT;
++ if( shouldFree ){
++ pFn = sqlite3_free;
++ shouldFree = 0;
++ }
++
++ if( SerialTypeIsBlob(iColType) ){
++ sqlite3_result_blob(ctx, pColData, l, pFn);
++ }else{
++ if( pCursor->iEncoding==SQLITE_UTF16LE ){
++ sqlite3_result_text16le(ctx, (const void*)pColData, l, pFn);
++ }else if( pCursor->iEncoding==SQLITE_UTF16BE ){
++ sqlite3_result_text16be(ctx, (const void*)pColData, l, pFn);
++ }else{
++ sqlite3_result_text(ctx, (const char*)pColData, l, pFn);
++ }
++ }
++ } break;
++ }
++ if( shouldFree ){
++ sqlite3_free(pColData);
++ }
++ return SQLITE_OK;
++}
++
++static int recoverRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *pRowid){
++ RecoverCursor *pCursor = (RecoverCursor*)pVtabCursor;
++ FNENTRY();
++ *pRowid = leafCursorCellRowid(pCursor->pLeafCursor);
++ return SQLITE_OK;
++}
++
++static sqlite3_module recoverModule = {
++ 0, /* iVersion */
++ recoverCreate, /* xCreate - create a table */
++ recoverConnect, /* xConnect - connect to an existing table */
++ recoverBestIndex, /* xBestIndex - Determine search strategy */
++ recoverDisconnect, /* xDisconnect - Disconnect from a table */
++ recoverDestroy, /* xDestroy - Drop a table */
++ recoverOpen, /* xOpen - open a cursor */
++ recoverClose, /* xClose - close a cursor */
++ recoverFilter, /* xFilter - configure scan constraints */
++ recoverNext, /* xNext - advance a cursor */
++ recoverEof, /* xEof */
++ recoverColumn, /* xColumn - read data */
++ recoverRowid, /* xRowid - read data */
++ 0, /* xUpdate - write data */
++ 0, /* xBegin - begin transaction */
++ 0, /* xSync - sync transaction */
++ 0, /* xCommit - commit transaction */
++ 0, /* xRollback - rollback transaction */
++ 0, /* xFindFunction - function overloading */
++ 0, /* xRename - rename the table */
++};
++
++SQLITE_API
++int chrome_sqlite3_recoverVtableInit(sqlite3 *db){
++ return sqlite3_create_module_v2(db, "recover", &recoverModule, NULL, 0);
++}
++
++/* This section of code is for parsing the create input and
++ * initializing the module.
++ */
++
++/* Find the next word in zText and place the endpoints in pzWord*.
++ * Returns true if the word is non-empty. "Word" is defined as
++ * ASCII alphanumeric plus '_' at this time.
++ */
++static int findWord(const char *zText,
++ const char **pzWordStart, const char **pzWordEnd){
++ int r;
++ while( ascii_isspace(*zText) ){
++ zText++;
++ }
++ *pzWordStart = zText;
++ while( ascii_isalnum(*zText) || *zText=='_' ){
++ zText++;
++ }
++ r = zText>*pzWordStart; /* In case pzWordStart==pzWordEnd */
++ *pzWordEnd = zText;
++ return r;
++}
++
++/* Return true if the next word in zText is zWord, also setting
++ * *pzContinue to the character after the word.
++ */
++static int expectWord(const char *zText, const char *zWord,
++ const char **pzContinue){
++ const char *zWordStart, *zWordEnd;
++ if( findWord(zText, &zWordStart, &zWordEnd) &&
++ ascii_strncasecmp(zWord, zWordStart, zWordEnd - zWordStart)==0 ){
++ *pzContinue = zWordEnd;
++ return 1;
++ }
++ return 0;
++}
++
++/* Parse the name and type information out of parameter. In case of
++ * success, *pzNameStart/End contain the name of the column,
++ * *pzTypeStart/End contain the top-level type, and *pTypeMask has the
++ * type mask to use for the column.
++ */
++static int findNameAndType(const char *parameter,
++ const char **pzNameStart, const char **pzNameEnd,
++ const char **pzTypeStart, const char **pzTypeEnd,
++ unsigned char *pTypeMask){
++ unsigned nNameLen; /* Length of found name. */
++ const char *zEnd; /* Current end of parsed column information. */
++ int bNotNull; /* Non-zero if NULL is not allowed for name. */
++ int bStrict; /* Non-zero if column requires exact type match. */
++ const char *zDummy; /* Dummy parameter, result unused. */
++ unsigned i;
++
++ /* strictMask is used for STRICT, strictMask|otherMask if STRICT is
++ * not supplied. zReplace provides an alternate type to expose to
++ * the caller.
++ */
++ static struct {
++ const char *zName;
++ unsigned char strictMask;
++ unsigned char otherMask;
++ const char *zReplace;
++ } kTypeInfo[] = {
++ { "ANY",
++ MASK_INTEGER | MASK_FLOAT | MASK_BLOB | MASK_TEXT | MASK_NULL,
++ 0, "",
++ },
++ { "ROWID", MASK_INTEGER | MASK_ROWID, 0, "INTEGER", },
++ { "INTEGER", MASK_INTEGER | MASK_NULL, 0, NULL, },
++ { "FLOAT", MASK_FLOAT | MASK_NULL, MASK_INTEGER, NULL, },
++ { "NUMERIC", MASK_INTEGER | MASK_FLOAT | MASK_NULL, MASK_TEXT, NULL, },
++ { "TEXT", MASK_TEXT | MASK_NULL, MASK_BLOB, NULL, },
++ { "BLOB", MASK_BLOB | MASK_NULL, 0, NULL, },
++ };
++
++ if( !findWord(parameter, pzNameStart, pzNameEnd) ){
++ return SQLITE_MISUSE;
++ }
++
++ /* Manifest typing, accept any storage type. */
++ if( !findWord(*pzNameEnd, pzTypeStart, pzTypeEnd) ){
++ *pzTypeEnd = *pzTypeStart = "";
++ *pTypeMask = MASK_INTEGER | MASK_FLOAT | MASK_BLOB | MASK_TEXT | MASK_NULL;
++ return SQLITE_OK;
++ }
++
++ nNameLen = *pzTypeEnd - *pzTypeStart;
++ for( i=0; i<ArraySize(kTypeInfo); ++i ){
++ if( ascii_strncasecmp(kTypeInfo[i].zName, *pzTypeStart, nNameLen)==0 ){
++ break;
++ }
++ }
++ if( i==ArraySize(kTypeInfo) ){
++ return SQLITE_MISUSE;
++ }
++
++ zEnd = *pzTypeEnd;
++ bStrict = 0;
++ if( expectWord(zEnd, "STRICT", &zEnd) ){
++ /* TODO(shess): Ick. But I don't want another single-purpose
++ * flag, either.
++ */
++ if( kTypeInfo[i].zReplace && !kTypeInfo[i].zReplace[0] ){
++ return SQLITE_MISUSE;
++ }
++ bStrict = 1;
++ }
++
++ bNotNull = 0;
++ if( expectWord(zEnd, "NOT", &zEnd) ){
++ if( expectWord(zEnd, "NULL", &zEnd) ){
++ bNotNull = 1;
++ }else{
++ /* Anything other than NULL after NOT is an error. */
++ return SQLITE_MISUSE;
++ }
++ }
++
++ /* Anything else is an error. */
++ if( findWord(zEnd, &zDummy, &zDummy) ){
++ return SQLITE_MISUSE;
++ }
++
++ *pTypeMask = kTypeInfo[i].strictMask;
++ if( !bStrict ){
++ *pTypeMask |= kTypeInfo[i].otherMask;
++ }
++ if( bNotNull ){
++ *pTypeMask &= ~MASK_NULL;
++ }
++ if( kTypeInfo[i].zReplace ){
++ *pzTypeStart = kTypeInfo[i].zReplace;
++ *pzTypeEnd = *pzTypeStart + strlen(*pzTypeStart);
++ }
++ return SQLITE_OK;
++}
++
++/* Parse the arguments, placing type masks in *pTypes and the exposed
++ * schema in *pzCreateSql (for sqlite3_declare_vtab).
++ */
++static int ParseColumnsAndGenerateCreate(unsigned nCols,
++ const char *const *pCols,
++ char **pzCreateSql,
++ unsigned char *pTypes,
++ char **pzErr){
++ unsigned i;
++ char *zCreateSql = sqlite3_mprintf("CREATE TABLE x(");
++ if( !zCreateSql ){
++ return SQLITE_NOMEM;
++ }
++
++ for( i=0; i<nCols; i++ ){
++ const char *zSep = (i < nCols - 1 ? ", " : ")");
++ const char *zNotNull = "";
++ const char *zNameStart, *zNameEnd;
++ const char *zTypeStart, *zTypeEnd;
++ int rc = findNameAndType(pCols[i],
++ &zNameStart, &zNameEnd,
++ &zTypeStart, &zTypeEnd,
++ &pTypes[i]);
++ if( rc!=SQLITE_OK ){
++ *pzErr = sqlite3_mprintf("unable to parse column %d", i);
++ sqlite3_free(zCreateSql);
++ return rc;
++ }
++
++ if( !(pTypes[i]&MASK_NULL) ){
++ zNotNull = " NOT NULL";
++ }
++
++ /* Add name and type to the create statement. */
++ zCreateSql = sqlite3_mprintf("%z%.*s %.*s%s%s",
++ zCreateSql,
++ zNameEnd - zNameStart, zNameStart,
++ zTypeEnd - zTypeStart, zTypeStart,
++ zNotNull, zSep);
++ if( !zCreateSql ){
++ return SQLITE_NOMEM;
++ }
++ }
++
++ *pzCreateSql = zCreateSql;
++ return SQLITE_OK;
++}
++
++/* Helper function for initializing the module. */
++/* argv[0] module name
++ * argv[1] db name for virtual table
++ * argv[2] virtual table name
++ * argv[3] backing table name
++ * argv[4] columns
++ */
++/* TODO(shess): Since connect isn't supported, could inline into
++ * recoverCreate().
++ */
++/* TODO(shess): Explore cases where it would make sense to set *pzErr. */
++static int recoverInit(
++ sqlite3 *db, /* Database connection */
++ void *pAux, /* unused */
++ int argc, const char *const*argv, /* Parameters to CREATE TABLE statement */
++ sqlite3_vtab **ppVtab, /* OUT: New virtual table */
++ char **pzErr /* OUT: Error message, if any */
++){
++ const int kTypeCol = 4; /* First argument with column type info. */
++ Recover *pRecover; /* Virtual table structure being created. */
++ char *zDot; /* Any dot found in "db.table" backing. */
++ u32 iRootPage; /* Root page of backing table. */
++ char *zCreateSql; /* Schema of created virtual table. */
++ int rc;
++
++ /* Require to be in the temp database. */
++ if( ascii_strcasecmp(argv[1], "temp")!=0 ){
++ *pzErr = sqlite3_mprintf("recover table must be in temp database");
++ return SQLITE_MISUSE;
++ }
++
++ /* Need the backing table and at least one column. */
++ if( argc<=kTypeCol ){
++ *pzErr = sqlite3_mprintf("no columns specified");
++ return SQLITE_MISUSE;
++ }
++
++ pRecover = sqlite3_malloc(sizeof(Recover));
++ if( !pRecover ){
++ return SQLITE_NOMEM;
++ }
++ memset(pRecover, 0, sizeof(*pRecover));
++ pRecover->base.pModule = &recoverModule;
++ pRecover->db = db;
++
++ /* Parse out db.table, assuming main if no dot. */
++ zDot = strchr(argv[3], '.');
++ if( !zDot ){
++ pRecover->zDb = sqlite3_strdup("main");
++ pRecover->zTable = sqlite3_strdup(argv[3]);
++ }else if( zDot>argv[3] && zDot[1]!='\0' ){
++ pRecover->zDb = sqlite3_strndup(argv[3], zDot - argv[3]);
++ pRecover->zTable = sqlite3_strdup(zDot + 1);
++ }else{
++ /* ".table" or "db." not allowed. */
++ *pzErr = sqlite3_mprintf("ill-formed table specifier");
++ recoverRelease(pRecover);
++ return SQLITE_ERROR;
++ }
++
++ pRecover->nCols = argc - kTypeCol;
++ pRecover->pTypes = sqlite3_malloc(pRecover->nCols);
++ if( !pRecover->zDb || !pRecover->zTable || !pRecover->pTypes ){
++ recoverRelease(pRecover);
++ return SQLITE_NOMEM;
++ }
++
++ /* Require the backing table to exist. */
++ /* TODO(shess): Be more pedantic about the form of the descriptor
++ * string. This already fails for poorly-formed strings, simply
++ * because there won't be a root page, but it would make more sense
++ * to be explicit.
++ */
++ rc = getRootPage(pRecover->db, pRecover->zDb, pRecover->zTable, &iRootPage);
++ if( rc!=SQLITE_OK ){
++ *pzErr = sqlite3_mprintf("unable to find backing table");
++ recoverRelease(pRecover);
++ return rc;
++ }
++
++ /* Parse the column definitions. */
++ rc = ParseColumnsAndGenerateCreate(pRecover->nCols, argv + kTypeCol,
++ &zCreateSql, pRecover->pTypes, pzErr);
++ if( rc!=SQLITE_OK ){
++ recoverRelease(pRecover);
++ return rc;
++ }
++
++ rc = sqlite3_declare_vtab(db, zCreateSql);
++ sqlite3_free(zCreateSql);
++ if( rc!=SQLITE_OK ){
++ recoverRelease(pRecover);
++ return rc;
++ }
++
++ *ppVtab = (sqlite3_vtab *)pRecover;
++ return SQLITE_OK;
++}
+diff --git a/third_party/sqlite/src/src/recover.h b/third_party/sqlite/src/src/recover.h
+new file mode 100644
+index 000000000000..49b0d9e860db
+--- /dev/null
++++ b/third_party/sqlite/src/src/recover.h
+@@ -0,0 +1,23 @@
++/* TODO(shess): sqliteicu.h is able to make this include without
++** trouble. It doesn't work when used with Chromium's SQLite. For
++** now the including code must include sqlite3.h first.
++*/
++/* #include "sqlite3.h" */
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/*
++** Call to initialize the recover virtual-table modules (see recover.c).
++**
++** This could be loaded by default in main.c, but that would make the
++** virtual table available to Web SQL. Breaking it out allows only
++** selected users to enable it (currently sql/recovery.cc).
++*/
++SQLITE_API
++int chrome_sqlite3_recoverVtableInit(sqlite3 *db);
++
++#ifdef __cplusplus
++} /* End of the 'extern "C"' block */
++#endif
+diff --git a/third_party/sqlite/src/src/recover_varint.c b/third_party/sqlite/src/src/recover_varint.c
+new file mode 100644
+index 000000000000..c111e2cedc44
+--- /dev/null
++++ b/third_party/sqlite/src/src/recover_varint.c
+@@ -0,0 +1,201 @@
++/*
++** 2016 Feb 29
++**
++** The author disclaims copyright to this source code. In place of
++** a legal notice, here is a blessing:
++**
++** May you do good and not evil.
++** May you find forgiveness for yourself and forgive others.
++** May you share freely, never taking more than you give.
++**
++******************************************************************************
++**
++** Copy of sqlite3Fts5GetVarint() from fts3_varint.c, which in turn is copied
++** from SQLite core.
++*/
++
++#include <assert.h>
++#include "sqlite3.h"
++
++/* Copied from fts3int.h. */
++#ifndef SQLITE_AMALGAMATION
++typedef unsigned char u8;
++typedef unsigned int u32;
++typedef sqlite3_uint64 u64;
++#endif
++
++/*
++** Bitmasks used by recoverGetVarint(). These precomputed constants
++** are defined here rather than simply putting the constant expressions
++** inline in order to work around bugs in the RVT compiler.
++**
++** SLOT_2_0 A mask for (0x7f<<14) | 0x7f
++**
++** SLOT_4_2_0 A mask for (0x7f<<28) | SLOT_2_0
++*/
++#define SLOT_2_0 0x001fc07f
++#define SLOT_4_2_0 0xf01fc07f
++
++/*
++** Read a 64-bit variable-length integer from memory starting at p[0].
++** Return the number of bytes read. The value is stored in *v.
++*/
++u8 recoverGetVarint(const unsigned char *p, u64 *v){
++ u32 a,b,s;
++
++ a = *p;
++ /* a: p0 (unmasked) */
++ if (!(a&0x80))
++ {
++ *v = a;
++ return 1;
++ }
++
++ p++;
++ b = *p;
++ /* b: p1 (unmasked) */
++ if (!(b&0x80))
++ {
++ a &= 0x7f;
++ a = a<<7;
++ a |= b;
++ *v = a;
++ return 2;
++ }
++
++ /* Verify that constants are precomputed correctly */
++ assert( SLOT_2_0 == ((0x7f<<14) | (0x7f)) );
++ assert( SLOT_4_2_0 == ((0xfU<<28) | (0x7f<<14) | (0x7f)) );
++
++ p++;
++ a = a<<14;
++ a |= *p;
++ /* a: p0<<14 | p2 (unmasked) */
++ if (!(a&0x80))
++ {
++ a &= SLOT_2_0;
++ b &= 0x7f;
++ b = b<<7;
++ a |= b;
++ *v = a;
++ return 3;
++ }
++
++ /* CSE1 from below */
++ a &= SLOT_2_0;
++ p++;
++ b = b<<14;
++ b |= *p;
++ /* b: p1<<14 | p3 (unmasked) */
++ if (!(b&0x80))
++ {
++ b &= SLOT_2_0;
++ /* moved CSE1 up */
++ /* a &= (0x7f<<14)|(0x7f); */
++ a = a<<7;
++ a |= b;
++ *v = a;
++ return 4;
++ }
++
++ /* a: p0<<14 | p2 (masked) */
++ /* b: p1<<14 | p3 (unmasked) */
++ /* 1:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
++ /* moved CSE1 up */
++ /* a &= (0x7f<<14)|(0x7f); */
++ b &= SLOT_2_0;
++ s = a;
++ /* s: p0<<14 | p2 (masked) */
++
++ p++;
++ a = a<<14;
++ a |= *p;
++ /* a: p0<<28 | p2<<14 | p4 (unmasked) */
++ if (!(a&0x80))
++ {
++ /* we can skip these cause they were (effectively) done above in calc'ing s */
++ /* a &= (0x7f<<28)|(0x7f<<14)|(0x7f); */
++ /* b &= (0x7f<<14)|(0x7f); */
++ b = b<<7;
++ a |= b;
++ s = s>>18;
++ *v = ((u64)s)<<32 | a;
++ return 5;
++ }
++
++ /* 2:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
++ s = s<<7;
++ s |= b;
++ /* s: p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
++
++ p++;
++ b = b<<14;
++ b |= *p;
++ /* b: p1<<28 | p3<<14 | p5 (unmasked) */
++ if (!(b&0x80))
++ {
++ /* we can skip this cause it was (effectively) done above in calc'ing s */
++ /* b &= (0x7f<<28)|(0x7f<<14)|(0x7f); */
++ a &= SLOT_2_0;
++ a = a<<7;
++ a |= b;
++ s = s>>18;
++ *v = ((u64)s)<<32 | a;
++ return 6;
++ }
++
++ p++;
++ a = a<<14;
++ a |= *p;
++ /* a: p2<<28 | p4<<14 | p6 (unmasked) */
++ if (!(a&0x80))
++ {
++ a &= SLOT_4_2_0;
++ b &= SLOT_2_0;
++ b = b<<7;
++ a |= b;
++ s = s>>11;
++ *v = ((u64)s)<<32 | a;
++ return 7;
++ }
++
++ /* CSE2 from below */
++ a &= SLOT_2_0;
++ p++;
++ b = b<<14;
++ b |= *p;
++ /* b: p3<<28 | p5<<14 | p7 (unmasked) */
++ if (!(b&0x80))
++ {
++ b &= SLOT_4_2_0;
++ /* moved CSE2 up */
++ /* a &= (0x7f<<14)|(0x7f); */
++ a = a<<7;
++ a |= b;
++ s = s>>4;
++ *v = ((u64)s)<<32 | a;
++ return 8;
++ }
++
++ p++;
++ a = a<<15;
++ a |= *p;
++ /* a: p4<<29 | p6<<15 | p8 (unmasked) */
++
++ /* moved CSE2 up */
++ /* a &= (0x7f<<29)|(0x7f<<15)|(0xff); */
++ b &= SLOT_2_0;
++ b = b<<8;
++ a |= b;
++
++ s = s<<4;
++ b = p[-4];
++ b &= 0x7f;
++ b = b>>3;
++ s |= b;
++
++ *v = ((u64)s)<<32 | a;
++
++ return 9;
++}
++
+diff --git a/third_party/sqlite/src/test/recover.test b/third_party/sqlite/src/test/recover.test
+new file mode 100644
+index 000000000000..bfb788814866
+--- /dev/null
++++ b/third_party/sqlite/src/test/recover.test
+@@ -0,0 +1,164 @@
++# 2012 January 11 {}
++#
++# The author disclaims copyright to this source code. In place of
++# a legal notice, here is a blessing:
++#
++# May you do good and not evil.
++# May you find forgiveness for yourself and forgive others.
++# May you share freely, never taking more than you give.
++#
++#***********************************************************************
++# This file implements regression tests for SQLite library.
++#
++# This file implements tests for the recover module, which can read
++# through corrupt rows and pages.
++#
++# $Id$
++
++# TODO(shess): These all test that the module correctly reads good
++# data. It would be good to implement tests of corrupt data.
++
++set testdir [file dirname $argv0]
++source $testdir/tester.tcl
++
++db eval {
++ DROP TABLE IF EXISTS altered;
++ CREATE TABLE altered (
++ c TEXT
++ );
++ INSERT INTO altered VALUES ('a');
++ INSERT INTO altered VALUES ('b');
++ INSERT INTO altered VALUES ('c');
++ ALTER TABLE altered ADD COLUMN i INTEGER NOT NULL DEFAULT 10;
++ INSERT INTO altered VALUES ('d', 5);
++}
++
++# SQLite will fill the earlier rows with the default.
++do_test recover-alter-1.0 {
++ execsql {SELECT c, i FROM altered ORDER BY rowid}
++} {a 10 b 10 c 10 d 5}
++
++# recover sees NULL for those rows.
++do_test recover-alter-1.1 {
++ db eval {
++ DROP TABLE IF EXISTS temp.altered_recover;
++ CREATE VIRTUAL TABLE temp.altered_recover USING recover(
++ altered,
++ c TEXT,
++ i INTEGER
++ );
++ }
++ execsql {SELECT c, i FROM altered_recover ORDER BY rowid}
++} {a {} b {} c {} d 5}
++
++# Can skip those NULL columns like if they contained a real NULL.
++do_test recover-alter-1.2 {
++ db eval {
++ DROP TABLE IF EXISTS temp.altered_recover;
++ CREATE VIRTUAL TABLE temp.altered_recover USING recover(
++ altered,
++ c TEXT,
++ i INTEGER NOT NULL
++ );
++ }
++ execsql {SELECT c, i FROM altered_recover ORDER BY rowid}
++} {d 5}
++
++if {0} {
++# It would be neat if this could work. I tried putting "DEFAULT ..."
++# in the schema exposed by the recover table, but it doesn't do the
++# trick.
++do_test recover-alter-1.2 {
++ db eval {
++ DROP TABLE IF EXISTS temp.altered_recover;
++ CREATE VIRTUAL TABLE temp.altered_recover USING recover(
++ altered,
++ c TEXT,
++ i INTEGER NOT NULL DEFAULT 10
++ );
++ }
++ execsql {SELECT c, i FROM altered_recover ORDER BY rowid}
++} {a 10 b 10 c 10 d 5}
++}
++
++# Helper function to generate an arbitrarily-sized table.
++proc generate {table base count} {
++ db eval "DROP TABLE IF EXISTS $table"
++ db transaction immediate {
++ db eval "CREATE TABLE $table (t TEXT,n INT)"
++ for {set i 0} {$i<$count} {incr i} {
++ set t [concat $base $i]
++ db eval [concat {INSERT INTO} $table {VALUES ($t, $i)}]
++ }
++ }
++}
++
++# Leaf-only database parses.
++do_test recover-leaf-1.0 {
++ db close
++ sqlite3 db test.db
++ generate "leaf" "Leaf-node-generating line " 10
++
++ db eval {
++ DROP TABLE IF EXISTS temp.leaf_recover;
++ CREATE VIRTUAL TABLE temp.leaf_recover USING recover(
++ leaf,
++ t TEXT,
++ n INTEGER
++ );
++ }
++ execsql {SELECT t, n FROM leaf_recover ORDER BY rowid}
++} {{Leaf-node-generating line 0} 0 {Leaf-node-generating line 1} 1 {Leaf-node-generating line 2} 2 {Leaf-node-generating line 3} 3 {Leaf-node-generating line 4} 4 {Leaf-node-generating line 5} 5 {Leaf-node-generating line 6} 6 {Leaf-node-generating line 7} 7 {Leaf-node-generating line 8} 8 {Leaf-node-generating line 9} 9}
++
++# Empty table gives empty results.
++do_test recover-leaf-2.0 {
++ db close
++ sqlite3 db test.db
++ generate "empty" "Leaf-node-generating line " 0
++
++ db eval {
++ DROP TABLE IF EXISTS temp.leaf_recover;
++ CREATE VIRTUAL TABLE temp.leaf_recover USING recover(
++ empty,
++ t TEXT,
++ n INTEGER
++ );
++ }
++ execsql {SELECT t, n FROM leaf_recover ORDER BY rowid}
++} {}
++
++# Single level of interior node.
++do_test recover-interior-1.0 {
++ db close
++ sqlite3 db test.db
++ generate "interior" "Interior-node-generating line " 100
++
++ db eval {
++ DROP TABLE IF EXISTS temp.interior_recover;
++ CREATE VIRTUAL TABLE temp.interior_recover USING recover(
++ interior,
++ t TEXT,
++ n INTEGER
++ );
++ }
++ execsql {SELECT t, n FROM interior_recover WHERE (rowid%10)=0 ORDER BY rowid}
++} {{Interior-node-generating line 9} 9 {Interior-node-generating line 19} 19 {Interior-node-generating line 29} 29 {Interior-node-generating line 39} 39 {Interior-node-generating line 49} 49 {Interior-node-generating line 59} 59 {Interior-node-generating line 69} 69 {Interior-node-generating line 79} 79 {Interior-node-generating line 89} 89 {Interior-node-generating line 99} 99}
++
++# Multiple levels of interior node.
++do_test recover-interior-2.0 {
++ db close
++ sqlite3 db test.db
++ generate "interior2" "Interior-node-generating line " 5000
++
++ db eval {
++ DROP TABLE IF EXISTS temp.interior2_recover;
++ CREATE VIRTUAL TABLE temp.interior2_recover USING recover(
++ interior2,
++ t TEXT,
++ n INTEGER
++ );
++ }
++ execsql {SELECT t, n FROM interior2_recover WHERE (rowid%500)=0 ORDER BY rowid}
++} {{Interior-node-generating line 499} 499 {Interior-node-generating line 999} 999 {Interior-node-generating line 1499} 1499 {Interior-node-generating line 1999} 1999 {Interior-node-generating line 2499} 2499 {Interior-node-generating line 2999} 2999 {Interior-node-generating line 3499} 3499 {Interior-node-generating line 3999} 3999 {Interior-node-generating line 4499} 4499 {Interior-node-generating line 4999} 4999}
++
++finish_test
+diff --git a/third_party/sqlite/src/test/recover0.test b/third_party/sqlite/src/test/recover0.test
+new file mode 100644
+index 000000000000..aac2ed9164ba
+--- /dev/null
++++ b/third_party/sqlite/src/test/recover0.test
+@@ -0,0 +1,532 @@
++# 2012 January 4 {}
++#
++# The author disclaims copyright to this source code. In place of
++# a legal notice, here is a blessing:
++#
++# May you do good and not evil.
++# May you find forgiveness for yourself and forgive others.
++# May you share freely, never taking more than you give.
++#
++#***********************************************************************
++# This file implements regression tests for SQLite library.
++#
++# Test recover module syntax.
++#
++# $Id$
++
++# TODO(shess): Test with attached databases.
++
++# TODO(shess): Handle column mismatches? As things stand, the code
++# only needs to pull the root page, so that may not be completely
++# feasible.
++
++set testdir [file dirname $argv0]
++source $testdir/tester.tcl
++
++db eval {
++ DROP TABLE IF EXISTS backing;
++ CREATE TABLE backing (t TEXT);
++
++ DROP TABLE IF EXISTS backing2;
++ CREATE TABLE backing2 (id INTEGER PRIMARY KEY, t TEXT);
++}
++
++# Baseline create works.
++do_test recover-syntax-0.0 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ catchsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ backing,
++ t TEXT
++ );
++ }
++} {0 {}}
++
++# Can specify database.
++do_test recover-syntax-0.1 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ catchsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ main.backing,
++ t TEXT
++ );
++ }
++} {0 {}}
++
++# Can specify sqlite_master.
++do_test recover-syntax-0.2 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ catchsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ sqlite_master,
++ type TEXT,
++ name TEXT,
++ tbl_name TEXT,
++ rootpage INTEGER,
++ sql TEXT
++ );
++ }
++} {0 {}}
++
++# Fails if virtual table is not in the temp database.
++do_test recover-syntax-1.0 {
++ db eval {DROP TABLE IF EXISTS temp.syntax;}
++ catchsql {
++ CREATE VIRTUAL TABLE syntax USING recover(
++ backing,
++ t TEXT
++ );
++ }
++} {1 {recover table must be in temp database}}
++
++# Fails if mentions missing table.
++do_test recover-syntax-2.0 {
++ db eval {DROP TABLE IF EXISTS temp.syntax;}
++ catchsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ snacking,
++ t TEXT
++ );
++ }
++} {1 {unable to find backing table}}
++
++# Fails if mentions missing database.
++do_test recover-syntax-2.1 {
++ db eval {DROP TABLE IF EXISTS temp.syntax;}
++ catchsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ db.backing,
++ t TEXT
++ );
++ }
++} {1 {unable to find backing table}}
++
++# Fails if mentions garbage backing.
++do_test recover-syntax-2.2 {
++ db eval {DROP TABLE IF EXISTS temp.syntax;}
++ catchsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ main.backing excess,
++ t TEXT
++ );
++ }
++} {1 {unable to find backing table}}
++
++# Database only fails.
++do_test recover-syntax-2.3 {
++ db eval {DROP TABLE IF EXISTS temp.syntax;}
++ catchsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ main.,
++ t TEXT
++ );
++ }
++} {1 {ill-formed table specifier}}
++
++# Table only fails.
++do_test recover-syntax-2.4 {
++ db eval {DROP TABLE IF EXISTS temp.syntax;}
++ catchsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ .backing,
++ t TEXT
++ );
++ }
++} {1 {ill-formed table specifier}}
++
++# Manifest typing.
++do_test recover-syntax-3.0 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ execsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ backing,
++ t
++ );
++ PRAGMA table_info(syntax);
++ }
++} {0 t {} 0 {} 0}
++
++# ANY as an alternative for manifest typing.
++do_test recover-syntax-3.1 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ execsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ backing,
++ t ANY
++ );
++ PRAGMA table_info(syntax);
++ }
++} {0 t {} 0 {} 0}
++
++# ANY NOT NULL
++do_test recover-syntax-3.2 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ execsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ backing,
++ t ANY NOT NULL
++ );
++ PRAGMA table_info(syntax);
++ }
++} {0 t {} 1 {} 0}
++
++# ANY STRICT is not sensible.
++do_test recover-syntax-3.3 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ catchsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ backing,
++ v ANY STRICT
++ );
++ PRAGMA table_info(syntax);
++ }
++} {1 {unable to parse column 0}}
++
++# TEXT column by type works.
++do_test recover-syntax-4.0 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ execsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ backing,
++ t TEXT
++ );
++ PRAGMA table_info(syntax);
++ }
++} {0 t TEXT 0 {} 0}
++
++# TEXT NOT NULL
++do_test recover-syntax-4.1 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ execsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ backing,
++ t TEXT NOT NULL
++ );
++ PRAGMA table_info(syntax);
++ }
++} {0 t TEXT 1 {} 0}
++
++# TEXT STRICT
++do_test recover-syntax-4.2 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ execsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ backing,
++ t TEXT STRICT
++ );
++ PRAGMA table_info(syntax);
++ }
++} {0 t TEXT 0 {} 0}
++
++# TEXT STRICT NOT NULL
++do_test recover-syntax-4.3 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ execsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ backing,
++ t TEXT STRICT NOT NULL
++ );
++ PRAGMA table_info(syntax);
++ }
++} {0 t TEXT 1 {} 0}
++
++# INTEGER
++do_test recover-syntax-5.0 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ execsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ backing,
++ i INTEGER
++ );
++ PRAGMA table_info(syntax);
++ }
++} {0 i INTEGER 0 {} 0}
++
++# INTEGER NOT NULL
++do_test recover-syntax-5.1 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ execsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ backing,
++ i INTEGER NOT NULL
++ );
++ PRAGMA table_info(syntax);
++ }
++} {0 i INTEGER 1 {} 0}
++
++# INTEGER STRICT
++do_test recover-syntax-5.2 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ execsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ backing,
++ i INTEGER STRICT
++ );
++ PRAGMA table_info(syntax);
++ }
++} {0 i INTEGER 0 {} 0}
++
++# INTEGER STRICT NOT NULL
++do_test recover-syntax-5.3 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ execsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ backing,
++ i INTEGER STRICT NOT NULL
++ );
++ PRAGMA table_info(syntax);
++ }
++} {0 i INTEGER 1 {} 0}
++
++# BLOB
++do_test recover-syntax-6.0 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ execsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ backing,
++ b BLOB
++ );
++ PRAGMA table_info(syntax);
++ }
++} {0 b BLOB 0 {} 0}
++
++# BLOB NOT NULL
++do_test recover-syntax-6.1 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ execsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ backing,
++ b BLOB NOT NULL
++ );
++ PRAGMA table_info(syntax);
++ }
++} {0 b BLOB 1 {} 0}
++
++# BLOB STRICT
++do_test recover-syntax-6.2 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ execsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ backing,
++ b BLOB STRICT
++ );
++ PRAGMA table_info(syntax);
++ }
++} {0 b BLOB 0 {} 0}
++
++# BLOB STRICT NOT NULL
++do_test recover-syntax-6.3 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ execsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ backing,
++ b BLOB STRICT NOT NULL
++ );
++ PRAGMA table_info(syntax);
++ }
++} {0 b BLOB 1 {} 0}
++
++# FLOAT
++do_test recover-syntax-7.0 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ execsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ backing,
++ f FLOAT
++ );
++ PRAGMA table_info(syntax);
++ }
++} {0 f FLOAT 0 {} 0}
++
++# FLOAT NOT NULL
++do_test recover-syntax-7.1 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ execsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ backing,
++ f FLOAT NOT NULL
++ );
++ PRAGMA table_info(syntax);
++ }
++} {0 f FLOAT 1 {} 0}
++
++# FLOAT STRICT
++do_test recover-syntax-7.2 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ execsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ backing,
++ f FLOAT STRICT
++ );
++ PRAGMA table_info(syntax);
++ }
++} {0 f FLOAT 0 {} 0}
++
++# FLOAT STRICT NOT NULL
++do_test recover-syntax-7.3 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ execsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ backing,
++ f FLOAT STRICT NOT NULL
++ );
++ PRAGMA table_info(syntax);
++ }
++} {0 f FLOAT 1 {} 0}
++
++# NUMERIC
++do_test recover-syntax-8.0 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ execsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ backing,
++ f NUMERIC
++ );
++ PRAGMA table_info(syntax);
++ }
++} {0 f NUMERIC 0 {} 0}
++
++# NUMERIC NOT NULL
++do_test recover-syntax-8.1 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ execsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ backing,
++ f NUMERIC NOT NULL
++ );
++ PRAGMA table_info(syntax);
++ }
++} {0 f NUMERIC 1 {} 0}
++
++# NUMERIC STRICT
++do_test recover-syntax-8.2 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ execsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ backing,
++ f NUMERIC STRICT
++ );
++ PRAGMA table_info(syntax);
++ }
++} {0 f NUMERIC 0 {} 0}
++
++# NUMERIC STRICT NOT NULL
++do_test recover-syntax-8.3 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ execsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ backing,
++ f NUMERIC STRICT NOT NULL
++ );
++ PRAGMA table_info(syntax);
++ }
++} {0 f NUMERIC 1 {} 0}
++
++# ROWID
++do_test recover-syntax-9.0 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ execsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ backing2,
++ id ROWID,
++ v
++ );
++ PRAGMA table_info(syntax);
++ }
++} {0 id INTEGER 1 {} 0 1 v {} 0 {} 0}
++
++# ROWID NOT NULL (is default)
++do_test recover-syntax-9.1 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ execsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ backing2,
++ id ROWID NOT NULL,
++ v
++ );
++ PRAGMA table_info(syntax);
++ }
++} {0 id INTEGER 1 {} 0 1 v {} 0 {} 0}
++
++# ROWID STRICT
++do_test recover-syntax-9.0 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ execsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ backing2,
++ id ROWID STRICT,
++ v
++ );
++ PRAGMA table_info(syntax);
++ }
++} {0 id INTEGER 1 {} 0 1 v {} 0 {} 0}
++
++# ROWID STRICT NOT NULL (is default)
++do_test recover-syntax-9.1 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ execsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ backing2,
++ id ROWID STRICT NOT NULL,
++ v
++ );
++ PRAGMA table_info(syntax);
++ }
++} {0 id INTEGER 1 {} 0 1 v {} 0 {} 0}
++
++# Invalid type info is not ignored.
++do_test recover-syntax-10.0 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ catchsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ backing,
++ v GARBAGE
++ );
++ }
++} {1 {unable to parse column 0}}
++
++# Extraneous type info is not ignored.
++do_test recover-syntax-10.1 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ catchsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ backing,
++ v INTEGER GARBAGE
++ );
++ }
++} {1 {unable to parse column 0}}
++
++# Extraneous type info is not ignored.
++do_test recover-syntax-10.2 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ catchsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ backing,
++ v INTEGER NOT NULL GARBAGE
++ );
++ }
++} {1 {unable to parse column 0}}
++
++# Multiple types don't work.
++do_test recover-syntax-10.3 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ catchsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ backing,
++ v INTEGER FLOAT BLOB
++ );
++ }
++} {1 {unable to parse column 0}}
++
++# Multiple types don't work.
++do_test recover-syntax-10.4 {
++ db eval {DROP TABLE IF EXISTS temp.syntax}
++ catchsql {
++ CREATE VIRTUAL TABLE temp.syntax USING recover(
++ backing,
++ v INTEGER NOT NULL TEXT
++ );
++ }
++} {1 {unable to parse column 0}}
++
++finish_test
+diff --git a/third_party/sqlite/src/test/recover1.test b/third_party/sqlite/src/test/recover1.test
+new file mode 100644
+index 000000000000..1d90f096b727
+--- /dev/null
++++ b/third_party/sqlite/src/test/recover1.test
+@@ -0,0 +1,429 @@
++# 2012 January 4 {}
++#
++# The author disclaims copyright to this source code. In place of
++# a legal notice, here is a blessing:
++#
++# May you do good and not evil.
++# May you find forgiveness for yourself and forgive others.
++# May you share freely, never taking more than you give.
++#
++#***********************************************************************
++# This file implements regression tests for SQLite library.
++#
++# Use tables to test leaf-node reading, and also type checking.
++#
++# $Id$
++
++set testdir [file dirname $argv0]
++source $testdir/tester.tcl
++
++# A really basic table with manifest typing and a row of each type.
++db close
++sqlite3 db test.db
++db eval {
++ DROP TABLE IF EXISTS types;
++ CREATE TABLE types (rowtype TEXT, value);
++ INSERT INTO types VALUES ("NULL", NULL);
++ INSERT INTO types VALUES ("INTEGER", 17);
++ INSERT INTO types VALUES ("FLOAT", 3.1415927);
++ INSERT INTO types VALUES ("TEXT", "This is text");
++ INSERT INTO types VALUES ("BLOB", CAST("This is a blob" AS BLOB));
++
++ -- Same contents, with an alias for rowid. Testing separately
++ -- because it changes the structure of the data (the alias column is
++ -- serialized as NULL).
++ DROP TABLE IF EXISTS types2;
++ CREATE TABLE types2 (id INTEGER PRIMARY KEY, rowtype TEXT, value);
++ INSERT INTO types2 (id, rowtype, value)
++ SELECT rowid, rowtype, value FROM types;
++}
++
++# Baseline results.
++do_test recover-types-0.0 {
++ execsql {SELECT rowid, rowtype, value, TYPEOF(value) FROM types}
++} {1 NULL {} null 2 INTEGER 17 integer 3 FLOAT 3.1415927 real 4 TEXT {This is text} text 5 BLOB {This is a blob} blob}
++
++# With no restrictions, recover table shows identical results.
++do_test recover-types-0.1 {
++ db eval {
++ DROP TABLE IF EXISTS temp.types_recover;
++ CREATE VIRTUAL TABLE temp.types_recover USING recover(
++ types,
++ rowtype TEXT,
++ value
++ );
++ }
++ execsql {SELECT rowid, rowtype, value, TYPEOF(value) FROM types_recover}
++} {1 NULL {} null 2 INTEGER 17 integer 3 FLOAT 3.1415927 real 4 TEXT {This is text} text 5 BLOB {This is a blob} blob}
++
++# Restrict by INTEGER
++do_test recover-types-1.0 {
++ db eval {
++ DROP TABLE IF EXISTS temp.types_recover;
++ CREATE VIRTUAL TABLE temp.types_recover USING recover(
++ types,
++ rowtype TEXT,
++ value INTEGER
++ );
++ }
++ execsql {SELECT rowid, rowtype, value, TYPEOF(value) FROM types_recover}
++} {1 NULL {} null 2 INTEGER 17 integer}
++
++# Restrict by INTEGER NOT NULL
++do_test recover-types-1.1 {
++ db eval {
++ DROP TABLE IF EXISTS temp.types_recover;
++ CREATE VIRTUAL TABLE temp.types_recover USING recover(
++ types,
++ rowtype TEXT,
++ value INTEGER NOT NULL
++ );
++ }
++ execsql {SELECT rowid, rowtype, value, TYPEOF(value) FROM types_recover}
++} {2 INTEGER 17 integer}
++
++# Restrict by FLOAT
++do_test recover-types-2.0 {
++ db eval {
++ DROP TABLE IF EXISTS temp.types_recover;
++ CREATE VIRTUAL TABLE temp.types_recover USING recover(
++ types,
++ rowtype TEXT,
++ value FLOAT
++ );
++ }
++ execsql {SELECT rowid, rowtype, value, TYPEOF(value) FROM types_recover}
++} {1 NULL {} null 2 INTEGER 17.0 real 3 FLOAT 3.1415927 real}
++
++# Restrict by FLOAT NOT NULL
++do_test recover-types-2.1 {
++ db eval {
++ DROP TABLE IF EXISTS temp.types_recover;
++ CREATE VIRTUAL TABLE temp.types_recover USING recover(
++ types,
++ rowtype TEXT,
++ value FLOAT NOT NULL
++ );
++ }
++ execsql {SELECT rowid, rowtype, value, TYPEOF(value) FROM types_recover}
++} {2 INTEGER 17.0 real 3 FLOAT 3.1415927 real}
++
++# Restrict by FLOAT STRICT
++do_test recover-types-2.2 {
++ db eval {
++ DROP TABLE IF EXISTS temp.types_recover;
++ CREATE VIRTUAL TABLE temp.types_recover USING recover(
++ types,
++ rowtype TEXT,
++ value FLOAT STRICT
++ );
++ }
++ execsql {SELECT rowid, rowtype, value, TYPEOF(value) FROM types_recover}
++} {1 NULL {} null 3 FLOAT 3.1415927 real}
++
++# Restrict by FLOAT STRICT NOT NULL
++do_test recover-types-2.3 {
++ db eval {
++ DROP TABLE IF EXISTS temp.types_recover;
++ CREATE VIRTUAL TABLE temp.types_recover USING recover(
++ types,
++ rowtype TEXT,
++ value FLOAT STRICT NOT NULL
++ );
++ }
++ execsql {SELECT rowid, rowtype, value, TYPEOF(value) FROM types_recover}
++} {3 FLOAT 3.1415927 real}
++
++# Restrict by TEXT
++do_test recover-types-3.0 {
++ db eval {
++ DROP TABLE IF EXISTS temp.types_recover;
++ CREATE VIRTUAL TABLE temp.types_recover USING recover(
++ types,
++ rowtype TEXT,
++ value TEXT
++ );
++ }
++ execsql {SELECT rowid, rowtype, value, TYPEOF(value) FROM types_recover}
++} {1 NULL {} null 4 TEXT {This is text} text 5 BLOB {This is a blob} blob}
++
++# Restrict by TEXT NOT NULL
++do_test recover-types-3.1 {
++ db eval {
++ DROP TABLE IF EXISTS temp.types_recover;
++ CREATE VIRTUAL TABLE temp.types_recover USING recover(
++ types,
++ rowtype TEXT,
++ value TEXT NOT NULL
++ );
++ }
++ execsql {SELECT rowid, rowtype, value, TYPEOF(value) FROM types_recover}
++} {4 TEXT {This is text} text 5 BLOB {This is a blob} blob}
++
++# Restrict by TEXT STRICT
++do_test recover-types-3.2 {
++ db eval {
++ DROP TABLE IF EXISTS temp.types_recover;
++ CREATE VIRTUAL TABLE temp.types_recover USING recover(
++ types,
++ rowtype TEXT,
++ value TEXT STRICT
++ );
++ }
++ execsql {SELECT rowid, rowtype, value, TYPEOF(value) FROM types_recover}
++} {1 NULL {} null 4 TEXT {This is text} text}
++
++# Restrict by TEXT STRICT NOT NULL
++do_test recover-types-3.3 {
++ db eval {
++ DROP TABLE IF EXISTS temp.types_recover;
++ CREATE VIRTUAL TABLE temp.types_recover USING recover(
++ types,
++ rowtype TEXT,
++ value TEXT STRICT NOT NULL
++ );
++ }
++ execsql {SELECT rowid, rowtype, value, TYPEOF(value) FROM types_recover}
++} {4 TEXT {This is text} text}
++
++# Restrict by BLOB
++do_test recover-types-4.0 {
++ db eval {
++ DROP TABLE IF EXISTS temp.types_recover;
++ CREATE VIRTUAL TABLE temp.types_recover USING recover(
++ types,
++ rowtype TEXT,
++ value BLOB
++ );
++ }
++ execsql {SELECT rowid, rowtype, value, TYPEOF(value) FROM types_recover}
++} {1 NULL {} null 5 BLOB {This is a blob} blob}
++
++# Restrict by BLOB NOT NULL
++do_test recover-types-4.1 {
++ db eval {
++ DROP TABLE IF EXISTS temp.types_recover;
++ CREATE VIRTUAL TABLE temp.types_recover USING recover(
++ types,
++ rowtype TEXT,
++ value BLOB NOT NULL
++ );
++ }
++ execsql {SELECT rowid, rowtype, value, TYPEOF(value) FROM types_recover}
++} {5 BLOB {This is a blob} blob}
++
++# Manifest typing.
++do_test recover-types-5.0 {
++ db eval {
++ DROP TABLE IF EXISTS temp.types_recover;
++ CREATE VIRTUAL TABLE temp.types_recover USING recover(
++ types,
++ rowtype TEXT,
++ value
++ );
++ }
++ execsql {SELECT rowid, rowtype, value, TYPEOF(value) FROM types_recover}
++} {1 NULL {} null 2 INTEGER 17 integer 3 FLOAT 3.1415927 real 4 TEXT {This is text} text 5 BLOB {This is a blob} blob}
++
++# Should get same results specifying manifest typing explicitly.
++do_test recover-types-5.1 {
++ db eval {
++ DROP TABLE IF EXISTS temp.types_recover;
++ CREATE VIRTUAL TABLE temp.types_recover USING recover(
++ types,
++ rowtype TEXT,
++ value ANY
++ );
++ }
++ execsql {SELECT rowid, rowtype, value, TYPEOF(value) FROM types_recover}
++} {1 NULL {} null 2 INTEGER 17 integer 3 FLOAT 3.1415927 real 4 TEXT {This is text} text 5 BLOB {This is a blob} blob}
++
++# Same results, skipping the NULL row.
++do_test recover-types-5.2 {
++ db eval {
++ DROP TABLE IF EXISTS temp.types_recover;
++ CREATE VIRTUAL TABLE temp.types_recover USING recover(
++ types,
++ rowtype TEXT,
++ value ANY NOT NULL
++ );
++ }
++ execsql {SELECT rowid, rowtype, value, TYPEOF(value) FROM types_recover}
++} {2 INTEGER 17 integer 3 FLOAT 3.1415927 real 4 TEXT {This is text} text 5 BLOB {This is a blob} blob}
++
++# Test ROWID values.
++do_test recover-types-6.0 {
++ db eval {
++ DROP TABLE IF EXISTS temp.types2_recover;
++ CREATE VIRTUAL TABLE temp.types2_recover USING recover(
++ types2,
++ id ROWID,
++ rowtype TEXT,
++ value
++ );
++ }
++ execsql {SELECT rowid, id, rowtype, value, TYPEOF(value) FROM types2_recover}
++} {1 1 NULL {} null 2 2 INTEGER 17 integer 3 3 FLOAT 3.1415927 real 4 4 TEXT {This is text} text 5 5 BLOB {This is a blob} blob}
++
++# ROWID NOT NULL is identical.
++do_test recover-types-6.1 {
++ db eval {
++ DROP TABLE IF EXISTS temp.types2_recover;
++ CREATE VIRTUAL TABLE temp.types2_recover USING recover(
++ types2,
++ id ROWID NOT NULL,
++ rowtype TEXT,
++ value
++ );
++ }
++ execsql {SELECT rowid, id, rowtype, value, TYPEOF(value) FROM types2_recover}
++} {1 1 NULL {} null 2 2 INTEGER 17 integer 3 3 FLOAT 3.1415927 real 4 4 TEXT {This is text} text 5 5 BLOB {This is a blob} blob}
++
++# Check that each of the possible integer sizes is being decoded.
++# TODO(shess): It would be neat to ACTUALLY test these things. As-is,
++# this should exercise the code paths, but one needs logging or a
++# debugger to verify that things are stored as expected.
++do_test recover-types-7.0 {
++ db eval {
++ DROP TABLE IF EXISTS integers;
++ CREATE TABLE integers (value);
++
++ -- encoded directly in type info.
++ INSERT INTO integers VALUES (0);
++ INSERT INTO integers VALUES (1);
++
++ -- 8-bit signed.
++ INSERT INTO integers VALUES (2);
++ INSERT INTO integers VALUES (-2);
++ INSERT INTO integers VALUES (127);
++ INSERT INTO integers VALUES (-128);
++
++ -- 16-bit signed.
++ INSERT INTO integers VALUES (12345);
++ INSERT INTO integers VALUES (-12345);
++ INSERT INTO integers VALUES (32767);
++ INSERT INTO integers VALUES (-32768);
++
++ -- 24-bit signed.
++ INSERT INTO integers VALUES (1234567);
++ INSERT INTO integers VALUES (-1234567);
++ INSERT INTO integers VALUES (8388607);
++ INSERT INTO integers VALUES (-8388608);
++
++ -- 32-bit signed.
++ INSERT INTO integers VALUES (1234567890);
++ INSERT INTO integers VALUES (-1234567890);
++ INSERT INTO integers VALUES (2147483647);
++ INSERT INTO integers VALUES (-2147483648);
++
++ -- 48-bit signed.
++ INSERT INTO integers VALUES (123456789012345);
++ INSERT INTO integers VALUES (-123456789012345);
++ INSERT INTO integers VALUES (140737488355327);
++ INSERT INTO integers VALUES (-140737488355328);
++
++ -- 64-bit signed.
++ INSERT INTO integers VALUES (9223372036854775807);
++ INSERT INTO integers VALUES (-9223372036854775808);
++
++ DROP TABLE IF EXISTS integers_recover;
++ CREATE VIRTUAL TABLE temp.integers_recover USING recover(
++ integers,
++ value INTEGER
++ );
++ }
++ execsql {SELECT rowid, value FROM integers_recover}
++} {1 0 2 1 3 2 4 -2 5 127 6 -128 7 12345 8 -12345 9 32767 10 -32768 11 1234567 12 -1234567 13 8388607 14 -8388608 15 1234567890 16 -1234567890 17 2147483647 18 -2147483648 19 123456789012345 20 -123456789012345 21 140737488355327 22 -140737488355328 23 9223372036854775807 24 -9223372036854775808}
++
++# If UTF16 support is disabled, ignore the rest of the tests.
++#
++ifcapable {!utf16} {
++ finish_test
++ return
++}
++
++# Baseline UTF-8.
++file delete -force test.db
++sqlite3 db test.db;
++db eval {
++ PRAGMA encoding = 'UTF-8';
++}
++
++do_test recover-encoding-1.0 {
++ execsql {
++ DROP TABLE IF EXISTS e;
++ CREATE TABLE e (v TEXT);
++ INSERT INTO e VALUES('Mjollnir');
++ INSERT INTO e VALUES('Mjölnir');
++ INSERT INTO e VALUES('Mjǫlnir');
++ INSERT INTO e VALUES('Mjölner');
++ INSERT INTO e VALUES('Mjølner');
++ INSERT INTO e VALUES('ハンマー');
++ PRAGMA encoding;
++
++ DROP TABLE IF EXISTS e_recover;
++ CREATE VIRTUAL TABLE temp.e_recover USING recover(
++ e,
++ v TEXT
++ );
++ SELECT rowid, v FROM e_recover ORDER BY rowid;
++ }
++} {UTF-8 1 Mjollnir 2 Mjölnir 3 Mjǫlnir 4 Mjölner 5 Mjølner 6 ハンマー}
++
++# Reset the database to UTF-16LE.
++file delete -force test.db
++sqlite3 db test.db;
++db eval {
++ PRAGMA encoding = 'UTF-16LE';
++}
++
++do_test recover-encoding-2.0 {
++ execsql {
++ DROP TABLE IF EXISTS e;
++ CREATE TABLE e (v TEXT);
++ INSERT INTO e VALUES('Mjollnir');
++ INSERT INTO e VALUES('Mjölnir');
++ INSERT INTO e VALUES('Mjǫlnir');
++ INSERT INTO e VALUES('Mjölner');
++ INSERT INTO e VALUES('Mjølner');
++ INSERT INTO e VALUES('ハンマー');
++ PRAGMA encoding;
++
++ DROP TABLE IF EXISTS e_recover;
++ CREATE VIRTUAL TABLE temp.e_recover USING recover(
++ e,
++ v TEXT
++ );
++ SELECT rowid, v FROM e_recover ORDER BY rowid;
++ }
++} {UTF-16le 1 Mjollnir 2 Mjölnir 3 Mjǫlnir 4 Mjölner 5 Mjølner 6 ハンマー}
++
++# Reset the database to UTF-16BE.
++file delete -force test.db
++sqlite3 db test.db;
++db eval {
++ PRAGMA encoding = 'UTF-16BE';
++}
++
++do_test recover-encoding-3.0 {
++ execsql {
++ DROP TABLE IF EXISTS e;
++ CREATE TABLE e (v TEXT);
++ INSERT INTO e VALUES('Mjollnir');
++ INSERT INTO e VALUES('Mjölnir');
++ INSERT INTO e VALUES('Mjǫlnir');
++ INSERT INTO e VALUES('Mjölner');
++ INSERT INTO e VALUES('Mjølner');
++ INSERT INTO e VALUES('ハンマー');
++ PRAGMA encoding;
++
++ DROP TABLE IF EXISTS e_recover;
++ CREATE VIRTUAL TABLE temp.e_recover USING recover(
++ e,
++ v TEXT
++ );
++ SELECT rowid, v FROM e_recover ORDER BY rowid;
++ }
++} {UTF-16be 1 Mjollnir 2 Mjölnir 3 Mjǫlnir 4 Mjölner 5 Mjølner 6 ハンマー}
++
++finish_test
+diff --git a/third_party/sqlite/src/test/recover2.test b/third_party/sqlite/src/test/recover2.test
+new file mode 100644
+index 000000000000..8aa4e049a010
+--- /dev/null
++++ b/third_party/sqlite/src/test/recover2.test
+@@ -0,0 +1,157 @@
++# 2012 January 4 {}
++#
++# The author disclaims copyright to this source code. In place of
++# a legal notice, here is a blessing:
++#
++# May you do good and not evil.
++# May you find forgiveness for yourself and forgive others.
++# May you share freely, never taking more than you give.
++#
++#***********************************************************************
++# This file implements regression tests for SQLite library.
++#
++# This file implements tests for how the recover module handles cell
++# overflow.
++#
++# $Id$
++
++set testdir [file dirname $argv0]
++source $testdir/tester.tcl
++
++set lorem "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam sagittis gravida odio vitae ultrices. Nulla facilisi. Maecenas pulvinar, tellus ut bibendum semper, nibh tellus auctor nulla, in dignissim nisi ipsum id arcu. Nullam tincidunt arcu malesuada turpis faucibus in adipiscing enim mattis. Fusce augue magna, scelerisque sollicitudin egestas in, cursus eu sapien. Pellentesque tempor risus at lectus convallis a convallis orci ornare. Integer tristique aliquam leo vel interdum.
++
++Phasellus quis dictum nisi. Curabitur at enim non felis pharetra imperdiet. Duis tempus massa eu leo varius porta. Vestibulum sodales nulla at purus tincidunt ultrices. Nam euismod posuere nibh, nec sodales magna luctus ac. Ut commodo hendrerit mauris vitae gravida. In interdum justo ut sem eleifend convallis. Donec cursus molestie elementum. Suspendisse at nisl tellus, vel consequat mauris. Nullam non justo nibh.
++
++Maecenas varius sollicitudin libero, nec feugiat turpis facilisis eget. Quisque et sem risus. Aenean a magna quis purus hendrerit mattis eu vel lorem. Aenean fringilla diam eget tortor lacinia sed mollis eros feugiat. Quisque ac purus sapien. Nullam quis tellus vel magna convallis tincidunt. Donec eget ligula at libero tincidunt congue ut ut lacus. Integer dignissim aliquet congue. Pellentesque sed risus vitae lorem porta viverra ac eu risus. Vivamus congue suscipit odio pulvinar aliquet. Aliquam porttitor nunc non sapien auctor et vehicula augue molestie.
++
++Aliquam et dui ac sem tempus dictum. Fusce arcu nulla, viverra sit amet suscipit quis, malesuada at felis. Fusce ut diam felis. Fusce id ligula non eros fermentum sodales in nec quam. Donec tempor bibendum arcu ac adipiscing. Praesent nisl lectus, tempor ut vehicula eget, mattis a justo. Mauris condimentum luctus eros a varius. Morbi mollis elit eget velit convallis eu sodales odio egestas. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vivamus interdum, metus sit amet varius varius, lectus eros semper risus, sed sagittis ipsum libero in sapien. Nam lacinia nulla vitae magna facilisis scelerisque. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
++
++Donec gravida dignissim eleifend. Aliquam vel tincidunt tortor. Curabitur massa ante, blandit a auctor at, ullamcorper sed nisl. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Suspendisse ut felis a eros egestas ultricies et quis mi. Vivamus ut risus massa. Donec nec ornare erat. Aliquam ornare, lorem a rhoncus aliquam, tellus diam tincidunt tellus, a mattis nunc ante ac arcu. Curabitur nec metus id risus commodo ullamcorper eu ut tortor."
++
++# Create a database which needs a multiple overflow pages to test the
++# transition from main page to overflow, and then overflow to
++# overflow.
++do_test recover-overflow-1.0 {
++ db eval {
++ DROP TABLE IF EXISTS overflow;
++ CREATE TABLE overflow (value TEXT);
++ INSERT INTO overflow VALUES ($lorem);
++
++ DROP TABLE IF EXISTS overflow_recover;
++ CREATE VIRTUAL TABLE temp.overflow_recover USING recover(
++ overflow,
++ value TEXT
++ );
++ }
++
++ # Should have root page, leaf page, and 2 overflow pages, because
++ # length(value) is more than 2x page_size.
++ execsql {
++ PRAGMA page_count;
++ PRAGMA page_size;
++ SELECT rowid, TYPEOF(value), length(value), value FROM overflow_recover;
++ }
++} [list 4 1024 1 text [string length $lorem] $lorem]
++
++# No overflow. [1024-35 == 990, overhead of 1-byte rowid, 2-byte
++# record length, 1-byte header length, 2-byte field type.]
++set substr [string range $lorem 0 985]
++do_test recover-overflow-1.1 {
++ db eval {
++ DROP TABLE IF EXISTS overflow;
++ CREATE TABLE overflow (value TEXT);
++ INSERT INTO overflow VALUES ($substr);
++
++ DROP TABLE IF EXISTS overflow_recover;
++ CREATE VIRTUAL TABLE temp.overflow_recover USING recover(
++ overflow,
++ value TEXT
++ );
++ }
++
++ # Trim to remove excess pages from prior tests.
++ db eval {VACUUM}
++
++ execsql {
++ PRAGMA page_count;
++ PRAGMA page_size;
++ SELECT rowid, TYPEOF(value), length(value), value FROM overflow_recover;
++ }
++} [list 2 1024 1 text [string length $substr] $substr]
++
++# One byte of overflow.
++set substr [string range $lorem 0 986]
++do_test recover-overflow-1.2 {
++ db eval {
++ DROP TABLE IF EXISTS overflow;
++ CREATE TABLE overflow (value TEXT);
++ INSERT INTO overflow VALUES ($substr);
++
++ DROP TABLE IF EXISTS overflow_recover;
++ CREATE VIRTUAL TABLE temp.overflow_recover USING recover(
++ overflow,
++ value TEXT
++ );
++ }
++
++ # Trim to remove excess pages from prior tests.
++ db eval {VACUUM}
++
++ execsql {
++ PRAGMA page_count;
++ PRAGMA page_size;
++ SELECT rowid, TYPEOF(value), length(value), value FROM overflow_recover;
++ }
++} [list 3 1024 1 text [string length $substr] $substr]
++
++# One full overflow page, plus maxLocal in-leaf. [985+1020]
++set substr [string range $lorem 0 2005]
++do_test recover-overflow-1.3 {
++ db eval {
++ DROP TABLE IF EXISTS overflow;
++ CREATE TABLE overflow (value TEXT);
++ INSERT INTO overflow VALUES ($substr);
++
++ DROP TABLE IF EXISTS overflow_recover;
++ CREATE VIRTUAL TABLE temp.overflow_recover USING recover(
++ overflow,
++ value TEXT
++ );
++ }
++
++ # Trim to remove excess pages from prior tests.
++ db eval {VACUUM}
++
++ execsql {
++ PRAGMA page_count;
++ PRAGMA page_size;
++ SELECT rowid, TYPEOF(value), length(value), value FROM overflow_recover;
++ }
++} [list 3 1024 1 text [string length $substr] $substr]
++
++# Overflow to a second overflow page.
++set substr [string range $lorem 0 2006]
++do_test recover-overflow-1.4 {
++ db eval {
++ DROP TABLE IF EXISTS overflow;
++ CREATE TABLE overflow (value TEXT);
++ INSERT INTO overflow VALUES ($substr);
++
++ DROP TABLE IF EXISTS overflow_recover;
++ CREATE VIRTUAL TABLE temp.overflow_recover USING recover(
++ overflow,
++ value TEXT
++ );
++ }
++
++ # Trim to remove excess pages from prior tests.
++ db eval {VACUUM}
++
++ execsql {
++ PRAGMA page_count;
++ PRAGMA page_size;
++ SELECT rowid, TYPEOF(value), length(value), value FROM overflow_recover;
++ }
++} [list 4 1024 1 text [string length $substr] $substr]
++
++finish_test
+--
+2.18.0
+
diff --git a/chromium/third_party/sqlite/patches/0003-Custom-shell.c-helpers-to-load-Chromium-s-ICU-data.patch b/chromium/third_party/sqlite/patches/0003-Custom-shell.c-helpers-to-load-Chromium-s-ICU-data.patch
new file mode 100644
index 00000000000..95f7042c522
--- /dev/null
+++ b/chromium/third_party/sqlite/patches/0003-Custom-shell.c-helpers-to-load-Chromium-s-ICU-data.patch
@@ -0,0 +1,145 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: "tc@google.com" <tc@google.com>
+Date: Tue, 6 Jan 2009 22:39:41 +0000
+Subject: [PATCH 03/17] Custom shell.c helpers to load Chromium's ICU data.
+
+History uses fts3 with an icu-based segmenter. These changes allow building a
+sqlite3 binary for Linux or Windows which can read those files.
+
+Original review URL: https://codereview.chromium.org/42250
+---
+ third_party/sqlite/src/Makefile.linux-gcc | 7 +++++
+ third_party/sqlite/src/main.mk | 2 +-
+ third_party/sqlite/src/src/shell.c.in | 10 ++++++
+ third_party/sqlite/src/src/shell_icu_linux.c | 27 +++++++++++++++++
+ third_party/sqlite/src/src/shell_icu_win.c | 32 ++++++++++++++++++++
+ 5 files changed, 77 insertions(+), 1 deletion(-)
+ create mode 100644 third_party/sqlite/src/src/shell_icu_linux.c
+ create mode 100644 third_party/sqlite/src/src/shell_icu_win.c
+
+diff --git a/third_party/sqlite/src/Makefile.linux-gcc b/third_party/sqlite/src/Makefile.linux-gcc
+index b838b844a312..3047d172389b 100644
+--- a/third_party/sqlite/src/Makefile.linux-gcc
++++ b/third_party/sqlite/src/Makefile.linux-gcc
+@@ -60,6 +60,13 @@ TLIBS =
+ OPTS = -DNDEBUG=1
+ OPTS += -DHAVE_FDATASYNC=1
+
++# Support for loading Chromium ICU data in sqlite3.
++ifeq ($(shell uname -s),Darwin)
++SHELL_ICU =
++else
++SHELL_ICU = $(TOP)/src/shell_icu_linux.c -licuuc
++endif
++
+ #### The suffix to add to executable files. ".exe" for windows.
+ # Nothing for unix.
+ #
+diff --git a/third_party/sqlite/src/main.mk b/third_party/sqlite/src/main.mk
+index 81774f9b100f..b460a58d9a94 100644
+--- a/third_party/sqlite/src/main.mk
++++ b/third_party/sqlite/src/main.mk
+@@ -549,7 +549,7 @@ libsqlite3.a: $(LIBOBJ)
+
+ sqlite3$(EXE): shell.c libsqlite3.a sqlite3.h
+ $(TCCX) $(READLINE_FLAGS) -o sqlite3$(EXE) $(SHELL_OPT) \
+- shell.c libsqlite3.a $(LIBREADLINE) $(TLIBS) $(THREADLIB)
++ shell.c $(SHELL_ICU) libsqlite3.a $(LIBREADLINE) $(TLIBS) $(THREADLIB)
+
+ sqldiff$(EXE): $(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h
+ $(TCCX) -o sqldiff$(EXE) -DSQLITE_THREADSAFE=0 \
+diff --git a/third_party/sqlite/src/src/shell.c.in b/third_party/sqlite/src/src/shell.c.in
+index 0007d984d045..b13551dc61f2 100644
+--- a/third_party/sqlite/src/src/shell.c.in
++++ b/third_party/sqlite/src/src/shell.c.in
+@@ -8555,6 +8555,16 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
+ }
+ #endif
+
++ /* Begin evanm patch. */
++#if !defined(__APPLE__)
++ extern int sqlite_shell_init_icu();
++ if( !sqlite_shell_init_icu() ){
++ fprintf(stderr, "%s: warning: couldn't find icudt38.dll; "
++ "queries against ICU FTS tables will fail.\n", argv[0]);
++ }
++#endif /* !defined(__APPLE__) */
++ /* End evanm patch. */
++
+ /* Do an initial pass through the command-line argument to locate
+ ** the name of the database file, the name of the initialization file,
+ ** the size of the alternative malloc heap,
+diff --git a/third_party/sqlite/src/src/shell_icu_linux.c b/third_party/sqlite/src/src/shell_icu_linux.c
+new file mode 100644
+index 000000000000..4ad0e42d2293
+--- /dev/null
++++ b/third_party/sqlite/src/src/shell_icu_linux.c
+@@ -0,0 +1,27 @@
++/* Copyright 2007 Google Inc. All Rights Reserved.
++**/
++
++#include <limits.h>
++#include <unistd.h>
++#include "unicode/putil.h"
++#include "unicode/udata.h"
++
++/*
++** This function attempts to load the ICU data tables from a data file.
++** Returns 0 on failure, nonzero on success.
++** This a hack job of icu_utils.cc:Initialize(). It's Chrome-specific code.
++*/
++int sqlite_shell_init_icu() {
++ char bin_dir[PATH_MAX + 1];
++ int bin_dir_size = readlink("/proc/self/exe", bin_dir, PATH_MAX);
++ if (bin_dir_size < 0 || bin_dir_size > PATH_MAX)
++ return 0;
++ bin_dir[bin_dir_size] = 0;;
++
++ u_setDataDirectory(bin_dir);
++ // Only look for the packaged data file;
++ // the default behavior is to look for individual files.
++ UErrorCode err = U_ZERO_ERROR;
++ udata_setFileAccess(UDATA_ONLY_PACKAGES, &err);
++ return err == U_ZERO_ERROR;
++}
+diff --git a/third_party/sqlite/src/src/shell_icu_win.c b/third_party/sqlite/src/src/shell_icu_win.c
+new file mode 100644
+index 000000000000..67ebbf4fbdb4
+--- /dev/null
++++ b/third_party/sqlite/src/src/shell_icu_win.c
+@@ -0,0 +1,32 @@
++/* Copyright 2011 Google Inc. All Rights Reserved.
++**/
++
++#include <windows.h>
++#include "unicode/udata.h"
++
++/*
++** This function attempts to load the ICU data tables from a DLL.
++** Returns 0 on failure, nonzero on success.
++** This a hack job of icu_utils.cc:Initialize(). It's Chrome-specific code.
++*/
++
++#define ICU_DATA_SYMBOL "icudt" U_ICU_VERSION_SHORT "_dat"
++int sqlite_shell_init_icu() {
++ HMODULE module;
++ FARPROC addr;
++ UErrorCode err;
++
++ // Chrome dropped U_ICU_VERSION_SHORT from the icu data dll name.
++ module = LoadLibrary(L"icudt.dll");
++ if (!module)
++ return 0;
++
++ addr = GetProcAddress(module, ICU_DATA_SYMBOL);
++ if (!addr)
++ return 0;
++
++ err = U_ZERO_ERROR;
++ udata_setCommonData(addr, &err);
++
++ return 1;
++}
+--
+2.18.0
+
diff --git a/chromium/third_party/sqlite/patches/0003-Virtual-table-supporting-recovery-of-corrupted-datab.patch b/chromium/third_party/sqlite/patches/0003-Virtual-table-supporting-recovery-of-corrupted-datab.patch
index ac0dc33cccd..f7f7e3e5941 100644
--- a/chromium/third_party/sqlite/patches/0003-Virtual-table-supporting-recovery-of-corrupted-datab.patch
+++ b/chromium/third_party/sqlite/patches/0003-Virtual-table-supporting-recovery-of-corrupted-datab.patch
@@ -1,8 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Scott Hess <shess@chromium.org>
Date: Sat, 20 Jul 2013 11:42:21 -0700
-Subject: [PATCH 03/10] Virtual table supporting recovery of corrupted
- databases.
+Subject: [PATCH 3/6] Virtual table supporting recovery of corrupted databases.
"recover" implements a virtual table which uses the SQLite pager layer
to read table pages and pull out the data which is structurally sound
@@ -34,7 +33,7 @@ third_party/sqlite/src/src/{recover,recover-alt}.c .
create mode 100644 third_party/sqlite/src/test/recover2.test
diff --git a/third_party/sqlite/src/main.mk b/third_party/sqlite/src/main.mk
-index ef2b67bd5116..f44fab7f777d 100644
+index 05c8f83b4212..9b50874926dc 100644
--- a/third_party/sqlite/src/main.mk
+++ b/third_party/sqlite/src/main.mk
@@ -77,6 +77,8 @@ LIBOBJ+= vdbe.o parse.o \
@@ -46,7 +45,7 @@ index ef2b67bd5116..f44fab7f777d 100644
LIBOBJ += sqlite3session.o
# All of the source code files.
-@@ -407,6 +409,8 @@ TESTSRC2 = \
+@@ -409,6 +411,8 @@ TESTSRC2 = \
$(TOP)/src/prepare.c \
$(TOP)/src/printf.c \
$(TOP)/src/random.c \
@@ -55,7 +54,7 @@ index ef2b67bd5116..f44fab7f777d 100644
$(TOP)/src/pcache.c \
$(TOP)/src/pcache1.c \
$(TOP)/src/select.c \
-@@ -873,6 +877,7 @@ TESTFIXTURE_FLAGS += -DSQLITE_DEFAULT_PAGE_SIZE=1024
+@@ -876,6 +880,7 @@ TESTFIXTURE_FLAGS += -DSQLITE_DEFAULT_PAGE_SIZE=1024
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_STMTVTAB
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_DBPAGE_VTAB
TESTFIXTURE_FLAGS += -DTCLSH_INIT_PROC=sqlite3TestInit
@@ -64,10 +63,10 @@ index ef2b67bd5116..f44fab7f777d 100644
testfixture$(EXE): $(TESTSRC2) libsqlite3.a $(TESTSRC) $(TOP)/src/tclsqlite.c
$(TCCX) $(TCL_FLAGS) $(TESTFIXTURE_FLAGS) \
diff --git a/third_party/sqlite/src/src/main.c b/third_party/sqlite/src/src/main.c
-index 24ca264d6408..f070fed33989 100644
+index d994c7176ea4..478428ac27c8 100644
--- a/third_party/sqlite/src/src/main.c
+++ b/third_party/sqlite/src/src/main.c
-@@ -3197,6 +3197,14 @@ static int openDatabase(
+@@ -3201,6 +3201,14 @@ static int openDatabase(
}
#endif
diff --git a/chromium/third_party/sqlite/patches/0004-Custom-shell.c-helpers-to-load-Chromium-s-ICU-data.patch b/chromium/third_party/sqlite/patches/0004-Custom-shell.c-helpers-to-load-Chromium-s-ICU-data.patch
index 04ef5a0b918..932b65a109b 100644
--- a/chromium/third_party/sqlite/patches/0004-Custom-shell.c-helpers-to-load-Chromium-s-ICU-data.patch
+++ b/chromium/third_party/sqlite/patches/0004-Custom-shell.c-helpers-to-load-Chromium-s-ICU-data.patch
@@ -1,7 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: "tc@google.com" <tc@google.com>
Date: Tue, 6 Jan 2009 22:39:41 +0000
-Subject: [PATCH 04/10] Custom shell.c helpers to load Chromium's ICU data.
+Subject: [PATCH 4/6] Custom shell.c helpers to load Chromium's ICU data.
History uses fts3 with an icu-based segmenter. These changes allow building a
sqlite3 binary for Linux or Windows which can read those files.
@@ -36,10 +36,10 @@ index 62d029430803..a37d41a0099d 100644
# Nothing for unix.
#
diff --git a/third_party/sqlite/src/main.mk b/third_party/sqlite/src/main.mk
-index f44fab7f777d..8992aadf9373 100644
+index 9b50874926dc..40ab267ec72c 100644
--- a/third_party/sqlite/src/main.mk
+++ b/third_party/sqlite/src/main.mk
-@@ -546,7 +546,7 @@ libsqlite3.a: $(LIBOBJ)
+@@ -549,7 +549,7 @@ libsqlite3.a: $(LIBOBJ)
sqlite3$(EXE): shell.c libsqlite3.a sqlite3.h
$(TCCX) $(READLINE_FLAGS) -o sqlite3$(EXE) $(SHELL_OPT) \
@@ -49,10 +49,10 @@ index f44fab7f777d..8992aadf9373 100644
sqldiff$(EXE): $(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h
$(TCCX) -o sqldiff$(EXE) -DSQLITE_THREADSAFE=0 \
diff --git a/third_party/sqlite/src/src/shell.c.in b/third_party/sqlite/src/src/shell.c.in
-index 5cc06e4ec63c..28d3d82a4203 100644
+index 0007d984d045..b13551dc61f2 100644
--- a/third_party/sqlite/src/src/shell.c.in
+++ b/third_party/sqlite/src/src/shell.c.in
-@@ -8438,6 +8438,16 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
+@@ -8555,6 +8555,16 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
}
#endif
diff --git a/chromium/third_party/sqlite/patches/0004-fts3-Disable-fts3_tokenizer-and-fts4.patch b/chromium/third_party/sqlite/patches/0004-fts3-Disable-fts3_tokenizer-and-fts4.patch
new file mode 100644
index 00000000000..13001c4210b
--- /dev/null
+++ b/chromium/third_party/sqlite/patches/0004-fts3-Disable-fts3_tokenizer-and-fts4.patch
@@ -0,0 +1,60 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Scott Hess <shess@chromium.org>
+Date: Tue, 16 Dec 2014 13:02:27 -0800
+Subject: [PATCH 04/17] [fts3] Disable fts3_tokenizer and fts4.
+
+fts3_tokenizer allows a SQLite user to specify a pointer to call as a
+function, which has obvious sercurity implications. Disable fts4 until
+someone explicitly decides to own support for it. Disable fts3tokenize
+virtual table until someone explicitly decides to own support for it.
+
+No original review URL because this was part of the initial Chromium commit.
+---
+ third_party/sqlite/src/ext/fts3/fts3.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/third_party/sqlite/src/ext/fts3/fts3.c b/third_party/sqlite/src/ext/fts3/fts3.c
+index 44d9e20cc667..ef69a7b18681 100644
+--- a/third_party/sqlite/src/ext/fts3/fts3.c
++++ b/third_party/sqlite/src/ext/fts3/fts3.c
+@@ -287,6 +287,7 @@
+ ** query logic likewise merges doclists so that newer data knocks out
+ ** older data.
+ */
++#define CHROMIUM_FTS3_CHANGES 1
+
+ #include "fts3Int.h"
+ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
+@@ -3988,7 +3989,11 @@ int sqlite3Fts3Init(sqlite3 *db){
+ ** module with sqlite.
+ */
+ if( SQLITE_OK==rc
++#if CHROMIUM_FTS3_CHANGES && !SQLITE_TEST
++ /* fts3_tokenizer() disabled for security reasons. */
++#else
+ && SQLITE_OK==(rc = sqlite3Fts3InitHashTable(db, pHash, "fts3_tokenizer"))
++#endif
+ && SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1))
+ && SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", 1))
+ && SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", 1))
+@@ -3998,6 +4003,9 @@ int sqlite3Fts3Init(sqlite3 *db){
+ rc = sqlite3_create_module_v2(
+ db, "fts3", &fts3Module, (void *)pHash, hashDestroy
+ );
++#if CHROMIUM_FTS3_CHANGES && !SQLITE_TEST
++ /* Disable fts4 and tokenizer vtab pending review. */
++#else
+ if( rc==SQLITE_OK ){
+ rc = sqlite3_create_module_v2(
+ db, "fts4", &fts3Module, (void *)pHash, 0
+@@ -4006,6 +4014,7 @@ int sqlite3Fts3Init(sqlite3 *db){
+ if( rc==SQLITE_OK ){
+ rc = sqlite3Fts3InitTok(db, (void *)pHash);
+ }
++#endif
+ return rc;
+ }
+
+--
+2.18.0
+
diff --git a/chromium/third_party/sqlite/patches/0005-fts3-Disable-fts3_tokenizer-and-fts4.patch b/chromium/third_party/sqlite/patches/0005-fts3-Disable-fts3_tokenizer-and-fts4.patch
index 33480e3e56a..922a41fd0fc 100644
--- a/chromium/third_party/sqlite/patches/0005-fts3-Disable-fts3_tokenizer-and-fts4.patch
+++ b/chromium/third_party/sqlite/patches/0005-fts3-Disable-fts3_tokenizer-and-fts4.patch
@@ -1,7 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Scott Hess <shess@chromium.org>
Date: Tue, 16 Dec 2014 13:02:27 -0800
-Subject: [PATCH 05/10] [fts3] Disable fts3_tokenizer and fts4.
+Subject: [PATCH 5/6] [fts3] Disable fts3_tokenizer and fts4.
fts3_tokenizer allows a SQLite user to specify a pointer to call as a
function, which has obvious sercurity implications. Disable fts4 until
@@ -14,7 +14,7 @@ No original review URL because this was part of the initial Chromium commit.
1 file changed, 9 insertions(+)
diff --git a/third_party/sqlite/src/ext/fts3/fts3.c b/third_party/sqlite/src/ext/fts3/fts3.c
-index e8c6a0090216..fd6d58c69b7d 100644
+index 44d9e20cc667..ef69a7b18681 100644
--- a/third_party/sqlite/src/ext/fts3/fts3.c
+++ b/third_party/sqlite/src/ext/fts3/fts3.c
@@ -287,6 +287,7 @@
@@ -25,7 +25,7 @@ index e8c6a0090216..fd6d58c69b7d 100644
#include "fts3Int.h"
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
-@@ -3972,7 +3973,11 @@ int sqlite3Fts3Init(sqlite3 *db){
+@@ -3988,7 +3989,11 @@ int sqlite3Fts3Init(sqlite3 *db){
** module with sqlite.
*/
if( SQLITE_OK==rc
@@ -37,7 +37,7 @@ index e8c6a0090216..fd6d58c69b7d 100644
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1))
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", 1))
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", 1))
-@@ -3982,6 +3987,9 @@ int sqlite3Fts3Init(sqlite3 *db){
+@@ -3998,6 +4003,9 @@ int sqlite3Fts3Init(sqlite3 *db){
rc = sqlite3_create_module_v2(
db, "fts3", &fts3Module, (void *)pHash, hashDestroy
);
@@ -47,7 +47,7 @@ index e8c6a0090216..fd6d58c69b7d 100644
if( rc==SQLITE_OK ){
rc = sqlite3_create_module_v2(
db, "fts4", &fts3Module, (void *)pHash, 0
-@@ -3990,6 +3998,7 @@ int sqlite3Fts3Init(sqlite3 *db){
+@@ -4006,6 +4014,7 @@ int sqlite3Fts3Init(sqlite3 *db){
if( rc==SQLITE_OK ){
rc = sqlite3Fts3InitTok(db, (void *)pHash);
}
diff --git a/chromium/third_party/sqlite/patches/0005-fuchsia-Use-dot-file-locking-for-sqlite.patch b/chromium/third_party/sqlite/patches/0005-fuchsia-Use-dot-file-locking-for-sqlite.patch
new file mode 100644
index 00000000000..defb867ea9a
--- /dev/null
+++ b/chromium/third_party/sqlite/patches/0005-fuchsia-Use-dot-file-locking-for-sqlite.patch
@@ -0,0 +1,27 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Scott Graham <scottmg@chromium.org>
+Date: Mon, 11 Sep 2017 13:37:46 -0700
+Subject: [PATCH 05/17] fuchsia: Use dot-file locking for sqlite
+
+---
+ third_party/sqlite/src/src/os_unix.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/third_party/sqlite/src/src/os_unix.c b/third_party/sqlite/src/src/os_unix.c
+index d0e1c39bc4b8..d0736e0a63de 100644
+--- a/third_party/sqlite/src/src/os_unix.c
++++ b/third_party/sqlite/src/src/os_unix.c
+@@ -7873,6 +7873,10 @@ int sqlite3_os_init(void){
+ UNIXVFS("unix", autolockIoFinder ),
+ #elif OS_VXWORKS
+ UNIXVFS("unix", vxworksIoFinder ),
++#elif __Fuchsia__
++ /* None of the system calls for other exclusion methods are currently
++ ** implemented on Fuchsia, so use simple dot-file locking for now. */
++ UNIXVFS("unix", dotlockIoFinder ),
+ #else
+ UNIXVFS("unix", posixIoFinder ),
+ #endif
+--
+2.18.0
+
diff --git a/chromium/third_party/sqlite/patches/0006-Fix-dbfuzz2-for-Clusterfuzz.patch b/chromium/third_party/sqlite/patches/0006-Fix-dbfuzz2-for-Clusterfuzz.patch
new file mode 100644
index 00000000000..a6ec51f7e2b
--- /dev/null
+++ b/chromium/third_party/sqlite/patches/0006-Fix-dbfuzz2-for-Clusterfuzz.patch
@@ -0,0 +1,25 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Matthew Denton <mpdenton@chromium.org>
+Date: Fri, 7 Dec 2018 14:49:36 -0700
+Subject: [PATCH 06/17] Fix dbfuzz2 for Clusterfuzz.
+
+This backports https://www.sqlite.org/src/info/9ad796a8822f1b7e
+---
+ third_party/sqlite/src/test/dbfuzz2.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/third_party/sqlite/src/test/dbfuzz2.c b/third_party/sqlite/src/test/dbfuzz2.c
+index 0833f0386884..9e3aca25274b 100644
+--- a/third_party/sqlite/src/test/dbfuzz2.c
++++ b/third_party/sqlite/src/test/dbfuzz2.c
+@@ -78,6 +78,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *aData, size_t nByte){
+ printf("************** nByte=%d ***************\n", (int)nByte);
+ fflush(stdout);
+ }
++ if( sqlite3_initialize() ) return 0;
+ rc = sqlite3_open(0, &db);
+ if( rc ) return 1;
+ a = sqlite3_malloc64(nByte+1);
+--
+2.18.0
+
diff --git a/chromium/third_party/sqlite/patches/0006-fts3-Fix-uninit-variable-in-fts3EvalDeferredPhrase.patch b/chromium/third_party/sqlite/patches/0006-fts3-Fix-uninit-variable-in-fts3EvalDeferredPhrase.patch
deleted file mode 100644
index 1c529d61ebb..00000000000
--- a/chromium/third_party/sqlite/patches/0006-fts3-Fix-uninit-variable-in-fts3EvalDeferredPhrase.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Scott Hess <shess@chromium.org>
-Date: Thu, 12 Feb 2015 15:01:26 -0800
-Subject: [PATCH 06/10] [fts3] Fix uninit variable in fts3EvalDeferredPhrase.
-
-Chromium compiles with SQLITE_DISABLE_FTS4_DEFERRED since fts4 is
-disabled. That compiles away sqlite3Fts3DeferredTokenList() which
-otherwise initialized pList and nList in fts3EvalDeferredPhrase().
-
-BUG=458266
-R=thakis@chromium.org
----
- third_party/sqlite/src/ext/fts3/fts3Int.h | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/third_party/sqlite/src/ext/fts3/fts3Int.h b/third_party/sqlite/src/ext/fts3/fts3Int.h
-index 3c6501cea432..24c0f2940f33 100644
---- a/third_party/sqlite/src/ext/fts3/fts3Int.h
-+++ b/third_party/sqlite/src/ext/fts3/fts3Int.h
-@@ -487,7 +487,7 @@ int sqlite3Fts3DeferredTokenList(Fts3DeferredToken *, char **, int *);
- # define sqlite3Fts3DeferToken(x,y,z) SQLITE_OK
- # define sqlite3Fts3CacheDeferredDoclists(x) SQLITE_OK
- # define sqlite3Fts3FreeDeferredDoclists(x)
--# define sqlite3Fts3DeferredTokenList(x,y,z) SQLITE_OK
-+# define sqlite3Fts3DeferredTokenList(x,y,z) ((*(y)=0),(*(z)=0),SQLITE_OK)
- #endif
-
- void sqlite3Fts3SegmentsClose(Fts3Table *);
---
-2.18.0
-
diff --git a/chromium/third_party/sqlite/patches/0006-fuchsia-Use-dot-file-locking-for-sqlite.patch b/chromium/third_party/sqlite/patches/0006-fuchsia-Use-dot-file-locking-for-sqlite.patch
new file mode 100644
index 00000000000..c8aa08dec5d
--- /dev/null
+++ b/chromium/third_party/sqlite/patches/0006-fuchsia-Use-dot-file-locking-for-sqlite.patch
@@ -0,0 +1,27 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Scott Graham <scottmg@chromium.org>
+Date: Mon, 11 Sep 2017 13:37:46 -0700
+Subject: [PATCH 6/6] fuchsia: Use dot-file locking for sqlite
+
+---
+ third_party/sqlite/src/src/os_unix.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/third_party/sqlite/src/src/os_unix.c b/third_party/sqlite/src/src/os_unix.c
+index d0e1c39bc4b8..d0736e0a63de 100644
+--- a/third_party/sqlite/src/src/os_unix.c
++++ b/third_party/sqlite/src/src/os_unix.c
+@@ -7873,6 +7873,10 @@ int sqlite3_os_init(void){
+ UNIXVFS("unix", autolockIoFinder ),
+ #elif OS_VXWORKS
+ UNIXVFS("unix", vxworksIoFinder ),
++#elif __Fuchsia__
++ /* None of the system calls for other exclusion methods are currently
++ ** implemented on Fuchsia, so use simple dot-file locking for now. */
++ UNIXVFS("unix", dotlockIoFinder ),
+ #else
+ UNIXVFS("unix", posixIoFinder ),
+ #endif
+--
+2.18.0
+
diff --git a/chromium/third_party/sqlite/patches/0007-Fix-the-Makefile-so-that-it-honors-CFLAGS-when-build.patch b/chromium/third_party/sqlite/patches/0007-Fix-the-Makefile-so-that-it-honors-CFLAGS-when-build.patch
new file mode 100644
index 00000000000..a20f7d621fb
--- /dev/null
+++ b/chromium/third_party/sqlite/patches/0007-Fix-the-Makefile-so-that-it-honors-CFLAGS-when-build.patch
@@ -0,0 +1,27 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Victor Costan <pwnall@chromium.org>
+Date: Wed, 19 Dec 2018 18:22:15 -0800
+Subject: [PATCH 07/17] Fix the Makefile so that it honors CFLAGS when building
+ sessionfuzz.
+
+This backports https://www.sqlite.org/src/info/54231ac4ca506e6c
+---
+ third_party/sqlite/src/Makefile.in | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/third_party/sqlite/src/Makefile.in b/third_party/sqlite/src/Makefile.in
+index d2f97100597b..3b05f1e25ca7 100644
+--- a/third_party/sqlite/src/Makefile.in
++++ b/third_party/sqlite/src/Makefile.in
+@@ -669,7 +669,7 @@ ossshell$(TEXE): $(TOP)/test/ossfuzz.c $(TOP)/test/ossshell.c sqlite3.c sqlite3.
+ $(TOP)/test/ossfuzz.c sqlite3.c $(TLIBS)
+
+ sessionfuzz$(TEXE): $(TOP)/test/sessionfuzz.c sqlite3.c sqlite3.h
+- $(CC) $(CFLAGS) -I. -o $@ $(TOP)/test/sessionfuzz.c $(TLIBS)
++ $(LTLINK) -o $@ $(TOP)/test/sessionfuzz.c $(TLIBS)
+
+ dbfuzz$(TEXE): $(TOP)/test/dbfuzz.c sqlite3.c sqlite3.h
+ $(LTLINK) -o $@ $(DBFUZZ_OPT) $(TOP)/test/dbfuzz.c sqlite3.c $(TLIBS)
+--
+2.18.0
+
diff --git a/chromium/third_party/sqlite/patches/0008-Adjustments-to-the-page-cache-to-try-to-avoid-harmle.patch b/chromium/third_party/sqlite/patches/0008-Adjustments-to-the-page-cache-to-try-to-avoid-harmle.patch
new file mode 100644
index 00000000000..8960fc9c0dd
--- /dev/null
+++ b/chromium/third_party/sqlite/patches/0008-Adjustments-to-the-page-cache-to-try-to-avoid-harmle.patch
@@ -0,0 +1,38 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Victor Costan <pwnall@chromium.org>
+Date: Fri, 11 Jan 2019 02:01:53 -0800
+Subject: [PATCH 08/17] Adjustments to the page cache to try to avoid harmless
+ TSAN warnings
+
+This backports https://www.sqlite.org/src/info/383437be276719ac
+
+Bug: 917380
+---
+ third_party/sqlite/src/src/pcache1.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/third_party/sqlite/src/src/pcache1.c b/third_party/sqlite/src/src/pcache1.c
+index 59c1869ff707..1986b22ca61c 100644
+--- a/third_party/sqlite/src/src/pcache1.c
++++ b/third_party/sqlite/src/src/pcache1.c
+@@ -167,6 +167,7 @@ struct PCache1 {
+ unsigned int nMax; /* Configured "cache_size" value */
+ unsigned int n90pct; /* nMax*9/10 */
+ unsigned int iMaxKey; /* Largest key seen since xTruncate() */
++ unsigned int nPurgeableDummy; /* pnPurgeable points here when not used*/
+
+ /* Hash table of all pages. The following variables may only be accessed
+ ** when the accessor is holding the PGroup mutex.
+@@ -780,8 +781,7 @@ static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){
+ pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
+ pCache->pnPurgeable = &pGroup->nPurgeable;
+ }else{
+- static unsigned int dummyCurrentPage;
+- pCache->pnPurgeable = &dummyCurrentPage;
++ pCache->pnPurgeable = &pCache->nPurgeableDummy;
+ }
+ pcache1LeaveMutex(pGroup);
+ if( pCache->nHash==0 ){
+--
+2.18.0
+
diff --git a/chromium/third_party/sqlite/patches/0009-Remove-an-ALWAYS-from-a-branch-that-is-not-always-ta.patch b/chromium/third_party/sqlite/patches/0009-Remove-an-ALWAYS-from-a-branch-that-is-not-always-ta.patch
new file mode 100644
index 00000000000..10a26d255c4
--- /dev/null
+++ b/chromium/third_party/sqlite/patches/0009-Remove-an-ALWAYS-from-a-branch-that-is-not-always-ta.patch
@@ -0,0 +1,29 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Victor Costan <pwnall@chromium.org>
+Date: Fri, 11 Jan 2019 02:26:10 -0800
+Subject: [PATCH 09/17] Remove an ALWAYS() from a branch that is not always
+ taken.
+
+This backports https://www.sqlite.org/src/info/5c7dab
+
+Bug: 918035
+---
+ third_party/sqlite/src/src/expr.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/third_party/sqlite/src/src/expr.c b/third_party/sqlite/src/src/expr.c
+index 4aff7f67c9b6..6b2c5a540a82 100644
+--- a/third_party/sqlite/src/src/expr.c
++++ b/third_party/sqlite/src/src/expr.c
+@@ -4755,7 +4755,7 @@ int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){
+ }
+ }
+ if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
+- if( ALWAYS((combinedFlags & EP_TokenOnly)==0) ){
++ if( (combinedFlags & EP_TokenOnly)==0 ){
+ if( combinedFlags & EP_xIsSelect ) return 2;
+ if( (combinedFlags & EP_FixedCol)==0
+ && sqlite3ExprCompare(pParse, pA->pLeft, pB->pLeft, iTab) ) return 2;
+--
+2.18.0
+
diff --git a/chromium/third_party/sqlite/patches/0010-Fix-a-problem-with-nested-CTEs-with-the-same-table.patch b/chromium/third_party/sqlite/patches/0010-Fix-a-problem-with-nested-CTEs-with-the-same-table.patch
new file mode 100644
index 00000000000..7277ec29a90
--- /dev/null
+++ b/chromium/third_party/sqlite/patches/0010-Fix-a-problem-with-nested-CTEs-with-the-same-table.patch
@@ -0,0 +1,42 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Victor Costan <pwnall@chromium.org>
+Date: Fri, 11 Jan 2019 02:30:28 -0800
+Subject: [PATCH 10/17] Fix a problem with nested CTEs with the same table.
+
+This backports https://www.sqlite.org/src/info/202dd033019dd274
+
+Bug: 917834
+---
+ third_party/sqlite/src/src/select.c | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/third_party/sqlite/src/src/select.c b/third_party/sqlite/src/src/select.c
+index 870c3b5c1739..fab4df68fa17 100644
+--- a/third_party/sqlite/src/src/select.c
++++ b/third_party/sqlite/src/src/select.c
+@@ -5464,14 +5464,19 @@ static struct SrcList_item *isSelfJoinView(
+ ){
+ struct SrcList_item *pItem;
+ for(pItem = pTabList->a; pItem<pThis; pItem++){
++ Select *pS1;
+ if( pItem->pSelect==0 ) continue;
+ if( pItem->fg.viaCoroutine ) continue;
+ if( pItem->zName==0 ) continue;
+ if( sqlite3_stricmp(pItem->zDatabase, pThis->zDatabase)!=0 ) continue;
+ if( sqlite3_stricmp(pItem->zName, pThis->zName)!=0 ) continue;
+- if( sqlite3ExprCompare(0,
+- pThis->pSelect->pWhere, pItem->pSelect->pWhere, -1)
+- ){
++ pS1 = pItem->pSelect;
++ if( pThis->pSelect->selId!=pS1->selId ){
++ /* The query flattener left two different CTE tables with identical
++ ** names in the same FROM clause. */
++ continue;
++ }
++ if( sqlite3ExprCompare(0, pThis->pSelect->pWhere, pS1->pWhere, -1) ){
+ /* The view was modified by some other optimization such as
+ ** pushDownWhereTerms() */
+ continue;
+--
+2.18.0
+
diff --git a/chromium/third_party/sqlite/patches/0011-Fix-detection-of-self-referencing-rows-in-foreign-ke.patch b/chromium/third_party/sqlite/patches/0011-Fix-detection-of-self-referencing-rows-in-foreign-ke.patch
new file mode 100644
index 00000000000..8c1148a1c12
--- /dev/null
+++ b/chromium/third_party/sqlite/patches/0011-Fix-detection-of-self-referencing-rows-in-foreign-ke.patch
@@ -0,0 +1,50 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Victor Costan <pwnall@chromium.org>
+Date: Fri, 11 Jan 2019 03:45:18 -0800
+Subject: [PATCH 11/17] Fix detection of self-referencing rows in foreign key
+ processing.
+
+This backports https://www.sqlite.org/src/info/16fff05347f42fe9
+
+Bug: 916478
+---
+ third_party/sqlite/src/src/fkey.c | 13 ++++++++-----
+ 1 file changed, 8 insertions(+), 5 deletions(-)
+
+diff --git a/third_party/sqlite/src/src/fkey.c b/third_party/sqlite/src/src/fkey.c
+index 71e55adaf8ab..b9aad0c96588 100644
+--- a/third_party/sqlite/src/src/fkey.c
++++ b/third_party/sqlite/src/src/fkey.c
+@@ -602,8 +602,11 @@ static void fkScanChildren(
+ ** NOT( $current_a==a AND $current_b==b AND ... )
+ **
+ ** The first form is used for rowid tables. The second form is used
+- ** for WITHOUT ROWID tables. In the second form, the primary key is
+- ** (a,b,...)
++ ** for WITHOUT ROWID tables. In the second form, the *parent* key is
++ ** (a,b,...). Either the parent or primary key could be used to
++ ** uniquely identify the current row, but the parent key is more convenient
++ ** as the required values have already been loaded into registers
++ ** by the caller.
+ */
+ if( pTab==pFKey->pFrom && nIncr>0 ){
+ Expr *pNe; /* Expression (pLeft != pRight) */
+@@ -617,12 +620,12 @@ static void fkScanChildren(
+ Expr *pEq, *pAll = 0;
+ Index *pPk = sqlite3PrimaryKeyIndex(pTab);
+ assert( pIdx!=0 );
+- for(i=0; i<pPk->nKeyCol; i++){
++ for(i=0; i<pIdx->nKeyCol; i++){
+ i16 iCol = pIdx->aiColumn[i];
+ assert( iCol>=0 );
+ pLeft = exprTableRegister(pParse, pTab, regData, iCol);
+- pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, iCol);
+- pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight);
++ pRight = sqlite3Expr(db, TK_ID, pTab->aCol[iCol].zName);
++ pEq = sqlite3PExpr(pParse, TK_IS, pLeft, pRight);
+ pAll = sqlite3ExprAnd(db, pAll, pEq);
+ }
+ pNe = sqlite3PExpr(pParse, TK_NOT, pAll, 0);
+--
+2.18.0
+
diff --git a/chromium/third_party/sqlite/patches/0012-Fix-a-segfault-caused-by-using-the-RAISE-function-in.patch b/chromium/third_party/sqlite/patches/0012-Fix-a-segfault-caused-by-using-the-RAISE-function-in.patch
new file mode 100644
index 00000000000..ec396585010
--- /dev/null
+++ b/chromium/third_party/sqlite/patches/0012-Fix-a-segfault-caused-by-using-the-RAISE-function-in.patch
@@ -0,0 +1,29 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Victor Costan <pwnall@chromium.org>
+Date: Fri, 11 Jan 2019 03:52:20 -0800
+Subject: [PATCH 12/17] Fix a segfault caused by using the RAISE function
+ incorrectly.
+
+This backports https://sqlite.org/src/info/ddf06db702761d66
+
+Bug: 915479
+---
+ third_party/sqlite/src/src/expr.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/third_party/sqlite/src/src/expr.c b/third_party/sqlite/src/src/expr.c
+index 6b2c5a540a82..0aa11c43bf4a 100644
+--- a/third_party/sqlite/src/src/expr.c
++++ b/third_party/sqlite/src/src/expr.c
+@@ -4722,7 +4722,7 @@ int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){
+ }
+ return 2;
+ }
+- if( pA->op!=pB->op ){
++ if( pA->op!=pB->op || pA->op==TK_RAISE ){
+ if( pA->op==TK_COLLATE && sqlite3ExprCompare(pParse, pA->pLeft,pB,iTab)<2 ){
+ return 1;
+ }
+--
+2.18.0
+
diff --git a/chromium/third_party/sqlite/patches/0013-Fix-for-an-assert-that-could-be-false.patch b/chromium/third_party/sqlite/patches/0013-Fix-for-an-assert-that-could-be-false.patch
new file mode 100644
index 00000000000..38703cc1004
--- /dev/null
+++ b/chromium/third_party/sqlite/patches/0013-Fix-for-an-assert-that-could-be-false.patch
@@ -0,0 +1,33 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Victor Costan <pwnall@chromium.org>
+Date: Fri, 11 Jan 2019 04:18:45 -0800
+Subject: [PATCH 13/17] Fix for an assert() that could be false.
+
+This backports https://www.sqlite.org/src/info/23b62fb160d86dc9 /
+https://www.sqlite.org/src/info/bc891ac6b62fe7d9
+
+Bug: 911255
+---
+ third_party/sqlite/src/src/expr.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/third_party/sqlite/src/src/expr.c b/third_party/sqlite/src/src/expr.c
+index 0aa11c43bf4a..05c9521b2030 100644
+--- a/third_party/sqlite/src/src/expr.c
++++ b/third_party/sqlite/src/src/expr.c
+@@ -4761,8 +4761,10 @@ int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){
+ && sqlite3ExprCompare(pParse, pA->pLeft, pB->pLeft, iTab) ) return 2;
+ if( sqlite3ExprCompare(pParse, pA->pRight, pB->pRight, iTab) ) return 2;
+ if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2;
+- assert( (combinedFlags & EP_Reduced)==0 );
+- if( pA->op!=TK_STRING && pA->op!=TK_TRUEFALSE ){
++ if( pA->op!=TK_STRING
++ && pA->op!=TK_TRUEFALSE
++ && (combinedFlags & EP_Reduced)==0
++ ){
+ if( pA->iColumn!=pB->iColumn ) return 2;
+ if( pA->iTable!=pB->iTable
+ && (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2;
+--
+2.18.0
+
diff --git a/chromium/third_party/sqlite/patches/0014-Fix-another-problem-found-by-Matthew-Denton-s-new-fu.patch b/chromium/third_party/sqlite/patches/0014-Fix-another-problem-found-by-Matthew-Denton-s-new-fu.patch
new file mode 100644
index 00000000000..47238268504
--- /dev/null
+++ b/chromium/third_party/sqlite/patches/0014-Fix-another-problem-found-by-Matthew-Denton-s-new-fu.patch
@@ -0,0 +1,40 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Victor Costan <pwnall@chromium.org>
+Date: Fri, 11 Jan 2019 04:21:21 -0800
+Subject: [PATCH 14/17] Fix another problem found by Matthew Denton's new
+ fuzzer.
+
+This backports https://sqlite.org/src/info/2b690dbdffe144bd
+
+Bug: 911253
+---
+ third_party/sqlite/src/src/expr.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/third_party/sqlite/src/src/expr.c b/third_party/sqlite/src/src/expr.c
+index 05c9521b2030..c61528288baf 100644
+--- a/third_party/sqlite/src/src/expr.c
++++ b/third_party/sqlite/src/src/expr.c
+@@ -141,8 +141,8 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
+ while( p ){
+ int op = p->op;
+ if( p->flags & EP_Generic ) break;
+- if( (op==TK_AGG_COLUMN || op==TK_COLUMN
+- || op==TK_REGISTER || op==TK_TRIGGER)
++ if( op==TK_REGISTER ) op = p->op2;
++ if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_TRIGGER)
+ && p->y.pTab!=0
+ ){
+ /* op==TK_REGISTER && p->y.pTab!=0 happens when pExpr was originally
+@@ -158,7 +158,7 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
+ p = p->pLeft;
+ continue;
+ }
+- if( op==TK_COLLATE || (op==TK_REGISTER && p->op2==TK_COLLATE) ){
++ if( op==TK_COLLATE ){
+ pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
+ break;
+ }
+--
+2.18.0
+
diff --git a/chromium/third_party/sqlite/patches/0015-Report-a-new-corruption-case.patch b/chromium/third_party/sqlite/patches/0015-Report-a-new-corruption-case.patch
new file mode 100644
index 00000000000..bdc0f68cb8b
--- /dev/null
+++ b/chromium/third_party/sqlite/patches/0015-Report-a-new-corruption-case.patch
@@ -0,0 +1,47 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Victor Costan <pwnall@chromium.org>
+Date: Fri, 11 Jan 2019 12:15:27 -0800
+Subject: [PATCH 15/17] Report a new corruption case.
+
+This backports https://sqlite.org/src/info/cc42dd15100db28a
+
+Bug: 917285
+---
+ third_party/sqlite/src/src/btree.c | 7 +++++++
+ third_party/sqlite/src/test/fuzzcheck.c | 2 +-
+ 2 files changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/third_party/sqlite/src/src/btree.c b/third_party/sqlite/src/src/btree.c
+index 7a8de2d78c6a..6b17bdee5c4f 100644
+--- a/third_party/sqlite/src/src/btree.c
++++ b/third_party/sqlite/src/src/btree.c
+@@ -992,6 +992,13 @@ static void ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent, int *pRC){
+ *pRC = rc;
+ return;
+ }
++ if( ((char*)sqlite3PagerGetExtra(pDbPage))[0]!=0 ){
++ /* The first byte of the extra data is the MemPage.isInit byte.
++ ** If that byte is set, it means this page is also being used
++ ** as a btree page. */
++ *pRC = SQLITE_CORRUPT_BKPT;
++ goto ptrmap_exit;
++ }
+ offset = PTRMAP_PTROFFSET(iPtrmap, key);
+ if( offset<0 ){
+ *pRC = SQLITE_CORRUPT_BKPT;
+diff --git a/third_party/sqlite/src/test/fuzzcheck.c b/third_party/sqlite/src/test/fuzzcheck.c
+index 61925fcbe435..7ed17ae8a7d1 100644
+--- a/third_party/sqlite/src/test/fuzzcheck.c
++++ b/third_party/sqlite/src/test/fuzzcheck.c
+@@ -447,7 +447,7 @@ static int inmemRead(
+ if( iOfst+iAmt>pVFile->sz ){
+ memset(pData, 0, iAmt);
+ iAmt = (int)(pVFile->sz - iOfst);
+- memcpy(pData, pVFile->a, iAmt);
++ memcpy(pData, pVFile->a + iOfst, iAmt);
+ return SQLITE_IOERR_SHORT_READ;
+ }
+ memcpy(pData, pVFile->a + iOfst, iAmt);
+--
+2.18.0
+
diff --git a/chromium/third_party/sqlite/patches/0016-Avoid-a-buffer-overread-in-ptrmapPutOvflPtr.patch b/chromium/third_party/sqlite/patches/0016-Avoid-a-buffer-overread-in-ptrmapPutOvflPtr.patch
new file mode 100644
index 00000000000..19d46bd276d
--- /dev/null
+++ b/chromium/third_party/sqlite/patches/0016-Avoid-a-buffer-overread-in-ptrmapPutOvflPtr.patch
@@ -0,0 +1,33 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Victor Costan <pwnall@chromium.org>
+Date: Fri, 11 Jan 2019 12:19:01 -0800
+Subject: [PATCH 16/17] Avoid a buffer overread in ptrmapPutOvflPtr().
+
+This backports https://sqlite.org/src/info/f8b781cf41800e9f
+
+Bug: 914407
+---
+ third_party/sqlite/src/src/btree.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/third_party/sqlite/src/src/btree.c b/third_party/sqlite/src/src/btree.c
+index 6b17bdee5c4f..14af51e15ab2 100644
+--- a/third_party/sqlite/src/src/btree.c
++++ b/third_party/sqlite/src/src/btree.c
+@@ -1364,7 +1364,12 @@ static void ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell, int *pRC){
+ assert( pCell!=0 );
+ pPage->xParseCell(pPage, pCell, &info);
+ if( info.nLocal<info.nPayload ){
+- Pgno ovfl = get4byte(&pCell[info.nSize-4]);
++ Pgno ovfl;
++ if( SQLITE_WITHIN(pPage->aDataEnd, pCell, pCell+info.nLocal) ){
++ *pRC = SQLITE_CORRUPT_BKPT;
++ return;
++ }
++ ovfl = get4byte(&pCell[info.nSize-4]);
+ ptrmapPut(pPage->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno, pRC);
+ }
+ }
+--
+2.18.0
+
diff --git a/chromium/third_party/sqlite/patches/0017-Improved-detection-of-cell-corruption-in-sqlite3Vdbe.patch b/chromium/third_party/sqlite/patches/0017-Improved-detection-of-cell-corruption-in-sqlite3Vdbe.patch
new file mode 100644
index 00000000000..5d0877f09a3
--- /dev/null
+++ b/chromium/third_party/sqlite/patches/0017-Improved-detection-of-cell-corruption-in-sqlite3Vdbe.patch
@@ -0,0 +1,35 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Victor Costan <pwnall@chromium.org>
+Date: Fri, 11 Jan 2019 13:22:44 -0800
+Subject: [PATCH 17/17] Improved detection of cell corruption in
+ sqlite3VdbeRecordCompareWithSkip().
+
+This backports https://www.sqlite.org/src/info/fa47f4c6589c431c
+
+Bug: 915348
+---
+ third_party/sqlite/src/src/vdbeaux.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/third_party/sqlite/src/src/vdbeaux.c b/third_party/sqlite/src/src/vdbeaux.c
+index ebcb652bad20..15a095ff6e7b 100644
+--- a/third_party/sqlite/src/src/vdbeaux.c
++++ b/third_party/sqlite/src/src/vdbeaux.c
+@@ -4167,12 +4167,12 @@ int sqlite3VdbeRecordCompareWithSkip(
+ }else{
+ idx1 = getVarint32(aKey1, szHdr1);
+ d1 = szHdr1;
++ i = 0;
++ }
+ if( d1>(unsigned)nKey1 ){
+ pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
+ return 0; /* Corruption */
+ }
+- i = 0;
+- }
+
+ VVA_ONLY( mem1.szMalloc = 0; ) /* Only needed by assert() statements */
+ assert( pPKey2->pKeyInfo->nAllField>=pPKey2->nField
+--
+2.18.0
+
diff --git a/chromium/third_party/sqlite/sqlite3.h b/chromium/third_party/sqlite/sqlite3.h
index 059bbf76ba3..a1b69691fd2 100644
--- a/chromium/third_party/sqlite/sqlite3.h
+++ b/chromium/third_party/sqlite/sqlite3.h
@@ -13,6 +13,31 @@
// using the component build, where our SQLite's symbols are visible to the
// dynamic library loader.
#include "third_party/sqlite/amalgamation/rename_exports.h"
+
+#if defined(SQLITE_OMIT_COMPLETE)
+// When SQLITE_OMIT_COMPLETE is defined, sqlite3.h does not emit a declaration
+// for sqlite3_complete(). SQLite's shell.c stubs out the function by #defining
+// a macro.
+//
+// In order to avoid a macro redefinition warning, we must undo the #define in
+// rename_exports.h.
+//
+// Historical note: SQLite's shell.c initially did not support building against
+// a libary with SQLITE_OMIT_COMPLETE at all. The first attempt at adding
+// support was https://www.sqlite.org/src/info/c3e816cca4ddf096 which defined
+// sqlite_complete() as a stub function in shell.c. This worked on UNIX systems,
+// but caused a compilation error on Windows, where sqlite3.h declares
+// sqlite3_complete() as a __declspec(dllimport). The Windows build error was
+// fixed in https://www.sqlite.org/src/info/d584a0cb51281594 at our request.
+// While the current approach of using a macro requires the workaround here, it
+// is preferable to the previous version, which did not build at all on Windows.
+#if defined(sqlite3_complete)
+#undef sqlite3_complete
+#else
+#error "This workaround is no longer needed."
+#endif // !defined(sqlite3_complete)
+#endif // defined(SQLITE_OMIT_COMPLETE)
+
#include "third_party/sqlite/amalgamation/sqlite3.h"
#endif // THIRD_PARTY_SQLITE_SQLITE3_H_
diff --git a/chromium/third_party/sqlite/src/Makefile.in b/chromium/third_party/sqlite/src/Makefile.in
index 2d9d28aff33..3b05f1e25ca 100644
--- a/chromium/third_party/sqlite/src/Makefile.in
+++ b/chromium/third_party/sqlite/src/Makefile.in
@@ -32,6 +32,7 @@ CC = @CC@
CFLAGS = @CPPFLAGS@ @CFLAGS@
TCC = ${CC} ${CFLAGS} -I. -I${TOP}/src -I${TOP}/ext/rtree -I${TOP}/ext/icu
TCC += -I${TOP}/ext/fts3 -I${TOP}/ext/async -I${TOP}/ext/session
+TCC += -I${TOP}/ext/userauth
# Define this for the autoconf-based build, so that the code knows it can
# include the generated config.h
@@ -187,7 +188,7 @@ LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \
random.lo resolve.lo rowset.lo rtree.lo \
sqlite3session.lo select.lo sqlite3rbu.lo status.lo stmt.lo \
table.lo threads.lo tokenize.lo treeview.lo trigger.lo \
- update.lo upsert.lo util.lo vacuum.lo \
+ update.lo userauth.lo upsert.lo util.lo vacuum.lo \
vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \
vdbetrace.lo wal.lo walker.lo where.lo wherecode.lo whereexpr.lo \
window.lo utf.lo vtab.lo
@@ -356,6 +357,9 @@ SRC += \
$(TOP)/ext/session/sqlite3session.c \
$(TOP)/ext/session/sqlite3session.h
SRC += \
+ $(TOP)/ext/userauth/userauth.c \
+ $(TOP)/ext/userauth/sqlite3userauth.h
+SRC += \
$(TOP)/ext/rbu/sqlite3rbu.h \
$(TOP)/ext/rbu/sqlite3rbu.c
SRC += \
@@ -437,6 +441,7 @@ TESTSRC += \
$(TOP)/ext/misc/closure.c \
$(TOP)/ext/misc/csv.c \
$(TOP)/ext/misc/eval.c \
+ $(TOP)/ext/misc/explain.c \
$(TOP)/ext/misc/fileio.c \
$(TOP)/ext/misc/fuzzer.c \
$(TOP)/ext/fts5/fts5_tcl.c \
@@ -454,7 +459,8 @@ TESTSRC += \
$(TOP)/ext/misc/totype.c \
$(TOP)/ext/misc/unionvtab.c \
$(TOP)/ext/misc/wholenumber.c \
- $(TOP)/ext/misc/zipfile.c
+ $(TOP)/ext/misc/zipfile.c \
+ $(TOP)/ext/userauth/userauth.c
# Source code to the library files needed by the test fixture
#
@@ -470,6 +476,7 @@ TESTSRC2 = \
$(TOP)/src/dbstat.c \
$(TOP)/src/expr.c \
$(TOP)/src/func.c \
+ $(TOP)/src/global.c \
$(TOP)/src/insert.c \
$(TOP)/src/wal.c \
$(TOP)/src/main.c \
@@ -559,6 +566,8 @@ EXTHDR += \
$(TOP)/ext/icu/sqliteicu.h
EXTHDR += \
$(TOP)/ext/rtree/sqlite3rtree.h
+EXTHDR += \
+ $(TOP)/ext/userauth/sqlite3userauth.h
# executables needed for testing
#
@@ -578,7 +587,8 @@ FUZZDATA = \
$(TOP)/test/fuzzdata3.db \
$(TOP)/test/fuzzdata4.db \
$(TOP)/test/fuzzdata5.db \
- $(TOP)/test/fuzzdata6.db
+ $(TOP)/test/fuzzdata6.db \
+ $(TOP)/test/fuzzdata7.db
# Standard options to testfixture
#
@@ -595,6 +605,7 @@ SHELL_OPT += -DSQLITE_ENABLE_STMTVTAB
SHELL_OPT += -DSQLITE_ENABLE_DBPAGE_VTAB
SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC
+SHELL_OPT += -DSQLITE_ENABLE_DESERIALIZE
SHELL_OPT += -DSQLITE_INTROSPECTION_PRAGMAS
FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ
@@ -658,11 +669,27 @@ ossshell$(TEXE): $(TOP)/test/ossfuzz.c $(TOP)/test/ossshell.c sqlite3.c sqlite3.
$(TOP)/test/ossfuzz.c sqlite3.c $(TLIBS)
sessionfuzz$(TEXE): $(TOP)/test/sessionfuzz.c sqlite3.c sqlite3.h
- $(CC) $(CFLAGS) -I. -o $@ $(TOP)/test/sessionfuzz.c $(TLIBS)
+ $(LTLINK) -o $@ $(TOP)/test/sessionfuzz.c $(TLIBS)
dbfuzz$(TEXE): $(TOP)/test/dbfuzz.c sqlite3.c sqlite3.h
$(LTLINK) -o $@ $(DBFUZZ_OPT) $(TOP)/test/dbfuzz.c sqlite3.c $(TLIBS)
+DBFUZZ2_OPTS = \
+ -DSQLITE_THREADSAFE=0 \
+ -DSQLITE_OMIT_LOAD_EXTENSION \
+ -DSQLITE_ENABLE_DESERIALIZE \
+ -DSQLITE_DEBUG \
+ -DSQLITE_ENABLE_DBSTAT_VTAB \
+ -DSQLITE_ENABLE_RTREE \
+ -DSQLITE_ENABLE_FTS4 \
+ -DSQLITE_EANBLE_FTS5
+
+dbfuzz2: $(TOP)/test/dbfuzz2.c sqlite3.c sqlite3.h
+ clang-6.0 -I. -g -O0 -fsanitize=fuzzer,undefined,address -o dbfuzz2 \
+ $(DBFUZZ2_OPTS) $(TOP)/test/dbfuzz2.c sqlite3.c
+ mkdir -p dbfuzz2-dir
+ cp $(TOP)/test/dbfuzz2-seed* dbfuzz2-dir
+
mptester$(TEXE): sqlite3.lo $(TOP)/mptest/mptest.c
$(LTLINK) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.lo \
$(TLIBS) -rpath "$(libdir)"
@@ -1098,7 +1125,10 @@ fts3_write.lo: $(TOP)/ext/fts3/fts3_write.c $(HDR) $(EXTHDR)
rtree.lo: $(TOP)/ext/rtree/rtree.c $(HDR) $(EXTHDR)
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/rtree/rtree.c
-sqlite3session.lo: $(TOP)/ext/session/sqlite3session.c $(HDR) $(EXTHDR)
+sqlite3session.lo: $(TOP)/ext/userauth/userauth.c $(HDR) $(EXTHDR)
+ $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/userauth/userauth.c
+
+userauth.lo: $(TOP)/ext/session/sqlite3session.c $(HDR) $(EXTHDR)
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/session/sqlite3session.c
json1.lo: $(TOP)/ext/misc/json1.c
@@ -1169,6 +1199,10 @@ testfixture$(TEXE): $(TESTFIXTURE_SRC)
$(LTLINK) -DSQLITE_NO_SYNC=1 $(TEMP_STORE) $(TESTFIXTURE_FLAGS) \
-o $@ $(TESTFIXTURE_SRC) $(LIBTCL) $(TLIBS)
+coretestprogs: $(TESTPROGS)
+
+testprogs: coretestprogs srcck1$(BEXE) fuzzcheck$(TEXE) sessionfuzz$(TEXE)
+
# A very detailed test running most or all test cases
fulltest: $(TESTPROGS) fuzztest
./testfixture$(TEXE) $(TOP)/test/all.test $(TESTOPTS)
@@ -1275,6 +1309,9 @@ showshm$(TEXE): $(TOP)/tool/showshm.c
changeset$(TEXE): $(TOP)/ext/session/changeset.c sqlite3.lo
$(LTLINK) -o $@ $(TOP)/ext/session/changeset.c sqlite3.lo $(TLIBS)
+changesetfuzz$(TEXE): $(TOP)/ext/session/changesetfuzz.c sqlite3.lo
+ $(LTLINK) -o $@ $(TOP)/ext/session/changesetfuzz.c sqlite3.lo $(TLIBS)
+
rollback-test$(TEXE): $(TOP)/tool/rollback-test.c sqlite3.lo
$(LTLINK) -o $@ $(TOP)/tool/rollback-test.c sqlite3.lo $(TLIBS)
diff --git a/chromium/third_party/sqlite/src/Makefile.msc b/chromium/third_party/sqlite/src/Makefile.msc
index 4c6cdfba1d2..e3feffab357 100644
--- a/chromium/third_party/sqlite/src/Makefile.msc
+++ b/chromium/third_party/sqlite/src/Makefile.msc
@@ -345,6 +345,7 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBSTAT_VTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_INTROSPECTION_PRAGMAS=1
+OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DESERIALIZE=1
!ENDIF
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
!ENDIF
@@ -1515,6 +1516,7 @@ TESTEXT = \
$(TOP)\ext\misc\closure.c \
$(TOP)\ext\misc\csv.c \
$(TOP)\ext\misc\eval.c \
+ $(TOP)\ext\misc\explain.c \
$(TOP)\ext\misc\fileio.c \
$(TOP)\ext\misc\fuzzer.c \
$(TOP)\ext\fts5\fts5_tcl.c \
@@ -1622,7 +1624,8 @@ FUZZDATA = \
$(TOP)\test\fuzzdata3.db \
$(TOP)\test\fuzzdata4.db \
$(TOP)\test\fuzzdata5.db \
- $(TOP)\test\fuzzdata6.db
+ $(TOP)\test\fuzzdata6.db \
+ $(TOP)\test\fuzzdata7.db
# <</mark>>
# Additional compiler options for the shell. These are only effective
@@ -1632,6 +1635,7 @@ FUZZDATA = \
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_FTS4=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC=1
+SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DESERIALIZE=1
!ENDIF
# <<mark>>
@@ -2334,6 +2338,10 @@ extensiontest: testfixture.exe testloadext.dll
@set PATH=$(LIBTCLPATH);$(PATH)
.\testfixture.exe $(TOP)\test\loadext.test $(TESTOPTS)
+coretestprogs: $(TESTPROGS)
+
+testprogs: coretestprogs srcck1.exe fuzzcheck.exe sessionfuzz.exe
+
fulltest: $(TESTPROGS) fuzztest
@set PATH=$(LIBTCLPATH);$(PATH)
.\testfixture.exe $(TOP)\test\all.test $(TESTOPTS)
@@ -2441,6 +2449,11 @@ changeset.exe: $(TOP)\ext\session\changeset.c $(SQLITE3C) $(SQLITE3H)
-DSQLITE_ENABLE_SESSION=1 -DSQLITE_ENABLE_PREUPDATE_HOOK=1 \
$(TOP)\ext\session\changeset.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
+changesetfuzz.exe: $(TOP)\ext\session\changesetfuzz.c $(SQLITE3C) $(SQLITE3H)
+ $(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
+ -DSQLITE_ENABLE_SESSION=1 -DSQLITE_ENABLE_PREUPDATE_HOOK=1 \
+ $(TOP)\ext\session\changesetfuzz.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
+
fts3view.exe: $(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
$(TOP)\ext\fts3\tool\fts3view.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
diff --git a/chromium/third_party/sqlite/src/VERSION b/chromium/third_party/sqlite/src/VERSION
index 703e89e7169..419ede3b9cb 100644
--- a/chromium/third_party/sqlite/src/VERSION
+++ b/chromium/third_party/sqlite/src/VERSION
@@ -1 +1 @@
-3.25.3
+3.26.0
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/configure b/chromium/third_party/sqlite/src/configure
index 6dde7464042..51653aa5994 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.25.3.
+# Generated by GNU Autoconf 2.69 for sqlite 3.26.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.25.3'
-PACKAGE_STRING='sqlite 3.25.3'
+PACKAGE_VERSION='3.26.0'
+PACKAGE_STRING='sqlite 3.26.0'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -1466,7 +1466,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures sqlite 3.25.3 to adapt to many kinds of systems.
+\`configure' configures sqlite 3.26.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1531,7 +1531,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of sqlite 3.25.3:";;
+ short | recursive ) echo "Configuration of sqlite 3.26.0:";;
esac
cat <<\_ACEOF
@@ -1657,7 +1657,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-sqlite configure 3.25.3
+sqlite configure 3.26.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2076,7 +2076,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by sqlite $as_me 3.25.3, which was
+It was created by sqlite $as_me 3.26.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -12232,7 +12232,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by sqlite $as_me 3.25.3, which was
+This file was extended by sqlite $as_me 3.26.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -12298,7 +12298,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-sqlite config.status 3.25.3
+sqlite config.status 3.26.0
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/chromium/third_party/sqlite/src/doc/F2FS.txt b/chromium/third_party/sqlite/src/doc/F2FS.txt
new file mode 100644
index 00000000000..066056b4b48
--- /dev/null
+++ b/chromium/third_party/sqlite/src/doc/F2FS.txt
@@ -0,0 +1,87 @@
+
+SQLite's OS layer contains the following definitions used in F2FS related
+calls:
+
+#define F2FS_IOCTL_MAGIC 0xf5
+#define F2FS_IOC_START_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 1)
+#define F2FS_IOC_COMMIT_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 2)
+#define F2FS_IOC_START_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 3)
+#define F2FS_IOC_ABORT_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 5)
+#define F2FS_IOC_GET_FEATURES _IOR(F2FS_IOCTL_MAGIC, 12, u32)
+#define F2FS_FEATURE_ATOMIC_WRITE 0x0004
+
+After opening a database file on Linux (including Android), SQLite determines
+whether or not a file supports F2FS atomic commits as follows:
+
+ u32 flags = 0;
+ rc = ioctl(fd, F2FS_IOC_GET_FEATURES, &flags);
+ if( rc==0 && (flags & F2FS_FEATURE_ATOMIC_WRITE) ){
+ /* File supports F2FS atomic commits */
+ }else{
+ /* File does NOT support F2FS atomic commits */
+ }
+
+where "fd" is the file-descriptor open on the database file.
+
+Usually, when writing to a database file that supports atomic commits, SQLite
+accumulates the entire transaction in heap memory, deferring all writes to the
+db file until the transaction is committed.
+
+When it is time to commit a transaction on a file that supports atomic
+commits, SQLite does:
+
+ /* Take an F_WRLCK lock on the database file. This prevents any other
+ ** SQLite clients from reading or writing the file until the lock
+ ** is released. */
+ rc = fcntl(fd, F_SETLK, ...);
+ if( rc!=0 ) goto failed;
+
+ rc = ioctl(fd, F2FS_IOC_START_ATOMIC_WRITE);
+ if( rc!=0 ) goto fallback_to_legacy_journal_commit;
+
+ foreach (dirty page){
+ rc = write(fd, ...dirty page...);
+ if( rc!=0 ){
+ ioctl(fd, F2FS_IOC_ABORT_VOLATILE_WRITE);
+ goto fallback_to_legacy_journal_commit;
+ }
+ }
+
+ rc = ioctl(fd, F2FS_IOC_COMMIT_ATOMIC_WRITE);
+ if( rc!=0 ){
+ ioctl(fd, F2FS_IOC_ABORT_VOLATILE_WRITE);
+ goto fallback_to_legacy_journal_commit;
+ }
+
+ /* If we get there, the transaction has been successfully
+ ** committed to persistent storage. The following call
+ ** relinquishes the F_WRLCK lock. */
+ fcntl(fd, F_SETLK, ...);
+
+Assumptions:
+
+1. After either of the F2FS_IOC_ABORT_VOLATILE_WRITE calls return,
+ the database file is in the state that it was in before
+ F2FS_IOC_START_ATOMIC_WRITE was invoked. Even if the ioctl()
+ fails - we're ignoring the return code.
+
+ This is true regardless of the type of error that occurred in
+ ioctl() or write().
+
+2. If the system fails before the F2FS_IOC_COMMIT_ATOMIC_WRITE is
+ completed, then following a reboot the database file is in the
+ state that it was in before F2FS_IOC_START_ATOMIC_WRITE was invoked.
+ Or, if the write was commited right before the system failed, in a
+ state indicating that all write() calls were successfully committed
+ to persistent storage before the failure occurred.
+
+3. If the process crashes before the F2FS_IOC_COMMIT_ATOMIC_WRITE is
+ completed then the file is automatically restored to the state that
+ it was in before F2FS_IOC_START_ATOMIC_WRITE was called. This occurs
+ before the posix advisory lock is automatically dropped - there is
+ no chance that another client will be able to read the file in a
+ half-committed state before the rollback operation occurs.
+
+
+
+
diff --git a/chromium/third_party/sqlite/src/doc/lemon.html b/chromium/third_party/sqlite/src/doc/lemon.html
index 98c816f1d18..3f51ba9ffb0 100644
--- a/chromium/third_party/sqlite/src/doc/lemon.html
+++ b/chromium/third_party/sqlite/src/doc/lemon.html
@@ -777,6 +777,9 @@ For example:</p>
<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>
+<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>
diff --git a/chromium/third_party/sqlite/src/ext/expert/sqlite3expert.c b/chromium/third_party/sqlite/src/ext/expert/sqlite3expert.c
index 68784493c07..b94182f895b 100644
--- a/chromium/third_party/sqlite/src/ext/expert/sqlite3expert.c
+++ b/chromium/third_party/sqlite/src/ext/expert/sqlite3expert.c
@@ -644,6 +644,7 @@ static int idxRegisterVtab(sqlite3expert *p){
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
+ 0, /* xShadowName */
};
return sqlite3_create_module(p->dbv, "expert", &expertModule, (void*)p);
diff --git a/chromium/third_party/sqlite/src/ext/fts3/fts3.c b/chromium/third_party/sqlite/src/ext/fts3/fts3.c
index fd6d58c69b7..ef69a7b1868 100644
--- a/chromium/third_party/sqlite/src/ext/fts3/fts3.c
+++ b/chromium/third_party/sqlite/src/ext/fts3/fts3.c
@@ -3847,8 +3847,23 @@ static int fts3RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){
return SQLITE_OK;
}
+/*
+** Return true if zName is the extension on one of the shadow tables used
+** by this module.
+*/
+static int fts3ShadowName(const char *zName){
+ static const char *azName[] = {
+ "content", "docsize", "segdir", "segments", "stat",
+ };
+ unsigned int i;
+ for(i=0; i<sizeof(azName)/sizeof(azName[0]); i++){
+ if( sqlite3_stricmp(zName, azName[i])==0 ) return 1;
+ }
+ return 0;
+}
+
static const sqlite3_module fts3Module = {
- /* iVersion */ 2,
+ /* iVersion */ 3,
/* xCreate */ fts3CreateMethod,
/* xConnect */ fts3ConnectMethod,
/* xBestIndex */ fts3BestIndexMethod,
@@ -3871,6 +3886,7 @@ static const sqlite3_module fts3Module = {
/* xSavepoint */ fts3SavepointMethod,
/* xRelease */ fts3ReleaseMethod,
/* xRollbackTo */ fts3RollbackToMethod,
+ /* xShadowName */ fts3ShadowName,
};
/*
@@ -4159,6 +4175,7 @@ static int fts3EvalPhraseLoad(
return rc;
}
+#ifndef SQLITE_DISABLE_FTS4_DEFERRED
/*
** This function is called on each phrase after the position lists for
** any deferred tokens have been loaded into memory. It updates the phrases
@@ -4262,6 +4279,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
return SQLITE_OK;
}
+#endif /* SQLITE_DISABLE_FTS4_DEFERRED */
/*
** Maximum number of tokens a phrase may have to be considered for the
diff --git a/chromium/third_party/sqlite/src/ext/fts3/fts3Int.h b/chromium/third_party/sqlite/src/ext/fts3/fts3Int.h
index 24c0f2940f3..3c6501cea43 100644
--- a/chromium/third_party/sqlite/src/ext/fts3/fts3Int.h
+++ b/chromium/third_party/sqlite/src/ext/fts3/fts3Int.h
@@ -487,7 +487,7 @@ int sqlite3Fts3DeferredTokenList(Fts3DeferredToken *, char **, int *);
# define sqlite3Fts3DeferToken(x,y,z) SQLITE_OK
# define sqlite3Fts3CacheDeferredDoclists(x) SQLITE_OK
# define sqlite3Fts3FreeDeferredDoclists(x)
-# define sqlite3Fts3DeferredTokenList(x,y,z) ((*(y)=0),(*(z)=0),SQLITE_OK)
+# define sqlite3Fts3DeferredTokenList(x,y,z) SQLITE_OK
#endif
void sqlite3Fts3SegmentsClose(Fts3Table *);
diff --git a/chromium/third_party/sqlite/src/ext/fts3/fts3_aux.c b/chromium/third_party/sqlite/src/ext/fts3/fts3_aux.c
index 258d3da698c..1ca830dd226 100644
--- a/chromium/third_party/sqlite/src/ext/fts3/fts3_aux.c
+++ b/chromium/third_party/sqlite/src/ext/fts3/fts3_aux.c
@@ -539,7 +539,8 @@ int sqlite3Fts3InitAux(sqlite3 *db){
0, /* xRename */
0, /* xSavepoint */
0, /* xRelease */
- 0 /* xRollbackTo */
+ 0, /* xRollbackTo */
+ 0 /* xShadowName */
};
int rc; /* Return code */
diff --git a/chromium/third_party/sqlite/src/ext/fts3/fts3_term.c b/chromium/third_party/sqlite/src/ext/fts3/fts3_term.c
index 644cfa803ba..4b2872fe99b 100644
--- a/chromium/third_party/sqlite/src/ext/fts3/fts3_term.c
+++ b/chromium/third_party/sqlite/src/ext/fts3/fts3_term.c
@@ -361,7 +361,8 @@ int sqlite3Fts3InitTerm(sqlite3 *db){
0, /* xRename */
0, /* xSavepoint */
0, /* xRelease */
- 0 /* xRollbackTo */
+ 0, /* xRollbackTo */
+ 0 /* xShadowName */
};
int rc; /* Return code */
diff --git a/chromium/third_party/sqlite/src/ext/fts3/fts3_tokenize_vtab.c b/chromium/third_party/sqlite/src/ext/fts3/fts3_tokenize_vtab.c
index 611c5eb29e1..87c5da3ce43 100644
--- a/chromium/third_party/sqlite/src/ext/fts3/fts3_tokenize_vtab.c
+++ b/chromium/third_party/sqlite/src/ext/fts3/fts3_tokenize_vtab.c
@@ -443,7 +443,8 @@ int sqlite3Fts3InitTok(sqlite3 *db, Fts3Hash *pHash){
0, /* xRename */
0, /* xSavepoint */
0, /* xRelease */
- 0 /* xRollbackTo */
+ 0, /* xRollbackTo */
+ 0 /* xShadowName */
};
int rc; /* Return code */
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 b970e2cc1a3..833b5e28364 100644
--- a/chromium/third_party/sqlite/src/ext/fts5/fts5_index.c
+++ b/chromium/third_party/sqlite/src/ext/fts5/fts5_index.c
@@ -5402,7 +5402,7 @@ int sqlite3Fts5IndexQuery(
fts5CloseReader(p);
}
- *ppIter = &pRet->base;
+ *ppIter = (Fts5IndexIter*)pRet;
sqlite3Fts5BufferFree(&buf);
}
return fts5IndexReturn(p);
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 aa4df702a16..9c10405c627 100644
--- a/chromium/third_party/sqlite/src/ext/fts5/fts5_main.c
+++ b/chromium/third_party/sqlite/src/ext/fts5/fts5_main.c
@@ -2645,9 +2645,24 @@ static void fts5SourceIdFunc(
sqlite3_result_text(pCtx, "--FTS5-SOURCE-ID--", -1, SQLITE_TRANSIENT);
}
+/*
+** Return true if zName is the extension on one of the shadow tables used
+** by this module.
+*/
+static int fts5ShadowName(const char *zName){
+ static const char *azName[] = {
+ "config", "content", "data", "docsize", "idx"
+ };
+ unsigned int i;
+ for(i=0; i<sizeof(azName)/sizeof(azName[0]); i++){
+ if( sqlite3_stricmp(zName, azName[i])==0 ) return 1;
+ }
+ return 0;
+}
+
static int fts5Init(sqlite3 *db){
static const sqlite3_module fts5Mod = {
- /* iVersion */ 2,
+ /* iVersion */ 3,
/* xCreate */ fts5CreateMethod,
/* xConnect */ fts5ConnectMethod,
/* xBestIndex */ fts5BestIndexMethod,
@@ -2670,6 +2685,7 @@ static int fts5Init(sqlite3 *db){
/* xSavepoint */ fts5SavepointMethod,
/* xRelease */ fts5ReleaseMethod,
/* xRollbackTo */ fts5RollbackToMethod,
+ /* xShadowName */ fts5ShadowName
};
int rc;
diff --git a/chromium/third_party/sqlite/src/ext/fts5/fts5_test_tok.c b/chromium/third_party/sqlite/src/ext/fts5/fts5_test_tok.c
index 2b7b3e284ce..7453638b317 100644
--- a/chromium/third_party/sqlite/src/ext/fts5/fts5_test_tok.c
+++ b/chromium/third_party/sqlite/src/ext/fts5/fts5_test_tok.c
@@ -471,7 +471,8 @@ int sqlite3Fts5TestRegisterTok(sqlite3 *db, fts5_api *pApi){
0, /* xRename */
0, /* xSavepoint */
0, /* xRelease */
- 0 /* xRollbackTo */
+ 0, /* xRollbackTo */
+ 0 /* xShadowName */
};
int rc; /* Return code */
diff --git a/chromium/third_party/sqlite/src/ext/fts5/fts5_vocab.c b/chromium/third_party/sqlite/src/ext/fts5/fts5_vocab.c
index 7ac56589e26..6820706fd8f 100644
--- a/chromium/third_party/sqlite/src/ext/fts5/fts5_vocab.c
+++ b/chromium/third_party/sqlite/src/ext/fts5/fts5_vocab.c
@@ -431,6 +431,8 @@ static int fts5VocabInstanceNext(Fts5VocabCursor *pCsr){
i64 *pp = &pCsr->iInstPos;
int *po = &pCsr->iInstOff;
+ assert( sqlite3Fts5IterEof(pIter)==0 );
+ assert( pCsr->bEof==0 );
while( eDetail==FTS5_DETAIL_NONE
|| sqlite3Fts5PoslistNext64(pIter->pData, pIter->nData, po, pp)
){
@@ -440,7 +442,7 @@ static int fts5VocabInstanceNext(Fts5VocabCursor *pCsr){
rc = sqlite3Fts5IterNextScan(pCsr->pIter);
if( rc==SQLITE_OK ){
rc = fts5VocabInstanceNewTerm(pCsr);
- if( eDetail==FTS5_DETAIL_NONE ) break;
+ if( pCsr->bEof || eDetail==FTS5_DETAIL_NONE ) break;
}
if( rc ){
pCsr->bEof = 1;
@@ -755,10 +757,9 @@ int sqlite3Fts5VocabInit(Fts5Global *pGlobal, sqlite3 *db){
/* xSavepoint */ 0,
/* xRelease */ 0,
/* xRollbackTo */ 0,
+ /* xShadowName */ 0
};
void *p = (void*)pGlobal;
return sqlite3_create_module_v2(db, "fts5vocab", &fts5Vocab, p, 0);
}
-
-
diff --git a/chromium/third_party/sqlite/src/ext/misc/amatch.c b/chromium/third_party/sqlite/src/ext/misc/amatch.c
index 6438028f3d4..519a5a0bf62 100644
--- a/chromium/third_party/sqlite/src/ext/misc/amatch.c
+++ b/chromium/third_party/sqlite/src/ext/misc/amatch.c
@@ -1473,7 +1473,8 @@ static sqlite3_module amatchModule = {
0, /* xRename */
0, /* xSavepoint */
0, /* xRelease */
- 0 /* xRollbackTo */
+ 0, /* xRollbackTo */
+ 0 /* xShadowName */
};
#endif /* SQLITE_OMIT_VIRTUALTABLE */
diff --git a/chromium/third_party/sqlite/src/ext/misc/btreeinfo.c b/chromium/third_party/sqlite/src/ext/misc/btreeinfo.c
index de0392bcbef..9b298a4b452 100644
--- a/chromium/third_party/sqlite/src/ext/misc/btreeinfo.c
+++ b/chromium/third_party/sqlite/src/ext/misc/btreeinfo.c
@@ -411,6 +411,7 @@ int sqlite3BinfoRegister(sqlite3 *db){
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
+ 0 /* xShadowName */
};
return sqlite3_create_module(db, "sqlite_btreeinfo", &binfo_module, 0);
}
diff --git a/chromium/third_party/sqlite/src/ext/misc/closure.c b/chromium/third_party/sqlite/src/ext/misc/closure.c
index 60c529384b7..bf1a8696fcb 100644
--- a/chromium/third_party/sqlite/src/ext/misc/closure.c
+++ b/chromium/third_party/sqlite/src/ext/misc/closure.c
@@ -938,7 +938,8 @@ static sqlite3_module closureModule = {
0, /* xRename */
0, /* xSavepoint */
0, /* xRelease */
- 0 /* xRollbackTo */
+ 0, /* xRollbackTo */
+ 0 /* xShadowName */
};
#endif /* SQLITE_OMIT_VIRTUALTABLE */
diff --git a/chromium/third_party/sqlite/src/ext/misc/completion.c b/chromium/third_party/sqlite/src/ext/misc/completion.c
index e6ce62d633c..363c1f30f38 100644
--- a/chromium/third_party/sqlite/src/ext/misc/completion.c
+++ b/chromium/third_party/sqlite/src/ext/misc/completion.c
@@ -468,7 +468,8 @@ static sqlite3_module completionModule = {
0, /* xRename */
0, /* xSavepoint */
0, /* xRelease */
- 0 /* xRollbackTo */
+ 0, /* xRollbackTo */
+ 0 /* xShadowName */
};
#endif /* SQLITE_OMIT_VIRTUALTABLE */
diff --git a/chromium/third_party/sqlite/src/ext/misc/csv.c b/chromium/third_party/sqlite/src/ext/misc/csv.c
index 55cc45a5d57..be58a3a9f8b 100644
--- a/chromium/third_party/sqlite/src/ext/misc/csv.c
+++ b/chromium/third_party/sqlite/src/ext/misc/csv.c
@@ -19,9 +19,9 @@
** CREATE VIRTUAL TABLE temp.csv USING csv(filename=FILENAME);
** SELECT * FROM csv;
**
-** The columns are named "c1", "c2", "c3", ... by default. But the
-** application can define its own CREATE TABLE statement as an additional
-** parameter. For example:
+** The columns are named "c1", "c2", "c3", ... by default. Or the
+** application can define its own CREATE TABLE statement using the
+** schema= parameter, like this:
**
** CREATE VIRTUAL TABLE temp.csv2 USING csv(
** filename = "../http.log",
@@ -32,9 +32,9 @@
** the data= parameter.
**
** If the columns=N parameter is supplied, then the CSV file is assumed to have
-** N columns. If the columns parameter is omitted, the CSV file is opened
-** as soon as the virtual table is constructed and the first row of the CSV
-** is read in order to count the tables.
+** N columns. If both the columns= and schema= parameters are omitted, then
+** the number and names of the columns is determined by the first line of
+** the CSV input.
**
** Some extra debugging features (used for testing virtual tables) are available
** if this module is compiled with -DSQLITE_TEST.
@@ -436,6 +436,34 @@ static int csv_boolean(const char *z){
return -1;
}
+/* Check to see if the string is of the form: "TAG = BOOLEAN" or just "TAG".
+** If it is, set *pValue to be the value of the boolean ("true" if there is
+** not "= BOOLEAN" component) and return non-zero. If the input string
+** does not begin with TAG, return zero.
+*/
+static int csv_boolean_parameter(
+ const char *zTag, /* Tag we are looking for */
+ int nTag, /* Size of the tag in bytes */
+ const char *z, /* Input parameter */
+ int *pValue /* Write boolean value here */
+){
+ int b;
+ z = csv_skip_whitespace(z);
+ if( strncmp(zTag, z, nTag)!=0 ) return 0;
+ z = csv_skip_whitespace(z + nTag);
+ if( z[0]==0 ){
+ *pValue = 1;
+ return 1;
+ }
+ if( z[0]!='=' ) return 0;
+ z = csv_skip_whitespace(z+1);
+ b = csv_boolean(z);
+ if( b>=0 ){
+ *pValue = b;
+ return 1;
+ }
+ return 0;
+}
/*
** Parameters:
@@ -469,6 +497,7 @@ static int csvtabConnect(
#ifdef SQLITE_TEST
int tstFlags = 0; /* Value for testflags=N parameter */
#endif
+ int b; /* Value of a boolean parameter */
int nCol = -99; /* Value of the columns= parameter */
CsvReader sRdr; /* A CSV file reader used to store an error
** message and/or to count the number of columns */
@@ -493,21 +522,12 @@ static int csvtabConnect(
if( j<sizeof(azParam)/sizeof(azParam[0]) ){
if( sRdr.zErr[0] ) goto csvtab_connect_error;
}else
- if( (zValue = csv_parameter("header",6,z))!=0 ){
- int x;
+ if( csv_boolean_parameter("header",6,z,&b) ){
if( bHeader>=0 ){
csv_errmsg(&sRdr, "more than one 'header' parameter");
goto csvtab_connect_error;
}
- x = csv_boolean(zValue);
- if( x==1 ){
- bHeader = 1;
- }else if( x==0 ){
- bHeader = 0;
- }else{
- csv_errmsg(&sRdr, "unrecognized argument to 'header': %s", zValue);
- goto csvtab_connect_error;
- }
+ bHeader = b;
}else
#ifdef SQLITE_TEST
if( (zValue = csv_parameter("testflags",9,z))!=0 ){
@@ -521,53 +541,94 @@ static int csvtabConnect(
}
nCol = atoi(zValue);
if( nCol<=0 ){
- csv_errmsg(&sRdr, "must have at least one column");
+ csv_errmsg(&sRdr, "column= value must be positive");
goto csvtab_connect_error;
}
}else
{
- csv_errmsg(&sRdr, "unrecognized parameter '%s'", z);
+ csv_errmsg(&sRdr, "bad parameter: '%s'", z);
goto csvtab_connect_error;
}
}
if( (CSV_FILENAME==0)==(CSV_DATA==0) ){
- csv_errmsg(&sRdr, "must either filename= or data= but not both");
+ csv_errmsg(&sRdr, "must specify either filename= or data= but not both");
goto csvtab_connect_error;
}
- if( nCol<=0 && csv_reader_open(&sRdr, CSV_FILENAME, CSV_DATA) ){
+
+ if( (nCol<=0 || bHeader==1)
+ && csv_reader_open(&sRdr, CSV_FILENAME, CSV_DATA)
+ ){
goto csvtab_connect_error;
}
pNew = sqlite3_malloc( sizeof(*pNew) );
*ppVtab = (sqlite3_vtab*)pNew;
if( pNew==0 ) goto csvtab_connect_oom;
memset(pNew, 0, sizeof(*pNew));
- if( nCol>0 ){
+ if( CSV_SCHEMA==0 ){
+ sqlite3_str *pStr = sqlite3_str_new(0);
+ char *zSep = "";
+ int iCol = 0;
+ sqlite3_str_appendf(pStr, "CREATE TABLE x(");
+ if( nCol<0 && bHeader<1 ){
+ nCol = 0;
+ do{
+ csv_read_one_field(&sRdr);
+ nCol++;
+ }while( sRdr.cTerm==',' );
+ }
+ if( nCol>0 && bHeader<1 ){
+ for(iCol=0; iCol<nCol; iCol++){
+ sqlite3_str_appendf(pStr, "%sc%d TEXT", zSep, iCol);
+ zSep = ",";
+ }
+ }else{
+ do{
+ char *z = csv_read_one_field(&sRdr);
+ if( (nCol>0 && iCol<nCol) || (nCol<0 && bHeader) ){
+ sqlite3_str_appendf(pStr,"%s\"%w\" TEXT", zSep, z);
+ zSep = ",";
+ iCol++;
+ }
+ }while( sRdr.cTerm==',' );
+ if( nCol<0 ){
+ nCol = iCol;
+ }else{
+ while( iCol<nCol ){
+ sqlite3_str_appendf(pStr,"%sc%d TEXT", zSep, ++iCol);
+ zSep = ",";
+ }
+ }
+ }
pNew->nCol = nCol;
- }else{
+ sqlite3_str_appendf(pStr, ")");
+ CSV_SCHEMA = sqlite3_str_finish(pStr);
+ if( CSV_SCHEMA==0 ) goto csvtab_connect_oom;
+ }else if( nCol<0 ){
do{
csv_read_one_field(&sRdr);
pNew->nCol++;
}while( sRdr.cTerm==',' );
+ }else{
+ pNew->nCol = nCol;
}
pNew->zFilename = CSV_FILENAME; CSV_FILENAME = 0;
pNew->zData = CSV_DATA; CSV_DATA = 0;
#ifdef SQLITE_TEST
pNew->tstFlags = tstFlags;
#endif
- pNew->iStart = bHeader==1 ? ftell(sRdr.in) : 0;
- csv_reader_reset(&sRdr);
- if( CSV_SCHEMA==0 ){
- char *zSep = "";
- CSV_SCHEMA = sqlite3_mprintf("CREATE TABLE x(");
- if( CSV_SCHEMA==0 ) goto csvtab_connect_oom;
- for(i=0; i<pNew->nCol; i++){
- CSV_SCHEMA = sqlite3_mprintf("%z%sc%d TEXT",CSV_SCHEMA, zSep, i);
- zSep = ",";
- }
- CSV_SCHEMA = sqlite3_mprintf("%z);", CSV_SCHEMA);
+ if( bHeader!=1 ){
+ pNew->iStart = 0;
+ }else if( pNew->zData ){
+ pNew->iStart = (int)sRdr.iIn;
+ }else{
+ pNew->iStart = ftell(sRdr.in);
}
+ csv_reader_reset(&sRdr);
rc = sqlite3_declare_vtab(db, CSV_SCHEMA);
- if( rc ) goto csvtab_connect_error;
+ if( rc ){
+ csv_errmsg(&sRdr, "bad schema: '%s' - %s", CSV_SCHEMA, sqlite3_errmsg(db));
+ goto csvtab_connect_error;
+ }
for(i=0; i<sizeof(azPValue)/sizeof(azPValue[0]); i++){
sqlite3_free(azPValue[i]);
}
diff --git a/chromium/third_party/sqlite/src/ext/misc/explain.c b/chromium/third_party/sqlite/src/ext/misc/explain.c
new file mode 100644
index 00000000000..917b3ad7fe6
--- /dev/null
+++ b/chromium/third_party/sqlite/src/ext/misc/explain.c
@@ -0,0 +1,322 @@
+/*
+** 2018-09-16
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file demonstrates an eponymous virtual table that returns the
+** EXPLAIN output from an SQL statement.
+**
+** Usage example:
+**
+** .load ./explain
+** SELECT p2 FROM explain('SELECT * FROM sqlite_master')
+** WHERE opcode='OpenRead';
+**
+** This module was originally written to help simplify SQLite testing,
+** by providing an easier means of verifying certain patterns in the
+** generated bytecode.
+*/
+#if !defined(SQLITEINT_H)
+#include "sqlite3ext.h"
+#endif
+SQLITE_EXTENSION_INIT1
+#include <assert.h>
+#include <string.h>
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+
+/* explain_vtab is a subclass of sqlite3_vtab which will
+** serve as the underlying representation of a explain virtual table
+*/
+typedef struct explain_vtab explain_vtab;
+struct explain_vtab {
+ sqlite3_vtab base; /* Base class - must be first */
+ sqlite3 *db; /* Database connection for this explain vtab */
+};
+
+/* explain_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 from an EXPLAIN operation.
+*/
+typedef struct explain_cursor explain_cursor;
+struct explain_cursor {
+ sqlite3_vtab_cursor base; /* Base class - must be first */
+ sqlite3 *db; /* Database connection for this cursor */
+ char *zSql; /* Value for the EXPLN_COLUMN_SQL column */
+ sqlite3_stmt *pExplain; /* Statement being explained */
+ int rc; /* Result of last sqlite3_step() on pExplain */
+};
+
+/*
+** The explainConnect() method is invoked to create a new
+** explain_vtab that describes the explain virtual table.
+**
+** Think of this routine as the constructor for explain_vtab objects.
+**
+** All this routine needs to do is:
+**
+** (1) Allocate the explain_vtab object and initialize all fields.
+**
+** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
+** result set of queries against explain will look like.
+*/
+static int explainConnect(
+ sqlite3 *db,
+ void *pAux,
+ int argc, const char *const*argv,
+ sqlite3_vtab **ppVtab,
+ char **pzErr
+){
+ explain_vtab *pNew;
+ int rc;
+
+/* Column numbers */
+#define EXPLN_COLUMN_ADDR 0 /* Instruction address */
+#define EXPLN_COLUMN_OPCODE 1 /* Opcode */
+#define EXPLN_COLUMN_P1 2 /* Operand 1 */
+#define EXPLN_COLUMN_P2 3 /* Operand 2 */
+#define EXPLN_COLUMN_P3 4 /* Operand 3 */
+#define EXPLN_COLUMN_P4 5 /* Operand 4 */
+#define EXPLN_COLUMN_P5 6 /* Operand 5 */
+#define EXPLN_COLUMN_COMMENT 7 /* Comment */
+#define EXPLN_COLUMN_SQL 8 /* SQL that is being explained */
+
+
+ rc = sqlite3_declare_vtab(db,
+ "CREATE TABLE x(addr,opcode,p1,p2,p3,p4,p5,comment,sql HIDDEN)");
+ if( rc==SQLITE_OK ){
+ pNew = sqlite3_malloc( sizeof(*pNew) );
+ *ppVtab = (sqlite3_vtab*)pNew;
+ if( pNew==0 ) return SQLITE_NOMEM;
+ memset(pNew, 0, sizeof(*pNew));
+ pNew->db = db;
+ }
+ return rc;
+}
+
+/*
+** This method is the destructor for explain_cursor objects.
+*/
+static int explainDisconnect(sqlite3_vtab *pVtab){
+ sqlite3_free(pVtab);
+ return SQLITE_OK;
+}
+
+/*
+** Constructor for a new explain_cursor object.
+*/
+static int explainOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
+ explain_cursor *pCur;
+ pCur = sqlite3_malloc( sizeof(*pCur) );
+ if( pCur==0 ) return SQLITE_NOMEM;
+ memset(pCur, 0, sizeof(*pCur));
+ pCur->db = ((explain_vtab*)p)->db;
+ *ppCursor = &pCur->base;
+ return SQLITE_OK;
+}
+
+/*
+** Destructor for a explain_cursor.
+*/
+static int explainClose(sqlite3_vtab_cursor *cur){
+ explain_cursor *pCur = (explain_cursor*)cur;
+ sqlite3_finalize(pCur->pExplain);
+ sqlite3_free(pCur->zSql);
+ sqlite3_free(pCur);
+ return SQLITE_OK;
+}
+
+
+/*
+** Advance a explain_cursor to its next row of output.
+*/
+static int explainNext(sqlite3_vtab_cursor *cur){
+ explain_cursor *pCur = (explain_cursor*)cur;
+ pCur->rc = sqlite3_step(pCur->pExplain);
+ if( pCur->rc!=SQLITE_DONE && pCur->rc!=SQLITE_ROW ) return pCur->rc;
+ return SQLITE_OK;
+}
+
+/*
+** Return values of columns for the row at which the explain_cursor
+** is currently pointing.
+*/
+static int explainColumn(
+ sqlite3_vtab_cursor *cur, /* The cursor */
+ sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
+ int i /* Which column to return */
+){
+ explain_cursor *pCur = (explain_cursor*)cur;
+ if( i==EXPLN_COLUMN_SQL ){
+ sqlite3_result_text(ctx, pCur->zSql, -1, SQLITE_TRANSIENT);
+ }else{
+ sqlite3_result_value(ctx, sqlite3_column_value(pCur->pExplain, i));
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Return the rowid for the current row. In this implementation, the
+** rowid is the same as the output value.
+*/
+static int explainRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
+ explain_cursor *pCur = (explain_cursor*)cur;
+ *pRowid = sqlite3_column_int64(pCur->pExplain, 0);
+ return SQLITE_OK;
+}
+
+/*
+** Return TRUE if the cursor has been moved off of the last
+** row of output.
+*/
+static int explainEof(sqlite3_vtab_cursor *cur){
+ explain_cursor *pCur = (explain_cursor*)cur;
+ return pCur->rc!=SQLITE_ROW;
+}
+
+/*
+** This method is called to "rewind" the explain_cursor object back
+** to the first row of output. This method is always called at least
+** once prior to any call to explainColumn() or explainRowid() or
+** explainEof().
+**
+** The argv[0] is the SQL statement that is to be explained.
+*/
+static int explainFilter(
+ sqlite3_vtab_cursor *pVtabCursor,
+ int idxNum, const char *idxStr,
+ int argc, sqlite3_value **argv
+){
+ explain_cursor *pCur = (explain_cursor *)pVtabCursor;
+ char *zSql = 0;
+ int rc;
+ sqlite3_finalize(pCur->pExplain);
+ pCur->pExplain = 0;
+ if( sqlite3_value_type(argv[0])!=SQLITE_TEXT ){
+ pCur->rc = SQLITE_DONE;
+ return SQLITE_OK;
+ }
+ sqlite3_free(pCur->zSql);
+ pCur->zSql = sqlite3_mprintf("%s", sqlite3_value_text(argv[0]));
+ if( pCur->zSql ){
+ zSql = sqlite3_mprintf("EXPLAIN %s", pCur->zSql);
+ }
+ if( zSql==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ rc = sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pExplain, 0);
+ sqlite3_free(zSql);
+ }
+ if( rc ){
+ sqlite3_finalize(pCur->pExplain);
+ pCur->pExplain = 0;
+ sqlite3_free(pCur->zSql);
+ pCur->zSql = 0;
+ }else{
+ pCur->rc = sqlite3_step(pCur->pExplain);
+ rc = (pCur->rc==SQLITE_DONE || pCur->rc==SQLITE_ROW) ? SQLITE_OK : pCur->rc;
+ }
+ return rc;
+}
+
+/*
+** SQLite will invoke this method one or more times while planning a query
+** that uses the explain virtual table. This routine needs to create
+** a query plan for each invocation and compute an estimated cost for that
+** plan.
+*/
+static int explainBestIndex(
+ sqlite3_vtab *tab,
+ sqlite3_index_info *pIdxInfo
+){
+ int i; /* Loop counter */
+ int idx = -1; /* Index of a usable == constraint against SQL */
+ int unusable = 0; /* True if there are unusable constraints on SQL */
+
+ pIdxInfo->estimatedRows = 500;
+ for(i=0; i<pIdxInfo->nConstraint; i++){
+ struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i];
+ if( p->iColumn!=EXPLN_COLUMN_SQL ) continue;
+ if( !p->usable ){
+ unusable = 1;
+ }else if( p->op==SQLITE_INDEX_CONSTRAINT_EQ ){
+ idx = i;
+ }
+ }
+ if( idx>=0 ){
+ /* There exists a usable == constraint against the SQL column */
+ pIdxInfo->estimatedCost = 10.0;
+ pIdxInfo->idxNum = 1;
+ pIdxInfo->aConstraintUsage[idx].argvIndex = 1;
+ pIdxInfo->aConstraintUsage[idx].omit = 1;
+ }else if( unusable ){
+ /* There are unusable constraints against the SQL column. Do not allow
+ ** this plan to continue forward. */
+ return SQLITE_CONSTRAINT;
+ }
+ return SQLITE_OK;
+}
+
+/*
+** This following structure defines all the methods for the
+** explain virtual table.
+*/
+static sqlite3_module explainModule = {
+ 0, /* iVersion */
+ 0, /* xCreate */
+ explainConnect, /* xConnect */
+ explainBestIndex, /* xBestIndex */
+ explainDisconnect, /* xDisconnect */
+ 0, /* xDestroy */
+ explainOpen, /* xOpen - open a cursor */
+ explainClose, /* xClose - close a cursor */
+ explainFilter, /* xFilter - configure scan constraints */
+ explainNext, /* xNext - advance a cursor */
+ explainEof, /* xEof - check for end of scan */
+ explainColumn, /* xColumn - read data */
+ explainRowid, /* 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 */
+
+int sqlite3ExplainVtabInit(sqlite3 *db){
+ int rc = SQLITE_OK;
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ rc = sqlite3_create_module(db, "explain", &explainModule, 0);
+#endif
+ return rc;
+}
+
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int sqlite3_explain_init(
+ sqlite3 *db,
+ char **pzErrMsg,
+ const sqlite3_api_routines *pApi
+){
+ int rc = SQLITE_OK;
+ SQLITE_EXTENSION_INIT2(pApi);
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ rc = sqlite3ExplainVtabInit(db);
+#endif
+ return rc;
+}
diff --git a/chromium/third_party/sqlite/src/ext/misc/fileio.c b/chromium/third_party/sqlite/src/ext/misc/fileio.c
index a4681270938..49f6f8aeb43 100644
--- a/chromium/third_party/sqlite/src/ext/misc/fileio.c
+++ b/chromium/third_party/sqlite/src/ext/misc/fileio.c
@@ -106,7 +106,18 @@ SQLITE_EXTENSION_INIT1
#include <errno.h>
+/*
+** Structure of the fsdir() table-valued function
+*/
+ /* 0 1 2 3 4 5 */
#define FSDIR_SCHEMA "(name,mode,mtime,data,path HIDDEN,dir HIDDEN)"
+#define FSDIR_COLUMN_NAME 0 /* Name of the file */
+#define FSDIR_COLUMN_MODE 1 /* Access mode */
+#define FSDIR_COLUMN_MTIME 2 /* Last modification time */
+#define FSDIR_COLUMN_DATA 3 /* File content */
+#define FSDIR_COLUMN_PATH 4 /* Path to top of search */
+#define FSDIR_COLUMN_DIR 5 /* Path is relative to this directory */
+
/*
** Set the result stored by context ctx to a blob containing the
@@ -695,20 +706,20 @@ static int fsdirColumn(
){
fsdir_cursor *pCur = (fsdir_cursor*)cur;
switch( i ){
- case 0: { /* name */
+ case FSDIR_COLUMN_NAME: {
sqlite3_result_text(ctx, &pCur->zPath[pCur->nBase], -1, SQLITE_TRANSIENT);
break;
}
- case 1: /* mode */
+ case FSDIR_COLUMN_MODE:
sqlite3_result_int64(ctx, pCur->sStat.st_mode);
break;
- case 2: /* mtime */
+ case FSDIR_COLUMN_MTIME:
sqlite3_result_int64(ctx, pCur->sStat.st_mtime);
break;
- case 3: { /* data */
+ case FSDIR_COLUMN_DATA: {
mode_t m = pCur->sStat.st_mode;
if( S_ISDIR(m) ){
sqlite3_result_null(ctx);
@@ -738,6 +749,12 @@ static int fsdirColumn(
readFileContents(ctx, pCur->zPath);
}
}
+ case FSDIR_COLUMN_PATH:
+ default: {
+ /* The FSDIR_COLUMN_PATH and FSDIR_COLUMN_DIR are input parameters.
+ ** always return their values as NULL */
+ break;
+ }
}
return SQLITE_OK;
}
@@ -764,6 +781,9 @@ static int fsdirEof(sqlite3_vtab_cursor *cur){
/*
** xFilter callback.
+**
+** idxNum==1 PATH parameter only
+** idxNum==2 Both PATH and DIR supplied
*/
static int fsdirFilter(
sqlite3_vtab_cursor *cur,
@@ -816,40 +836,63 @@ static int fsdirFilter(
** In this implementation idxNum is used to represent the
** query plan. idxStr is unused.
**
-** The query plan is represented by bits in idxNum:
+** The query plan is represented by values of idxNum:
**
-** (1) start = $value -- constraint exists
-** (2) stop = $value -- constraint exists
-** (4) step = $value -- constraint exists
-** (8) output in descending order
+** (1) The path value is supplied by argv[0]
+** (2) Path is in argv[0] and dir is in argv[1]
*/
static int fsdirBestIndex(
sqlite3_vtab *tab,
sqlite3_index_info *pIdxInfo
){
int i; /* Loop over constraints */
- int idx4 = -1;
- int idx5 = -1;
+ int idxPath = -1; /* Index in pIdxInfo->aConstraint of PATH= */
+ int idxDir = -1; /* Index in pIdxInfo->aConstraint of DIR= */
+ int seenPath = 0; /* True if an unusable PATH= constraint is seen */
+ int seenDir = 0; /* True if an unusable DIR= constraint is seen */
const struct sqlite3_index_constraint *pConstraint;
(void)tab;
pConstraint = pIdxInfo->aConstraint;
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
- if( pConstraint->usable==0 ) continue;
if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
- if( pConstraint->iColumn==4 ) idx4 = i;
- if( pConstraint->iColumn==5 ) idx5 = i;
+ switch( pConstraint->iColumn ){
+ case FSDIR_COLUMN_PATH: {
+ if( pConstraint->usable ){
+ idxPath = i;
+ seenPath = 0;
+ }else if( idxPath<0 ){
+ seenPath = 1;
+ }
+ break;
+ }
+ case FSDIR_COLUMN_DIR: {
+ if( pConstraint->usable ){
+ idxDir = i;
+ seenDir = 0;
+ }else if( idxDir<0 ){
+ seenDir = 1;
+ }
+ break;
+ }
+ }
+ }
+ if( seenPath || seenDir ){
+ /* If input parameters are unusable, disallow this plan */
+ return SQLITE_CONSTRAINT;
}
- if( idx4<0 ){
+ if( idxPath<0 ){
pIdxInfo->idxNum = 0;
- pIdxInfo->estimatedCost = (double)(((sqlite3_int64)1) << 50);
+ /* The pIdxInfo->estimatedCost should have been initialized to a huge
+ ** number. Leave it unchanged. */
+ pIdxInfo->estimatedRows = 0x7fffffff;
}else{
- pIdxInfo->aConstraintUsage[idx4].omit = 1;
- pIdxInfo->aConstraintUsage[idx4].argvIndex = 1;
- if( idx5>=0 ){
- pIdxInfo->aConstraintUsage[idx5].omit = 1;
- pIdxInfo->aConstraintUsage[idx5].argvIndex = 2;
+ pIdxInfo->aConstraintUsage[idxPath].omit = 1;
+ pIdxInfo->aConstraintUsage[idxPath].argvIndex = 1;
+ if( idxDir>=0 ){
+ pIdxInfo->aConstraintUsage[idxDir].omit = 1;
+ pIdxInfo->aConstraintUsage[idxDir].argvIndex = 2;
pIdxInfo->idxNum = 2;
pIdxInfo->estimatedCost = 10.0;
}else{
@@ -888,7 +931,8 @@ static int fsdirRegister(sqlite3 *db){
0, /* xRename */
0, /* xSavepoint */
0, /* xRelease */
- 0 /* xRollbackTo */
+ 0, /* xRollbackTo */
+ 0, /* xShadowName */
};
int rc = sqlite3_create_module(db, "fsdir", &fsdirModule, 0);
diff --git a/chromium/third_party/sqlite/src/ext/misc/json1.c b/chromium/third_party/sqlite/src/ext/misc/json1.c
index f3c3b1cf9d8..2a99e3b73b7 100644
--- a/chromium/third_party/sqlite/src/ext/misc/json1.c
+++ b/chromium/third_party/sqlite/src/ext/misc/json1.c
@@ -1994,6 +1994,9 @@ static int jsonEachConnect(
#define JEACH_PARENT 5
#define JEACH_FULLKEY 6
#define JEACH_PATH 7
+/* The xBestIndex method assumes that the JSON and ROOT columns are
+** the last two columns in the table. Should this ever changes, be
+** sure to update the xBestIndex method. */
#define JEACH_JSON 8
#define JEACH_ROOT 9
@@ -2251,35 +2254,54 @@ static int jsonEachBestIndex(
sqlite3_vtab *tab,
sqlite3_index_info *pIdxInfo
){
- int i;
- int jsonIdx = -1;
- int rootIdx = -1;
+ int i; /* Loop counter or computed array index */
+ int aIdx[2]; /* Index of constraints for JSON and ROOT */
+ int unusableMask = 0; /* Mask of unusable JSON and ROOT constraints */
+ int idxMask = 0; /* Mask of usable == constraints JSON and ROOT */
const struct sqlite3_index_constraint *pConstraint;
+ /* This implementation assumes that JSON and ROOT are the last two
+ ** columns in the table */
+ assert( JEACH_ROOT == JEACH_JSON+1 );
UNUSED_PARAM(tab);
+ aIdx[0] = aIdx[1] = -1;
pConstraint = pIdxInfo->aConstraint;
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
- if( pConstraint->usable==0 ) continue;
- if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
- switch( pConstraint->iColumn ){
- case JEACH_JSON: jsonIdx = i; break;
- case JEACH_ROOT: rootIdx = i; break;
- default: /* no-op */ break;
- }
- }
- if( jsonIdx<0 ){
+ int iCol;
+ int iMask;
+ if( pConstraint->iColumn < JEACH_JSON ) continue;
+ iCol = pConstraint->iColumn - JEACH_JSON;
+ assert( iCol==0 || iCol==1 );
+ iMask = 1 << iCol;
+ if( pConstraint->usable==0 ){
+ unusableMask |= iMask;
+ }else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
+ aIdx[iCol] = i;
+ idxMask |= iMask;
+ }
+ }
+ if( (unusableMask & ~idxMask)!=0 ){
+ /* If there are any unusable constraints on JSON or ROOT, then reject
+ ** this entire plan */
+ return SQLITE_CONSTRAINT;
+ }
+ if( aIdx[0]<0 ){
+ /* No JSON input. Leave estimatedCost at the huge value that it was
+ ** initialized to to discourage the query planner from selecting this
+ ** plan. */
pIdxInfo->idxNum = 0;
- pIdxInfo->estimatedCost = 1e99;
}else{
pIdxInfo->estimatedCost = 1.0;
- pIdxInfo->aConstraintUsage[jsonIdx].argvIndex = 1;
- pIdxInfo->aConstraintUsage[jsonIdx].omit = 1;
- if( rootIdx<0 ){
- pIdxInfo->idxNum = 1;
+ i = aIdx[0];
+ pIdxInfo->aConstraintUsage[i].argvIndex = 1;
+ pIdxInfo->aConstraintUsage[i].omit = 1;
+ if( aIdx[1]<0 ){
+ pIdxInfo->idxNum = 1; /* Only JSON supplied. Plan 1 */
}else{
- pIdxInfo->aConstraintUsage[rootIdx].argvIndex = 2;
- pIdxInfo->aConstraintUsage[rootIdx].omit = 1;
- pIdxInfo->idxNum = 3;
+ i = aIdx[1];
+ pIdxInfo->aConstraintUsage[i].argvIndex = 2;
+ pIdxInfo->aConstraintUsage[i].omit = 1;
+ pIdxInfo->idxNum = 3; /* Both JSON and ROOT are supplied. Plan 3 */
}
}
return SQLITE_OK;
@@ -2388,7 +2410,8 @@ static sqlite3_module jsonEachModule = {
0, /* xRename */
0, /* xSavepoint */
0, /* xRelease */
- 0 /* xRollbackTo */
+ 0, /* xRollbackTo */
+ 0 /* xShadowName */
};
/* The methods of the json_tree virtual table. */
@@ -2415,7 +2438,8 @@ static sqlite3_module jsonTreeModule = {
0, /* xRename */
0, /* xSavepoint */
0, /* xRelease */
- 0 /* xRollbackTo */
+ 0, /* xRollbackTo */
+ 0 /* xShadowName */
};
#endif /* SQLITE_OMIT_VIRTUALTABLE */
diff --git a/chromium/third_party/sqlite/src/ext/misc/memstat.c b/chromium/third_party/sqlite/src/ext/misc/memstat.c
new file mode 100644
index 00000000000..f072398d2f6
--- /dev/null
+++ b/chromium/third_party/sqlite/src/ext/misc/memstat.c
@@ -0,0 +1,428 @@
+/*
+** 2018-09-27
+**
+** 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 an eponymous virtual table that returns information
+** from sqlite3_status64() and sqlite3_db_status().
+**
+** Usage example:
+**
+** .load ./memstat
+** .mode quote
+** .header on
+** SELECT * FROM memstat;
+*/
+#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_MEMSTATVTAB)
+#if !defined(SQLITEINT_H)
+#include "sqlite3ext.h"
+#endif
+SQLITE_EXTENSION_INIT1
+#include <assert.h>
+#include <string.h>
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+
+/* memstat_vtab is a subclass of sqlite3_vtab which will
+** serve as the underlying representation of a memstat virtual table
+*/
+typedef struct memstat_vtab memstat_vtab;
+struct memstat_vtab {
+ sqlite3_vtab base; /* Base class - must be first */
+ sqlite3 *db; /* Database connection for this memstat vtab */
+};
+
+/* memstat_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 memstat_cursor memstat_cursor;
+struct memstat_cursor {
+ sqlite3_vtab_cursor base; /* Base class - must be first */
+ sqlite3 *db; /* Database connection for this cursor */
+ int iRowid; /* Current row in aMemstatColumn[] */
+ int iDb; /* Which schema we are looking at */
+ int nDb; /* Number of schemas */
+ char **azDb; /* Names of all schemas */
+ sqlite3_int64 aVal[2]; /* Result values */
+};
+
+/*
+** The memstatConnect() method is invoked to create a new
+** memstat_vtab that describes the memstat virtual table.
+**
+** Think of this routine as the constructor for memstat_vtab objects.
+**
+** All this routine needs to do is:
+**
+** (1) Allocate the memstat_vtab object and initialize all fields.
+**
+** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
+** result set of queries against memstat will look like.
+*/
+static int memstatConnect(
+ sqlite3 *db,
+ void *pAux,
+ int argc, const char *const*argv,
+ sqlite3_vtab **ppVtab,
+ char **pzErr
+){
+ memstat_vtab *pNew;
+ int rc;
+
+/* Column numbers */
+#define MSV_COLUMN_NAME 0 /* Name of quantity being measured */
+#define MSV_COLUMN_SCHEMA 1 /* schema name */
+#define MSV_COLUMN_VALUE 2 /* Current value */
+#define MSV_COLUMN_HIWTR 3 /* Highwater mark */
+
+ rc = sqlite3_declare_vtab(db,"CREATE TABLE x(name,schema,value,hiwtr)");
+ if( rc==SQLITE_OK ){
+ pNew = sqlite3_malloc( sizeof(*pNew) );
+ *ppVtab = (sqlite3_vtab*)pNew;
+ if( pNew==0 ) return SQLITE_NOMEM;
+ memset(pNew, 0, sizeof(*pNew));
+ pNew->db = db;
+ }
+ return rc;
+}
+
+/*
+** This method is the destructor for memstat_cursor objects.
+*/
+static int memstatDisconnect(sqlite3_vtab *pVtab){
+ sqlite3_free(pVtab);
+ return SQLITE_OK;
+}
+
+/*
+** Constructor for a new memstat_cursor object.
+*/
+static int memstatOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
+ memstat_cursor *pCur;
+ pCur = sqlite3_malloc( sizeof(*pCur) );
+ if( pCur==0 ) return SQLITE_NOMEM;
+ memset(pCur, 0, sizeof(*pCur));
+ pCur->db = ((memstat_vtab*)p)->db;
+ *ppCursor = &pCur->base;
+ return SQLITE_OK;
+}
+
+/*
+** Clear all the schema names from a cursor
+*/
+static void memstatClearSchema(memstat_cursor *pCur){
+ int i;
+ if( pCur->azDb==0 ) return;
+ for(i=0; i<pCur->nDb; i++){
+ sqlite3_free(pCur->azDb[i]);
+ }
+ sqlite3_free(pCur->azDb);
+ pCur->azDb = 0;
+ pCur->nDb = 0;
+}
+
+/*
+** Fill in the azDb[] array for the cursor.
+*/
+static int memstatFindSchemas(memstat_cursor *pCur){
+ sqlite3_stmt *pStmt = 0;
+ int rc;
+ if( pCur->nDb ) return SQLITE_OK;
+ rc = sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pStmt, 0);
+ if( rc ){
+ sqlite3_finalize(pStmt);
+ return rc;
+ }
+ while( sqlite3_step(pStmt)==SQLITE_ROW ){
+ char **az, *z;
+ az = sqlite3_realloc(pCur->azDb, sizeof(char*)*(pCur->nDb+1));
+ if( az==0 ){
+ memstatClearSchema(pCur);
+ return SQLITE_NOMEM;
+ }
+ pCur->azDb = az;
+ z = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
+ if( z==0 ){
+ memstatClearSchema(pCur);
+ return SQLITE_NOMEM;
+ }
+ pCur->azDb[pCur->nDb] = z;
+ pCur->nDb++;
+ }
+ sqlite3_finalize(pStmt);
+ return SQLITE_OK;
+}
+
+
+/*
+** Destructor for a memstat_cursor.
+*/
+static int memstatClose(sqlite3_vtab_cursor *cur){
+ memstat_cursor *pCur = (memstat_cursor*)cur;
+ memstatClearSchema(pCur);
+ sqlite3_free(cur);
+ return SQLITE_OK;
+}
+
+
+/*
+** Allowed values for aMemstatColumn[].eType
+*/
+#define MSV_GSTAT 0 /* sqlite3_status64() information */
+#define MSV_DB 1 /* sqlite3_db_status() information */
+#define MSV_ZIPVFS 2 /* ZIPVFS file-control with 64-bit return */
+
+/*
+** An array of quantities that can be measured and reported by
+** this virtual table
+*/
+static const struct MemstatColumns {
+ const char *zName; /* Symbolic name */
+ unsigned char eType; /* Type of interface */
+ unsigned char mNull; /* Bitmask of which columns are NULL */
+ /* 2: dbname, 4: current, 8: hiwtr */
+ int eOp; /* Opcode */
+} aMemstatColumn[] = {
+ {"MEMORY_USED", MSV_GSTAT, 2, SQLITE_STATUS_MEMORY_USED },
+ {"MALLOC_SIZE", MSV_GSTAT, 6, SQLITE_STATUS_MALLOC_SIZE },
+ {"MALLOC_COUNT", MSV_GSTAT, 2, SQLITE_STATUS_MALLOC_COUNT },
+ {"PAGECACHE_USED", MSV_GSTAT, 2, SQLITE_STATUS_PAGECACHE_USED },
+ {"PAGECACHE_OVERFLOW", MSV_GSTAT, 2, SQLITE_STATUS_PAGECACHE_OVERFLOW },
+ {"PAGECACHE_SIZE", MSV_GSTAT, 6, SQLITE_STATUS_PAGECACHE_SIZE },
+ {"PARSER_STACK", MSV_GSTAT, 6, SQLITE_STATUS_PARSER_STACK },
+ {"DB_LOOKASIDE_USED", MSV_DB, 2, SQLITE_DBSTATUS_LOOKASIDE_USED },
+ {"DB_LOOKASIDE_HIT", MSV_DB, 6, SQLITE_DBSTATUS_LOOKASIDE_HIT },
+ {"DB_LOOKASIDE_MISS_SIZE", MSV_DB, 6, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE},
+ {"DB_LOOKASIDE_MISS_FULL", MSV_DB, 6, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL},
+ {"DB_CACHE_USED", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_USED },
+#if SQLITE_VERSION_NUMBER >= 3140000
+ {"DB_CACHE_USED_SHARED", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_USED_SHARED },
+#endif
+ {"DB_SCHEMA_USED", MSV_DB, 10, SQLITE_DBSTATUS_SCHEMA_USED },
+ {"DB_STMT_USED", MSV_DB, 10, SQLITE_DBSTATUS_STMT_USED },
+ {"DB_CACHE_HIT", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_HIT },
+ {"DB_CACHE_MISS", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_MISS },
+ {"DB_CACHE_WRITE", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_WRITE },
+#if SQLITE_VERSION_NUMBER >= 3230000
+ {"DB_CACHE_SPILL", MSV_DB, 10, SQLITE_DBSTATUS_CACHE_SPILL },
+#endif
+ {"DB_DEFERRED_FKS", MSV_DB, 10, SQLITE_DBSTATUS_DEFERRED_FKS },
+#ifdef SQLITE_ENABLE_ZIPVFS
+ {"ZIPVFS_CACHE_USED", MSV_ZIPVFS, 8, 231454 },
+ {"ZIPVFS_CACHE_HIT", MSV_ZIPVFS, 8, 231455 },
+ {"ZIPVFS_CACHE_MISS", MSV_ZIPVFS, 8, 231456 },
+ {"ZIPVFS_CACHE_WRITE", MSV_ZIPVFS, 8, 231457 },
+ {"ZIPVFS_DIRECT_READ", MSV_ZIPVFS, 8, 231458 },
+ {"ZIPVFS_DIRECT_BYTES", MSV_ZIPVFS, 8, 231459 },
+#endif /* SQLITE_ENABLE_ZIPVFS */
+};
+#define MSV_NROW (sizeof(aMemstatColumn)/sizeof(aMemstatColumn[0]))
+
+/*
+** Advance a memstat_cursor to its next row of output.
+*/
+static int memstatNext(sqlite3_vtab_cursor *cur){
+ memstat_cursor *pCur = (memstat_cursor*)cur;
+ int i;
+ assert( pCur->iRowid<=MSV_NROW );
+ while(1){
+ i = (int)pCur->iRowid - 1;
+ if( i<0 || (aMemstatColumn[i].mNull & 2)!=0 || (++pCur->iDb)>=pCur->nDb ){
+ pCur->iRowid++;
+ if( pCur->iRowid>MSV_NROW ) return SQLITE_OK; /* End of the table */
+ pCur->iDb = 0;
+ i++;
+ }
+ pCur->aVal[0] = 0;
+ pCur->aVal[1] = 0;
+ switch( aMemstatColumn[i].eType ){
+ case MSV_GSTAT: {
+ if( sqlite3_libversion_number()>=3010000 ){
+ sqlite3_status64(aMemstatColumn[i].eOp,
+ &pCur->aVal[0], &pCur->aVal[1],0);
+ }else{
+ int xCur, xHiwtr;
+ sqlite3_status(aMemstatColumn[i].eOp, &xCur, &xHiwtr, 0);
+ pCur->aVal[0] = xCur;
+ pCur->aVal[1] = xHiwtr;
+ }
+ break;
+ }
+ case MSV_DB: {
+ int xCur, xHiwtr;
+ sqlite3_db_status(pCur->db, aMemstatColumn[i].eOp, &xCur, &xHiwtr, 0);
+ pCur->aVal[0] = xCur;
+ pCur->aVal[1] = xHiwtr;
+ break;
+ }
+ case MSV_ZIPVFS: {
+ int rc;
+ rc = sqlite3_file_control(pCur->db, pCur->azDb[pCur->iDb],
+ aMemstatColumn[i].eOp, (void*)&pCur->aVal[0]);
+ if( rc!=SQLITE_OK ) continue;
+ break;
+ }
+ }
+ break;
+ }
+ return SQLITE_OK;
+}
+
+
+/*
+** Return values of columns for the row at which the memstat_cursor
+** is currently pointing.
+*/
+static int memstatColumn(
+ sqlite3_vtab_cursor *cur, /* The cursor */
+ sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
+ int iCol /* Which column to return */
+){
+ memstat_cursor *pCur = (memstat_cursor*)cur;
+ int i;
+ assert( pCur->iRowid>0 && pCur->iRowid<=MSV_NROW );
+ i = (int)pCur->iRowid - 1;
+ if( (aMemstatColumn[i].mNull & (1<<iCol))!=0 ){
+ return SQLITE_OK;
+ }
+ switch( iCol ){
+ case MSV_COLUMN_NAME: {
+ sqlite3_result_text(ctx, aMemstatColumn[i].zName, -1, SQLITE_STATIC);
+ break;
+ }
+ case MSV_COLUMN_SCHEMA: {
+ sqlite3_result_text(ctx, pCur->azDb[pCur->iDb], -1, 0);
+ break;
+ }
+ case MSV_COLUMN_VALUE: {
+ sqlite3_result_int64(ctx, pCur->aVal[0]);
+ break;
+ }
+ case MSV_COLUMN_HIWTR: {
+ sqlite3_result_int64(ctx, pCur->aVal[1]);
+ break;
+ }
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Return the rowid for the current row. In this implementation, the
+** rowid is the same as the output value.
+*/
+static int memstatRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
+ memstat_cursor *pCur = (memstat_cursor*)cur;
+ *pRowid = pCur->iRowid*1000 + pCur->iDb;
+ return SQLITE_OK;
+}
+
+/*
+** Return TRUE if the cursor has been moved off of the last
+** row of output.
+*/
+static int memstatEof(sqlite3_vtab_cursor *cur){
+ memstat_cursor *pCur = (memstat_cursor*)cur;
+ return pCur->iRowid>MSV_NROW;
+}
+
+/*
+** This method is called to "rewind" the memstat_cursor object back
+** to the first row of output. This method is always called at least
+** once prior to any call to memstatColumn() or memstatRowid() or
+** memstatEof().
+*/
+static int memstatFilter(
+ sqlite3_vtab_cursor *pVtabCursor,
+ int idxNum, const char *idxStr,
+ int argc, sqlite3_value **argv
+){
+ memstat_cursor *pCur = (memstat_cursor *)pVtabCursor;
+ int rc = memstatFindSchemas(pCur);
+ if( rc ) return rc;
+ pCur->iRowid = 0;
+ pCur->iDb = 0;
+ return memstatNext(pVtabCursor);
+}
+
+/*
+** SQLite will invoke this method one or more times while planning a query
+** that uses the memstat virtual table. This routine needs to create
+** a query plan for each invocation and compute an estimated cost for that
+** plan.
+*/
+static int memstatBestIndex(
+ sqlite3_vtab *tab,
+ sqlite3_index_info *pIdxInfo
+){
+ pIdxInfo->estimatedCost = (double)500;
+ pIdxInfo->estimatedRows = 500;
+ return SQLITE_OK;
+}
+
+/*
+** This following structure defines all the methods for the
+** memstat virtual table.
+*/
+static sqlite3_module memstatModule = {
+ 0, /* iVersion */
+ 0, /* xCreate */
+ memstatConnect, /* xConnect */
+ memstatBestIndex, /* xBestIndex */
+ memstatDisconnect, /* xDisconnect */
+ 0, /* xDestroy */
+ memstatOpen, /* xOpen - open a cursor */
+ memstatClose, /* xClose - close a cursor */
+ memstatFilter, /* xFilter - configure scan constraints */
+ memstatNext, /* xNext - advance a cursor */
+ memstatEof, /* xEof - check for end of scan */
+ memstatColumn, /* xColumn - read data */
+ memstatRowid, /* 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 */
+
+int sqlite3MemstatVtabInit(sqlite3 *db){
+ int rc = SQLITE_OK;
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ rc = sqlite3_create_module(db, "sqlite_memstat", &memstatModule, 0);
+#endif
+ return rc;
+}
+
+#ifndef SQLITE_CORE
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int sqlite3_memstat_init(
+ sqlite3 *db,
+ char **pzErrMsg,
+ const sqlite3_api_routines *pApi
+){
+ int rc = SQLITE_OK;
+ SQLITE_EXTENSION_INIT2(pApi);
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ rc = sqlite3MemstatVtabInit(db);
+#endif
+ return rc;
+}
+#endif /* SQLITE_CORE */
+#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_MEMSTATVTAB) */
diff --git a/chromium/third_party/sqlite/src/ext/misc/series.c b/chromium/third_party/sqlite/src/ext/misc/series.c
index cf591bfad1e..2c69b741e68 100644
--- a/chromium/third_party/sqlite/src/ext/misc/series.c
+++ b/chromium/third_party/sqlite/src/ext/misc/series.c
@@ -313,44 +313,45 @@ static int seriesBestIndex(
sqlite3_vtab *tab,
sqlite3_index_info *pIdxInfo
){
- int i; /* Loop over constraints */
+ int i, j; /* Loop over constraints */
int idxNum = 0; /* The query plan bitmask */
- int startIdx = -1; /* Index of the start= constraint, or -1 if none */
- int stopIdx = -1; /* Index of the stop= constraint, or -1 if none */
- int stepIdx = -1; /* Index of the step= constraint, or -1 if none */
+ 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 );
+ aIdx[0] = aIdx[1] = aIdx[2] = -1;
pConstraint = pIdxInfo->aConstraint;
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
- if( pConstraint->usable==0 ) continue;
- if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
- switch( pConstraint->iColumn ){
- case SERIES_COLUMN_START:
- startIdx = i;
- idxNum |= 1;
- break;
- case SERIES_COLUMN_STOP:
- stopIdx = i;
- idxNum |= 2;
- break;
- case SERIES_COLUMN_STEP:
- stepIdx = i;
- idxNum |= 4;
- break;
+ 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;
}
}
- if( startIdx>=0 ){
- pIdxInfo->aConstraintUsage[startIdx].argvIndex = ++nArg;
- pIdxInfo->aConstraintUsage[startIdx].omit= !SQLITE_SERIES_CONSTRAINT_VERIFY;
- }
- if( stopIdx>=0 ){
- pIdxInfo->aConstraintUsage[stopIdx].argvIndex = ++nArg;
- pIdxInfo->aConstraintUsage[stopIdx].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY;
+ 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( stepIdx>=0 ){
- pIdxInfo->aConstraintUsage[stepIdx].argvIndex = ++nArg;
- pIdxInfo->aConstraintUsage[stepIdx].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
@@ -365,7 +366,6 @@ static int seriesBestIndex(
/* 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->estimatedCost = (double)2147483647;
pIdxInfo->estimatedRows = 2147483647;
}
pIdxInfo->idxNum = idxNum;
diff --git a/chromium/third_party/sqlite/src/ext/misc/sha1.c b/chromium/third_party/sqlite/src/ext/misc/sha1.c
index e2843bdefa4..886b1db7bdf 100644
--- a/chromium/third_party/sqlite/src/ext/misc/sha1.c
+++ b/chromium/third_party/sqlite/src/ext/misc/sha1.c
@@ -10,7 +10,7 @@
**
******************************************************************************
**
-** This SQLite extension implements a functions that compute SHA1 hashes.
+** This SQLite extension implements functions that compute SHA1 hashes.
** Two SQL functions are implemented:
**
** sha1(X)
diff --git a/chromium/third_party/sqlite/src/ext/misc/shathree.c b/chromium/third_party/sqlite/src/ext/misc/shathree.c
index 9ffa1201f9f..e5ae69afbe3 100644
--- a/chromium/third_party/sqlite/src/ext/misc/shathree.c
+++ b/chromium/third_party/sqlite/src/ext/misc/shathree.c
@@ -10,7 +10,7 @@
**
******************************************************************************
**
-** This SQLite extension implements a functions that compute SHA1 hashes.
+** This SQLite extension implements functions that compute SHA3 hashes.
** Two SQL functions are implemented:
**
** sha3(X,SIZE)
diff --git a/chromium/third_party/sqlite/src/ext/misc/spellfix.c b/chromium/third_party/sqlite/src/ext/misc/spellfix.c
index 981bd391046..271f5614771 100644
--- a/chromium/third_party/sqlite/src/ext/misc/spellfix.c
+++ b/chromium/third_party/sqlite/src/ext/misc/spellfix.c
@@ -1295,6 +1295,9 @@ typedef struct Transliteration Transliteration;
struct Transliteration {
unsigned short int cFrom;
unsigned char cTo0, cTo1, cTo2, cTo3;
+#ifdef SQLITE_SPELLFIX_5BYTE_MAPPINGS
+ unsigned char cTo4;
+#endif
};
/*
@@ -1708,7 +1711,11 @@ static const Transliteration *spellfixFindTranslit(int c, int *pxTop){
** should be freed by the caller.
*/
static unsigned char *transliterate(const unsigned char *zIn, int nIn){
+#ifdef SQLITE_SPELLFIX_5BYTE_MAPPINGS
+ unsigned char *zOut = sqlite3_malloc64( nIn*5 + 1 );
+#else
unsigned char *zOut = sqlite3_malloc64( nIn*4 + 1 );
+#endif
int c, sz, nOut;
if( zOut==0 ) return 0;
nOut = 0;
@@ -1732,6 +1739,11 @@ static unsigned char *transliterate(const unsigned char *zIn, int nIn){
zOut[nOut++] = tbl[x].cTo2;
if( tbl[x].cTo3 ){
zOut[nOut++] = tbl[x].cTo3;
+#ifdef SQLITE_SPELLFIX_5BYTE_MAPPINGS
+ if( tbl[x].cTo4 ){
+ zOut[nOut++] = tbl[x].cTo4;
+ }
+#endif /* SQLITE_SPELLFIX_5BYTE_MAPPINGS */
}
}
}
diff --git a/chromium/third_party/sqlite/src/ext/misc/stmt.c b/chromium/third_party/sqlite/src/ext/misc/stmt.c
index be216ee9bdb..5983e129fce 100644
--- a/chromium/third_party/sqlite/src/ext/misc/stmt.c
+++ b/chromium/third_party/sqlite/src/ext/misc/stmt.c
@@ -266,6 +266,7 @@ static sqlite3_module stmtModule = {
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
+ 0, /* xShadowName */
};
#endif /* SQLITE_OMIT_VIRTUALTABLE */
diff --git a/chromium/third_party/sqlite/src/ext/misc/templatevtab.c b/chromium/third_party/sqlite/src/ext/misc/templatevtab.c
index 31d7c4ee839..52024871b80 100644
--- a/chromium/third_party/sqlite/src/ext/misc/templatevtab.c
+++ b/chromium/third_party/sqlite/src/ext/misc/templatevtab.c
@@ -248,7 +248,8 @@ static sqlite3_module templatevtabModule = {
/* xRename */ 0,
/* xSavepoint */ 0,
/* xRelease */ 0,
- /* xRollbackTo */ 0
+ /* xRollbackTo */ 0,
+ /* xShadowName */ 0
};
diff --git a/chromium/third_party/sqlite/src/ext/misc/unionvtab.c b/chromium/third_party/sqlite/src/ext/misc/unionvtab.c
index ed58ed364e1..8a1d493de50 100644
--- a/chromium/third_party/sqlite/src/ext/misc/unionvtab.c
+++ b/chromium/third_party/sqlite/src/ext/misc/unionvtab.c
@@ -1350,7 +1350,8 @@ static int createUnionVtab(sqlite3 *db){
0, /* xRename */
0, /* xSavepoint */
0, /* xRelease */
- 0 /* xRollbackTo */
+ 0, /* xRollbackTo */
+ 0 /* xShadowName */
};
int rc;
diff --git a/chromium/third_party/sqlite/src/ext/misc/vtablog.c b/chromium/third_party/sqlite/src/ext/misc/vtablog.c
index e183906165f..8312387c702 100644
--- a/chromium/third_party/sqlite/src/ext/misc/vtablog.c
+++ b/chromium/third_party/sqlite/src/ext/misc/vtablog.c
@@ -492,6 +492,7 @@ static sqlite3_module vtablogModule = {
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
+ 0, /* xShadowName */
};
#ifdef _WIN32
diff --git a/chromium/third_party/sqlite/src/ext/misc/zipfile.c b/chromium/third_party/sqlite/src/ext/misc/zipfile.c
index 0466c8154a3..a69f3a7e9e9 100644
--- a/chromium/third_party/sqlite/src/ext/misc/zipfile.c
+++ b/chromium/third_party/sqlite/src/ext/misc/zipfile.c
@@ -1296,25 +1296,26 @@ static int zipfileBestIndex(
sqlite3_index_info *pIdxInfo
){
int i;
+ int idx = -1;
+ int unusable = 0;
for(i=0; i<pIdxInfo->nConstraint; i++){
const struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i];
- if( pCons->usable==0 ) continue;
- if( pCons->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
if( pCons->iColumn!=ZIPFILE_F_COLUMN_IDX ) continue;
- break;
+ if( pCons->usable==0 ){
+ unusable = 1;
+ }else if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){
+ idx = i;
+ }
}
-
- if( i<pIdxInfo->nConstraint ){
- pIdxInfo->aConstraintUsage[i].argvIndex = 1;
- pIdxInfo->aConstraintUsage[i].omit = 1;
+ if( idx>=0 ){
+ pIdxInfo->aConstraintUsage[idx].argvIndex = 1;
+ pIdxInfo->aConstraintUsage[idx].omit = 1;
pIdxInfo->estimatedCost = 1000.0;
pIdxInfo->idxNum = 1;
- }else{
- pIdxInfo->estimatedCost = (double)(((sqlite3_int64)1) << 50);
- pIdxInfo->idxNum = 0;
+ }else if( unusable ){
+ return SQLITE_CONSTRAINT;
}
-
return SQLITE_OK;
}
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbu1.test b/chromium/third_party/sqlite/src/ext/rbu/rbu1.test
index baa382a5fc8..5552f40c1fa 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbu1.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbu1.test
@@ -670,4 +670,3 @@ foreach {tn3 create_vfs destroy_vfs} {
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbu10.test b/chromium/third_party/sqlite/src/ext/rbu/rbu10.test
index 98d60760b01..a2c72583a08 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbu10.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbu10.test
@@ -185,4 +185,3 @@ do_test 4.3 {
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbu11.test b/chromium/third_party/sqlite/src/ext/rbu/rbu11.test
index 77b7a094a31..8244e4c3129 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbu11.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbu11.test
@@ -195,4 +195,3 @@ do_test 4.7.2 {
} {1 {SQLITE_ERROR - rbu_state mismatch error}}
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbu12.test b/chromium/third_party/sqlite/src/ext/rbu/rbu12.test
index 20b1d9e9095..43126b14ad7 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbu12.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbu12.test
@@ -232,4 +232,3 @@ do_multiclient_test tn {
}
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbu13.test b/chromium/third_party/sqlite/src/ext/rbu/rbu13.test
index ad67a98f802..624c587cc3a 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbu13.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbu13.test
@@ -62,4 +62,3 @@ do_execsql_test 1.4 {
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbu14.test b/chromium/third_party/sqlite/src/ext/rbu/rbu14.test
index c4c3be6be56..ce0055de245 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbu14.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbu14.test
@@ -92,4 +92,3 @@ foreach {tn schema} {
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbu3.test b/chromium/third_party/sqlite/src/ext/rbu/rbu3.test
index 7d418d89214..7751c6c252b 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbu3.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbu3.test
@@ -203,5 +203,3 @@ do_test 5.3 {
do_test 6.1 { sqlite3rbu_internal_test } {}
finish_test
-
-
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbu5.test b/chromium/third_party/sqlite/src/ext/rbu/rbu5.test
index 94e38031040..0542f60a6e0 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbu5.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbu5.test
@@ -300,7 +300,3 @@ foreach {tn idx} {
finish_test
-
-
-
-
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbu6.test b/chromium/third_party/sqlite/src/ext/rbu/rbu6.test
index ad8dd78dc1a..979f545d290 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbu6.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbu6.test
@@ -100,4 +100,3 @@ for {set nStep 8} {$nStep < 20} {incr nStep} {
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbu7.test b/chromium/third_party/sqlite/src/ext/rbu/rbu7.test
index c2f2211bcec..81704d21188 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbu7.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbu7.test
@@ -106,5 +106,3 @@ foreach {tn tbl} {
}
finish_test
-
-
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbu8.test b/chromium/third_party/sqlite/src/ext/rbu/rbu8.test
index 75edd4efbaf..c0ccd8c5eb8 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbu8.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbu8.test
@@ -72,4 +72,3 @@ integrity_check 1.3.3
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbu9.test b/chromium/third_party/sqlite/src/ext/rbu/rbu9.test
index 4524b0a1517..233eaa364d6 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbu9.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbu9.test
@@ -125,4 +125,3 @@ foreach {tn idx} {
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbuA.test b/chromium/third_party/sqlite/src/ext/rbu/rbuA.test
index 286194c4fc1..642caca1960 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbuA.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbuA.test
@@ -80,4 +80,3 @@ do_test 2.2 {
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbuB.test b/chromium/third_party/sqlite/src/ext/rbu/rbuB.test
index bbc10a30838..9d2ab59ced1 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbuB.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbuB.test
@@ -59,4 +59,3 @@ sqlite3_shutdown
test_sqlite3_log
sqlite3_initialize
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbuC.test b/chromium/third_party/sqlite/src/ext/rbu/rbuC.test
index e3083222b5a..004def63ca2 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbuC.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbuC.test
@@ -139,4 +139,3 @@ foreach {tn schema} {
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbucollate.test b/chromium/third_party/sqlite/src/ext/rbu/rbucollate.test
index a9c3b4d4a18..62935b5a7e6 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbucollate.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbucollate.test
@@ -60,4 +60,3 @@ do_test 1.2 {
#forcedelete testrbu.db
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbucrash.test b/chromium/third_party/sqlite/src/ext/rbu/rbucrash.test
index 8602b6acf53..8a9ca6646c4 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbucrash.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbucrash.test
@@ -145,4 +145,3 @@ for {set nPre 0} {$nPre < $rbu_num_steps} {incr nPre} {
}
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbucrash2.test b/chromium/third_party/sqlite/src/ext/rbu/rbucrash2.test
index 6db3833b148..59e700e5467 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbucrash2.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbucrash2.test
@@ -103,4 +103,3 @@ for {set x 1} {$x < 2} {incr x} {
}
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbudiff.test b/chromium/third_party/sqlite/src/ext/rbu/rbudiff.test
index 97e89b57a47..4dbfce2adf4 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbudiff.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbudiff.test
@@ -300,4 +300,3 @@ tablE t1 USING FTs5(c);
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbudor.test b/chromium/third_party/sqlite/src/ext/rbu/rbudor.test
index f69468c30e2..16ba18b77ed 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbudor.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbudor.test
@@ -56,4 +56,3 @@ do_execsql_test 1.4 {
} [list 1 $bigA 2 $bigB]
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbufault.test b/chromium/third_party/sqlite/src/ext/rbu/rbufault.test
index c7fb0577c6d..3e1642cecf7 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbufault.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbufault.test
@@ -234,4 +234,3 @@ foreach {tn2 setup sql expect} {
}
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbufault2.test b/chromium/third_party/sqlite/src/ext/rbu/rbufault2.test
index 8e6a476b7cb..0f4542fa25c 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbufault2.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbufault2.test
@@ -55,4 +55,3 @@ do_faultsim_test 1 -faults oom* -prep {
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbufault3.test b/chromium/third_party/sqlite/src/ext/rbu/rbufault3.test
index 3e8f8cc22eb..cdf0d7f24a3 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbufault3.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbufault3.test
@@ -95,4 +95,3 @@ foreach {fault errlist} {
}
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbufault4.test b/chromium/third_party/sqlite/src/ext/rbu/rbufault4.test
index 507a36181ec..f1fe0c8965b 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbufault4.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbufault4.test
@@ -63,4 +63,3 @@ for {set tn 1} {1} {incr tn} {
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbufts.test b/chromium/third_party/sqlite/src/ext/rbu/rbufts.test
index dd4148209f4..d065bfc94d4 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbufts.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbufts.test
@@ -131,4 +131,3 @@ do_test 3.3 {
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbumulti.test b/chromium/third_party/sqlite/src/ext/rbu/rbumulti.test
index 148800277b5..9be186f9585 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbumulti.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbumulti.test
@@ -172,4 +172,3 @@ for {set i 0} {$i<=3} {incr i} {
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbuprogress.test b/chromium/third_party/sqlite/src/ext/rbu/rbuprogress.test
index 66c66e8ad90..058b89eed33 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbuprogress.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbuprogress.test
@@ -416,4 +416,3 @@ foreach {bReopen} { 0 1 } {
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rburesume.test b/chromium/third_party/sqlite/src/ext/rbu/rburesume.test
index 5dc3c0e9159..2d118d16352 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rburesume.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rburesume.test
@@ -251,4 +251,3 @@ for {set n 1} {$n < 5000} {incr n} {
}
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbusave.test b/chromium/third_party/sqlite/src/ext/rbu/rbusave.test
index eb94b621341..fa7c44509a9 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbusave.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbusave.test
@@ -102,4 +102,3 @@ do_execsql_test 1.5 {
} {1 one 1 3 3 3 4 4 4 1 one 1 3 3 3 4 4 4}
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbusplit.test b/chromium/third_party/sqlite/src/ext/rbu/rbusplit.test
index 8e088feecdd..9bd689af3a0 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbusplit.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbusplit.test
@@ -92,4 +92,3 @@ foreach {tn cmd} {
}
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbutemplimit.test b/chromium/third_party/sqlite/src/ext/rbu/rbutemplimit.test
index 066c61ecd2a..686c5530ce5 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbutemplimit.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbutemplimit.test
@@ -126,4 +126,3 @@ do_test 1.6.1 {
do_test 1.6.2 { info commands rbu } {}
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbuvacuum.test b/chromium/third_party/sqlite/src/ext/rbu/rbuvacuum.test
index 2a03c936b4c..4fc7a4e1cab 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbuvacuum.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbuvacuum.test
@@ -397,4 +397,3 @@ do_test 3.5 {
catch { db close }
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbuvacuum2.test b/chromium/third_party/sqlite/src/ext/rbu/rbuvacuum2.test
index 8a2cd411732..140a0c1a8c4 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbuvacuum2.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbuvacuum2.test
@@ -232,4 +232,3 @@ do_test 6.3 {
} {ok}
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/rbu/sqlite3rbu.c b/chromium/third_party/sqlite/src/ext/rbu/sqlite3rbu.c
index 0a3d15ea10e..0762529dcb0 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/sqlite3rbu.c
+++ b/chromium/third_party/sqlite/src/ext/rbu/sqlite3rbu.c
@@ -405,7 +405,8 @@ struct rbu_vfs {
sqlite3_vfs *pRealVfs; /* Underlying VFS */
sqlite3_mutex *mutex; /* Mutex to protect pMain */
sqlite3rbu *pRbu; /* Owner RBU object */
- rbu_file *pMain; /* Linked list of main db files */
+ rbu_file *pMain; /* List of main db files */
+ rbu_file *pMainRbu; /* List of main db files with pRbu!=0 */
};
/*
@@ -434,6 +435,7 @@ struct rbu_file {
const char *zWal; /* Wal filename for this main db file */
rbu_file *pWalFd; /* Wal file descriptor for this main db */
rbu_file *pMainNext; /* Next MAIN_DB file */
+ rbu_file *pMainRbuNext; /* Next MAIN_DB file with pRbu!=0 */
};
/*
@@ -4031,6 +4033,69 @@ static int rbuUpdateTempSize(rbu_file *pFd, sqlite3_int64 nNew){
}
/*
+** Add an item to the main-db lists, if it is not already present.
+**
+** There are two main-db lists. One for all file descriptors, and one
+** for all file descriptors with rbu_file.pDb!=0. If the argument has
+** rbu_file.pDb!=0, then it is assumed to already be present on the
+** main list and is only added to the pDb!=0 list.
+*/
+static void rbuMainlistAdd(rbu_file *p){
+ rbu_vfs *pRbuVfs = p->pRbuVfs;
+ rbu_file *pIter;
+ assert( (p->openFlags & SQLITE_OPEN_MAIN_DB) );
+ sqlite3_mutex_enter(pRbuVfs->mutex);
+ if( p->pRbu==0 ){
+ for(pIter=pRbuVfs->pMain; pIter; pIter=pIter->pMainNext);
+ p->pMainNext = pRbuVfs->pMain;
+ pRbuVfs->pMain = p;
+ }else{
+ for(pIter=pRbuVfs->pMainRbu; pIter && pIter!=p; pIter=pIter->pMainRbuNext){}
+ if( pIter==0 ){
+ p->pMainRbuNext = pRbuVfs->pMainRbu;
+ pRbuVfs->pMainRbu = p;
+ }
+ }
+ sqlite3_mutex_leave(pRbuVfs->mutex);
+}
+
+/*
+** Remove an item from the main-db lists.
+*/
+static void rbuMainlistRemove(rbu_file *p){
+ rbu_file **pp;
+ sqlite3_mutex_enter(p->pRbuVfs->mutex);
+ for(pp=&p->pRbuVfs->pMain; *pp && *pp!=p; pp=&((*pp)->pMainNext)){}
+ if( *pp ) *pp = p->pMainNext;
+ p->pMainNext = 0;
+ for(pp=&p->pRbuVfs->pMainRbu; *pp && *pp!=p; pp=&((*pp)->pMainRbuNext)){}
+ if( *pp ) *pp = p->pMainRbuNext;
+ p->pMainRbuNext = 0;
+ sqlite3_mutex_leave(p->pRbuVfs->mutex);
+}
+
+/*
+** Given that zWal points to a buffer containing a wal file name passed to
+** either the xOpen() or xAccess() VFS method, search the main-db list for
+** a file-handle opened by the same database connection on the corresponding
+** database file.
+**
+** If parameter bRbu is true, only search for file-descriptors with
+** rbu_file.pDb!=0.
+*/
+static rbu_file *rbuFindMaindb(rbu_vfs *pRbuVfs, const char *zWal, int bRbu){
+ rbu_file *pDb;
+ sqlite3_mutex_enter(pRbuVfs->mutex);
+ if( bRbu ){
+ for(pDb=pRbuVfs->pMainRbu; pDb && pDb->zWal!=zWal; pDb=pDb->pMainRbuNext){}
+ }else{
+ for(pDb=pRbuVfs->pMain; pDb && pDb->zWal!=zWal; pDb=pDb->pMainNext){}
+ }
+ sqlite3_mutex_leave(pRbuVfs->mutex);
+ return pDb;
+}
+
+/*
** Close an rbu file.
*/
static int rbuVfsClose(sqlite3_file *pFile){
@@ -4047,17 +4112,14 @@ static int rbuVfsClose(sqlite3_file *pFile){
sqlite3_free(p->zDel);
if( p->openFlags & SQLITE_OPEN_MAIN_DB ){
- rbu_file **pp;
- sqlite3_mutex_enter(p->pRbuVfs->mutex);
- for(pp=&p->pRbuVfs->pMain; *pp!=p; pp=&((*pp)->pMainNext));
- *pp = p->pMainNext;
- sqlite3_mutex_leave(p->pRbuVfs->mutex);
+ rbuMainlistRemove(p);
rbuUnlockShm(p);
p->pReal->pMethods->xShmUnmap(p->pReal, 0);
}
else if( (p->openFlags & SQLITE_OPEN_DELETEONCLOSE) && p->pRbu ){
rbuUpdateTempSize(p, 0);
}
+ assert( p->pMainNext==0 && p->pRbuVfs->pMain!=p );
/* Close the underlying file handle */
rc = p->pReal->pMethods->xClose(p->pReal);
@@ -4316,6 +4378,9 @@ static int rbuVfsFileControl(sqlite3_file *pFile, int op, void *pArg){
}else if( rc==SQLITE_NOTFOUND ){
pRbu->pTargetFd = p;
p->pRbu = pRbu;
+ if( p->openFlags & SQLITE_OPEN_MAIN_DB ){
+ rbuMainlistAdd(p);
+ }
if( p->pWalFd ) p->pWalFd->pRbu = pRbu;
rc = SQLITE_OK;
}
@@ -4478,20 +4543,6 @@ static int rbuVfsShmUnmap(sqlite3_file *pFile, int delFlag){
}
/*
-** Given that zWal points to a buffer containing a wal file name passed to
-** either the xOpen() or xAccess() VFS method, return a pointer to the
-** file-handle opened by the same database connection on the corresponding
-** database file.
-*/
-static rbu_file *rbuFindMaindb(rbu_vfs *pRbuVfs, const char *zWal){
- rbu_file *pDb;
- sqlite3_mutex_enter(pRbuVfs->mutex);
- for(pDb=pRbuVfs->pMain; pDb && pDb->zWal!=zWal; pDb=pDb->pMainNext){}
- sqlite3_mutex_leave(pRbuVfs->mutex);
- return pDb;
-}
-
-/*
** A main database named zName has just been opened. The following
** function returns a pointer to a buffer owned by SQLite that contains
** the name of the *-wal file this db connection will use. SQLite
@@ -4569,7 +4620,7 @@ static int rbuVfsOpen(
pFd->zWal = rbuMainToWal(zName, flags);
}
else if( flags & SQLITE_OPEN_WAL ){
- rbu_file *pDb = rbuFindMaindb(pRbuVfs, zName);
+ rbu_file *pDb = rbuFindMaindb(pRbuVfs, zName, 0);
if( pDb ){
if( pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){
/* This call is to open a *-wal file. Intead, open the *-oal. This
@@ -4621,10 +4672,7 @@ static int rbuVfsOpen(
** mutex protected linked list of all such files. */
pFile->pMethods = &rbuvfs_io_methods;
if( flags & SQLITE_OPEN_MAIN_DB ){
- sqlite3_mutex_enter(pRbuVfs->mutex);
- pFd->pMainNext = pRbuVfs->pMain;
- pRbuVfs->pMain = pFd;
- sqlite3_mutex_leave(pRbuVfs->mutex);
+ rbuMainlistAdd(pFd);
}
}else{
sqlite3_free(pFd->zDel);
@@ -4672,7 +4720,7 @@ static int rbuVfsAccess(
** file opened instead.
*/
if( rc==SQLITE_OK && flags==SQLITE_ACCESS_EXISTS ){
- rbu_file *pDb = rbuFindMaindb(pRbuVfs, zPath);
+ rbu_file *pDb = rbuFindMaindb(pRbuVfs, zPath, 1);
if( pDb && pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){
if( *pResOut ){
rc = SQLITE_CANTOPEN;
diff --git a/chromium/third_party/sqlite/src/ext/rtree/geopoly.c b/chromium/third_party/sqlite/src/ext/rtree/geopoly.c
index e315b013bc2..d7f6cd5f253 100644
--- a/chromium/third_party/sqlite/src/ext/rtree/geopoly.c
+++ b/chromium/third_party/sqlite/src/ext/rtree/geopoly.c
@@ -106,14 +106,24 @@ typedef float GeoCoord;
**
** encoding (1 byte) 0=big-endian, 1=little-endian
** nvertex (3 bytes) Number of vertexes as a big-endian integer
+**
+** Enough space is allocated for 4 coordinates, to work around over-zealous
+** warnings coming from some compiler (notably, clang). In reality, the size
+** of each GeoPoly memory allocate is adjusted as necessary so that the
+** GeoPoly.a[] array at the end is the appropriate size.
*/
typedef struct GeoPoly GeoPoly;
struct GeoPoly {
int nVertex; /* Number of vertexes */
unsigned char hdr[4]; /* Header for on-disk representation */
- GeoCoord a[2]; /* 2*nVertex values. X (longitude) first, then Y */
+ GeoCoord a[8]; /* 2*nVertex values. X (longitude) first, then Y */
};
+/* The size of a memory allocation needed for a GeoPoly object sufficient
+** to hold N coordinate pairs.
+*/
+#define GEOPOLY_SZ(N) (sizeof(GeoPoly) + sizeof(GeoCoord)*2*((N)-4))
+
/*
** State of a parse of a GeoJSON input.
*/
@@ -138,7 +148,7 @@ static void geopolySwab32(unsigned char *a){
/* Skip whitespace. Return the next non-whitespace character. */
static char geopolySkipSpace(GeoParse *p){
- while( p->z[0] && safe_isspace(p->z[0]) ) p->z++;
+ while( safe_isspace(p->z[0]) ) p->z++;
return p->z[0];
}
@@ -158,7 +168,7 @@ static int geopolyParseNumber(GeoParse *p, GeoCoord *pVal){
if( c=='0' && z[j+1]>='0' && z[j+1]<='9' ) return 0;
for(;; j++){
c = z[j];
- if( c>='0' && c<='9' ) continue;
+ if( safe_isdigit(c) ) continue;
if( c=='.' ){
if( z[j-1]=='-' ) return 0;
if( seenDP ) return 0;
@@ -180,7 +190,17 @@ static int geopolyParseNumber(GeoParse *p, GeoCoord *pVal){
break;
}
if( z[j-1]<'0' ) return 0;
- if( pVal ) *pVal = (GeoCoord)atof((const char*)p->z);
+ if( pVal ){
+#ifdef SQLITE_AMALGAMATION
+ /* The sqlite3AtoF() routine is much much faster than atof(), if it
+ ** is available */
+ double r;
+ (void)sqlite3AtoF((const char*)p->z, &r, j, SQLITE_UTF8);
+ *pVal = r;
+#else
+ *pVal = (GeoCoord)atof((const char*)p->z);
+#endif
+ }
p->z += j;
return 1;
}
@@ -238,12 +258,10 @@ static GeoPoly *geopolyParseJson(const unsigned char *z, int *pRc){
&& s.a[1]==s.a[s.nVertex*2-1]
&& (s.z++, geopolySkipSpace(&s)==0)
){
- int nByte;
GeoPoly *pOut;
int x = 1;
s.nVertex--; /* Remove the redundant vertex at the end */
- nByte = sizeof(GeoPoly) * s.nVertex*2*sizeof(GeoCoord);
- pOut = sqlite3_malloc64( nByte );
+ pOut = sqlite3_malloc64( GEOPOLY_SZ(s.nVertex) );
x = 1;
if( pOut==0 ) goto parse_json_err;
pOut->nVertex = s.nVertex;
@@ -447,6 +465,27 @@ static void geopolyXformFunc(
}
/*
+** Compute the area enclosed by the polygon.
+**
+** This routine can also be used to detect polygons that rotate in
+** the wrong direction. Polygons are suppose to be counter-clockwise (CCW).
+** This routine returns a negative value for clockwise (CW) polygons.
+*/
+static double geopolyArea(GeoPoly *p){
+ double rArea = 0.0;
+ int ii;
+ for(ii=0; ii<p->nVertex-1; ii++){
+ rArea += (p->a[ii*2] - p->a[ii*2+2]) /* (x0 - x1) */
+ * (p->a[ii*2+1] + p->a[ii*2+3]) /* (y0 + y1) */
+ * 0.5;
+ }
+ rArea += (p->a[ii*2] - p->a[0]) /* (xN - x0) */
+ * (p->a[ii*2+1] + p->a[1]) /* (yN + y0) */
+ * 0.5;
+ return rArea;
+}
+
+/*
** Implementation of the geopoly_area(X) function.
**
** If the input is a well-formed Geopoly BLOB then return the area
@@ -461,21 +500,106 @@ static void geopolyAreaFunc(
){
GeoPoly *p = geopolyFuncParam(context, argv[0], 0);
if( p ){
- double rArea = 0.0;
- int ii;
- for(ii=0; ii<p->nVertex-1; ii++){
- rArea += (p->a[ii*2] - p->a[ii*2+2]) /* (x0 - x1) */
- * (p->a[ii*2+1] + p->a[ii*2+3]) /* (y0 + y1) */
- * 0.5;
+ sqlite3_result_double(context, geopolyArea(p));
+ sqlite3_free(p);
+ }
+}
+
+/*
+** Implementation of the geopoly_ccw(X) function.
+**
+** If the rotation of polygon X is clockwise (incorrect) instead of
+** counter-clockwise (the correct winding order according to RFC7946)
+** then reverse the order of the vertexes in polygon X.
+**
+** In other words, this routine returns a CCW polygon regardless of the
+** winding order of its input.
+**
+** Use this routine to sanitize historical inputs that that sometimes
+** contain polygons that wind in the wrong direction.
+*/
+static void geopolyCcwFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ GeoPoly *p = geopolyFuncParam(context, argv[0], 0);
+ if( p ){
+ if( geopolyArea(p)<0.0 ){
+ int ii, jj;
+ for(ii=2, jj=p->nVertex*2 - 2; ii<jj; ii+=2, jj-=2){
+ GeoCoord t = p->a[ii];
+ p->a[ii] = p->a[jj];
+ p->a[jj] = t;
+ t = p->a[ii+1];
+ p->a[ii+1] = p->a[jj+1];
+ p->a[jj+1] = t;
+ }
}
- rArea += (p->a[ii*2] - p->a[0]) /* (xN - x0) */
- * (p->a[ii*2+1] + p->a[1]) /* (yN + y0) */
- * 0.5;
- sqlite3_result_double(context, rArea);
+ sqlite3_result_blob(context, p->hdr,
+ 4+8*p->nVertex, SQLITE_TRANSIENT);
sqlite3_free(p);
}
}
+#define GEOPOLY_PI 3.1415926535897932385
+
+/* Fast approximation for sine(X) for X between -0.5*pi and 2*pi
+*/
+static double geopolySine(double r){
+ assert( r>=-0.5*GEOPOLY_PI && r<=2.0*GEOPOLY_PI );
+ if( r>=1.5*GEOPOLY_PI ){
+ r -= 2.0*GEOPOLY_PI;
+ }
+ if( r>=0.5*GEOPOLY_PI ){
+ return -geopolySine(r-GEOPOLY_PI);
+ }else{
+ double r2 = r*r;
+ double r3 = r2*r;
+ double r5 = r3*r2;
+ return 0.9996949*r - 0.1656700*r3 + 0.0075134*r5;
+ }
+}
+
+/*
+** Function: geopoly_regular(X,Y,R,N)
+**
+** Construct a simple, convex, regular polygon centered at X, Y
+** with circumradius R and with N sides.
+*/
+static void geopolyRegularFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ double x = sqlite3_value_double(argv[0]);
+ double y = sqlite3_value_double(argv[1]);
+ double r = sqlite3_value_double(argv[2]);
+ int n = sqlite3_value_int(argv[3]);
+ int i;
+ GeoPoly *p;
+
+ if( n<3 || r<=0.0 ) return;
+ if( n>1000 ) n = 1000;
+ p = sqlite3_malloc64( sizeof(*p) + (n-1)*2*sizeof(GeoCoord) );
+ if( p==0 ){
+ sqlite3_result_error_nomem(context);
+ return;
+ }
+ i = 1;
+ p->hdr[0] = *(unsigned char*)&i;
+ p->hdr[1] = 0;
+ p->hdr[2] = (n>>8)&0xff;
+ p->hdr[3] = n&0xff;
+ for(i=0; i<n; i++){
+ double rAngle = 2.0*GEOPOLY_PI*i/n;
+ p->a[i*2] = x - r*geopolySine(rAngle-0.5*GEOPOLY_PI);
+ p->a[i*2+1] = y + r*geopolySine(rAngle);
+ }
+ sqlite3_result_blob(context, p->hdr, 4+8*n, SQLITE_TRANSIENT);
+ sqlite3_free(p);
+}
+
/*
** If pPoly is a polygon, compute its bounding box. Then:
**
@@ -520,7 +644,7 @@ static GeoPoly *geopolyBBox(
if( pRc ) *pRc = SQLITE_OK;
if( aCoord==0 ){
geopolyBboxFill:
- pOut = sqlite3_realloc(p, sizeof(GeoPoly)+sizeof(GeoCoord)*6);
+ pOut = sqlite3_realloc(p, GEOPOLY_SZ(4));
if( pOut==0 ){
sqlite3_free(p);
if( context ) sqlite3_result_error_nomem(context);
@@ -1548,7 +1672,16 @@ static int geopolyUpdate(
if( sqlite3_value_nochange(aData[2]) ){
sqlite3_bind_null(pUp, 2);
}else{
- sqlite3_bind_value(pUp, 2, aData[2]);
+ GeoPoly *p = 0;
+ if( sqlite3_value_type(aData[2])==SQLITE_TEXT
+ && (p = geopolyFuncParam(0, aData[2], &rc))!=0
+ && rc==SQLITE_OK
+ ){
+ sqlite3_bind_blob(pUp, 2, p->hdr, 4+8*p->nVertex, SQLITE_TRANSIENT);
+ }else{
+ sqlite3_bind_value(pUp, 2, aData[2]);
+ }
+ sqlite3_free(p);
nChange = 1;
}
for(jj=1; jj<pRtree->nAux; jj++){
@@ -1592,7 +1725,7 @@ static int geopolyFindFunction(
static sqlite3_module geopolyModule = {
- 2, /* iVersion */
+ 3, /* iVersion */
geopolyCreate, /* xCreate - create a table */
geopolyConnect, /* xConnect - connect to an existing table */
geopolyBestIndex, /* xBestIndex - Determine search strategy */
@@ -1615,25 +1748,29 @@ static sqlite3_module geopolyModule = {
rtreeSavepoint, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
+ rtreeShadowName /* xShadowName */
};
static int sqlite3_geopoly_init(sqlite3 *db){
int rc = SQLITE_OK;
static const struct {
void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
- int nArg;
+ signed char nArg;
+ unsigned char bPure;
const char *zName;
} aFunc[] = {
- { geopolyAreaFunc, 1, "geopoly_area" },
- { geopolyBlobFunc, 1, "geopoly_blob" },
- { geopolyJsonFunc, 1, "geopoly_json" },
- { geopolySvgFunc, -1, "geopoly_svg" },
- { geopolyWithinFunc, 2, "geopoly_within" },
- { geopolyContainsPointFunc, 3, "geopoly_contains_point" },
- { geopolyOverlapFunc, 2, "geopoly_overlap" },
- { geopolyDebugFunc, 1, "geopoly_debug" },
- { geopolyBBoxFunc, 1, "geopoly_bbox" },
- { geopolyXformFunc, 7, "geopoly_xform" },
+ { geopolyAreaFunc, 1, 1, "geopoly_area" },
+ { geopolyBlobFunc, 1, 1, "geopoly_blob" },
+ { geopolyJsonFunc, 1, 1, "geopoly_json" },
+ { geopolySvgFunc, -1, 1, "geopoly_svg" },
+ { geopolyWithinFunc, 2, 1, "geopoly_within" },
+ { geopolyContainsPointFunc, 3, 1, "geopoly_contains_point" },
+ { geopolyOverlapFunc, 2, 1, "geopoly_overlap" },
+ { geopolyDebugFunc, 1, 0, "geopoly_debug" },
+ { geopolyBBoxFunc, 1, 1, "geopoly_bbox" },
+ { geopolyXformFunc, 7, 1, "geopoly_xform" },
+ { geopolyRegularFunc, 4, 1, "geopoly_regular" },
+ { geopolyCcwFunc, 1, 1, "geopoly_ccw" },
};
static const struct {
void (*xStep)(sqlite3_context*,int,sqlite3_value**);
@@ -1644,8 +1781,9 @@ static int sqlite3_geopoly_init(sqlite3 *db){
};
int i;
for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
+ int enc = aFunc[i].bPure ? SQLITE_UTF8|SQLITE_DETERMINISTIC : SQLITE_UTF8;
rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg,
- SQLITE_UTF8, 0,
+ enc, 0,
aFunc[i].xFunc, 0, 0);
}
for(i=0; i<sizeof(aAgg)/sizeof(aAgg[0]) && rc==SQLITE_OK; i++){
diff --git a/chromium/third_party/sqlite/src/ext/rtree/rtree.c b/chromium/third_party/sqlite/src/ext/rtree/rtree.c
index e25bc86b865..9c436d5989e 100644
--- a/chromium/third_party/sqlite/src/ext/rtree/rtree.c
+++ b/chromium/third_party/sqlite/src/ext/rtree/rtree.c
@@ -3325,8 +3325,24 @@ static int rtreeQueryStat1(sqlite3 *db, Rtree *pRtree){
return rc;
}
+
+/*
+** Return true if zName is the extension on one of the shadow tables used
+** by this module.
+*/
+static int rtreeShadowName(const char *zName){
+ static const char *azName[] = {
+ "node", "parent", "rowid"
+ };
+ unsigned int i;
+ for(i=0; i<sizeof(azName)/sizeof(azName[0]); i++){
+ if( sqlite3_stricmp(zName, azName[i])==0 ) return 1;
+ }
+ return 0;
+}
+
static sqlite3_module rtreeModule = {
- 2, /* iVersion */
+ 3, /* iVersion */
rtreeCreate, /* xCreate - create a table */
rtreeConnect, /* xConnect - connect to an existing table */
rtreeBestIndex, /* xBestIndex - Determine search strategy */
@@ -3349,6 +3365,7 @@ static sqlite3_module rtreeModule = {
rtreeSavepoint, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
+ rtreeShadowName /* xShadowName */
};
static int rtreeSqlInit(
diff --git a/chromium/third_party/sqlite/src/ext/rtree/rtree8.test b/chromium/third_party/sqlite/src/ext/rtree/rtree8.test
index facf4260bb0..d682fe20176 100644
--- a/chromium/third_party/sqlite/src/ext/rtree/rtree8.test
+++ b/chromium/third_party/sqlite/src/ext/rtree/rtree8.test
@@ -101,6 +101,7 @@ do_test rtree8-1.3.5 {
#
populate_t1 50
do_execsql_test rtree8-2.1.1 { SELECT max(nodeno) FROM t1_node } {5}
+sqlite3_db_config db DEFENSIVE 0
do_execsql_test rtree8-2.1.2 { DELETE FROM t1_node } {}
for {set i 1} {$i <= 50} {incr i} {
do_catchsql_test rtree8-2.1.3.$i {
@@ -121,6 +122,7 @@ do_execsql_test rtree8-2.1.6 {
populate_t1 50
+sqlite3_db_config db DEFENSIVE 0
do_execsql_test rtree8-2.2.1 {
DELETE FROM t1_parent
} {}
diff --git a/chromium/third_party/sqlite/src/ext/rtree/rtreeA.test b/chromium/third_party/sqlite/src/ext/rtree/rtreeA.test
index eb01271d870..0d69fb8ad8c 100644
--- a/chromium/third_party/sqlite/src/ext/rtree/rtreeA.test
+++ b/chromium/third_party/sqlite/src/ext/rtree/rtreeA.test
@@ -36,6 +36,7 @@ proc populate_t1 {} {
execsql { INSERT INTO t1 VALUES($i, $i, $x2, $i, $y2) }
}
execsql COMMIT
+ sqlite3_db_config db DEFENSIVE 0
}
proc truncate_node {nodeno nTrunc} {
@@ -246,6 +247,7 @@ do_execsql_test rtreeA-6.2 {
create_t1
populate_t1
sqlite3 db test.db
+sqlite3_db_config db DEFENSIVE 0
do_execsql_test rtreeA-7.100 {
UPDATE t1_node SET data=x'' WHERE rowid=1;
} {}
@@ -258,4 +260,3 @@ do_test rtreeA-7.120 {
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/rtree/rtreecheck.test b/chromium/third_party/sqlite/src/ext/rtree/rtreecheck.test
index be4e487fa3e..e795acacc01 100644
--- a/chromium/third_party/sqlite/src/ext/rtree/rtreecheck.test
+++ b/chromium/third_party/sqlite/src/ext/rtree/rtreecheck.test
@@ -61,6 +61,7 @@ proc setup_simple_db {{module rtree}} {
INSERT INTO r1 VALUES(4, 8, 8, 8, 8); -- 21
INSERT INTO r1 VALUES(5, 9, 9, 9, 9); -- 27
"
+ sqlite3_db_config db DEFENSIVE 0
}
setup_simple_db
@@ -112,6 +113,7 @@ do_execsql_test 3.1 {
SELECT rtreecheck('r2')
} {ok}
+sqlite3_db_config db DEFENSIVE 0
do_execsql_test 3.2 {
BEGIN;
UPDATE r2_node SET data = X'123456';
@@ -140,6 +142,7 @@ do_execsql_test 5.0 {
)
INSERT INTO r3 SELECT i, i, i, i, i FROM x;
}
+sqlite3_db_config db DEFENSIVE 0
do_execsql_test 5.1 {
BEGIN;
UPDATE r3_node SET data = set_int32(data, 3, 5000);
@@ -155,4 +158,3 @@ do_execsql_test 5.2 {
} 0
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/rtree/sqlite3rtree.h b/chromium/third_party/sqlite/src/ext/rtree/sqlite3rtree.h
index 8035d5ffe73..682070a665b 100644
--- a/chromium/third_party/sqlite/src/ext/rtree/sqlite3rtree.h
+++ b/chromium/third_party/sqlite/src/ext/rtree/sqlite3rtree.h
@@ -96,7 +96,7 @@ struct sqlite3_rtree_query_info {
sqlite3_int64 iRowid; /* Rowid for current entry */
sqlite3_rtree_dbl rParentScore; /* Score of parent node */
int eParentWithin; /* Visibility of parent node */
- int eWithin; /* OUT: Visiblity */
+ int eWithin; /* OUT: Visibility */
sqlite3_rtree_dbl rScore; /* OUT: Write the score here */
/* The following fields are only available in 3.8.11 and later */
sqlite3_value **apSqlParam; /* Original SQL values of parameters */
diff --git a/chromium/third_party/sqlite/src/ext/rtree/util/randomshape.tcl b/chromium/third_party/sqlite/src/ext/rtree/util/randomshape.tcl
new file mode 100644
index 00000000000..98725bc9dc2
--- /dev/null
+++ b/chromium/third_party/sqlite/src/ext/rtree/util/randomshape.tcl
@@ -0,0 +1,87 @@
+#!/usr/bin/tclsh
+#
+# This script generates a cluster of random polygons that are useful
+# for testing the geopoly extension.
+#
+# Usage:
+#
+# tclsh randomshape.tcl | tee x.sql | sqlite3 >x.html
+#
+# The output files are x.sql and x.html. Run the above multiple times
+# until an interesting "x.html" file is found, then use the "x.sql" inputs
+# to construct test cases.
+#
+proc randomenclosure {cx cy p1 p2 p3 p4} {
+ set r 0
+ set pi 3.145926
+ set pi2 [expr {$pi*2}]
+ set x0 [expr {$cx + rand()*$p3 + $p4}]
+ set ans "\[\[$x0,$cy\]"
+ while {1} {
+ set r [expr {$r+$p1+$p2*rand()}]
+ if {$r>=$pi2} break
+ set m [expr {rand()*$p3 + $p4}]
+ set x [expr {$cx+$m*cos($r)}]
+ set y [expr {$cy+$m*sin($r)}]
+ append ans ",\[$x,$y\]"
+ }
+ append ans ",\[$x0,$cy\]\]"
+ return $ans
+}
+proc randomshape1 {} {
+ set cx [expr {100+int(rand()*800)}]
+ set cy [expr {100+int(rand()*600)}]
+ set p1 [expr {rand()*0.1}]
+ set p2 [expr {rand()*0.5+0.5}]
+ set p3 [expr {rand()*100+25}]
+ set p4 [expr {rand()*25}]
+ return [randomenclosure $cx $cy $p1 $p2 $p3 $p4]
+}
+proc randomshape1_sm {} {
+ set cx [expr {100+int(rand()*800)}]
+ set cy [expr {100+int(rand()*600)}]
+ set p1 [expr {rand()*0.1}]
+ set p2 [expr {rand()*0.5+0.5}]
+ set p3 [expr {rand()*10+25}]
+ set p4 [expr {rand()*5}]
+ return [randomenclosure $cx $cy $p1 $p2 $p3 $p4]
+}
+proc randomshape2 {} {
+ set cx [expr {400+int(rand()*200)}]
+ set cy [expr {300+int(rand()*200)}]
+ set p1 [expr {rand()*0.05}]
+ set p2 [expr {rand()*0.5+0.5}]
+ set p3 [expr {rand()*50+200}]
+ set p4 [expr {rand()*50+100}]
+ return [randomenclosure $cx $cy $p1 $p2 $p3 $p4]
+}
+proc randomcolor {} {
+ set n [expr {int(rand()*5)}]
+ return [lindex {red orange green blue purple} $n]
+}
+
+puts {.print '<html>'}
+puts {.print '<svg width="1000" height="800" style="border:1px solid black">'}
+puts {CREATE TABLE t1(poly,clr);}
+puts {CREATE TABLE t2(poly,clr);}
+for {set i 0} {$i<30} {incr i} {
+ puts "INSERT INTO t1(rowid,poly,clr)"
+ puts " VALUES($i,'[randomshape1]','[randomcolor]');"
+}
+for {set i 30} {$i<80} {incr i} {
+ puts "INSERT INTO t1(rowid,poly,clr)"
+ puts " VALUES($i,'[randomshape1_sm]','[randomcolor]');"
+}
+for {set i 100} {$i<105} {incr i} {
+ puts "INSERT INTO t2(rowid,poly,clr)"
+ puts " VALUES($i,'[randomshape2]','[randomcolor]');"
+}
+
+puts {DELETE FROM t1 WHERE geopoly_json(poly) IS NULL;}
+puts {SELECT geopoly_svg(poly,
+ printf('style="fill:none;stroke:%s;stroke-width:1;"',clr))
+ FROM t1;}
+puts {SELECT geopoly_svg(poly,
+ printf('style="fill:none;stroke:%s;stroke-width:2;"',clr))
+ FROM t2;}
+puts {.print '<svg>'}
diff --git a/chromium/third_party/sqlite/src/ext/rtree/visual01.txt b/chromium/third_party/sqlite/src/ext/rtree/visual01.txt
new file mode 100644
index 00000000000..287e4471e6b
--- /dev/null
+++ b/chromium/third_party/sqlite/src/ext/rtree/visual01.txt
@@ -0,0 +1,602 @@
+#!sqlite3
+#
+# This is a visual test case for the geopoly virtual table.
+#
+# Run this script in the sqlite3 CLI, and redirect output into an
+# HTML file. This display the HTML in a webbrowser.
+#
+
+/* Test data.
+** Lots of shapes to be displayed over a 1000x800 canvas.
+*/
+CREATE TEMP TABLE basis(name TEXT, jshape TEXT);
+INSERT INTO basis(name,jshape) VALUES
+ ('box-20','[[0,0],[20,0],[20,20],[0,20],[0,0]]'),
+ ('house-70','[[0,0],[50,0],[50,50],[25,70],[0,50],[0,0]]'),
+ ('line-40','[[0,0],[40,0],[40,5],[0,5],[0,0]]'),
+ ('line-80','[[0,0],[80,0],[80,7],[0,7],[0,0]]'),
+ ('arrow-50','[[0,0],[25,25],[0,50],[15,25],[0,0]]'),
+ ('triangle-30','[[0,0],[30,0],[15,30],[0,0]]'),
+ ('angle-30','[[0,0],[30,0],[30,30],[26,30],[26,4],[0,4],[0,0]]'),
+ ('star-10','[[1,0],[5,2],[9,0],[7,4],[10,8],[7,7],[5,10],[3,7],[0,8],[3,4],[1,0]]');
+CREATE TEMP TABLE xform(A,B,C,D,clr);
+INSERT INTO xform(A,B,clr) VALUES
+ (1,0,'black'),
+ (0.707,0.707,'blue'),
+ (0.5,0.866,'red'),
+ (-0.866,0.5,'green');
+CREATE TEMP TABLE xyoff(id1,id2,xoff,yoff,PRIMARY KEY(id1,id2,xoff,yoff))
+ WITHOUT ROWID;
+INSERT INTO xyoff VALUES(1,1,811,659);
+INSERT INTO xyoff VALUES(1,1,235,550);
+INSERT INTO xyoff VALUES(1,1,481,620);
+INSERT INTO xyoff VALUES(1,1,106,494);
+INSERT INTO xyoff VALUES(1,1,487,106);
+INSERT INTO xyoff VALUES(1,1,817,595);
+INSERT INTO xyoff VALUES(1,1,240,504);
+INSERT INTO xyoff VALUES(1,1,806,457);
+INSERT INTO xyoff VALUES(1,1,608,107);
+INSERT INTO xyoff VALUES(1,1,768,662);
+INSERT INTO xyoff VALUES(1,2,808,528);
+INSERT INTO xyoff VALUES(1,2,768,528);
+INSERT INTO xyoff VALUES(1,2,771,171);
+INSERT INTO xyoff VALUES(1,2,275,671);
+INSERT INTO xyoff VALUES(1,2,326,336);
+INSERT INTO xyoff VALUES(1,2,690,688);
+INSERT INTO xyoff VALUES(1,2,597,239);
+INSERT INTO xyoff VALUES(1,2,317,528);
+INSERT INTO xyoff VALUES(1,2,366,223);
+INSERT INTO xyoff VALUES(1,2,621,154);
+INSERT INTO xyoff VALUES(1,3,829,469);
+INSERT INTO xyoff VALUES(1,3,794,322);
+INSERT INTO xyoff VALUES(1,3,358,387);
+INSERT INTO xyoff VALUES(1,3,184,444);
+INSERT INTO xyoff VALUES(1,3,729,500);
+INSERT INTO xyoff VALUES(1,3,333,523);
+INSERT INTO xyoff VALUES(1,3,117,595);
+INSERT INTO xyoff VALUES(1,3,496,201);
+INSERT INTO xyoff VALUES(1,3,818,601);
+INSERT INTO xyoff VALUES(1,3,541,343);
+INSERT INTO xyoff VALUES(1,4,603,248);
+INSERT INTO xyoff VALUES(1,4,761,649);
+INSERT INTO xyoff VALUES(1,4,611,181);
+INSERT INTO xyoff VALUES(1,4,607,233);
+INSERT INTO xyoff VALUES(1,4,860,206);
+INSERT INTO xyoff VALUES(1,4,310,231);
+INSERT INTO xyoff VALUES(1,4,727,539);
+INSERT INTO xyoff VALUES(1,4,660,661);
+INSERT INTO xyoff VALUES(1,4,403,133);
+INSERT INTO xyoff VALUES(1,4,619,331);
+INSERT INTO xyoff VALUES(2,1,712,578);
+INSERT INTO xyoff VALUES(2,1,567,313);
+INSERT INTO xyoff VALUES(2,1,231,423);
+INSERT INTO xyoff VALUES(2,1,490,175);
+INSERT INTO xyoff VALUES(2,1,898,353);
+INSERT INTO xyoff VALUES(2,1,589,483);
+INSERT INTO xyoff VALUES(2,1,188,462);
+INSERT INTO xyoff VALUES(2,1,720,106);
+INSERT INTO xyoff VALUES(2,1,793,380);
+INSERT INTO xyoff VALUES(2,1,154,396);
+INSERT INTO xyoff VALUES(2,2,324,218);
+INSERT INTO xyoff VALUES(2,2,120,327);
+INSERT INTO xyoff VALUES(2,2,655,133);
+INSERT INTO xyoff VALUES(2,2,516,603);
+INSERT INTO xyoff VALUES(2,2,529,572);
+INSERT INTO xyoff VALUES(2,2,481,212);
+INSERT INTO xyoff VALUES(2,2,802,107);
+INSERT INTO xyoff VALUES(2,2,234,509);
+INSERT INTO xyoff VALUES(2,2,501,269);
+INSERT INTO xyoff VALUES(2,2,349,553);
+INSERT INTO xyoff VALUES(2,3,495,685);
+INSERT INTO xyoff VALUES(2,3,897,372);
+INSERT INTO xyoff VALUES(2,3,350,681);
+INSERT INTO xyoff VALUES(2,3,832,257);
+INSERT INTO xyoff VALUES(2,3,778,149);
+INSERT INTO xyoff VALUES(2,3,683,426);
+INSERT INTO xyoff VALUES(2,3,693,217);
+INSERT INTO xyoff VALUES(2,3,746,317);
+INSERT INTO xyoff VALUES(2,3,805,369);
+INSERT INTO xyoff VALUES(2,3,336,585);
+INSERT INTO xyoff VALUES(2,4,890,255);
+INSERT INTO xyoff VALUES(2,4,556,565);
+INSERT INTO xyoff VALUES(2,4,865,555);
+INSERT INTO xyoff VALUES(2,4,230,293);
+INSERT INTO xyoff VALUES(2,4,247,251);
+INSERT INTO xyoff VALUES(2,4,730,563);
+INSERT INTO xyoff VALUES(2,4,318,282);
+INSERT INTO xyoff VALUES(2,4,220,431);
+INSERT INTO xyoff VALUES(2,4,828,336);
+INSERT INTO xyoff VALUES(2,4,278,525);
+INSERT INTO xyoff VALUES(3,1,324,656);
+INSERT INTO xyoff VALUES(3,1,625,362);
+INSERT INTO xyoff VALUES(3,1,155,570);
+INSERT INTO xyoff VALUES(3,1,267,433);
+INSERT INTO xyoff VALUES(3,1,599,121);
+INSERT INTO xyoff VALUES(3,1,873,498);
+INSERT INTO xyoff VALUES(3,1,789,520);
+INSERT INTO xyoff VALUES(3,1,656,378);
+INSERT INTO xyoff VALUES(3,1,831,601);
+INSERT INTO xyoff VALUES(3,1,256,471);
+INSERT INTO xyoff VALUES(3,2,332,258);
+INSERT INTO xyoff VALUES(3,2,305,463);
+INSERT INTO xyoff VALUES(3,2,796,341);
+INSERT INTO xyoff VALUES(3,2,830,229);
+INSERT INTO xyoff VALUES(3,2,413,271);
+INSERT INTO xyoff VALUES(3,2,269,140);
+INSERT INTO xyoff VALUES(3,2,628,441);
+INSERT INTO xyoff VALUES(3,2,747,643);
+INSERT INTO xyoff VALUES(3,2,584,435);
+INSERT INTO xyoff VALUES(3,2,784,314);
+INSERT INTO xyoff VALUES(3,3,722,233);
+INSERT INTO xyoff VALUES(3,3,815,421);
+INSERT INTO xyoff VALUES(3,3,401,267);
+INSERT INTO xyoff VALUES(3,3,451,650);
+INSERT INTO xyoff VALUES(3,3,329,485);
+INSERT INTO xyoff VALUES(3,3,878,370);
+INSERT INTO xyoff VALUES(3,3,162,616);
+INSERT INTO xyoff VALUES(3,3,844,183);
+INSERT INTO xyoff VALUES(3,3,161,216);
+INSERT INTO xyoff VALUES(3,3,176,676);
+INSERT INTO xyoff VALUES(3,4,780,128);
+INSERT INTO xyoff VALUES(3,4,566,121);
+INSERT INTO xyoff VALUES(3,4,646,120);
+INSERT INTO xyoff VALUES(3,4,223,557);
+INSERT INTO xyoff VALUES(3,4,251,117);
+INSERT INTO xyoff VALUES(3,4,139,209);
+INSERT INTO xyoff VALUES(3,4,813,597);
+INSERT INTO xyoff VALUES(3,4,454,538);
+INSERT INTO xyoff VALUES(3,4,616,198);
+INSERT INTO xyoff VALUES(3,4,210,159);
+INSERT INTO xyoff VALUES(4,1,208,415);
+INSERT INTO xyoff VALUES(4,1,326,665);
+INSERT INTO xyoff VALUES(4,1,612,133);
+INSERT INTO xyoff VALUES(4,1,537,513);
+INSERT INTO xyoff VALUES(4,1,638,438);
+INSERT INTO xyoff VALUES(4,1,808,269);
+INSERT INTO xyoff VALUES(4,1,552,121);
+INSERT INTO xyoff VALUES(4,1,100,189);
+INSERT INTO xyoff VALUES(4,1,643,664);
+INSERT INTO xyoff VALUES(4,1,726,378);
+INSERT INTO xyoff VALUES(4,2,478,409);
+INSERT INTO xyoff VALUES(4,2,497,507);
+INSERT INTO xyoff VALUES(4,2,233,148);
+INSERT INTO xyoff VALUES(4,2,587,237);
+INSERT INTO xyoff VALUES(4,2,604,166);
+INSERT INTO xyoff VALUES(4,2,165,455);
+INSERT INTO xyoff VALUES(4,2,320,258);
+INSERT INTO xyoff VALUES(4,2,353,496);
+INSERT INTO xyoff VALUES(4,2,347,495);
+INSERT INTO xyoff VALUES(4,2,166,622);
+INSERT INTO xyoff VALUES(4,3,461,332);
+INSERT INTO xyoff VALUES(4,3,685,278);
+INSERT INTO xyoff VALUES(4,3,427,594);
+INSERT INTO xyoff VALUES(4,3,467,346);
+INSERT INTO xyoff VALUES(4,3,125,548);
+INSERT INTO xyoff VALUES(4,3,597,680);
+INSERT INTO xyoff VALUES(4,3,820,445);
+INSERT INTO xyoff VALUES(4,3,144,330);
+INSERT INTO xyoff VALUES(4,3,557,434);
+INSERT INTO xyoff VALUES(4,3,254,315);
+INSERT INTO xyoff VALUES(4,4,157,339);
+INSERT INTO xyoff VALUES(4,4,249,220);
+INSERT INTO xyoff VALUES(4,4,391,323);
+INSERT INTO xyoff VALUES(4,4,589,429);
+INSERT INTO xyoff VALUES(4,4,859,592);
+INSERT INTO xyoff VALUES(4,4,337,680);
+INSERT INTO xyoff VALUES(4,4,410,288);
+INSERT INTO xyoff VALUES(4,4,636,596);
+INSERT INTO xyoff VALUES(4,4,734,433);
+INSERT INTO xyoff VALUES(4,4,559,549);
+INSERT INTO xyoff VALUES(5,1,549,607);
+INSERT INTO xyoff VALUES(5,1,584,498);
+INSERT INTO xyoff VALUES(5,1,699,116);
+INSERT INTO xyoff VALUES(5,1,525,524);
+INSERT INTO xyoff VALUES(5,1,304,667);
+INSERT INTO xyoff VALUES(5,1,302,232);
+INSERT INTO xyoff VALUES(5,1,403,149);
+INSERT INTO xyoff VALUES(5,1,824,403);
+INSERT INTO xyoff VALUES(5,1,697,203);
+INSERT INTO xyoff VALUES(5,1,293,689);
+INSERT INTO xyoff VALUES(5,2,199,275);
+INSERT INTO xyoff VALUES(5,2,395,393);
+INSERT INTO xyoff VALUES(5,2,657,642);
+INSERT INTO xyoff VALUES(5,2,200,655);
+INSERT INTO xyoff VALUES(5,2,882,234);
+INSERT INTO xyoff VALUES(5,2,483,565);
+INSERT INTO xyoff VALUES(5,2,755,640);
+INSERT INTO xyoff VALUES(5,2,810,305);
+INSERT INTO xyoff VALUES(5,2,731,655);
+INSERT INTO xyoff VALUES(5,2,466,690);
+INSERT INTO xyoff VALUES(5,3,563,584);
+INSERT INTO xyoff VALUES(5,3,491,117);
+INSERT INTO xyoff VALUES(5,3,779,292);
+INSERT INTO xyoff VALUES(5,3,375,637);
+INSERT INTO xyoff VALUES(5,3,253,553);
+INSERT INTO xyoff VALUES(5,3,797,514);
+INSERT INTO xyoff VALUES(5,3,229,480);
+INSERT INTO xyoff VALUES(5,3,257,194);
+INSERT INTO xyoff VALUES(5,3,449,555);
+INSERT INTO xyoff VALUES(5,3,849,630);
+INSERT INTO xyoff VALUES(5,4,329,286);
+INSERT INTO xyoff VALUES(5,4,640,197);
+INSERT INTO xyoff VALUES(5,4,104,150);
+INSERT INTO xyoff VALUES(5,4,438,272);
+INSERT INTO xyoff VALUES(5,4,773,226);
+INSERT INTO xyoff VALUES(5,4,441,650);
+INSERT INTO xyoff VALUES(5,4,242,340);
+INSERT INTO xyoff VALUES(5,4,301,435);
+INSERT INTO xyoff VALUES(5,4,171,397);
+INSERT INTO xyoff VALUES(5,4,541,619);
+INSERT INTO xyoff VALUES(6,1,651,301);
+INSERT INTO xyoff VALUES(6,1,637,137);
+INSERT INTO xyoff VALUES(6,1,765,643);
+INSERT INTO xyoff VALUES(6,1,173,296);
+INSERT INTO xyoff VALUES(6,1,263,192);
+INSERT INTO xyoff VALUES(6,1,791,302);
+INSERT INTO xyoff VALUES(6,1,860,601);
+INSERT INTO xyoff VALUES(6,1,780,445);
+INSERT INTO xyoff VALUES(6,1,462,214);
+INSERT INTO xyoff VALUES(6,1,802,207);
+INSERT INTO xyoff VALUES(6,2,811,685);
+INSERT INTO xyoff VALUES(6,2,533,531);
+INSERT INTO xyoff VALUES(6,2,390,614);
+INSERT INTO xyoff VALUES(6,2,260,580);
+INSERT INTO xyoff VALUES(6,2,116,377);
+INSERT INTO xyoff VALUES(6,2,860,458);
+INSERT INTO xyoff VALUES(6,2,438,590);
+INSERT INTO xyoff VALUES(6,2,604,562);
+INSERT INTO xyoff VALUES(6,2,241,242);
+INSERT INTO xyoff VALUES(6,2,667,298);
+INSERT INTO xyoff VALUES(6,3,787,698);
+INSERT INTO xyoff VALUES(6,3,868,521);
+INSERT INTO xyoff VALUES(6,3,412,587);
+INSERT INTO xyoff VALUES(6,3,640,131);
+INSERT INTO xyoff VALUES(6,3,748,410);
+INSERT INTO xyoff VALUES(6,3,257,244);
+INSERT INTO xyoff VALUES(6,3,411,195);
+INSERT INTO xyoff VALUES(6,3,464,356);
+INSERT INTO xyoff VALUES(6,3,157,339);
+INSERT INTO xyoff VALUES(6,3,434,505);
+INSERT INTO xyoff VALUES(6,4,480,671);
+INSERT INTO xyoff VALUES(6,4,519,228);
+INSERT INTO xyoff VALUES(6,4,404,513);
+INSERT INTO xyoff VALUES(6,4,120,538);
+INSERT INTO xyoff VALUES(6,4,403,663);
+INSERT INTO xyoff VALUES(6,4,477,677);
+INSERT INTO xyoff VALUES(6,4,690,154);
+INSERT INTO xyoff VALUES(6,4,606,498);
+INSERT INTO xyoff VALUES(6,4,430,665);
+INSERT INTO xyoff VALUES(6,4,499,273);
+INSERT INTO xyoff VALUES(7,1,118,526);
+INSERT INTO xyoff VALUES(7,1,817,522);
+INSERT INTO xyoff VALUES(7,1,388,638);
+INSERT INTO xyoff VALUES(7,1,181,265);
+INSERT INTO xyoff VALUES(7,1,442,332);
+INSERT INTO xyoff VALUES(7,1,475,282);
+INSERT INTO xyoff VALUES(7,1,722,633);
+INSERT INTO xyoff VALUES(7,1,104,394);
+INSERT INTO xyoff VALUES(7,1,631,262);
+INSERT INTO xyoff VALUES(7,1,372,392);
+INSERT INTO xyoff VALUES(7,2,600,413);
+INSERT INTO xyoff VALUES(7,2,386,223);
+INSERT INTO xyoff VALUES(7,2,839,174);
+INSERT INTO xyoff VALUES(7,2,293,410);
+INSERT INTO xyoff VALUES(7,2,281,391);
+INSERT INTO xyoff VALUES(7,2,859,387);
+INSERT INTO xyoff VALUES(7,2,478,347);
+INSERT INTO xyoff VALUES(7,2,646,690);
+INSERT INTO xyoff VALUES(7,2,713,234);
+INSERT INTO xyoff VALUES(7,2,199,588);
+INSERT INTO xyoff VALUES(7,3,389,256);
+INSERT INTO xyoff VALUES(7,3,349,542);
+INSERT INTO xyoff VALUES(7,3,363,345);
+INSERT INTO xyoff VALUES(7,3,751,302);
+INSERT INTO xyoff VALUES(7,3,423,386);
+INSERT INTO xyoff VALUES(7,3,267,444);
+INSERT INTO xyoff VALUES(7,3,243,182);
+INSERT INTO xyoff VALUES(7,3,453,658);
+INSERT INTO xyoff VALUES(7,3,126,345);
+INSERT INTO xyoff VALUES(7,3,120,472);
+INSERT INTO xyoff VALUES(7,4,359,654);
+INSERT INTO xyoff VALUES(7,4,339,516);
+INSERT INTO xyoff VALUES(7,4,710,452);
+INSERT INTO xyoff VALUES(7,4,810,560);
+INSERT INTO xyoff VALUES(7,4,644,692);
+INSERT INTO xyoff VALUES(7,4,826,327);
+INSERT INTO xyoff VALUES(7,4,465,462);
+INSERT INTO xyoff VALUES(7,4,310,456);
+INSERT INTO xyoff VALUES(7,4,577,613);
+INSERT INTO xyoff VALUES(7,4,502,555);
+INSERT INTO xyoff VALUES(8,1,601,620);
+INSERT INTO xyoff VALUES(8,1,372,683);
+INSERT INTO xyoff VALUES(8,1,758,399);
+INSERT INTO xyoff VALUES(8,1,485,552);
+INSERT INTO xyoff VALUES(8,1,159,563);
+INSERT INTO xyoff VALUES(8,1,536,303);
+INSERT INTO xyoff VALUES(8,1,122,263);
+INSERT INTO xyoff VALUES(8,1,836,435);
+INSERT INTO xyoff VALUES(8,1,544,146);
+INSERT INTO xyoff VALUES(8,1,270,277);
+INSERT INTO xyoff VALUES(8,2,849,281);
+INSERT INTO xyoff VALUES(8,2,563,242);
+INSERT INTO xyoff VALUES(8,2,704,463);
+INSERT INTO xyoff VALUES(8,2,102,165);
+INSERT INTO xyoff VALUES(8,2,797,524);
+INSERT INTO xyoff VALUES(8,2,612,426);
+INSERT INTO xyoff VALUES(8,2,345,372);
+INSERT INTO xyoff VALUES(8,2,820,376);
+INSERT INTO xyoff VALUES(8,2,789,156);
+INSERT INTO xyoff VALUES(8,2,321,466);
+INSERT INTO xyoff VALUES(8,3,150,332);
+INSERT INTO xyoff VALUES(8,3,136,152);
+INSERT INTO xyoff VALUES(8,3,468,528);
+INSERT INTO xyoff VALUES(8,3,409,192);
+INSERT INTO xyoff VALUES(8,3,820,216);
+INSERT INTO xyoff VALUES(8,3,847,249);
+INSERT INTO xyoff VALUES(8,3,801,267);
+INSERT INTO xyoff VALUES(8,3,181,670);
+INSERT INTO xyoff VALUES(8,3,398,563);
+INSERT INTO xyoff VALUES(8,3,439,576);
+INSERT INTO xyoff VALUES(8,4,123,309);
+INSERT INTO xyoff VALUES(8,4,190,496);
+INSERT INTO xyoff VALUES(8,4,571,531);
+INSERT INTO xyoff VALUES(8,4,290,255);
+INSERT INTO xyoff VALUES(8,4,244,412);
+INSERT INTO xyoff VALUES(8,4,264,596);
+INSERT INTO xyoff VALUES(8,4,253,420);
+INSERT INTO xyoff VALUES(8,4,847,536);
+INSERT INTO xyoff VALUES(8,4,120,288);
+INSERT INTO xyoff VALUES(8,4,331,639);
+
+/* Create the geopoly object from test data above */
+CREATE VIRTUAL TABLE geo1 USING geopoly(type,clr);
+INSERT INTO geo1(_shape,type,clr)
+ SELECT geopoly_xform(jshape,A,B,-B,A,xoff,yoff), basis.name, xform.clr
+ FROM basis, xform, xyoff
+ WHERE xyoff.id1=basis.rowid AND xyoff.id2=xform.rowid;
+
+
+/* Query polygon */
+CREATE TEMP TABLE querypoly(poly JSON, clr TEXT);
+INSERT INTO querypoly(clr, poly) VALUES
+ ('orange', '[[300,300],[400,350],[500,250],[480,500],[400,480],[300,550],[280,450],[320,400],[280,350],[300,300]]');
+
+/* Generate the HTML */
+.print '<html>'
+.print '<h1>Everything</h1>'
+.print '<svg width="1000" height="800" style="border:1px solid black">'
+SELECT geopoly_svg(_shape,
+ printf('style="fill:none;stroke:%s;stroke-width:1"',clr)
+ )
+ FROM geo1;
+SELECT geopoly_svg(poly,
+ printf('style="fill:%s;fill-opacity:0.5;"',clr)
+ )
+ FROM querypoly;
+.print '</svg>'
+
+.print '<h1>Overlap Query</h1>'
+.print '<pre>'
+.print 'SELECT *'
+.print ' FROM geo1, querypoly'
+.print ' WHERE geopoly_overlap(_shape, poly);'
+.print
+EXPLAIN QUERY PLAN
+SELECT geopoly_svg(_shape,
+ printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr)
+ )
+ FROM geo1, querypoly
+ WHERE geopoly_overlap(_shape, poly);
+.print '</pre>'
+.print '<svg width="1000" height="800" style="border:1px solid black">'
+SELECT geopoly_svg(_shape,
+ printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr)
+ )
+ FROM geo1, querypoly
+ WHERE geopoly_overlap(_shape, poly);
+SELECT geopoly_svg(poly,
+ printf('style="fill:%s;fill-opacity:0.5;"',clr)
+ )
+ FROM querypoly;
+.print '</svg>'
+
+.print '<h1>Overlap Query And Result Bounding Box</h1>'
+.print '<svg width="1000" height="800" style="border:1px solid black">'
+SELECT geopoly_svg(_shape,
+ printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr)
+ )
+ FROM geo1, querypoly
+ WHERE geopoly_overlap(_shape, poly);
+SELECT geopoly_svg(geopoly_bbox(poly),
+ 'style="fill:none;stroke:black;stroke-width:3"'
+ )
+ FROM querypoly;
+SELECT geopoly_svg(poly,
+ printf('style="fill:%s;fill-opacity:0.5;"',clr)
+ )
+ FROM querypoly;
+SELECT geopoly_svg(geopoly_group_bbox(_shape),
+ 'style="fill:none;stroke:red;stroke-width:3"'
+ )
+ FROM geo1, querypoly
+ WHERE geopoly_overlap(_shape, poly);
+.print '</svg>'
+
+.print '<h1>Bounding-Box Overlap Query</h1>'
+.print '<svg width="1000" height="800" style="border:1px solid black">'
+SELECT geopoly_svg(_shape,
+ printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr)
+ ),
+ geopoly_svg(geopoly_bbox(_shape),
+ 'style="fill:none;stroke:black;stroke-width:1"'
+ )
+ FROM geo1, querypoly
+ WHERE geopoly_overlap(geopoly_bbox(_shape), geopoly_bbox(poly));
+SELECT geopoly_svg(poly,
+ printf('style="fill:%s;fill-opacity:0.5;"',clr)
+ )
+ FROM querypoly;
+SELECT geopoly_svg(geopoly_bbox(poly),
+ 'style="fill:none;stroke:black;stroke-width:3"'
+ )
+ FROM querypoly;
+.print '</svg>'
+
+.print '<h1>Within Query</h1>'
+.print '<pre>'
+.print 'SELECT *'
+.print ' FROM geo1, querypoly'
+.print ' WHERE geopoly_within(_shape, poly);'
+.print
+EXPLAIN QUERY PLAN
+SELECT geopoly_svg(_shape,
+ printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr)
+ )
+ FROM geo1, querypoly
+ WHERE geopoly_within(_shape, poly);
+.print '</pre>'
+.print '<svg width="1000" height="800" style="border:1px solid black">'
+SELECT geopoly_svg(_shape,
+ printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr)
+ )
+ FROM geo1, querypoly
+ WHERE geopoly_within(_shape, poly);
+SELECT geopoly_svg(poly,
+ printf('style="fill:%s;fill-opacity:0.5;"',clr)
+ )
+ FROM querypoly;
+.print '</svg>'
+
+.print '<h1>Bounding-Box WITHIN Query</h1>'
+.print '<svg width="1000" height="800" style="border:1px solid black">'
+SELECT geopoly_svg(_shape,
+ printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr)
+ ),
+ geopoly_svg(geopoly_bbox(_shape),
+ 'style="fill:none;stroke:black;stroke-width:1"'
+ )
+ FROM geo1, querypoly
+ WHERE geopoly_within(geopoly_bbox(_shape), geopoly_bbox(poly));
+SELECT geopoly_svg(poly,
+ printf('style="fill:%s;fill-opacity:0.5;"',clr)
+ )
+ FROM querypoly;
+SELECT geopoly_svg(geopoly_bbox(poly),
+ 'style="fill:none;stroke:black;stroke-width:3"'
+ )
+ FROM querypoly;
+.print '</svg>'
+
+.print '<h1>Not Overlap Query</h1>'
+.print '<pre>'
+.print 'SELECT *'
+.print ' FROM geo1, querypoly'
+.print ' WHERE NOT geopoly_overlap(_shape, poly);'
+.print
+EXPLAIN QUERY PLAN
+SELECT geopoly_svg(_shape,
+ printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr)
+ )
+ FROM geo1, querypoly
+ WHERE NOT geopoly_overlap(_shape, poly);
+.print '</pre>'
+.print '<svg width="1000" height="800" style="border:1px solid black">'
+SELECT geopoly_svg(_shape,
+ printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr)
+ )
+ FROM geo1, querypoly
+ WHERE NOT geopoly_overlap(_shape, poly);
+SELECT geopoly_svg(poly,
+ printf('style="fill:%s;fill-opacity:0.5;"',clr)
+ )
+ FROM querypoly;
+.print '</svg>'
+
+.print '<h1>Not Within Query</h1>'
+.print '<pre>'
+.print 'SELECT *'
+.print ' FROM geo1, querypoly'
+.print ' WHERE NOT geopoly_within(_shape, poly);'
+.print
+EXPLAIN QUERY PLAN
+SELECT geopoly_svg(_shape,
+ printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr)
+ )
+ FROM geo1, querypoly
+ WHERE NOT geopoly_within(_shape, poly);
+.print '</pre>'
+.print '<svg width="1000" height="800" style="border:1px solid black">'
+SELECT geopoly_svg(_shape,
+ printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr)
+ )
+ FROM geo1, querypoly
+ WHERE NOT geopoly_within(_shape, poly);
+SELECT geopoly_svg(poly,
+ printf('style="fill:%s;fill-opacity:0.5;"',clr)
+ )
+ FROM querypoly;
+.print '</svg>'
+
+.print '<h1>Color-Change For Overlapping Elements</h1>'
+BEGIN;
+UPDATE geo1
+ SET clr=CASE WHEN rowid IN (SELECT geo1.rowid FROM geo1, querypoly
+ WHERE geopoly_overlap(_shape,poly))
+ THEN 'red' ELSE 'blue' END;
+.print '<svg width="1000" height="800" style="border:1px solid black">'
+SELECT geopoly_svg(_shape,
+ printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr)
+ )
+ FROM geo1;
+SELECT geopoly_svg(poly,'style="fill:none;stroke:black;stroke-width:2"')
+ FROM querypoly;
+ROLLBACK;
+.print '</svg>'
+
+.print '<h1>Color-Change And Move Overlapping Elements</h1>'
+BEGIN;
+UPDATE geo1
+ SET clr=CASE WHEN rowid IN (SELECT geo1.rowid FROM geo1, querypoly
+ WHERE geopoly_overlap(_shape,poly))
+ THEN 'red' ELSE '#76ccff' END;
+UPDATE geo1
+ SET _shape=geopoly_xform(_shape,1,0,0,1,300,0)
+ WHERE geopoly_overlap(_shape,(SELECT poly FROM querypoly));
+.print '<svg width="1000" height="800" style="border:1px solid black">'
+SELECT geopoly_svg(_shape,
+ printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr)
+ )
+ FROM geo1;
+SELECT geopoly_svg(poly,'style="fill:none;stroke:black;stroke-width:2"')
+ FROM querypoly;
+--ROLLBACK;
+.print '</svg>'
+
+
+.print '<h1>Overlap With Translated Query Polygon</h1>'
+UPDATE querypoly SET poly=geopoly_xform(poly,1,0,0,1,300,0);
+.print '<svg width="1000" height="800" style="border:1px solid black">'
+SELECT geopoly_svg(_shape,
+ printf('style="fill:none;stroke:%s;stroke-width:1"',geo1.clr)
+ )
+ FROM geo1
+ WHERE geopoly_overlap(_shape,(SELECT poly FROM querypoly));
+SELECT geopoly_svg(poly,'style="fill:none;stroke:black;stroke-width:2"')
+ FROM querypoly;
+ROLLBACK;
+.print '</svg>'
+
+.print '<h1>Regular Polygons</h1>'
+.print '<svg width="1000" height="200" style="border:1px solid black">'
+SELECT geopoly_svg(geopoly_regular(100,100,40,3),'style="fill:none;stroke:red;stroke-width:1"');
+SELECT geopoly_svg(geopoly_regular(200,100,40,4),'style="fill:none;stroke:orange;stroke-width:1"');
+SELECT geopoly_svg(geopoly_regular(300,100,40,5),'style="fill:none;stroke:green;stroke-width:1"');
+SELECT geopoly_svg(geopoly_regular(400,100,40,6),'style="fill:none;stroke:blue;stroke-width:1"');
+SELECT geopoly_svg(geopoly_regular(500,100,40,7),'style="fill:none;stroke:purple;stroke-width:1"');
+SELECT geopoly_svg(geopoly_regular(600,100,40,8),'style="fill:none;stroke:red;stroke-width:1"');
+SELECT geopoly_svg(geopoly_regular(700,100,40,10),'style="fill:none;stroke:orange;stroke-width:1"');
+SELECT geopoly_svg(geopoly_regular(800,100,40,20),'style="fill:none;stroke:green;stroke-width:1"');
+SELECT geopoly_svg(geopoly_regular(900,100,40,30),'style="fill:none;stroke:blue;stroke-width:1"');
+.print '</svg>'
+
+.print '</html>'
diff --git a/chromium/third_party/sqlite/src/ext/session/changesetfuzz.c b/chromium/third_party/sqlite/src/ext/session/changesetfuzz.c
new file mode 100644
index 00000000000..9b3619d64fe
--- /dev/null
+++ b/chromium/third_party/sqlite/src/ext/session/changesetfuzz.c
@@ -0,0 +1,1240 @@
+/*
+** 2018-11-01
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains code to implement the "changesetfuzz" command
+** line utility for fuzzing changeset blobs without corrupting them.
+*/
+
+
+/************************************************************************
+** USAGE:
+**
+** This program may be invoked in two ways:
+**
+** changesetfuzz INPUT
+** changesetfuzz INPUT SEED N
+**
+** Argument INPUT must be the name of a file containing a binary changeset.
+** In the first form above, this program outputs a human-readable version
+** of the same changeset. This is chiefly for debugging.
+**
+** As well as changesets, this program can also dump and fuzz patchsets.
+** The term "changeset" is used for both patchsets and changesets from this
+** point on.
+**
+** In the second form, arguments SEED and N must both be integers. In this
+** case, this program writes N binary changesets to disk. Each output
+** changeset is a slightly modified - "fuzzed" - version of the input.
+** The output changesets are written to files name "INPUT-$n", where $n is
+** an integer between 0 and N-1, inclusive. Output changesets are always
+** well-formed. Parameter SEED is used to seed the PRNG - any two
+** invocations of this program with the same SEED and input changeset create
+** the same N output changesets.
+**
+** The ways in which an input changeset may be fuzzed are as follows:
+**
+** 1. Any two values within the changeset may be exchanged.
+**
+** 2. Any TEXT, BLOB, INTEGER or REAL value within the changeset
+** may have a single bit of its content flipped.
+**
+** 3. Any value within a changeset may be replaced by a pseudo-randomly
+** generated value.
+**
+** The above operations never set a PRIMARY KEY column to NULL. Nor do they
+** set any value to "undefined", or replace any "undefined" value with
+** another. Any such operation risks producing a changeset that is not
+** well-formed.
+**
+** 4. A single change may be duplicated.
+**
+** 5. A single change may be removed, so long as this does not mean that
+** there are zero changes following a table-header within the changeset.
+**
+** 6. A single change may have its type (INSERT, DELETE, UPDATE) changed.
+** If an INSERT is changed to a DELETE (or vice versa), the type is
+** simply changed - no other modifications are required. If an INSERT
+** or DELETE is changed to an UPDATE, then the single record is duplicated
+** (as both the old.* and new.* records of the new UPDATE change). If an
+** UPDATE is changed to a DELETE or INSERT, the new.* record is discarded
+** and any "undefined" fields replaced with pseudo-randomly generated
+** values.
+**
+** 7. An UPDATE change that modifies N table columns may be modified so
+** that it updates N-1 columns, so long as (N>1).
+**
+** 8. The "indirect" flag may be toggled for any change.
+**
+** Entire group of changes may also be operated on:
+**
+** 9. Duplicate an existing group.
+**
+** 10. Remove an existing group.
+**
+** 11. The positions of two groups may be exchanged.
+**
+** There are also schema changes:
+**
+** 12. A non-PK column may be added to a table. In this case a NULL
+** value is appended to all records.
+**
+** 13. A PK column may be added to a table. In this case a non-NULL
+** value is appended to all INSERT, DELETE and UPDATE old.* records.
+** An "undefined" is appended to new.* UPDATE records.
+**
+** 14. A column may be removed from a table, provided that it is not the
+** only PRIMARY KEY column in the table. In this case the corresponding
+** field is removed from all records. In cases where this leaves an UPDATE
+** with no non-PK, non-undefined fields, the entire change is removed.
+*/
+
+#include "sqlite3.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+
+#define FUZZ_VALUE_SUB 1 /* Replace one value with a copy of another */
+#define FUZZ_VALUE_MOD 2 /* Modify content by 1 bit */
+#define FUZZ_VALUE_RND 3 /* Replace with pseudo-random value */
+
+#define FUZZ_CHANGE_DUP 4 /* Duplicate an existing change */
+#define FUZZ_CHANGE_DEL 5 /* Completely remove one change */
+#define FUZZ_CHANGE_TYPE 6 /* Change the type of one change */
+#define FUZZ_CHANGE_FIELD 7 /* Change an UPDATE to modify fewer columns */
+#define FUZZ_CHANGE_INDIRECT 8 /* Toggle the "indirect" flag of a change */
+
+#define FUZZ_GROUP_DUP 9 /* Duplicate a change group */
+#define FUZZ_GROUP_DEL 10 /* Delete an entire change group */
+#define FUZZ_GROUP_SWAP 11 /* Exchange the position of two groups */
+
+#define FUZZ_COLUMN_ADD 12 /* Add column to table definition */
+#define FUZZ_COLUMN_ADDPK 13 /* Add PK column to table definition */
+#define FUZZ_COLUMN_DEL 14 /* Remove column from table definition */
+
+
+
+typedef unsigned char u8;
+typedef sqlite3_uint64 u64;
+typedef sqlite3_int64 i64;
+typedef unsigned int u32;
+
+/*
+** Show a usage message on stderr then quit.
+*/
+static void usage(const char *argv0){
+ fprintf(stderr, "Usage: %s FILENAME ?SEED N?\n", argv0);
+ exit(1);
+}
+
+/*
+** Read the content of a disk file into an in-memory buffer
+*/
+static void fuzzReadFile(const char *zFilename, int *pSz, void **ppBuf){
+ FILE *f;
+ int sz;
+ void *pBuf;
+ f = fopen(zFilename, "rb");
+ if( f==0 ){
+ fprintf(stderr, "cannot open \"%s\" for reading\n", zFilename);
+ exit(1);
+ }
+ fseek(f, 0, SEEK_END);
+ sz = (int)ftell(f);
+ rewind(f);
+ pBuf = sqlite3_malloc( sz ? sz : 1 );
+ if( pBuf==0 ){
+ fprintf(stderr, "cannot allocate %d to hold content of \"%s\"\n",
+ sz, zFilename);
+ exit(1);
+ }
+ if( sz>0 ){
+ if( fread(pBuf, sz, 1, f)!=1 ){
+ fprintf(stderr, "cannot read all %d bytes of \"%s\"\n", sz, zFilename);
+ exit(1);
+ }
+ fclose(f);
+ }
+ *pSz = sz;
+ *ppBuf = pBuf;
+}
+
+/*
+** Write the contents of buffer pBuf, size nBuf bytes, into file zFilename
+** on disk. zFilename, if it already exists, is clobbered.
+*/
+static void fuzzWriteFile(const char *zFilename, void *pBuf, int nBuf){
+ FILE *f;
+ f = fopen(zFilename, "wb");
+ if( f==0 ){
+ fprintf(stderr, "cannot open \"%s\" for writing\n", zFilename);
+ exit(1);
+ }
+ if( fwrite(pBuf, nBuf, 1, f)!=1 ){
+ fprintf(stderr, "cannot write to \"%s\"\n", zFilename);
+ exit(1);
+ }
+ fclose(f);
+}
+
+static int fuzzCorrupt(){
+ return SQLITE_CORRUPT;
+}
+
+/*************************************************************************
+** The following block is a copy of the implementation of SQLite function
+** sqlite3_randomness. This version has two important differences:
+**
+** 1. It always uses the same seed. So the sequence of random data output
+** is the same for every run of the program.
+**
+** 2. It is not threadsafe.
+*/
+static struct sqlite3PrngType {
+ unsigned char i, j; /* State variables */
+ unsigned char s[256]; /* State variables */
+} sqlite3Prng = {
+ 0xAF, 0x28,
+ {
+ 0x71, 0xF5, 0xB4, 0x6E, 0x80, 0xAB, 0x1D, 0xB8,
+ 0xFB, 0xB7, 0x49, 0xBF, 0xFF, 0x72, 0x2D, 0x14,
+ 0x79, 0x09, 0xE3, 0x78, 0x76, 0xB0, 0x2C, 0x0A,
+ 0x8E, 0x23, 0xEE, 0xDF, 0xE0, 0x9A, 0x2F, 0x67,
+ 0xE1, 0xBE, 0x0E, 0xA7, 0x08, 0x97, 0xEB, 0x77,
+ 0x78, 0xBA, 0x9D, 0xCA, 0x49, 0x4C, 0x60, 0x9A,
+ 0xF6, 0xBD, 0xDA, 0x7F, 0xBC, 0x48, 0x58, 0x52,
+ 0xE5, 0xCD, 0x83, 0x72, 0x23, 0x52, 0xFF, 0x6D,
+ 0xEF, 0x0F, 0x82, 0x29, 0xA0, 0x83, 0x3F, 0x7D,
+ 0xA4, 0x88, 0x31, 0xE7, 0x88, 0x92, 0x3B, 0x9B,
+ 0x3B, 0x2C, 0xC2, 0x4C, 0x71, 0xA2, 0xB0, 0xEA,
+ 0x36, 0xD0, 0x00, 0xF1, 0xD3, 0x39, 0x17, 0x5D,
+ 0x2A, 0x7A, 0xE4, 0xAD, 0xE1, 0x64, 0xCE, 0x0F,
+ 0x9C, 0xD9, 0xF5, 0xED, 0xB0, 0x22, 0x5E, 0x62,
+ 0x97, 0x02, 0xA3, 0x8C, 0x67, 0x80, 0xFC, 0x88,
+ 0x14, 0x0B, 0x15, 0x10, 0x0F, 0xC7, 0x40, 0xD4,
+ 0xF1, 0xF9, 0x0E, 0x1A, 0xCE, 0xB9, 0x1E, 0xA1,
+ 0x72, 0x8E, 0xD7, 0x78, 0x39, 0xCD, 0xF4, 0x5D,
+ 0x2A, 0x59, 0x26, 0x34, 0xF2, 0x73, 0x0B, 0xA0,
+ 0x02, 0x51, 0x2C, 0x03, 0xA3, 0xA7, 0x43, 0x13,
+ 0xE8, 0x98, 0x2B, 0xD2, 0x53, 0xF8, 0xEE, 0x91,
+ 0x7D, 0xE7, 0xE3, 0xDA, 0xD5, 0xBB, 0xC0, 0x92,
+ 0x9D, 0x98, 0x01, 0x2C, 0xF9, 0xB9, 0xA0, 0xEB,
+ 0xCF, 0x32, 0xFA, 0x01, 0x49, 0xA5, 0x1D, 0x9A,
+ 0x76, 0x86, 0x3F, 0x40, 0xD4, 0x89, 0x8F, 0x9C,
+ 0xE2, 0xE3, 0x11, 0x31, 0x37, 0xB2, 0x49, 0x28,
+ 0x35, 0xC0, 0x99, 0xB6, 0xD0, 0xBC, 0x66, 0x35,
+ 0xF7, 0x83, 0x5B, 0xD7, 0x37, 0x1A, 0x2B, 0x18,
+ 0xA6, 0xFF, 0x8D, 0x7C, 0x81, 0xA8, 0xFC, 0x9E,
+ 0xC4, 0xEC, 0x80, 0xD0, 0x98, 0xA7, 0x76, 0xCC,
+ 0x9C, 0x2F, 0x7B, 0xFF, 0x8E, 0x0E, 0xBB, 0x90,
+ 0xAE, 0x13, 0x06, 0xF5, 0x1C, 0x4E, 0x52, 0xF7
+ }
+};
+
+/*
+** Generate and return single random byte
+*/
+static unsigned char fuzzRandomByte(void){
+ unsigned char t;
+ sqlite3Prng.i++;
+ t = sqlite3Prng.s[sqlite3Prng.i];
+ sqlite3Prng.j += t;
+ sqlite3Prng.s[sqlite3Prng.i] = sqlite3Prng.s[sqlite3Prng.j];
+ sqlite3Prng.s[sqlite3Prng.j] = t;
+ t += sqlite3Prng.s[sqlite3Prng.i];
+ return sqlite3Prng.s[t];
+}
+
+/*
+** Return N random bytes.
+*/
+static void fuzzRandomBlob(int nBuf, unsigned char *zBuf){
+ int i;
+ for(i=0; i<nBuf; i++){
+ zBuf[i] = fuzzRandomByte();
+ }
+}
+
+/*
+** Return a random integer between 0 and nRange (not inclusive).
+*/
+static unsigned int fuzzRandomInt(unsigned int nRange){
+ unsigned int ret;
+ assert( nRange>0 );
+ fuzzRandomBlob(sizeof(ret), (unsigned char*)&ret);
+ return (ret % nRange);
+}
+
+static u64 fuzzRandomU64(){
+ u64 ret;
+ fuzzRandomBlob(sizeof(ret), (unsigned char*)&ret);
+ return ret;
+}
+
+static void fuzzRandomSeed(unsigned int iSeed){
+ int i;
+ for(i=0; i<256; i+=4){
+ sqlite3Prng.s[i] ^= ((iSeed >> 24) & 0xFF);
+ sqlite3Prng.s[i+1] ^= ((iSeed >> 16) & 0xFF);
+ sqlite3Prng.s[i+2] ^= ((iSeed >> 8) & 0xFF);
+ sqlite3Prng.s[i+3] ^= ((iSeed >> 0) & 0xFF);
+ }
+}
+/*
+** End of code for generating pseudo-random values.
+*************************************************************************/
+
+typedef struct FuzzChangeset FuzzChangeset;
+typedef struct FuzzChangesetGroup FuzzChangesetGroup;
+typedef struct FuzzChange FuzzChange;
+
+/*
+** Object containing partially parsed changeset.
+*/
+struct FuzzChangeset {
+ int bPatchset; /* True for a patchset */
+ FuzzChangesetGroup **apGroup; /* Array of groups in changeset */
+ int nGroup; /* Number of items in list pGroup */
+ u8 **apVal; /* Array of all values in changeset */
+ int nVal; /* Number of used slots in apVal[] */
+ int nChange; /* Number of changes in changeset */
+ int nUpdate; /* Number of UPDATE changes in changeset */
+};
+
+/*
+** There is one object of this type for each change-group (table header)
+** in the input changeset.
+*/
+struct FuzzChangesetGroup {
+ const char *zTab; /* Name of table */
+ int nCol; /* Number of columns in table */
+ u8 *aPK; /* PK array for this table */
+ u8 *aChange; /* Buffer containing array of changes */
+ int szChange; /* Size of buffer aChange[] in bytes */
+ int nChange; /* Number of changes in buffer aChange[] */
+};
+
+/*
+** Description of a fuzz change to be applied to a changeset.
+*/
+struct FuzzChange {
+ int eType; /* One of the FUZZ_* constants above */
+ int iChange; /* Change or UPDATE to modify */
+ int iGroup; /* Group to modify */
+ int iDelete; /* Field to remove (FUZZ_COLUMN_DEL) */
+ u8 *pSub1; /* Replace this value with pSub2 */
+ u8 *pSub2; /* And this one with pSub1 */
+ u8 aSub[128]; /* Buffer for substitute value */
+ int iCurrent; /* Current change number */
+};
+
+/*
+** Allocate and return nByte bytes of zeroed memory.
+*/
+static void *fuzzMalloc(int nByte){
+ void *pRet = sqlite3_malloc(nByte);
+ if( pRet ){
+ memset(pRet, 0, nByte);
+ }
+ return pRet;
+}
+
+/*
+** Free the buffer indicated by the first argument. This function is used
+** to free buffers allocated by fuzzMalloc().
+*/
+static void fuzzFree(void *p){
+ sqlite3_free(p);
+}
+
+/*
+** Argument p points to a buffer containing an SQLite varint that, assuming the
+** input is not corrupt, may be between 0 and 0x7FFFFFFF, inclusive. Before
+** returning, this function sets (*pnVal) to the value of that varint, and
+** returns the number of bytes of space that it takes up.
+*/
+static int fuzzGetVarint(u8 *p, int *pnVal){
+ int i;
+ sqlite3_uint64 nVal = 0;
+ for(i=0; i<9; i++){
+ nVal = (nVal<<7) + (p[i] & 0x7F);
+ if( (p[i] & 0x80)==0 ){
+ i++;
+ break;
+ }
+ }
+ *pnVal = (int)nVal;
+ return i;
+}
+
+/*
+** Write value nVal into the buffer indicated by argument p as an SQLite
+** varint. nVal is guaranteed to be between 0 and (2^21-1), inclusive.
+** Return the number of bytes written to buffer p.
+*/
+static int fuzzPutVarint(u8 *p, int nVal){
+ assert( nVal>0 && nVal<2097152 );
+ if( nVal<128 ){
+ p[0] = nVal;
+ return 1;
+ }
+ if( nVal<16384 ){
+ p[0] = ((nVal >> 7) & 0x7F) | 0x80;
+ p[1] = (nVal & 0x7F);
+ return 2;
+ }
+
+ p[0] = ((nVal >> 14) & 0x7F) | 0x80;
+ p[1] = ((nVal >> 7) & 0x7F) | 0x80;
+ p[2] = (nVal & 0x7F);
+ return 3;
+}
+
+/*
+** Read a 64-bit big-endian integer value from buffer aRec[]. Return
+** the value read.
+*/
+static i64 fuzzGetI64(u8 *aRec){
+ return (i64)(
+ (((u64)aRec[0]) << 56)
+ + (((u64)aRec[1]) << 48)
+ + (((u64)aRec[2]) << 40)
+ + (((u64)aRec[3]) << 32)
+ + (((u64)aRec[4]) << 24)
+ + (((u64)aRec[5]) << 16)
+ + (((u64)aRec[6]) << 8)
+ + (((u64)aRec[7]) << 0)
+ );
+}
+
+/*
+** Write value iVal to buffer aRec[] as an unsigned 64-bit big-endian integer.
+*/
+static void fuzzPutU64(u8 *aRec, u64 iVal){
+ aRec[0] = (iVal>>56) & 0xFF;
+ aRec[1] = (iVal>>48) & 0xFF;
+ aRec[2] = (iVal>>40) & 0xFF;
+ aRec[3] = (iVal>>32) & 0xFF;
+ aRec[4] = (iVal>>24) & 0xFF;
+ aRec[5] = (iVal>>16) & 0xFF;
+ aRec[6] = (iVal>> 8) & 0xFF;
+ aRec[7] = (iVal) & 0xFF;
+}
+
+/*
+** Parse a single table-header from the input. Allocate a new change-group
+** object with the results. Return SQLITE_OK if successful, or an error code
+** otherwise.
+*/
+static int fuzzParseHeader(
+ FuzzChangeset *pParse, /* Changeset parse object */
+ u8 **ppHdr, /* IN/OUT: Iterator */
+ u8 *pEnd, /* 1 byte past EOF */
+ FuzzChangesetGroup **ppGrp /* OUT: New change-group object */
+){
+ int rc = SQLITE_OK;
+ FuzzChangesetGroup *pGrp;
+ u8 cHdr = (pParse->bPatchset ? 'P' : 'T');
+
+ assert( pEnd>(*ppHdr) );
+ pGrp = (FuzzChangesetGroup*)fuzzMalloc(sizeof(FuzzChangesetGroup));
+ if( !pGrp ){
+ rc = SQLITE_NOMEM;
+ }else{
+ u8 *p = *ppHdr;
+ if( p[0]!=cHdr ){
+ rc = fuzzCorrupt();
+ }else{
+ p++;
+ p += fuzzGetVarint(p, &pGrp->nCol);
+ pGrp->aPK = p;
+ p += pGrp->nCol;
+ pGrp->zTab = (const char*)p;
+ p = &p[strlen(p)+1];
+
+ if( p>=pEnd ){
+ rc = fuzzCorrupt();
+ }
+ }
+ *ppHdr = p;
+ }
+
+ if( rc!=SQLITE_OK ){
+ fuzzFree(pGrp);
+ pGrp = 0;
+ }
+
+ *ppGrp = pGrp;
+ return rc;
+}
+
+/*
+** Argument p points to a buffer containing a single changeset-record value.
+** This function attempts to determine the size of the value in bytes. If
+** successful, it sets (*pSz) to the size and returns SQLITE_OK. Or, if the
+** buffer does not contain a valid value, SQLITE_CORRUPT is returned and
+** the final value of (*pSz) is undefined.
+*/
+static int fuzzChangeSize(u8 *p, int *pSz){
+ u8 eType = p[0];
+ switch( eType ){
+ case 0x00: /* undefined */
+ case 0x05: /* null */
+ *pSz = 1;
+ break;
+
+ case 0x01: /* integer */
+ case 0x02: /* real */
+ *pSz = 9;
+ break;
+
+ case 0x03: /* text */
+ case 0x04: { /* blob */
+ int nTxt;
+ int sz;
+ sz = fuzzGetVarint(&p[1], &nTxt);
+ *pSz = 1 + sz + nTxt;
+ break;
+ }
+
+ default:
+ return fuzzCorrupt();
+ }
+ return SQLITE_OK;
+}
+
+/*
+** When this function is called, (*ppRec) points to the start of a
+** record in a changeset being parsed. This function adds entries
+** to the pParse->apVal[] array for all values and advances (*ppRec)
+** to one byte past the end of the record. Argument pEnd points to
+** one byte past the end of the input changeset.
+**
+** Argument bPkOnly is true if the record being parsed is part of
+** a DELETE record in a patchset. In this case, all non-primary-key
+** fields have been omitted from the record.
+**
+** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
+*/
+static int fuzzParseRecord(
+ u8 **ppRec, /* IN/OUT: Iterator */
+ u8 *pEnd, /* One byte after end of input data */
+ FuzzChangeset *pParse, /* Changeset parse context */
+ int bPkOnly /* True if non-PK fields omitted */
+){
+ int rc = SQLITE_OK;
+ FuzzChangesetGroup *pGrp = pParse->apGroup[pParse->nGroup-1];
+ int i;
+ u8 *p = *ppRec;
+
+ for(i=0; rc==SQLITE_OK && i<pGrp->nCol; i++){
+ if( bPkOnly==0 || pGrp->aPK[i] ){
+ int sz;
+ if( p>=pEnd ) break;
+ if( (pParse->nVal & (pParse->nVal-1))==0 ){
+ int nNew = pParse->nVal ? pParse->nVal*2 : 4;
+ u8 **apNew = (u8**)sqlite3_realloc(pParse->apVal, nNew*sizeof(u8*));
+ if( apNew==0 ) return SQLITE_NOMEM;
+ pParse->apVal = apNew;
+ }
+ pParse->apVal[pParse->nVal++] = p;
+ rc = fuzzChangeSize(p, &sz);
+ p += sz;
+ }
+ }
+
+ if( rc==SQLITE_OK && i<pGrp->nCol ){
+ rc = fuzzCorrupt();
+ }
+
+ *ppRec = p;
+ return rc;
+}
+
+/*
+** Parse the array of changes starting at (*ppData) and add entries for
+** all values to the pParse->apVal[] array. Argument pEnd points to one byte
+** past the end of the input changeset. If successful, set (*ppData) to point
+** to one byte past the end of the change array and return SQLITE_OK.
+** Otherwise, return an SQLite error code. The final value of (*ppData) is
+** undefined in this case.
+*/
+static int fuzzParseChanges(u8 **ppData, u8 *pEnd, FuzzChangeset *pParse){
+ u8 cHdr = (pParse->bPatchset ? 'P' : 'T');
+ FuzzChangesetGroup *pGrp = pParse->apGroup[pParse->nGroup-1];
+ int rc = SQLITE_OK;
+ u8 *p = *ppData;
+
+ pGrp->aChange = p;
+ while( rc==SQLITE_OK && p<pEnd && p[0]!=cHdr ){
+ u8 eOp = p[0];
+ u8 bIndirect = p[1];
+
+ p += 2;
+ if( eOp==SQLITE_UPDATE ){
+ pParse->nUpdate++;
+ if( pParse->bPatchset==0 ){
+ rc = fuzzParseRecord(&p, pEnd, pParse, 0);
+ }
+ }else if( eOp!=SQLITE_INSERT && eOp!=SQLITE_DELETE ){
+ rc = fuzzCorrupt();
+ }
+ if( rc==SQLITE_OK ){
+ int bPkOnly = (eOp==SQLITE_DELETE && pParse->bPatchset);
+ rc = fuzzParseRecord(&p, pEnd, pParse, bPkOnly);
+ }
+ pGrp->nChange++;
+ pParse->nChange++;
+ }
+ pGrp->szChange = p - pGrp->aChange;
+
+ *ppData = p;
+ return rc;
+}
+
+/*
+** Parse the changeset stored in buffer pChangeset (nChangeset bytes in
+** size). If successful, write the results into (*pParse) and return
+** SQLITE_OK. Or, if an error occurs, return an SQLite error code. The
+** final state of (*pParse) is undefined in this case.
+*/
+static int fuzzParseChangeset(
+ u8 *pChangeset, /* Buffer containing changeset */
+ int nChangeset, /* Size of buffer in bytes */
+ FuzzChangeset *pParse /* OUT: Results of parse */
+){
+ u8 *pEnd = &pChangeset[nChangeset];
+ u8 *p = pChangeset;
+ int rc = SQLITE_OK;
+
+ memset(pParse, 0, sizeof(FuzzChangeset));
+ if( nChangeset>0 ){
+ pParse->bPatchset = (pChangeset[0]=='P');
+ }
+
+ while( rc==SQLITE_OK && p<pEnd ){
+ FuzzChangesetGroup *pGrp = 0;
+
+ /* Read a table-header from the changeset */
+ rc = fuzzParseHeader(pParse, &p, pEnd, &pGrp);
+ assert( (rc==SQLITE_OK)==(pGrp!=0) );
+
+ /* If the table-header was successfully parsed, add the new change-group
+ ** to the array and parse the associated changes. */
+ if( rc==SQLITE_OK ){
+ FuzzChangesetGroup **apNew = (FuzzChangesetGroup**)sqlite3_realloc(
+ pParse->apGroup, sizeof(FuzzChangesetGroup*)*(pParse->nGroup+1)
+ );
+ if( apNew==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ apNew[pParse->nGroup] = pGrp;
+ pParse->apGroup = apNew;
+ pParse->nGroup++;
+ }
+ rc = fuzzParseChanges(&p, pEnd, pParse);
+ }
+ }
+
+ return rc;
+}
+
+/*
+** When this function is called, (*ppRec) points to the first byte of
+** a record that is part of change-group pGrp. This function attempts
+** to output a human-readable version of the record to stdout and advance
+** (*ppRec) to point to the first byte past the end of the record before
+** returning. If successful, SQLITE_OK is returned. Otherwise, an SQLite
+** error code.
+**
+** If parameter bPkOnly is non-zero, then all non-primary-key fields have
+** been omitted from the record. This occurs for records that are part
+** of DELETE changes in patchsets.
+*/
+static int fuzzPrintRecord(FuzzChangesetGroup *pGrp, u8 **ppRec, int bPKOnly){
+ int rc = SQLITE_OK;
+ u8 *p = *ppRec;
+ int i;
+ const char *zPre = " (";
+
+ for(i=0; i<pGrp->nCol; i++){
+ if( bPKOnly==0 || pGrp->aPK[i] ){
+ u8 eType = p++[0];
+ switch( eType ){
+ case 0x00: /* undefined */
+ printf("%sn/a", zPre);
+ break;
+
+ case 0x01: { /* integer */
+ sqlite3_int64 iVal = 0;
+ iVal = fuzzGetI64(p);
+ printf("%s%lld", zPre, iVal);
+ p += 8;
+ break;
+ }
+
+ case 0x02: { /* real */
+ sqlite3_int64 iVal = 0;
+ double fVal = 0.0;
+ iVal = fuzzGetI64(p);
+ memcpy(&fVal, &iVal, 8);
+ printf("%s%f", zPre, fVal);
+ p += 8;
+ break;
+ }
+
+ case 0x03: /* text */
+ case 0x04: { /* blob */
+ int nTxt;
+ int sz;
+ int i;
+ p += fuzzGetVarint(p, &nTxt);
+ printf("%s%s", zPre, eType==0x03 ? "'" : "X'");
+ for(i=0; i<nTxt; i++){
+ if( eType==0x03 ){
+ printf("%c", p[i]);
+ }else{
+ char aHex[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+ };
+ printf("%c", aHex[ p[i]>>4 ]);
+ printf("%c", aHex[ p[i] & 0x0F ]);
+ }
+ }
+ printf("'");
+ p += nTxt;
+ break;
+ }
+
+ case 0x05: /* null */
+ printf("%sNULL", zPre);
+ break;
+ }
+ zPre = ", ";
+ }
+ }
+ printf(")");
+
+ *ppRec = p;
+ return rc;
+}
+
+/*
+** Print a human-readable version of the table-header and all changes in the
+** change-group passed as the second argument.
+*/
+static void fuzzPrintGroup(FuzzChangeset *pParse, FuzzChangesetGroup *pGrp){
+ int i;
+ u8 *p;
+
+ /* The table header */
+ printf("TABLE: %s nCol=%d aPK=", pGrp->zTab, pGrp->nCol);
+ for(i=0; i<pGrp->nCol; i++){
+ printf("%d", (int)pGrp->aPK[i]);
+ }
+ printf("\n");
+
+ /* The array of changes */
+ p = pGrp->aChange;
+ for(i=0; i<pGrp->nChange; i++){
+ u8 eType = p[0];
+ u8 bIndirect = p[1];
+ printf("%s (ind=%d):",
+ (eType==SQLITE_INSERT) ? "INSERT" :
+ (eType==SQLITE_DELETE ? "DELETE" : "UPDATE"),
+ bIndirect
+ );
+ p += 2;
+
+ if( pParse->bPatchset==0 && eType==SQLITE_UPDATE ){
+ fuzzPrintRecord(pGrp, &p, 0);
+ }
+ fuzzPrintRecord(pGrp, &p, eType==SQLITE_DELETE && pParse->bPatchset);
+ printf("\n");
+ }
+}
+
+/*
+** Initialize the object passed as the second parameter with details
+** of the change that will be attempted (type of change, to which part of the
+** changeset it applies etc.). If successful, return SQLITE_OK. Or, if an
+** error occurs, return an SQLite error code.
+**
+** If a negative value is returned, then the selected change would have
+** produced a non-well-formed changeset. In this case the caller should
+** call this function again.
+*/
+static int fuzzSelectChange(FuzzChangeset *pParse, FuzzChange *pChange){
+ int iSub;
+
+ memset(pChange, 0, sizeof(FuzzChange));
+ pChange->eType = fuzzRandomInt(FUZZ_COLUMN_DEL) + 1;
+
+ assert( pChange->eType==FUZZ_VALUE_SUB
+ || pChange->eType==FUZZ_VALUE_MOD
+ || pChange->eType==FUZZ_VALUE_RND
+ || pChange->eType==FUZZ_CHANGE_DUP
+ || pChange->eType==FUZZ_CHANGE_DEL
+ || pChange->eType==FUZZ_CHANGE_TYPE
+ || pChange->eType==FUZZ_CHANGE_FIELD
+ || pChange->eType==FUZZ_CHANGE_INDIRECT
+ || pChange->eType==FUZZ_GROUP_DUP
+ || pChange->eType==FUZZ_GROUP_DEL
+ || pChange->eType==FUZZ_GROUP_SWAP
+ || pChange->eType==FUZZ_COLUMN_ADD
+ || pChange->eType==FUZZ_COLUMN_ADDPK
+ || pChange->eType==FUZZ_COLUMN_DEL
+ );
+
+ pChange->iGroup = fuzzRandomInt(pParse->nGroup);
+ pChange->iChange = fuzzRandomInt(pParse->nChange);
+ if( pChange->eType==FUZZ_CHANGE_FIELD ){
+ if( pParse->nUpdate==0 ) return -1;
+ pChange->iChange = fuzzRandomInt(pParse->nUpdate);
+ }
+
+ pChange->iDelete = -1;
+ if( pChange->eType==FUZZ_COLUMN_DEL ){
+ FuzzChangesetGroup *pGrp = pParse->apGroup[pChange->iGroup];
+ int i;
+ pChange->iDelete = fuzzRandomInt(pGrp->nCol);
+ for(i=pGrp->nCol-1; i>=0; i--){
+ if( pGrp->aPK[i] && pChange->iDelete!=i ) break;
+ }
+ if( i<0 ) return -1;
+ }
+
+ if( pChange->eType==FUZZ_GROUP_SWAP ){
+ FuzzChangesetGroup *pGrp;
+ int iGrp = pChange->iGroup;
+ if( pParse->nGroup==1 ) return -1;
+ while( iGrp==pChange->iGroup ){
+ iGrp = fuzzRandomInt(pParse->nGroup);
+ }
+ pGrp = pParse->apGroup[pChange->iGroup];
+ pParse->apGroup[pChange->iGroup] = pParse->apGroup[iGrp];
+ pParse->apGroup[iGrp] = pGrp;
+ }
+
+ if( pChange->eType==FUZZ_VALUE_SUB
+ || pChange->eType==FUZZ_VALUE_MOD
+ || pChange->eType==FUZZ_VALUE_RND
+ ){
+ iSub = fuzzRandomInt(pParse->nVal);
+ pChange->pSub1 = pParse->apVal[iSub];
+ if( pChange->eType==FUZZ_VALUE_SUB ){
+ iSub = fuzzRandomInt(pParse->nVal);
+ pChange->pSub2 = pParse->apVal[iSub];
+ }else{
+ pChange->pSub2 = pChange->aSub;
+ }
+
+ if( pChange->eType==FUZZ_VALUE_RND ){
+ pChange->aSub[0] = (u8)(fuzzRandomInt(5) + 1);
+ switch( pChange->aSub[0] ){
+ case 0x01: { /* integer */
+ u64 iVal = fuzzRandomU64();
+ fuzzPutU64(&pChange->aSub[1], iVal);
+ break;
+ }
+
+ case 0x02: { /* real */
+ u64 iVal1 = fuzzRandomU64();
+ u64 iVal2 = fuzzRandomU64();
+ double d = (double)iVal1 / (double)iVal2;
+ memcpy(&iVal1, &d, sizeof(iVal1));
+ fuzzPutU64(&pChange->aSub[1], iVal1);
+ break;
+ }
+
+ case 0x03: /* text */
+ case 0x04: { /* blob */
+ int nByte = fuzzRandomInt(48);
+ pChange->aSub[1] = nByte;
+ fuzzRandomBlob(nByte, &pChange->aSub[2]);
+ if( pChange->aSub[0]==0x03 ){
+ int i;
+ for(i=0; i<nByte; i++){
+ pChange->aSub[2+i] &= 0x7F;
+ }
+ }
+ break;
+ }
+ }
+ }
+ if( pChange->eType==FUZZ_VALUE_MOD ){
+ int sz;
+ int iMod = -1;
+ fuzzChangeSize(pChange->pSub1, &sz);
+ memcpy(pChange->aSub, pChange->pSub1, sz);
+ switch( pChange->aSub[0] ){
+ case 0x01:
+ case 0x02:
+ iMod = fuzzRandomInt(8) + 1;
+ break;
+
+ case 0x03: /* text */
+ case 0x04: { /* blob */
+ int nByte;
+ int iFirst = 1 + fuzzGetVarint(&pChange->aSub[1], &nByte);
+ if( nByte>0 ){
+ iMod = fuzzRandomInt(nByte) + iFirst;
+ }
+ break;
+ }
+ }
+
+ if( iMod>=0 ){
+ u8 mask = (1 << fuzzRandomInt(8 - (pChange->aSub[0]==0x03)));
+ pChange->aSub[iMod] ^= mask;
+ }
+ }
+ }
+
+ return SQLITE_OK;
+}
+
+/*
+** Copy a single change from the input to the output changeset, making
+** any modifications specified by (*pFuzz).
+*/
+static int fuzzCopyChange(
+ FuzzChangeset *pParse,
+ int iGrp,
+ FuzzChange *pFuzz,
+ u8 **pp, u8 **ppOut /* IN/OUT: Input and output pointers */
+){
+ int bPS = pParse->bPatchset;
+ FuzzChangesetGroup *pGrp = pParse->apGroup[iGrp];
+ u8 *p = *pp;
+ u8 *pOut = *ppOut;
+ u8 eType = p++[0];
+ int iRec;
+ int nRec = ((eType==SQLITE_UPDATE && !bPS) ? 2 : 1);
+ int iUndef = -1;
+ int nUpdate = 0;
+
+ u8 eNew = eType;
+ if( pFuzz->iCurrent==pFuzz->iChange && pFuzz->eType==FUZZ_CHANGE_TYPE ){
+ switch( eType ){
+ case SQLITE_INSERT:
+ eNew = SQLITE_DELETE;
+ break;
+ case SQLITE_DELETE:
+ eNew = SQLITE_UPDATE;
+ break;
+ case SQLITE_UPDATE:
+ eNew = SQLITE_INSERT;
+ break;
+ }
+ }
+
+ if( pFuzz->iCurrent==pFuzz->iChange
+ && pFuzz->eType==FUZZ_CHANGE_FIELD && eType==SQLITE_UPDATE
+ ){
+ int sz;
+ int i;
+ int nDef = 0;
+ u8 *pCsr = p+1;
+ for(i=0; i<pGrp->nCol; i++){
+ if( pCsr[0] && pGrp->aPK[i]==0 ) nDef++;
+ fuzzChangeSize(pCsr, &sz);
+ pCsr += sz;
+ }
+ if( nDef<=1 ) return -1;
+ nDef = fuzzRandomInt(nDef);
+ pCsr = p+1;
+ for(i=0; i<pGrp->nCol; i++){
+ if( pCsr[0] && pGrp->aPK[i]==0 ){
+ if( nDef==0 ) iUndef = i;
+ nDef--;
+ }
+ fuzzChangeSize(pCsr, &sz);
+ pCsr += sz;
+ }
+ }
+
+ /* Copy the change type and indirect flag. If the fuzz mode is
+ ** FUZZ_CHANGE_INDIRECT, and the current change is the one selected for
+ ** fuzzing, invert the indirect flag. */
+ *(pOut++) = eNew;
+ if( pFuzz->eType==FUZZ_CHANGE_INDIRECT && pFuzz->iCurrent==pFuzz->iChange ){
+ *(pOut++) = !(*(p++));
+ }else{
+ *(pOut++) = *(p++);
+ }
+
+ for(iRec=0; iRec<nRec; iRec++){
+ int i;
+
+ /* Copy the next record from the output to the input.
+ */
+ for(i=0; i<pGrp->nCol; i++){
+ int sz;
+ u8 *pCopy = p;
+
+ /* If this is a patchset, and the input is a DELETE, then the only
+ ** fields present are the PK fields. So, if this is not a PK, skip to
+ ** the next column. If the current fuzz is FUZZ_CHANGE_TYPE, then
+ ** write a randomly selected value to the output. */
+ if( bPS && eType==SQLITE_DELETE && pGrp->aPK[i]==0 ){
+ if( eType!=eNew ){
+ assert( eNew==SQLITE_UPDATE );
+ do {
+ pCopy = pParse->apVal[fuzzRandomInt(pParse->nVal)];
+ }while( pCopy[0]==0x00 );
+ fuzzChangeSize(pCopy, &sz);
+ memcpy(pOut, pCopy, sz);
+ pOut += sz;
+ }
+ continue;
+ }
+
+ if( p==pFuzz->pSub1 ){
+ pCopy = pFuzz->pSub2;
+ }else if( p==pFuzz->pSub2 ){
+ pCopy = pFuzz->pSub1;
+ }else if( i==iUndef ){
+ pCopy = "\0";
+ }
+
+ if( pCopy[0]==0x00 && eNew!=eType && eType==SQLITE_UPDATE && iRec==0 ){
+ while( pCopy[0]==0x00 ){
+ pCopy = pParse->apVal[fuzzRandomInt(pParse->nVal)];
+ }
+ }else if( p[0]==0x00 && pCopy[0]!=0x00 ){
+ return -1;
+ }else{
+ if( pGrp->aPK[i]>0 && pCopy[0]==0x05 ) return -1;
+ }
+
+ if( (pFuzz->iGroup!=iGrp || i!=pFuzz->iDelete)
+ && (eNew==eType || eType!=SQLITE_UPDATE || iRec==0)
+ && (eNew==eType || eNew!=SQLITE_DELETE || !bPS || pGrp->aPK[i])
+ ){
+ fuzzChangeSize(pCopy, &sz);
+ memcpy(pOut, pCopy, sz);
+ pOut += sz;
+ nUpdate += (pGrp->aPK[i]==0 && pCopy[0]!=0x00);
+ }
+
+ fuzzChangeSize(p, &sz);
+ p += sz;
+ }
+
+ if( iGrp==pFuzz->iGroup ){
+ if( pFuzz->eType==FUZZ_COLUMN_ADD ){
+ if( !bPS || eType!=SQLITE_DELETE ) *(pOut++) = 0x05;
+ }else if( pFuzz->eType==FUZZ_COLUMN_ADDPK ){
+ if( iRec==1 ){
+ *(pOut++) = 0x00;
+ }else{
+ u8 *pNew;
+ int szNew;
+ do {
+ pNew = pParse->apVal[fuzzRandomInt(pParse->nVal)];
+ }while( pNew[0]==0x00 || pNew[0]==0x05 );
+ fuzzChangeSize(pNew, &szNew);
+ memcpy(pOut, pNew, szNew);
+ pOut += szNew;
+ }
+ }
+ }
+ }
+
+ if( pFuzz->iCurrent==pFuzz->iChange ){
+ if( pFuzz->eType==FUZZ_CHANGE_DUP ){
+ int nByte = pOut - (*ppOut);
+ memcpy(pOut, *ppOut, nByte);
+ pOut += nByte;
+ }
+
+ if( pFuzz->eType==FUZZ_CHANGE_DEL ){
+ pOut = *ppOut;
+ }
+ if( eNew!=eType && eNew==SQLITE_UPDATE && !bPS ){
+ int i;
+ u8 *pCsr = (*ppOut) + 2;
+ for(i=0; i<pGrp->nCol; i++){
+ int sz;
+ u8 *pCopy = pCsr;
+ if( pGrp->aPK[i] ) pCopy = "\0";
+ fuzzChangeSize(pCopy, &sz);
+ memcpy(pOut, pCopy, sz);
+ pOut += sz;
+ fuzzChangeSize(pCsr, &sz);
+ pCsr += sz;
+ }
+ }
+ }
+
+ /* If a column is being deleted from this group, and this change was an
+ ** UPDATE, and there are now no non-PK, non-undefined columns in the
+ ** change, remove it altogether. */
+ if( pFuzz->eType==FUZZ_COLUMN_DEL && pFuzz->iGroup==iGrp
+ && eType==SQLITE_UPDATE && nUpdate==0
+ ){
+ pOut = *ppOut;
+ }
+
+ *pp = p;
+ *ppOut = pOut;
+ pFuzz->iCurrent += (eType==SQLITE_UPDATE || pFuzz->eType!=FUZZ_CHANGE_FIELD);
+ return SQLITE_OK;
+}
+
+/*
+** Fuzz the changeset parsed into object pParse and write the results
+** to file zOut on disk. Argument pBuf points to a buffer that is guaranteed
+** to be large enough to hold the fuzzed changeset.
+**
+** Return SQLITE_OK if successful, or an SQLite error code if an error occurs.
+*/
+static int fuzzDoOneFuzz(
+ const char *zOut, /* Filename to write modified changeset to */
+ u8 *pBuf, /* Buffer to use for modified changeset */
+ FuzzChangeset *pParse /* Parse of input changeset */
+){
+ FuzzChange change;
+ int iGrp;
+ int rc = -1;
+
+ while( rc<0 ){
+ u8 *pOut = pBuf;
+ rc = fuzzSelectChange(pParse, &change);
+ for(iGrp=0; rc==SQLITE_OK && iGrp<pParse->nGroup; iGrp++){
+ FuzzChangesetGroup *pGrp = pParse->apGroup[iGrp];
+ int nTab = strlen(pGrp->zTab) + 1;
+ int j;
+ int nRep = 1;
+
+ /* If this is the group to delete for a FUZZ_GROUP_DEL change, jump to
+ ** the next group. Unless this is the only group in the changeset - in
+ ** that case this change cannot be applied.
+ **
+ ** Or, if this is a FUZZ_GROUP_DUP, set nRep to 2 to output two
+ ** copies of the group. */
+ if( change.iGroup==iGrp ){
+ if( change.eType==FUZZ_GROUP_DEL ){
+ if( pParse->nGroup==1 ) rc = -1;
+ continue;
+ }
+ else if( change.eType==FUZZ_GROUP_DUP ){
+ nRep = 2;
+ }
+ }
+
+ for(j=0; j<nRep; j++){
+ int i;
+ u8 *pSaved;
+ u8 *p = pGrp->aChange;
+ int nCol = pGrp->nCol;
+ int iPKDel = 0;
+ if( iGrp==change.iGroup ){
+ if( change.eType==FUZZ_COLUMN_ADD
+ || change.eType==FUZZ_COLUMN_ADDPK
+ ){
+ nCol++;
+ }else if( change.eType==FUZZ_COLUMN_DEL ){
+ nCol--;
+ iPKDel = pGrp->aPK[change.iDelete];
+ }
+ }
+
+ /* Output a table header */
+ pOut++[0] = pParse->bPatchset ? 'P' : 'T';
+ pOut += fuzzPutVarint(pOut, nCol);
+
+ for(i=0; i<pGrp->nCol; i++){
+ if( iGrp!=change.iGroup || i!=change.iDelete ){
+ u8 v = pGrp->aPK[i];
+ if( iPKDel && v>iPKDel ) v--;
+ *(pOut++) = v;
+ }
+ }
+ if( nCol>pGrp->nCol ){
+ if( change.eType==FUZZ_COLUMN_ADD ){
+ *(pOut++) = 0x00;
+ }else{
+ u8 max = 0;
+ for(i=0; i<pGrp->nCol; i++){
+ if( pGrp->aPK[i]>max ) max = pGrp->aPK[i];
+ }
+ *(pOut++) = max+1;
+ }
+ }
+ memcpy(pOut, pGrp->zTab, nTab);
+ pOut += nTab;
+
+ /* Output the change array. */
+ pSaved = pOut;
+ for(i=0; rc==SQLITE_OK && i<pGrp->nChange; i++){
+ rc = fuzzCopyChange(pParse, iGrp, &change, &p, &pOut);
+ }
+ if( pOut==pSaved ) rc = -1;
+ }
+ }
+ if( rc==SQLITE_OK ){
+ fuzzWriteFile(zOut, pBuf, pOut-pBuf);
+ }
+ }
+
+ return rc;
+}
+
+int main(int argc, char **argv){
+ int nRepeat = 0; /* Number of output files */
+ int iSeed = 0; /* Value of PRNG seed */
+ const char *zInput; /* Name of input file */
+ void *pChangeset = 0; /* Input changeset */
+ int nChangeset = 0; /* Size of input changeset in bytes */
+ int i; /* Current output file */
+ FuzzChangeset changeset; /* Partially parsed changeset */
+ int rc;
+ u8 *pBuf = 0;
+
+ if( argc!=4 && argc!=2 ) usage(argv[0]);
+ zInput = argv[1];
+
+ fuzzReadFile(zInput, &nChangeset, &pChangeset);
+ rc = fuzzParseChangeset(pChangeset, nChangeset, &changeset);
+
+ if( rc==SQLITE_OK ){
+ if( argc==2 ){
+ for(i=0; i<changeset.nGroup; i++){
+ fuzzPrintGroup(&changeset, changeset.apGroup[i]);
+ }
+ }else{
+ pBuf = (u8*)fuzzMalloc(nChangeset*2 + 1024);
+ if( pBuf==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ iSeed = atoi(argv[2]);
+ nRepeat = atoi(argv[3]);
+ fuzzRandomSeed((unsigned int)iSeed);
+ for(i=0; rc==SQLITE_OK && i<nRepeat; i++){
+ char *zOut = sqlite3_mprintf("%s-%d", zInput, i);
+ rc = fuzzDoOneFuzz(zOut, pBuf, &changeset);
+ sqlite3_free(zOut);
+ }
+ fuzzFree(pBuf);
+ }
+ }
+ }
+
+ if( rc!=SQLITE_OK ){
+ fprintf(stderr, "error while processing changeset: %d\n", rc);
+ }
+
+ return rc;
+}
+
diff --git a/chromium/third_party/sqlite/src/ext/session/changesetfuzz1.test b/chromium/third_party/sqlite/src/ext/session/changesetfuzz1.test
new file mode 100644
index 00000000000..f721e829c8d
--- /dev/null
+++ b/chromium/third_party/sqlite/src/ext/session/changesetfuzz1.test
@@ -0,0 +1,84 @@
+# 2018 November 08
+#
+# 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.
+#
+#***********************************************************************
+#
+
+if {![info exists testdir]} {
+ set testdir [file join [file dirname [info script]] .. .. test]
+}
+source [file join [file dirname [info script]] session_common.tcl]
+source $testdir/tester.tcl
+ifcapable !session {finish_test; return}
+set testprefix changesetfuzz1
+
+
+set CF [test_find_binary changesetfuzz]
+if {$CF==""} {
+ finish_test
+ return
+}
+
+proc writefile {zFile data} {
+ set fd [open $zFile w]
+ fconfigure $fd -translation binary -encoding binary
+ puts -nonewline $fd $data
+ close $fd
+}
+
+do_execsql_test 1.0 {
+ CREATE TABLE t1(a, b, c, d, PRIMARY KEY(c, d));
+ CREATE TABLE t2(a INTEGER PRIMARY KEY, b, c);
+
+ INSERT INTO t1 VALUES ('one', 'two', 'three', 'four'),
+ ('five', 'six', 'seven', 'eight'),
+ ('nine', 'ten', 'eleven', 'twelve');
+ INSERT INTO t2 VALUES (1, 2, 3), (4, 5, 6), (7, 8, 9);
+}
+
+set C [changeset_from_sql {
+ INSERT INTO t2 VALUES(10, 11, 12);
+ DELETE FROM t2 WHERE a=1;
+ UPDATE t1 SET b='forty-five' WHERE a='one';
+ UPDATE t1 SET a='twenty-nine', b='seventy' WHERE a='five';
+}]
+writefile c1.changeset $C
+
+do_test 1.1 {
+ for {set j 0} {$j < 200} {incr j} {
+ forcecopy c1.changeset input.changeset
+ for {set i 0} {$i < 6} {incr i} {
+ exec $CF input.changeset $i 1
+ exec $CF input.changeset-0
+ forcecopy input.changeset-0 input.changeset
+ }
+ }
+} {}
+
+set P [patchset_from_sql {
+ INSERT INTO t2 VALUES(13, 14, 15);
+ DELETE FROM t2 WHERE a=4;
+ UPDATE t1 SET b='thirteen' WHERE a='one';
+ UPDATE t1 SET a='ninety-seven', b='twenty' WHERE a='five';
+}]
+writefile p1.patchset $P
+do_test 1.2 {
+ for {set j 0} {$j < 200} {incr j} {
+ forcecopy p1.patchset input.patchset
+ for {set i 0} {$i < 6} {incr i} {
+ exec $CF input.patchset $i 1
+ exec $CF input.patchset-0
+ forcecopy input.patchset-0 input.patchset
+ }
+ }
+} {}
+
+
+finish_test
+
diff --git a/chromium/third_party/sqlite/src/ext/session/session1.test b/chromium/third_party/sqlite/src/ext/session/session1.test
index f3556167176..7dfac9580d6 100644
--- a/chromium/third_party/sqlite/src/ext/session/session1.test
+++ b/chromium/third_party/sqlite/src/ext/session/session1.test
@@ -655,6 +655,13 @@ do_test $tn.13.3 {
} {1 one 2 two 3 iii}
execsql ROLLBACK
+do_test $tn.14.1 { sqlite3session_config strm_size -1 } 64
+do_test $tn.14.2 { sqlite3session_config strm_size 65536 } 65536
+do_test $tn.14.3 { sqlite3session_config strm_size 64 } 64
+do_test $tn.14.4 {
+ list [catch {sqlite3session_config invalid 123} msg] $msg
+} {1 SQLITE_MISUSE}
+
}]
}
diff --git a/chromium/third_party/sqlite/src/ext/session/sessionC.test b/chromium/third_party/sqlite/src/ext/session/sessionC.test
index dd48c5f8af1..d4bb1abbd45 100644
--- a/chromium/third_party/sqlite/src/ext/session/sessionC.test
+++ b/chromium/third_party/sqlite/src/ext/session/sessionC.test
@@ -195,4 +195,3 @@ do_test 3.3 {
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/session/sessionD.test b/chromium/third_party/sqlite/src/ext/session/sessionD.test
index 0f69b2923c4..8012e500370 100644
--- a/chromium/third_party/sqlite/src/ext/session/sessionD.test
+++ b/chromium/third_party/sqlite/src/ext/session/sessionD.test
@@ -255,4 +255,3 @@ do_catchsql_test 4.5.2 {
} {1 {no such table: ixua.i8}}
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/session/sessionE.test b/chromium/third_party/sqlite/src/ext/session/sessionE.test
index c4de1601674..4c1fc5f83fb 100644
--- a/chromium/third_party/sqlite/src/ext/session/sessionE.test
+++ b/chromium/third_party/sqlite/src/ext/session/sessionE.test
@@ -111,5 +111,3 @@ do_changeset_test 3.4 S {
S delete
finish_test
-
-
diff --git a/chromium/third_party/sqlite/src/ext/session/sessionF.test b/chromium/third_party/sqlite/src/ext/session/sessionF.test
index 14dd888c388..7c5e58cf984 100644
--- a/chromium/third_party/sqlite/src/ext/session/sessionF.test
+++ b/chromium/third_party/sqlite/src/ext/session/sessionF.test
@@ -292,4 +292,3 @@ foreach {tn setup1 sql1 setup2 sql2 result} {
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/session/sessionG.test b/chromium/third_party/sqlite/src/ext/session/sessionG.test
index 465e3309b30..dcd271844e3 100644
--- a/chromium/third_party/sqlite/src/ext/session/sessionG.test
+++ b/chromium/third_party/sqlite/src/ext/session/sessionG.test
@@ -248,4 +248,3 @@ do_execsql_test 6.4 {
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/session/sessionH.test b/chromium/third_party/sqlite/src/ext/session/sessionH.test
index 696ef582fe4..0022df95f6a 100644
--- a/chromium/third_party/sqlite/src/ext/session/sessionH.test
+++ b/chromium/third_party/sqlite/src/ext/session/sessionH.test
@@ -36,4 +36,3 @@ do_test 1.0 {
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/session/session_common.tcl b/chromium/third_party/sqlite/src/ext/session/session_common.tcl
index 350cba6eba2..3fe153d495e 100644
--- a/chromium/third_party/sqlite/src/ext/session/session_common.tcl
+++ b/chromium/third_party/sqlite/src/ext/session/session_common.tcl
@@ -95,6 +95,23 @@ proc changeset_from_sql {sql {dbname main}} {
return $changeset
}
+proc patchset_from_sql {sql {dbname main}} {
+ set rc [catch {
+ sqlite3session S db $dbname
+ db eval "SELECT name FROM $dbname.sqlite_master WHERE type = 'table'" {
+ S attach $name
+ }
+ db eval $sql
+ S patchset
+ } patchset]
+ catch { S delete }
+
+ if {$rc} {
+ error $patchset
+ }
+ return $patchset
+}
+
proc do_then_apply_sql {sql {dbname main}} {
proc xConflict args { return "OMIT" }
set rc [catch {
diff --git a/chromium/third_party/sqlite/src/ext/session/sessionfault2.test b/chromium/third_party/sqlite/src/ext/session/sessionfault2.test
index b91fb831f47..69a9267bdf5 100644
--- a/chromium/third_party/sqlite/src/ext/session/sessionfault2.test
+++ b/chromium/third_party/sqlite/src/ext/session/sessionfault2.test
@@ -282,4 +282,3 @@ do_faultsim_test 3.2 -faults oom* -prep {
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/session/sessioninvert.test b/chromium/third_party/sqlite/src/ext/session/sessioninvert.test
new file mode 100644
index 00000000000..67b7b851dcd
--- /dev/null
+++ b/chromium/third_party/sqlite/src/ext/session/sessioninvert.test
@@ -0,0 +1,159 @@
+# 2018 October 18
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library.
+#
+
+if {![info exists testdir]} {
+ set testdir [file join [file dirname [info script]] .. .. test]
+}
+source [file join [file dirname [info script]] session_common.tcl]
+source $testdir/tester.tcl
+ifcapable !session {finish_test; return}
+
+set testprefix sessioninvert
+
+proc iter_invert {C} {
+ set x [list]
+ sqlite3session_foreach -invert c $C { lappend x $c }
+ set x
+}
+
+proc do_invert_test {tn sql {iter {}}} {
+
+ forcecopy test.db test.db2
+ sqlite3 db2 test.db2
+
+ set C [changeset_from_sql $sql]
+
+ forcecopy test.db test.db3
+ sqlite3 db3 test.db3
+ uplevel [list do_test $tn.1 [list compare_db db db3] {}]
+
+ set I [sqlite3changeset_invert $C]
+ sqlite3changeset_apply db $I {}
+ uplevel [list do_test $tn.2 [list compare_db db db2] {}]
+
+ sqlite3changeset_apply_v2 -invert db3 $C {}
+ uplevel [list do_test $tn.3 [list compare_db db db3] {}]
+
+ if {$iter!=""} {
+ uplevel [list do_test $tn.4 [list iter_invert $C] [list {*}$iter]]
+ }
+
+ catch { db2 close }
+ catch { db3 close }
+}
+
+do_execsql_test 1.0 {
+ CREATE TABLE t1(a PRIMARY KEY, b, c);
+ CREATE TABLE t2(d, e, f, PRIMARY KEY(e, f));
+
+ INSERT INTO t1 VALUES(1, 'one', 'i');
+ INSERT INTO t1 VALUES(2, 'two', 'ii');
+ INSERT INTO t1 VALUES(3, 'three', 'iii');
+ INSERT INTO t1 VALUES(4, 'four', 'iv');
+ INSERT INTO t1 VALUES(5, 'five', 'v');
+ INSERT INTO t1 VALUES(6, 'six', 'vi');
+
+ INSERT INTO t2 SELECT * FROM t1;
+}
+
+do_invert_test 1.1 {
+ INSERT INTO t1 VALUES(7, 'seven', 'vii');
+} {
+ {DELETE t1 0 X.. {i 7 t seven t vii} {}}
+}
+
+do_invert_test 1.2 {
+ DELETE FROM t1 WHERE a<4;
+} {
+ {INSERT t1 0 X.. {} {i 1 t one t i}}
+ {INSERT t1 0 X.. {} {i 2 t two t ii}}
+ {INSERT t1 0 X.. {} {i 3 t three t iii}}
+}
+
+do_invert_test 1.3 {
+ UPDATE t1 SET c=5;
+} {
+ {UPDATE t1 0 X.. {i 1 {} {} i 5} {{} {} {} {} t i}}
+ {UPDATE t1 0 X.. {i 2 {} {} i 5} {{} {} {} {} t ii}}
+ {UPDATE t1 0 X.. {i 3 {} {} i 5} {{} {} {} {} t iii}}
+ {UPDATE t1 0 X.. {i 4 {} {} i 5} {{} {} {} {} t iv}}
+ {UPDATE t1 0 X.. {i 5 {} {} i 5} {{} {} {} {} t v}}
+ {UPDATE t1 0 X.. {i 6 {} {} i 5} {{} {} {} {} t vi}}
+}
+
+do_invert_test 1.4 {
+ UPDATE t1 SET b = a+1 WHERE a%2;
+ DELETE FROM t2;
+ INSERT INTO t1 VALUES(10, 'ten', NULL);
+}
+
+do_invert_test 1.5 {
+ UPDATE t2 SET d = d-1;
+} {
+ {UPDATE t2 0 .XX {i 2 t three t iii} {i 3 {} {} {} {}}}
+ {UPDATE t2 0 .XX {i 1 t two t ii} {i 2 {} {} {} {}}}
+ {UPDATE t2 0 .XX {i 5 t six t vi} {i 6 {} {} {} {}}}
+ {UPDATE t2 0 .XX {i 3 t four t iv} {i 4 {} {} {} {}}}
+ {UPDATE t2 0 .XX {i 0 t one t i} {i 1 {} {} {} {}}}
+ {UPDATE t2 0 .XX {i 4 t five t v} {i 5 {} {} {} {}}}
+}
+
+do_execsql_test 2.0 {
+ ANALYZE;
+ PRAGMA writable_schema = 1;
+ DROP TABLE IF EXISTS sqlite_stat4;
+ SELECT * FROM sqlite_stat1;
+} {
+ t2 sqlite_autoindex_t2_1 {6 1 1}
+ t1 sqlite_autoindex_t1_1 {6 1}
+}
+
+do_invert_test 2.1 {
+ INSERT INTO sqlite_stat1 VALUES('t3', 'idx2', '1 2 3');
+} {
+ {DELETE sqlite_stat1 0 XX. {t t3 t idx2 t {1 2 3}} {}}
+}
+
+do_invert_test 2.2 {
+ DELETE FROM sqlite_stat1;
+} {
+ {INSERT sqlite_stat1 0 XX. {} {t t1 t sqlite_autoindex_t1_1 t {6 1}}}
+ {INSERT sqlite_stat1 0 XX. {} {t t2 t sqlite_autoindex_t2_1 t {6 1 1}}}
+}
+
+do_invert_test 2.3 {
+ UPDATE sqlite_stat1 SET stat = 'hello world';
+}
+
+do_test 3.0 {
+ forcecopy test.db test.db2
+ sqlite3 db2 test.db2
+ set P [patchset_from_sql {
+ INSERT INTO t2 VALUES(1, 2, 3);
+ DELETE FROM t2 WHERE d = 3;
+ }]
+
+ list [catch { sqlite3changeset_apply_v2 -invert db2 $P {} } msg] $msg
+} {1 SQLITE_CORRUPT}
+
+do_test 3.1 {
+ list [catch { sqlite3session_foreach -invert db2 $P {} } msg] $msg
+} {1 SQLITE_CORRUPT}
+
+do_test 3.2 {
+ sqlite3changeset_apply_v2 db2 $P {}
+ compare_db db db2
+} {}
+
+
+finish_test
diff --git a/chromium/third_party/sqlite/src/ext/session/sessionrebase.test b/chromium/third_party/sqlite/src/ext/session/sessionrebase.test
index cf267fa78d7..c8dc43b1530 100644
--- a/chromium/third_party/sqlite/src/ext/session/sessionrebase.test
+++ b/chromium/third_party/sqlite/src/ext/session/sessionrebase.test
@@ -474,4 +474,3 @@ foreach {tn cmd rebasable} {
catch { R delete }
}
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/session/sessionstat1.test b/chromium/third_party/sqlite/src/ext/session/sessionstat1.test
index eefd876111f..a40cd949765 100644
--- a/chromium/third_party/sqlite/src/ext/session/sessionstat1.test
+++ b/chromium/third_party/sqlite/src/ext/session/sessionstat1.test
@@ -308,4 +308,3 @@ do_test 4.2.3 {
} {t3 null 3}
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/session/sessionwor.test b/chromium/third_party/sqlite/src/ext/session/sessionwor.test
index 72c46f18cae..e9545c5376e 100644
--- a/chromium/third_party/sqlite/src/ext/session/sessionwor.test
+++ b/chromium/third_party/sqlite/src/ext/session/sessionwor.test
@@ -54,4 +54,3 @@ do_iterator_test 1.3 t1 {
}
finish_test
-
diff --git a/chromium/third_party/sqlite/src/ext/session/sqlite3session.c b/chromium/third_party/sqlite/src/ext/session/sqlite3session.c
index f7e79109b39..2e9a8ba7278 100644
--- a/chromium/third_party/sqlite/src/ext/session/sqlite3session.c
+++ b/chromium/third_party/sqlite/src/ext/session/sqlite3session.c
@@ -25,6 +25,8 @@ typedef struct SessionInput SessionInput;
# endif
#endif
+static int sessions_strm_chunk_size = SESSIONS_STRM_CHUNK_SIZE;
+
typedef struct SessionHook SessionHook;
struct SessionHook {
void *pCtx;
@@ -87,6 +89,7 @@ struct sqlite3_changeset_iter {
SessionInput in; /* Input buffer or stream */
SessionBuffer tblhdr; /* Buffer to hold apValue/zTab/abPK/ */
int bPatchset; /* True if this is a patchset */
+ int bInvert; /* True to invert changeset */
int rc; /* Iterator error code */
sqlite3_stmt *pConflict; /* Points to conflicting row, if any */
char *zTab; /* Current table */
@@ -243,6 +246,42 @@ struct SessionTable {
** The records associated with INSERT changes are in the same format as for
** changesets. It is not possible for a record associated with an INSERT
** change to contain a field set to "undefined".
+**
+** REBASE BLOB FORMAT:
+**
+** A rebase blob may be output by sqlite3changeset_apply_v2() and its
+** streaming equivalent for use with the sqlite3_rebaser APIs to rebase
+** existing changesets. A rebase blob contains one entry for each conflict
+** resolved using either the OMIT or REPLACE strategies within the apply_v2()
+** call.
+**
+** The format used for a rebase blob is very similar to that used for
+** changesets. All entries related to a single table are grouped together.
+**
+** Each group of entries begins with a table header in changeset format:
+**
+** 1 byte: Constant 0x54 (capital 'T')
+** Varint: Number of columns in the table.
+** nCol bytes: 0x01 for PK columns, 0x00 otherwise.
+** N bytes: Unqualified table name (encoded using UTF-8). Nul-terminated.
+**
+** Followed by one or more entries associated with the table.
+**
+** 1 byte: Either SQLITE_INSERT (0x12), DELETE (0x09).
+** 1 byte: Flag. 0x01 for REPLACE, 0x00 for OMIT.
+** record: (in the record format defined above).
+**
+** In a rebase blob, the first field is set to SQLITE_INSERT if the change
+** that caused the conflict was an INSERT or UPDATE, or to SQLITE_DELETE if
+** it was a DELETE. The second field is set to 0x01 if the conflict
+** resolution strategy was REPLACE, or 0x00 if it was OMIT.
+**
+** If the change that caused the conflict was a DELETE, then the single
+** record is a copy of the old.* record from the original changeset. If it
+** was an INSERT, then the single record is a copy of the new.* record. If
+** the conflicting change was an UPDATE, then the single record is a copy
+** of the new.* record with the PK fields filled in based on the original
+** old.* record.
*/
/*
@@ -1793,12 +1832,12 @@ int sqlite3session_attach(
static int sessionBufferGrow(SessionBuffer *p, int nByte, int *pRc){
if( *pRc==SQLITE_OK && p->nAlloc-p->nBuf<nByte ){
u8 *aNew;
- int nNew = p->nAlloc ? p->nAlloc : 128;
+ i64 nNew = p->nAlloc ? p->nAlloc : 128;
do {
nNew = nNew*2;
- }while( nNew<(p->nBuf+nByte) );
+ }while( (nNew-p->nBuf)<nByte );
- aNew = (u8 *)sqlite3_realloc(p->aBuf, nNew);
+ aNew = (u8 *)sqlite3_realloc64(p->aBuf, nNew);
if( 0==aNew ){
*pRc = SQLITE_NOMEM;
}else{
@@ -2396,12 +2435,12 @@ static int sessionGenerateChangeset(
rc = sqlite3_reset(pSel);
}
- /* If the buffer is now larger than SESSIONS_STRM_CHUNK_SIZE, pass
+ /* If the buffer is now larger than sessions_strm_chunk_size, pass
** its contents to the xOutput() callback. */
if( xOutput
&& rc==SQLITE_OK
&& buf.nBuf>nNoop
- && buf.nBuf>SESSIONS_STRM_CHUNK_SIZE
+ && buf.nBuf>sessions_strm_chunk_size
){
rc = xOutput(pOut, (void*)buf.aBuf, buf.nBuf);
nNoop = -1;
@@ -2540,7 +2579,8 @@ static int sessionChangesetStart(
int (*xInput)(void *pIn, void *pData, int *pnData),
void *pIn,
int nChangeset, /* Size of buffer pChangeset in bytes */
- void *pChangeset /* Pointer to buffer containing changeset */
+ void *pChangeset, /* Pointer to buffer containing changeset */
+ int bInvert /* True to invert changeset */
){
sqlite3_changeset_iter *pRet; /* Iterator to return */
int nByte; /* Number of bytes to allocate for iterator */
@@ -2560,6 +2600,7 @@ static int sessionChangesetStart(
pRet->in.xInput = xInput;
pRet->in.pIn = pIn;
pRet->in.bEof = (xInput ? 0 : 1);
+ pRet->bInvert = bInvert;
/* Populate the output variable and return success. */
*pp = pRet;
@@ -2574,7 +2615,16 @@ int sqlite3changeset_start(
int nChangeset, /* Size of buffer pChangeset in bytes */
void *pChangeset /* Pointer to buffer containing changeset */
){
- return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset);
+ return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset, 0);
+}
+int sqlite3changeset_start_v2(
+ sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */
+ int nChangeset, /* Size of buffer pChangeset in bytes */
+ void *pChangeset, /* Pointer to buffer containing changeset */
+ int flags
+){
+ int bInvert = !!(flags & SQLITE_CHANGESETSTART_INVERT);
+ return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset, bInvert);
}
/*
@@ -2585,7 +2635,16 @@ int sqlite3changeset_start_strm(
int (*xInput)(void *pIn, void *pData, int *pnData),
void *pIn
){
- return sessionChangesetStart(pp, xInput, pIn, 0, 0);
+ return sessionChangesetStart(pp, xInput, pIn, 0, 0, 0);
+}
+int sqlite3changeset_start_v2_strm(
+ sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */
+ int (*xInput)(void *pIn, void *pData, int *pnData),
+ void *pIn,
+ int flags
+){
+ int bInvert = !!(flags & SQLITE_CHANGESETSTART_INVERT);
+ return sessionChangesetStart(pp, xInput, pIn, 0, 0, bInvert);
}
/*
@@ -2593,7 +2652,7 @@ int sqlite3changeset_start_strm(
** object and the buffer is full, discard some data to free up space.
*/
static void sessionDiscardData(SessionInput *pIn){
- if( pIn->xInput && pIn->iNext>=SESSIONS_STRM_CHUNK_SIZE ){
+ if( pIn->xInput && pIn->iNext>=sessions_strm_chunk_size ){
int nMove = pIn->buf.nBuf - pIn->iNext;
assert( nMove>=0 );
if( nMove>0 ){
@@ -2616,7 +2675,7 @@ static int sessionInputBuffer(SessionInput *pIn, int nByte){
int rc = SQLITE_OK;
if( pIn->xInput ){
while( !pIn->bEof && (pIn->iNext+nByte)>=pIn->nData && rc==SQLITE_OK ){
- int nNew = SESSIONS_STRM_CHUNK_SIZE;
+ int nNew = sessions_strm_chunk_size;
if( pIn->bNoDiscard==0 ) sessionDiscardData(pIn);
if( SQLITE_OK==sessionBufferGrow(&pIn->buf, nNew, &rc) ){
@@ -2964,10 +3023,10 @@ static int sessionChangesetNext(
op = p->in.aData[p->in.iNext++];
}
- if( p->zTab==0 ){
+ if( p->zTab==0 || (p->bPatchset && p->bInvert) ){
/* The first record in the changeset is not a table header. Must be a
** corrupt changeset. */
- assert( p->in.iNext==1 );
+ assert( p->in.iNext==1 || p->zTab );
return (p->rc = SQLITE_CORRUPT_BKPT);
}
@@ -2992,33 +3051,39 @@ static int sessionChangesetNext(
*paRec = &p->in.aData[p->in.iNext];
p->in.iNext += *pnRec;
}else{
+ sqlite3_value **apOld = (p->bInvert ? &p->apValue[p->nCol] : p->apValue);
+ sqlite3_value **apNew = (p->bInvert ? p->apValue : &p->apValue[p->nCol]);
/* If this is an UPDATE or DELETE, read the old.* record. */
if( p->op!=SQLITE_INSERT && (p->bPatchset==0 || p->op==SQLITE_DELETE) ){
u8 *abPK = p->bPatchset ? p->abPK : 0;
- p->rc = sessionReadRecord(&p->in, p->nCol, abPK, p->apValue);
+ p->rc = sessionReadRecord(&p->in, p->nCol, abPK, apOld);
if( p->rc!=SQLITE_OK ) return p->rc;
}
/* If this is an INSERT or UPDATE, read the new.* record. */
if( p->op!=SQLITE_DELETE ){
- p->rc = sessionReadRecord(&p->in, p->nCol, 0, &p->apValue[p->nCol]);
+ p->rc = sessionReadRecord(&p->in, p->nCol, 0, apNew);
if( p->rc!=SQLITE_OK ) return p->rc;
}
- if( p->bPatchset && p->op==SQLITE_UPDATE ){
+ if( (p->bPatchset || p->bInvert) && p->op==SQLITE_UPDATE ){
/* If this is an UPDATE that is part of a patchset, then all PK and
** modified fields are present in the new.* record. The old.* record
** is currently completely empty. This block shifts the PK fields from
** new.* to old.*, to accommodate the code that reads these arrays. */
for(i=0; i<p->nCol; i++){
- assert( p->apValue[i]==0 );
+ assert( p->bPatchset==0 || p->apValue[i]==0 );
if( p->abPK[i] ){
+ assert( p->apValue[i]==0 );
p->apValue[i] = p->apValue[i+p->nCol];
if( p->apValue[i]==0 ) return (p->rc = SQLITE_CORRUPT_BKPT);
p->apValue[i+p->nCol] = 0;
}
}
+ }else if( p->bInvert ){
+ if( p->op==SQLITE_INSERT ) p->op = SQLITE_DELETE;
+ else if( p->op==SQLITE_DELETE ) p->op = SQLITE_INSERT;
}
}
@@ -3335,7 +3400,7 @@ static int sessionChangesetInvert(
}
assert( rc==SQLITE_OK );
- if( xOutput && sOut.nBuf>=SESSIONS_STRM_CHUNK_SIZE ){
+ if( xOutput && sOut.nBuf>=sessions_strm_chunk_size ){
rc = xOutput(pOut, sOut.aBuf, sOut.nBuf);
sOut.nBuf = 0;
if( rc!=SQLITE_OK ) goto finished_invert;
@@ -3414,7 +3479,8 @@ struct SessionApplyCtx {
int bDeferConstraints; /* True to defer constraints */
SessionBuffer constraints; /* Deferred constraints are stored here */
SessionBuffer rebase; /* Rebase information (if any) here */
- int bRebaseStarted; /* If table header is already in rebase */
+ u8 bRebaseStarted; /* If table header is already in rebase */
+ u8 bRebase; /* True to collect rebase information */
};
/*
@@ -3811,35 +3877,36 @@ static int sessionRebaseAdd(
sqlite3_changeset_iter *pIter /* Iterator pointing at current change */
){
int rc = SQLITE_OK;
- int i;
- int eOp = pIter->op;
- if( p->bRebaseStarted==0 ){
- /* Append a table-header to the rebase buffer */
- const char *zTab = pIter->zTab;
- sessionAppendByte(&p->rebase, 'T', &rc);
- sessionAppendVarint(&p->rebase, p->nCol, &rc);
- sessionAppendBlob(&p->rebase, p->abPK, p->nCol, &rc);
- sessionAppendBlob(&p->rebase, (u8*)zTab, (int)strlen(zTab)+1, &rc);
- p->bRebaseStarted = 1;
- }
-
- assert( eType==SQLITE_CHANGESET_REPLACE||eType==SQLITE_CHANGESET_OMIT );
- assert( eOp==SQLITE_DELETE || eOp==SQLITE_INSERT || eOp==SQLITE_UPDATE );
-
- sessionAppendByte(&p->rebase,
- (eOp==SQLITE_DELETE ? SQLITE_DELETE : SQLITE_INSERT), &rc
- );
- sessionAppendByte(&p->rebase, (eType==SQLITE_CHANGESET_REPLACE), &rc);
- for(i=0; i<p->nCol; i++){
- sqlite3_value *pVal = 0;
- if( eOp==SQLITE_DELETE || (eOp==SQLITE_UPDATE && p->abPK[i]) ){
- sqlite3changeset_old(pIter, i, &pVal);
- }else{
- sqlite3changeset_new(pIter, i, &pVal);
+ if( p->bRebase ){
+ int i;
+ int eOp = pIter->op;
+ if( p->bRebaseStarted==0 ){
+ /* Append a table-header to the rebase buffer */
+ const char *zTab = pIter->zTab;
+ sessionAppendByte(&p->rebase, 'T', &rc);
+ sessionAppendVarint(&p->rebase, p->nCol, &rc);
+ sessionAppendBlob(&p->rebase, p->abPK, p->nCol, &rc);
+ sessionAppendBlob(&p->rebase, (u8*)zTab, (int)strlen(zTab)+1, &rc);
+ p->bRebaseStarted = 1;
}
- sessionAppendValue(&p->rebase, pVal, &rc);
- }
+ assert( eType==SQLITE_CHANGESET_REPLACE||eType==SQLITE_CHANGESET_OMIT );
+ assert( eOp==SQLITE_DELETE || eOp==SQLITE_INSERT || eOp==SQLITE_UPDATE );
+
+ sessionAppendByte(&p->rebase,
+ (eOp==SQLITE_DELETE ? SQLITE_DELETE : SQLITE_INSERT), &rc
+ );
+ sessionAppendByte(&p->rebase, (eType==SQLITE_CHANGESET_REPLACE), &rc);
+ for(i=0; i<p->nCol; i++){
+ sqlite3_value *pVal = 0;
+ if( eOp==SQLITE_DELETE || (eOp==SQLITE_UPDATE && p->abPK[i]) ){
+ sqlite3changeset_old(pIter, i, &pVal);
+ }else{
+ sqlite3changeset_new(pIter, i, &pVal);
+ }
+ sessionAppendValue(&p->rebase, pVal, &rc);
+ }
+ }
return rc;
}
@@ -4182,7 +4249,7 @@ static int sessionRetryConstraints(
SessionBuffer cons = pApply->constraints;
memset(&pApply->constraints, 0, sizeof(SessionBuffer));
- rc = sessionChangesetStart(&pIter2, 0, 0, cons.nBuf, cons.aBuf);
+ rc = sessionChangesetStart(&pIter2, 0, 0, cons.nBuf, cons.aBuf, 0);
if( rc==SQLITE_OK ){
int nByte = 2*pApply->nCol*sizeof(sqlite3_value*);
int rc2;
@@ -4248,6 +4315,7 @@ static int sessionChangesetApply(
pIter->in.bNoDiscard = 1;
memset(&sApply, 0, sizeof(sApply));
+ sApply.bRebase = (ppRebase && pnRebase);
sqlite3_mutex_enter(sqlite3_db_mutex(db));
if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){
rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0);
@@ -4398,7 +4466,8 @@ static int sessionChangesetApply(
}
}
- if( rc==SQLITE_OK && bPatchset==0 && ppRebase && pnRebase ){
+ assert( sApply.bRebase || sApply.rebase.nBuf==0 );
+ if( rc==SQLITE_OK && bPatchset==0 && sApply.bRebase ){
*ppRebase = (void*)sApply.rebase.aBuf;
*pnRebase = sApply.rebase.nBuf;
sApply.rebase.aBuf = 0;
@@ -4436,7 +4505,8 @@ int sqlite3changeset_apply_v2(
int flags
){
sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */
- int rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset);
+ int bInverse = !!(flags & SQLITE_CHANGESETAPPLY_INVERT);
+ int rc = sessionChangesetStart(&pIter, 0, 0, nChangeset, pChangeset,bInverse);
if( rc==SQLITE_OK ){
rc = sessionChangesetApply(
db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags
@@ -4493,7 +4563,8 @@ int sqlite3changeset_apply_v2_strm(
int flags
){
sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */
- int rc = sqlite3changeset_start_strm(&pIter, xInput, pIn);
+ int bInverse = !!(flags & SQLITE_CHANGESETAPPLY_INVERT);
+ int rc = sessionChangesetStart(&pIter, xInput, pIn, 0, 0, bInverse);
if( rc==SQLITE_OK ){
rc = sessionChangesetApply(
db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags
@@ -4866,13 +4937,12 @@ static int sessionChangegroupOutput(
sessionAppendByte(&buf, p->op, &rc);
sessionAppendByte(&buf, p->bIndirect, &rc);
sessionAppendBlob(&buf, p->aRecord, p->nRecord, &rc);
+ if( rc==SQLITE_OK && xOutput && buf.nBuf>=sessions_strm_chunk_size ){
+ rc = xOutput(pOut, buf.aBuf, buf.nBuf);
+ buf.nBuf = 0;
+ }
}
}
-
- if( rc==SQLITE_OK && xOutput && buf.nBuf>=SESSIONS_STRM_CHUNK_SIZE ){
- rc = xOutput(pOut, buf.aBuf, buf.nBuf);
- buf.nBuf = 0;
- }
}
if( rc==SQLITE_OK ){
@@ -5263,7 +5333,7 @@ static int sessionRebase(
sessionAppendByte(&sOut, pIter->bIndirect, &rc);
sessionAppendBlob(&sOut, aRec, nRec, &rc);
}
- if( rc==SQLITE_OK && xOutput && sOut.nBuf>SESSIONS_STRM_CHUNK_SIZE ){
+ if( rc==SQLITE_OK && xOutput && sOut.nBuf>sessions_strm_chunk_size ){
rc = xOutput(pOut, sOut.aBuf, sOut.nBuf);
sOut.nBuf = 0;
}
@@ -5374,4 +5444,25 @@ void sqlite3rebaser_delete(sqlite3_rebaser *p){
}
}
+/*
+** Global configuration
+*/
+int sqlite3session_config(int op, void *pArg){
+ int rc = SQLITE_OK;
+ switch( op ){
+ case SQLITE_SESSION_CONFIG_STRMSIZE: {
+ int *pInt = (int*)pArg;
+ if( *pInt>0 ){
+ sessions_strm_chunk_size = *pInt;
+ }
+ *pInt = sessions_strm_chunk_size;
+ break;
+ }
+ default:
+ rc = SQLITE_MISUSE;
+ break;
+ }
+ return rc;
+}
+
#endif /* SQLITE_ENABLE_SESSION && SQLITE_ENABLE_PREUPDATE_HOOK */
diff --git a/chromium/third_party/sqlite/src/ext/session/sqlite3session.h b/chromium/third_party/sqlite/src/ext/session/sqlite3session.h
index f0f785a3a68..c93d0ecdaf4 100644
--- a/chromium/third_party/sqlite/src/ext/session/sqlite3session.h
+++ b/chromium/third_party/sqlite/src/ext/session/sqlite3session.h
@@ -473,12 +473,38 @@ int sqlite3session_isempty(sqlite3_session *pSession);
** consecutively. There is no chance that the iterator will visit a change
** the applies to table X, then one for table Y, and then later on visit
** another change for table X.
+**
+** The behavior of sqlite3changeset_start_v2() and its streaming equivalent
+** may be modified by passing a combination of
+** [SQLITE_CHANGESETSTART_INVERT | supported flags] as the 4th parameter.
+**
+** Note that the sqlite3changeset_start_v2() API is still <b>experimental</b>
+** and therefore subject to change.
*/
int sqlite3changeset_start(
sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */
int nChangeset, /* Size of changeset blob in bytes */
void *pChangeset /* Pointer to blob containing changeset */
);
+int sqlite3changeset_start_v2(
+ sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */
+ int nChangeset, /* Size of changeset blob in bytes */
+ void *pChangeset, /* Pointer to blob containing changeset */
+ int flags /* SESSION_CHANGESETSTART_* flags */
+);
+
+/*
+** CAPI3REF: Flags for sqlite3changeset_start_v2
+**
+** The following flags may passed via the 4th parameter to
+** [sqlite3changeset_start_v2] and [sqlite3changeset_start_v2_strm]:
+**
+** <dt>SQLITE_CHANGESETAPPLY_INVERT <dd>
+** Invert the changeset while iterating through it. This is equivalent to
+** inverting a changeset using sqlite3changeset_invert() before applying it.
+** It is an error to specify this flag with a patchset.
+*/
+#define SQLITE_CHANGESETSTART_INVERT 0x0002
/*
@@ -1133,7 +1159,7 @@ int sqlite3changeset_apply_v2(
),
void *pCtx, /* First argument passed to xConflict */
void **ppRebase, int *pnRebase, /* OUT: Rebase data */
- int flags /* Combination of SESSION_APPLY_* flags */
+ int flags /* SESSION_CHANGESETAPPLY_* flags */
);
/*
@@ -1151,8 +1177,14 @@ int sqlite3changeset_apply_v2(
** causes the sessions module to omit this savepoint. In this case, if the
** caller has an open transaction or savepoint when apply_v2() is called,
** it may revert the partially applied changeset by rolling it back.
+**
+** <dt>SQLITE_CHANGESETAPPLY_INVERT <dd>
+** Invert the changeset before applying it. This is equivalent to inverting
+** a changeset using sqlite3changeset_invert() before applying it. It is
+** an error to specify this flag with a patchset.
*/
#define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001
+#define SQLITE_CHANGESETAPPLY_INVERT 0x0002
/*
** CAPI3REF: Constants Passed To The Conflict Handler
@@ -1546,6 +1578,12 @@ int sqlite3changeset_start_strm(
int (*xInput)(void *pIn, void *pData, int *pnData),
void *pIn
);
+int sqlite3changeset_start_v2_strm(
+ sqlite3_changeset_iter **pp,
+ int (*xInput)(void *pIn, void *pData, int *pnData),
+ void *pIn,
+ int flags
+);
int sqlite3session_changeset_strm(
sqlite3_session *pSession,
int (*xOutput)(void *pOut, const void *pData, int nData),
@@ -1572,6 +1610,45 @@ int sqlite3rebaser_rebase_strm(
void *pOut
);
+/*
+** CAPI3REF: Configure global parameters
+**
+** The sqlite3session_config() interface is used to make global configuration
+** changes to the sessions module in order to tune it to the specific needs
+** of the application.
+**
+** The sqlite3session_config() interface is not threadsafe. If it is invoked
+** while any other thread is inside any other sessions method then the
+** results are undefined. Furthermore, if it is invoked after any sessions
+** related objects have been created, the results are also undefined.
+**
+** The first argument to the sqlite3session_config() function must be one
+** of the SQLITE_SESSION_CONFIG_XXX constants defined below. The
+** interpretation of the (void*) value passed as the second parameter and
+** the effect of calling this function depends on the value of the first
+** parameter.
+**
+** <dl>
+** <dt>SQLITE_SESSION_CONFIG_STRMSIZE<dd>
+** By default, the sessions module streaming interfaces attempt to input
+** and output data in approximately 1 KiB chunks. This operand may be used
+** to set and query the value of this configuration setting. The pointer
+** passed as the second argument must point to a value of type (int).
+** If this value is greater than 0, it is used as the new streaming data
+** chunk size for both input and output. Before returning, the (int) value
+** pointed to by pArg is set to the final value of the streaming interface
+** chunk size.
+** </dl>
+**
+** This function returns SQLITE_OK if successful, or an SQLite error code
+** otherwise.
+*/
+int sqlite3session_config(int op, void *pArg);
+
+/*
+** CAPI3REF: Values for sqlite3session_config().
+*/
+#define SQLITE_SESSION_CONFIG_STRMSIZE 1
/*
** Make sure we can call this stuff from C++.
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 3cd529a5977..7273ebe242c 100644
--- a/chromium/third_party/sqlite/src/ext/session/test_session.c
+++ b/chromium/third_party/sqlite/src/ext/session/test_session.c
@@ -737,20 +737,32 @@ static int SQLITE_TCLAPI testSqlite3changesetApply(
sStr.nStream = test_tcl_integer(interp, SESSION_STREAM_TCL_VAR);
/* Check for the -nosavepoint flag */
- if( bV2 && objc>1 ){
- const char *z1 = Tcl_GetString(objv[1]);
- int n = strlen(z1);
- if( n>1 && n<=12 && 0==sqlite3_strnicmp("-nosavepoint", z1, n) ){
- flags = SQLITE_CHANGESETAPPLY_NOSAVEPOINT;
- objc--;
- objv++;
+ if( bV2 ){
+ if( objc>1 ){
+ const char *z1 = Tcl_GetString(objv[1]);
+ int n = strlen(z1);
+ if( n>1 && n<=12 && 0==sqlite3_strnicmp("-nosavepoint", z1, n) ){
+ flags |= SQLITE_CHANGESETAPPLY_NOSAVEPOINT;
+ objc--;
+ objv++;
+ }
+ }
+ if( objc>1 ){
+ const char *z1 = Tcl_GetString(objv[1]);
+ int n = strlen(z1);
+ if( n>1 && n<=7 && 0==sqlite3_strnicmp("-invert", z1, n) ){
+ flags |= SQLITE_CHANGESETAPPLY_INVERT;
+ objc--;
+ objv++;
+ }
}
}
if( objc!=4 && objc!=5 ){
const char *zMsg;
if( bV2 ){
- zMsg = "?-nosavepoint? DB CHANGESET CONFLICT-SCRIPT ?FILTER-SCRIPT?";
+ zMsg = "?-nosavepoint? ?-inverse? "
+ "DB CHANGESET CONFLICT-SCRIPT ?FILTER-SCRIPT?";
}else{
zMsg = "DB CHANGESET CONFLICT-SCRIPT ?FILTER-SCRIPT?";
}
@@ -969,31 +981,56 @@ static int SQLITE_TCLAPI test_sqlite3session_foreach(
Tcl_Obj *pCS;
Tcl_Obj *pScript;
int isCheckNext = 0;
+ int isInvert = 0;
TestStreamInput sStr;
memset(&sStr, 0, sizeof(sStr));
- if( objc>1 ){
+ while( objc>1 ){
char *zOpt = Tcl_GetString(objv[1]);
- isCheckNext = (strcmp(zOpt, "-next")==0);
+ int nOpt = strlen(zOpt);
+ if( zOpt[0]!='-' ) break;
+ if( nOpt<=7 && 0==sqlite3_strnicmp(zOpt, "-invert", nOpt) ){
+ isInvert = 1;
+ }else
+ if( nOpt<=5 && 0==sqlite3_strnicmp(zOpt, "-next", nOpt) ){
+ isCheckNext = 1;
+ }else{
+ break;
+ }
+ objv++;
+ objc--;
}
- if( objc!=4+isCheckNext ){
- Tcl_WrongNumArgs(interp, 1, objv, "?-next? VARNAME CHANGESET SCRIPT");
+ if( objc!=4 ){
+ Tcl_WrongNumArgs(
+ interp, 1, objv, "?-next? ?-invert? VARNAME CHANGESET SCRIPT");
return TCL_ERROR;
}
- pVarname = objv[1+isCheckNext];
- pCS = objv[2+isCheckNext];
- pScript = objv[3+isCheckNext];
+ pVarname = objv[1];
+ pCS = objv[2];
+ pScript = objv[3];
pChangeset = (void *)Tcl_GetByteArrayFromObj(pCS, &nChangeset);
sStr.nStream = test_tcl_integer(interp, SESSION_STREAM_TCL_VAR);
- if( sStr.nStream==0 ){
- rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset);
+ if( isInvert ){
+ int f = SQLITE_CHANGESETSTART_INVERT;
+ if( sStr.nStream==0 ){
+ rc = sqlite3changeset_start_v2(&pIter, nChangeset, pChangeset, f);
+ }else{
+ void *pCtx = (void*)&sStr;
+ sStr.aData = (unsigned char*)pChangeset;
+ sStr.nData = nChangeset;
+ rc = sqlite3changeset_start_v2_strm(&pIter, testStreamInput, pCtx, f);
+ }
}else{
- sStr.aData = (unsigned char*)pChangeset;
- sStr.nData = nChangeset;
- rc = sqlite3changeset_start_strm(&pIter, testStreamInput, (void*)&sStr);
+ if( sStr.nStream==0 ){
+ rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset);
+ }else{
+ sStr.aData = (unsigned char*)pChangeset;
+ sStr.nData = nChangeset;
+ rc = sqlite3changeset_start_strm(&pIter, testStreamInput, (void*)&sStr);
+ }
}
if( rc!=SQLITE_OK ){
return test_session_error(interp, rc, 0);
@@ -1202,6 +1239,45 @@ static int SQLITE_TCLAPI test_sqlite3rebaser_create(
return TCL_OK;
}
+/*
+** tclcmd: sqlite3rebaser_configure OP VALUE
+*/
+static int SQLITE_TCLAPI test_sqlite3session_config(
+ void * clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+ struct ConfigOpt {
+ const char *zSub;
+ int op;
+ } aSub[] = {
+ { "strm_size", SQLITE_SESSION_CONFIG_STRMSIZE },
+ { "invalid", 0 },
+ { 0 }
+ };
+ int rc;
+ int iSub;
+ int iVal;
+
+ if( objc!=3 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "OP VALUE");
+ return SQLITE_ERROR;
+ }
+ rc = Tcl_GetIndexFromObjStruct(interp,
+ objv[1], aSub, sizeof(aSub[0]), "sub-command", 0, &iSub
+ );
+ if( rc!=TCL_OK ) return rc;
+ if( Tcl_GetIntFromObj(interp, objv[2], &iVal) ) return TCL_ERROR;
+
+ rc = sqlite3session_config(aSub[iSub].op, (void*)&iVal);
+ if( rc!=SQLITE_OK ){
+ return test_session_error(interp, rc, 0);
+ }
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(iVal));
+ return TCL_OK;
+}
+
int TestSession_Init(Tcl_Interp *interp){
struct Cmd {
const char *zCmd;
@@ -1217,6 +1293,7 @@ int TestSession_Init(Tcl_Interp *interp){
test_sqlite3changeset_apply_replace_all },
{ "sql_exec_changeset", test_sql_exec_changeset },
{ "sqlite3rebaser_create", test_sqlite3rebaser_create },
+ { "sqlite3session_config", test_sqlite3session_config },
};
int i;
diff --git a/chromium/third_party/sqlite/src/main.mk b/chromium/third_party/sqlite/src/main.mk
index 8992aadf937..40ab267ec72 100644
--- a/chromium/third_party/sqlite/src/main.mk
+++ b/chromium/third_party/sqlite/src/main.mk
@@ -363,6 +363,7 @@ TESTSRC += \
$(TOP)/ext/misc/closure.c \
$(TOP)/ext/misc/csv.c \
$(TOP)/ext/misc/eval.c \
+ $(TOP)/ext/misc/explain.c \
$(TOP)/ext/misc/fileio.c \
$(TOP)/ext/misc/fuzzer.c \
$(TOP)/ext/misc/ieee754.c \
@@ -397,6 +398,7 @@ TESTSRC2 = \
$(TOP)/src/dbstat.c \
$(TOP)/src/expr.c \
$(TOP)/src/func.c \
+ $(TOP)/src/global.c \
$(TOP)/src/insert.c \
$(TOP)/src/wal.c \
$(TOP)/src/main.c \
@@ -510,7 +512,8 @@ FUZZDATA = \
$(TOP)/test/fuzzdata3.db \
$(TOP)/test/fuzzdata4.db \
$(TOP)/test/fuzzdata5.db \
- $(TOP)/test/fuzzdata6.db
+ $(TOP)/test/fuzzdata6.db \
+ $(TOP)/test/fuzzdata7.db
# Standard options to testfixture
#
@@ -897,6 +900,10 @@ fts3-testfixture$(EXE): sqlite3.c fts3amal.c $(TESTSRC) $(TOP)/src/tclsqlite.c
$(TESTSRC) $(TOP)/src/tclsqlite.c sqlite3.c fts3amal.c \
-o testfixture$(EXE) $(LIBTCL) $(THREADLIB)
+coretestprogs: $(TESTPROGS)
+
+testprogs: coretestprogs srcck1$(EXE) fuzzcheck$(EXE) sessionfuzz$(EXE)
+
fulltest: $(TESTPROGS) fuzztest
./testfixture$(EXE) $(TOP)/test/all.test $(TESTOPTS)
@@ -997,6 +1004,10 @@ changeset$(EXE): $(TOP)/ext/session/changeset.c sqlite3.o
$(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o changeset$(EXE) \
$(TOP)/ext/session/changeset.c sqlite3.o $(THREADLIB)
+changesetfuzz$(EXE): $(TOP)/ext/session/changesetfuzz.c sqlite3.o
+ $(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o changesetfuzz$(EXE) \
+ $(TOP)/ext/session/changesetfuzz.c sqlite3.o $(THREADLIB)
+
fts3view$(EXE): $(TOP)/ext/fts3/tool/fts3view.c sqlite3.o
$(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o fts3view$(EXE) \
$(TOP)/ext/fts3/tool/fts3view.c sqlite3.o $(THREADLIB)
diff --git a/chromium/third_party/sqlite/src/manifest b/chromium/third_party/sqlite/src/manifest
index 3f62d03554d..bb8f3728c11 100644
--- a/chromium/third_party/sqlite/src/manifest
+++ b/chromium/third_party/sqlite/src/manifest
@@ -1,12 +1,12 @@
-C Version\s3.25.3
-D 2018-11-05T20:37:38.221
+C Version\s3.26.0
+D 2018-12-01T12:34:55.966
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
-F Makefile.in 6b650013511fd9d8b094203ac268af9220d292cc7d4e1bc9fbca15aacd8c7995
+F Makefile.in a050c8670ea0d7b37b2192306cbb50d392acd9902b84e9b56f3444d006f97a6c
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
-F Makefile.msc a889c6981a222d639f8a548adcfb3183ac07871e27452ace4d810735750f216a
+F Makefile.msc 0d6831ff7951b302e888d86d4c469e2ec3c22f59eba4118b8c38d5a51d9e2d4f
F README.md 377233394b905d3b2e2b33741289e093bc93f2e7adbe00923b2c5958c9a9edee
-F VERSION a0e6c0b0a597b690112e0efc8079eac843d09051529e7fd7451f893d03ba4a2c
+F VERSION 654da1d4053fb09ffc33a3910e6d427182a7dcdc67e934fa83de2849ac83fccb
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
@@ -33,11 +33,11 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
-F configure d48f51d52de9fda6eacabaa3c1ac43b0ac7137fa0fe5a3879f122a2de6ac8990 x
+F configure 5811ffcd4866902d1706dcf8e0527f89165ec52859659942c9649bb1d3e4cc7b x
F configure.ac 3552d3aecade98a9d4b64bceb48ffb7726cbc85902efde956812942f060fbd0a
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
-F doc/lemon.html ac63db056bce24b7368e29319cd1a7eb5f1798cc85922d96a80b6c3a4ff9f51b
+F doc/lemon.html 24956ab2995e55fe171e55bdd04f22b553957dc8bb43501dbb9311e30187e0d3
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
F doc/vfs-shm.txt e101f27ea02a8387ce46a05be2b1a902a021d37a
F ext/README.md fd5f78013b0a2bc6f0067afb19e6ad040e89a10179b4f6f03eee58fac5f169bd
@@ -47,7 +47,7 @@ F ext/async/sqlite3async.h f489b080af7e72aec0e1ee6f1d98ab6cf2e4dcef
F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3
F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4
F ext/expert/expert1.test 333d037021c901322f9afc4a5687648ea23d56f1a0a079358a390664babf01be
-F ext/expert/sqlite3expert.c 89b7b59be610b929958db02416539a46ac088fd84f81623c4190aff62e92c3c4
+F ext/expert/sqlite3expert.c 3da865f2286433588260f41e796422c611bceaca3a0bbf9139a619cf7d062c19
F ext/expert/sqlite3expert.h af6354f8ee5c9e025024e63fec3bd640a802afcc3099a44d804752cf0791d811
F ext/expert/test_expert.c d56c194b769bdc90cf829a14c9ecbc1edca9c850b837a4d0b13be14095c32a72
F ext/fts1/README.txt 20ac73b006a70bcfd80069bdaf59214b6cf1db5e
@@ -80,19 +80,19 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
-F ext/fts3/fts3.c 012384f01df28345a8d0d0c7fe465ab211598a91d78a7331b3664533756ed9fa
+F ext/fts3/fts3.c 65b8489e35da23b127992c6dd6cfd382a486f8c87bf26dfa72876efe46e551bb
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
F ext/fts3/fts3Int.h 3378157f383540857a466420b8279626204434c3eb0dc948ad9bcd3991fc41f5
-F ext/fts3/fts3_aux.c 9edc3655fcb287f0467d0a4b886a01c6185fe9f1
+F ext/fts3/fts3_aux.c e9b465f8469acc2cd700a90c0242912a3202e4e4e15df72d7db7f1e3a2222c85
F ext/fts3/fts3_expr.c 3b1dbceddd8622599f3cc2626897667fe40487aaa1676707d6c37ec5a8422fc1
F ext/fts3/fts3_hash.c 29b986e43f4e9dd40110eafa377dc0d63c422c60
F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf
F ext/fts3/fts3_icu.c deb46f7020d87ea7a14a433fb7a7f4bef42a9652
F ext/fts3/fts3_porter.c 3565faf04b626cddf85f03825e86056a4562c009
F ext/fts3/fts3_snippet.c 68ae118b0f834ea53d2b89e4087fc0f0b8c4ee4e
-F ext/fts3/fts3_term.c 88c55a6fa1a51ab494e33dced0401a6c28791fd7
+F ext/fts3/fts3_term.c 9b8065cc70ad514fcc25a7b099ddab8b5333f724dedd57184b7e79238e2b2a39
F ext/fts3/fts3_test.c 79f2a7fbb3f672fa032e5a432ca274ea3ee93c34
-F ext/fts3/fts3_tokenize_vtab.c a27593ab19657166f6fa5ec073b678cc29a75860
+F ext/fts3/fts3_tokenize_vtab.c a47c2a33de6db00816704315ac0a9afdfa1c71fa5b99f79171c0f7b30861f784
F ext/fts3/fts3_tokenizer.c a22bf311a71f3efa9d7012d8cc48fc9b0f3dace7
F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004
@@ -115,20 +115,20 @@ F ext/fts5/fts5_buffer.c 1dd1ec0446b3acfc2d7d407eb894762a461613e2695273f48e449bf
F ext/fts5/fts5_config.c 5af9c360e99669d29f06492c370892394aba0857
F ext/fts5/fts5_expr.c 5aef080ba3c8947e22f38ce1ff9fe548e4a740e72b77241f35ed941ae128d2c7
F ext/fts5/fts5_hash.c 32be400cf761868c9db33efe81a06eb19a17c5402ad477ee9efb51301546dd55
-F ext/fts5/fts5_index.c d1b2d7d92cb2b72b9465da35b7d7c30e4b426c7f208bf6f94ce86b50eed8a1cb
-F ext/fts5/fts5_main.c 7e52868e6b444e5353ff30e1dcd2a9273e8eaa543ddccf0c94b3cd2c235ff104
+F ext/fts5/fts5_index.c baf3ad4451d32d35c2bd692ee4a81235ca7f26bd6f7613f7f73505474c33bbf2
+F ext/fts5/fts5_main.c 287a1a56580df304d7fa2fc1890f85b9cb6ac6b9e7c8af7dfa2151528db4b059
F ext/fts5/fts5_storage.c 4bec8a1b3905978b22a67bca5f4a3cfdb94af234cf51efb36f4f2d733d278634
F ext/fts5/fts5_tcl.c 39bcbae507f594aad778172fa914cad0f585bf92fd3b078c686e249282db0d95
F ext/fts5/fts5_test_mi.c 65864ba1e5c34a61d409c4c587e0bbe0466eb4f8f478d85dc42a92caad1338e6
-F ext/fts5/fts5_test_tok.c ffd657dd67e7fcdb31bf63fb60b6d867299a581d0f46e97086abacd66c2a9b26
+F ext/fts5/fts5_test_tok.c 80de1a4b1a3caa216c3be8862440f0117a8357dd9b7cfc5a2a2ce11fe6eb64ae
F ext/fts5/fts5_tokenize.c ebd13d034f3dc7c841e1c32c364a4fca5cc2e05a0b91682a93fa1e6defcd4292
F ext/fts5/fts5_unicode2.c 543cf0987c27ad59e5a7a6222480b917b5431009b7b139027c9581a63e39e37e
F ext/fts5/fts5_varint.c a5aceacda04dafcbae725413d7a16818ecd65738
-F ext/fts5/fts5_vocab.c 1cd79854cb21543e66507b25b0578bc1b20aa6a1349b7feceb8e8fed0e7a77a6
+F ext/fts5/fts5_vocab.c fbe38044889b2d2d99babeeef239c620fb0332bb928a84506ac748d81500b354
F ext/fts5/fts5parse.y eb526940f892ade5693f22ffd6c4f2702543a9059942772526eac1fde256bb05
F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
F ext/fts5/test/fts5_common.tcl b01c584144b5064f30e6c648145a2dd6bc440841
-F ext/fts5/test/fts5aa.test 87f4b50e755b52c6192c76ceccf4247d462bb44b52fa17358f273d8ce5d975f0
+F ext/fts5/test/fts5aa.test 840081efaee97f5ec570146bbdd79cfdfaea0ab303de3d5037b6d6c78b42ccdd
F ext/fts5/test/fts5ab.test 9205c839332c908aaad2b01ab8670ece8b161e8f2ec8a9fabf18ca9385880bb7
F ext/fts5/test/fts5ac.test a7aa7e1fefc6e1918aa4d3111d5c44a09177168e962c5fd2cca9620de8a7ed6d
F ext/fts5/test/fts5ad.test e8cf959dfcd57c8e46d6f5f25665686f3b6627130a9a981371dafdf6482790de
@@ -151,11 +151,11 @@ F ext/fts5/test/fts5colset.test a30473451321bbf0b6218af62e96b4ae5fa99931cfdb210b
F ext/fts5/test/fts5columnsize.test 45459ce4dd9fd853b6044cdc9674921bff89e3d840f348ca8c1630f9edbf5482
F ext/fts5/test/fts5config.test 60094712debc59286c59aef0e6cf511c37d866802776a825ce437d26afe0817f
F ext/fts5/test/fts5conflict.test 655925678e630d3cdf145d18725a558971806416f453ac8410ca8c04d934238d
-F ext/fts5/test/fts5connect.test b12a2a8b02af3c31c18abbc33aa8100d364de19a888a44457484d21dbccb18a7
+F ext/fts5/test/fts5connect.test 08030168fc96fc278fa81f28654fb7e90566f33aff269c073e19b3ae9126b2f4
F ext/fts5/test/fts5content.test 688d5ac7af194ebc67495daea76a69e3cd5480122c2320e72d41241b423b4116
-F ext/fts5/test/fts5corrupt.test 8957f0f7e57e0f8a102c5b6e1a7326d6a1966b28e1d99c5883822af1e6038e9e
-F ext/fts5/test/fts5corrupt2.test 6deaf9f9606b3c957529db9881622bb3a7829b19bb3cdf8f276f074d684ede56
-F ext/fts5/test/fts5corrupt3.test 1b489101212206da1f27d0d03b9667e54571cba72db7e70b195fdf39f867b48c
+F ext/fts5/test/fts5corrupt.test 77ae6f41a7eba10620efb921cf7dbe218b0ef232b04519deb43581cb17a57ebe
+F ext/fts5/test/fts5corrupt2.test 7453752ba12ce91690c469a6449d412561cc604b1dec994e16ab132952e7805f
+F ext/fts5/test/fts5corrupt3.test ff9aee403611461e2619d2217c0d7d101a9c0179277c13c8a89516d7cf0dda43
F ext/fts5/test/fts5delete.test cbf87e3b8867c4d5cfcaed975c7475fd3f99d072bce2075fcedf43d1f82af775
F ext/fts5/test/fts5detail.test 31b240dbf6d44ac3507e2f8b65f29fdc12465ffd531212378c7ce1066766f54e
F ext/fts5/test/fts5determin.test 1b77879b2ae818b5b71c859e534ee334dac088b7cf3ff3bf76a2c82b1c788d11
@@ -175,11 +175,11 @@ F ext/fts5/test/fts5fault9.test 098e6b894bbdf9b2192f994a30f4043673fb3f338b6b8ab1
F ext/fts5/test/fts5faultA.test be4487576bff8c22cee6597d1893b312f306504a8c6ccd3c53ca85af12290c8c
F ext/fts5/test/fts5faultB.test e6d04f9ea7b21be1d89abb8df2cb4baf65b0453b744d5a805fcd3ef45ff86a7e
F ext/fts5/test/fts5faultD.test cc5d1225556e356615e719c612e845d41bff7d5a
-F ext/fts5/test/fts5first.test 707a591b1b7d893fcfcb2366cbfe56aefab5d9c7cfa58bef35eba73a1dbf3b29
+F ext/fts5/test/fts5first.test 3fcf2365c00a15fc9704233674789a3b95131d12de18a9b996159f6909dc8079
F ext/fts5/test/fts5full.test 49b565da02918c06e58f51f0b953b0302b96f155aa68baba24782b81570685e2
F ext/fts5/test/fts5fuzz1.test 238d8c45f3b81342aa384de3e581ff2fa330bf922a7b69e484bbc06051a1080e
F ext/fts5/test/fts5hash.test a4cf51acad99bfc43c16fb74f9d22495dc221ae0701fc5e908ca963a9b26a02b
-F ext/fts5/test/fts5integrity.test 6c4aad7f7380ec459a0c27ebbc0cb314fa67f3a3dad0cc820f612d33aa887166
+F ext/fts5/test/fts5integrity.test 4317561cd25eca7df16aa1f7d1a700ee958059fa639785f94aba0a84df9ab17b
F ext/fts5/test/fts5lastrowid.test be98fe3e03235296585b72daad7aed5717ba0062bae5e5c18dd6e04e194c6b28
F ext/fts5/test/fts5leftjoin.test c0b4cafb9661379e576dc4405c0891d8fcc2782680740513c4d1fc114b43d4ad
F ext/fts5/test/fts5matchinfo.test 79129ff6c9a2d86943b287a5a8caa7ee639f6dcf004d8975d15c279374e82e35
@@ -195,10 +195,10 @@ F ext/fts5/test/fts5porter.test 8d08010c28527db66bc3feebd2b8767504aaeb9b101a9863
F ext/fts5/test/fts5porter2.test 0d251a673f02fa13ca7f011654873b3add20745f7402f108600a23e52d8c7457
F ext/fts5/test/fts5prefix.test a0fa67b06650f2deaa7bf27745899d94e0fb547ad9ecbd08bfad98c04912c056
F ext/fts5/test/fts5query.test ac363b17a442620bb0780e93c24f16a5f963dfe2f23dc85647b869efcfada728
-F ext/fts5/test/fts5rank.test beb1adae7b076beea98277f140e713f9713f503866d3ff7286c9805b220dd4a2
-F ext/fts5/test/fts5rebuild.test 6d09fd54b1170a1e54fe17b808bbf17fba3154956cc2f065dd94bf1e3d254f63
+F ext/fts5/test/fts5rank.test ca5000241924ecc2882db33c60f4f3a62b1ee6b16b5a9c8c6ddd9b6b2138489c
+F ext/fts5/test/fts5rebuild.test 55d6f17715cddbf825680dd6551efbc72ed916d8cf1cde40a46fc5d785b451e7
F ext/fts5/test/fts5restart.test 835ecc8f449e3919f72509ab58056d0cedca40d1fe04108ccf8ac4c2ba41f415
-F ext/fts5/test/fts5rowid.test 365997f5aebd619df3ae46c2a4bfc8edba361899bc4e52cebfba0dbcbf720522
+F ext/fts5/test/fts5rowid.test b8790ec170a8dc1942a15aef3db926a5f3061b1ff171013003d8297203a20ad6
F ext/fts5/test/fts5simple.test 313ad28ef38ebe25f0a1673dd18f2fac446e25feb15bbb0c223a65ea00594f72
F ext/fts5/test/fts5simple2.test 258a1b0c590409bfa5271e872c79572b319d2a56554d0585f68f146a0da603f0
F ext/fts5/test/fts5simple3.test d5c74a9d3ca71bd5dd5cacb7c55b86ea12cdddfc8b1910e3de2995206898380f
@@ -213,9 +213,9 @@ F ext/fts5/test/fts5unicode3.test c3caecbe8264629ffe653b43ca5790b9793eba4422f922
F ext/fts5/test/fts5unicode4.test 6463301d669f963c83988017aa354108be0b947d325aef58d3abddf27147b687
F ext/fts5/test/fts5unindexed.test 9021af86a0fb9fc616f7a69a996db0116e7936d0db63892db6bafabbec21af4d
F ext/fts5/test/fts5update.test 0737876e20e97a6a6abf45de19fc99315727bcee6a83fadcada1cc080b9aa8f0
-F ext/fts5/test/fts5version.test 99b81372630fbf359107c96580fa761e41cdfb1dafc9966e148629ca72efee71
-F ext/fts5/test/fts5vocab.test 2ba98bcef0fcab3e5fead8eaabd6c0efb7e57bfe707a5cfcc18572ca9b277360
-F ext/fts5/test/fts5vocab2.test 2beeec974a305a1d79b91426622cc922c87065874437d22b400de7438979959e
+F ext/fts5/test/fts5version.test c8f2cc105f0abf0224965f93e584633dee3e06c91478bc67e468f7cfdf97fd6a
+F ext/fts5/test/fts5vocab.test 2de834ee6405130d3373817ced8fefbfee392b63d932e471740e09829f1e4510
+F ext/fts5/test/fts5vocab2.test d6039b20118e886113fc63614d9ad39a466fc2af34184f3e915b9f92b7ebfa10
F ext/fts5/tool/fts5speed.tcl b0056f91a55b2d1a3684ec05729de92b042e2f85
F ext/fts5/tool/fts5txt2db.tcl 526a9979c963f1c54fd50976a05a502e533a4c59
F ext/fts5/tool/loadfts5.tcl 95b03429ee6b138645703c6ca192c3ac96eaf093
@@ -270,21 +270,23 @@ F ext/lsm1/test/lsm1_common.tcl 5ed4bab07c93be2e4f300ebe46007ecf4b3e20bc5fbe1ded
F ext/lsm1/test/lsm1_simple.test ca949efefa102f4644231dcd9291d8cda7699a4ce1006b26e0e3fcb72233f422
F ext/lsm1/tool/mklsm1c.tcl f31561bbee5349f0a554d1ad7236ac1991fc09176626f529f6078e07335398b0
F ext/misc/README.md d6dd0fe1d8af77040216798a6a2b0c46c73054d2f0ea544fbbcdccf6f238c240
-F ext/misc/amatch.c 6db4607cb17c54b853a2d7c7c36046d004853f65b9b733e6f019d543d5dfae87
+F ext/misc/amatch.c c0a6a807a553eaa220bf69fca0353cd1587a3bfb3d2224fa425e3e6efcacc98a
F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb
F ext/misc/appendvfs.c 3777f22ec1057dc4e5fd89f2fbddcc7a29fbeef1ad038c736c54411bb1967af7
-F ext/misc/btreeinfo.c 78c8c57d325185ccc04b7679e5b020e34a4d9c87453e6b7ac943d0a26cee3256
+F ext/misc/btreeinfo.c 4f0ebf278f46e68e6306c667917766cebc5550fd35d5de17847988e22892d4d2
F ext/misc/carray.c ed96c218ea940b85c9a274c4d9c59fe9491c299147a38a8bba537687bd6c6005
-F ext/misc/closure.c fe928228e8dfb2f00227311c203ccba9c2e5561f4f6de6da87e5b4a30cd8af15
-F ext/misc/completion.c fc811dda86d899c15848079c32cad40c181da1dd7a1a4f8d768a2c6ce07a1904
+F ext/misc/closure.c 9f8fa11aa6c6e2f6d7296ffa88f103df4b46abd9602bcab3ea2f8fc24f334f63
+F ext/misc/completion.c cec672d40604075bb341a7f11ac48393efdcd90a979269b8fe7977ea62d0547f
F ext/misc/compress.c dd4f8a6d0baccff3c694757db5b430f3bbd821d8686d1fc24df55cf9f035b189
-F ext/misc/csv.c 65297bcce8d5acd5aadef42acbe739aef5a2ef5e74c7b73361ca19f3e21de657
+F ext/misc/csv.c 88333dc9f7dcf6a8148406f10ae04261e24e3b4c721550ae33e9e71f1265c1f1
F ext/misc/dbdump.c 12389a10c410fadf1e68eeb382def92d5a7fa9ce7cce4fb86a736fa2bac1000a
F ext/misc/eval.c 6ea9b22a5fa0dd973b67ca4e53555be177bc0b7b263aadf1024429457c82c0e3
-F ext/misc/fileio.c 7317d825fab6a3c48f6e3822a00a6a22e08e55af31700ac96f16a523f83069fd
+F ext/misc/explain.c d5c12962d79913ef774b297006872af1fccda388f61a11d37758f9179a09551f
+F ext/misc/fileio.c e3153b04433897a18a3d17185845f286892e96fdf87f4301290d09c36ae1759f
F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25
F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c
-F ext/misc/json1.c 276f87dc8365b34b0fffb7ef32481dd07fac6fdb3224e2822396a48377ac8363
+F ext/misc/json1.c 3f017d2659e531d021d015ec5d69ea0b1c71f2e15bf9768b1e149fcdf6c3e0b1
+F ext/misc/memstat.c 941928c6104d8ed569a6c47caa756dc78b8091f7a15f87d3004f3b1e576b10da
F ext/misc/memvfs.c ab36f49e02ebcdf85a1e08dc4d8599ea8f343e073ac9e0bca18a98b7e1ec9567
F ext/misc/mmapwarm.c 70b618f2d0bde43fae288ad0b7498a629f2b6f61b50a27e06fae3cd23c83af29
F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
@@ -294,59 +296,59 @@ F ext/misc/regexp.c a68d25c659bd2d893cd1215667bbf75ecb9dc7d4
F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
F ext/misc/rot13.c 540a169cb0d74f15522a8930b0cccdcb37a4fd071d219a5a083a319fc6e8db77
F ext/misc/scrub.c db9fff56fed322ca587d73727c6021b11ae79ce3f31b389e1d82891d144f22ad
-F ext/misc/series.c c7197db304f7009b08d6459a9de02e7f51ad0e1a3fdacbc1ebf5252a9a346959
-F ext/misc/sha1.c 0b9e9b855354910d3ca467bf39099d570e73db56
-F ext/misc/shathree.c 9e960ba50483214c6a7a4b1517f8d8cef799e9db381195178c3fd3ad207e10c0
+F ext/misc/series.c 0c97f63378fddc9f425e82ba139b9aaf902211f24ced115c2b6ae12b425f7334
+F ext/misc/sha1.c df0a667211baa2c0612d8486acbf6331b9f8633fd4d605c17c7cccd26d59c6bd
+F ext/misc/shathree.c 22ba7ca84a433d6466a7d05dcc876910b435a715da8cc462517db9351412b8c8
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
-F ext/misc/spellfix.c 54d650f44f3a69a851814791bd4d304575cdbbf78d96d4f0801b44a8f31a58c5
+F ext/misc/spellfix.c f88ecb2c0294453ce8b7704b211f5350c41b085b38c8e056852e3a08b0f5e484
F ext/misc/sqlar.c 57d5bc45cd5492208e451f697404be88f8612527d64c9d42f96b325b64983d74
-F ext/misc/stmt.c 6f16443abb3551e3f5813bb13ba19a30e7032830015b0f92fe0c0453045c0a11
-F ext/misc/templatevtab.c 8251b31011dd00fc38e739c78c234c930be42b3b274bbe0493b79cd40db02a9e
+F ext/misc/stmt.c 8a8dc4675042e4551e4afe99b8d0cc7a4a2fc1a8dacc0a9ce1b1bbff145da93d
+F ext/misc/templatevtab.c 8a16a91a5ceaccfcbd6aaaa56d46828806e460dd194965b3f77bf38f14b942c4
F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
-F ext/misc/unionvtab.c 0b3173f69b8899da640a13a345dc5ef1400199405f738abe6145b2454195b8ff
+F ext/misc/unionvtab.c acf947858054850db2d4a611bfeae072cdc6d9f517b46a993fe1f2f1ea20031e
F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95
F ext/misc/vfsstat.c bf10ef0bc51e1ad6756629e1edb142f7a8db1178
-F ext/misc/vtablog.c 31d0d8f4406795679dcd3a67917c213d3a2a5fb3ea5de35f6e773491ed7e13c9
+F ext/misc/vtablog.c 5538acd0c8ddaae372331bee11608d76973436b77d6a91e8635cfc9432fba5ae
F ext/misc/vtshim.c 1976e6dd68dd0d64508c91a6dfab8e75f8aaf6cd
F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212
-F ext/misc/zipfile.c c4de8f0ad446ce4a49aae11ff7b771cd7af60d7136c0bcfb53da1475b9075e79
+F ext/misc/zipfile.c 1d731db326c40e11fc608f38132acff31619946c000e85ab8efe75bbedc2a441
F ext/misc/zorder.c b0ff58fa643afa1d846786d51ea8d5c4b6b35aa0254ab5a82617db92f3adda64
F ext/rbu/rbu.c 8681f6157db6adc82c34af24b14ea8a3be0146ad2a3b6c1d5da6cb8a5796c8ce
-F ext/rbu/rbu1.test 41123c64e8c88bd14eb7d3f8562f37fa87aaeb154b1eade2881de21d3504be55
-F ext/rbu/rbu10.test 1846519a438697f45e9dcb246908af81b551c29e1078d0304fae83f1fed7e9ee
-F ext/rbu/rbu11.test 9bc68c2d3dbeb1720153626e3bd0466dcc017702
-F ext/rbu/rbu12.test bde22ed0004dd5d1888c72a84ae407e574aeae16
-F ext/rbu/rbu13.test 462ff799c4afedc3ef8a47ff818c0ffbf14ae4f2
-F ext/rbu/rbu14.test 01f5dcba904aecadbaea69d4ccdc2ea43dd30560
-F ext/rbu/rbu3.test 8bd4c6b87367c358981b6a47dc3d654fa60bff90
-F ext/rbu/rbu5.test cf1fa84d6107efd73e292a7be8e1fb31953ca45c
-F ext/rbu/rbu6.test 32e8ed60631b6facdb6366bd2b5f5f25245e7edb
-F ext/rbu/rbu7.test fd025d5ba440fcfe151fbb0e3835e1e7fe964fa1
-F ext/rbu/rbu8.test 3bbf2c35d71a843c463efe93946f14ad10c3ede0
-F ext/rbu/rbu9.test 0806d1772c9f4981774ff028de6656e4183082af
-F ext/rbu/rbuA.test 4e58e46e60d4064248614c43303d71f1b18cc804dd834ce6a913b3861828b28d
-F ext/rbu/rbuB.test c25bc325b8072a766e56bb76c001866b405925c2
-F ext/rbu/rbuC.test efe47db508a0269b683cb2a1913a425ffd39a831
+F ext/rbu/rbu1.test 221d9c18a5e600ac9ac6b1810d99d9f99163a7909ba61597876ab6e4d4beb3d6
+F ext/rbu/rbu10.test 0a201c32202143f23c81c0144503da339786fc20acb7a2fda11601b65659f314
+F ext/rbu/rbu11.test 5c834cf491086b45e071eabf71f708febc143e86a384a92de69e0b1a4cace144
+F ext/rbu/rbu12.test 29f8b2118f6c96fac3755bd6d2b55c2db24f878b1f11fbfbe294f3a230a3dcdc
+F ext/rbu/rbu13.test 1285298e3360ec74511764841b3c174dcfe21da2f618c22febf1a20abd0365c2
+F ext/rbu/rbu14.test 4a7bf0b3a4516d3ab0bc0ba4ceb53eb7e3324147ccda152e561060f659dbba31
+F ext/rbu/rbu3.test d6c6cc7a1326e8e23b9820f30bd3054f22092e503fadfd2a660ae006653f6d80
+F ext/rbu/rbu5.test 724b38ea5f722e3d22dc76343860bd998bb676c3f78c4bc8175df5c5d7720e23
+F ext/rbu/rbu6.test 401064236d3cf86b7edc01c586d7c5554f48553946fbfa1a3af35d7e47dce9e3
+F ext/rbu/rbu7.test ae25f47b56f178197fc1098537a35a39176cc73d1629b03dc9d795929fc36ec2
+F ext/rbu/rbu8.test b98a6fc58ead84a0e6ddee775b9702cd981f318d5d4fd1d4df0fa0c40db7251b
+F ext/rbu/rbu9.test 0e4d985e25620d61920597e8ea69c871c9e8c1f5a0be2ae9fa70bb641d74378c
+F ext/rbu/rbuA.test b34a90cb495682c25b5fc03a9d5e7a4fc99541c29256f25e2e2a4f6542b4f5b3
+F ext/rbu/rbuB.test 52b07158824c6927b7e25554ace92a695cdebfc296ae3d308ac386984aded9bc
+F ext/rbu/rbuC.test 80f1cc2fb74f44b1128fd0ed8eedab3a76fefeb72a947860e2869ef76fc8dc6b
F ext/rbu/rbu_common.tcl acfb7fbbaf8d46a9f6f6a5ec795616c84d705e1565d918afe43f0ff53ea0efa5
-F ext/rbu/rbucollate.test 86d6fc9b8f59a27b7b5a6e20b5e29816d338a0dbdea8c54bfcc549a0d437f3ea
-F ext/rbu/rbucrash.test 61470d977a06a0abc2ec35b05d82a1d7d87d10f4ffabad14c1c231edc942ad66
-F ext/rbu/rbucrash2.test b2ecbdd7bb72c88bd217c65bd00dafa07f7f2d4d
-F ext/rbu/rbudiff.test 3e605cf624d00d04d0fb1316a3acec4fbe3b3ac5
-F ext/rbu/rbudor.test 99b05cc0df613e962c2c8085cfb05686a09cf315
-F ext/rbu/rbufault.test 2654aef20f8ee7de37c9c1997a44f2773dc7bf24887adea39fb19314ef32cb90
-F ext/rbu/rbufault2.test 9a7f19edd6ea35c4c9f807d8a3db0a03a5670c06
-F ext/rbu/rbufault3.test 0913c1aeaee266d9c36c33179341a5a504aad7d423d1979cfec43c8346a29899
-F ext/rbu/rbufault4.test 34e70701cbec51571ffbd9fbf9d4e0f2ec495ca7
-F ext/rbu/rbufts.test a2bbd202c9321fba15fb4a62a90add7d70e07bd8404e1e598135adbfff8a0508
-F ext/rbu/rbumulti.test 2cf153ab3d5861ff26517dc6cbaec430787a59f1d50e8771fe7a7529a0551cf1
-F ext/rbu/rbuprogress.test 1849d4e0e50616edf5ce75ce7db86622e656b5cf
-F ext/rbu/rburesume.test 8acb77f4a422ff55acfcfc9cc15a5cb210b1de83
-F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48
-F ext/rbu/rbusplit.test 69271c790732b28bd465551d80b0a9a3f074e189896ee8490ce56d22078c124d
-F ext/rbu/rbutemplimit.test cd553a9288d515d0b5f87d277e76fd18c4aa740b761e7880fab11ce986ea18d1
-F ext/rbu/rbuvacuum.test ff357e9b556ca7ad4673da0ff7f244def919ff858e0f9f350d3e30fdd83a62a8
-F ext/rbu/rbuvacuum2.test 2074ab14fe66e1c7e7210c62562650dcd215bbaa
-F ext/rbu/sqlite3rbu.c f438fea899d15d13ff3e3133242b9e378c37b5a3d76add8c342c68bdd65c6819
+F ext/rbu/rbucollate.test cac528a9a46318cba42e61258bb42660bbbf4fdb9a8c863de5a54ad0c658d197
+F ext/rbu/rbucrash.test 000981a1fe8a6e4d9a684232f6a129e66a3ef595f5ed74655e2f9c68ffa613b4
+F ext/rbu/rbucrash2.test efa143cc94228eb0266d3f1abfbee60a5838a84cef7cc3fcb8c145b74d96fd41
+F ext/rbu/rbudiff.test 156957851136b63c143478518dc1bda6c832103cdbe8ac1d7cdd47edb3cbe0a3
+F ext/rbu/rbudor.test e3e8623926012f43eebe51fedf06a102df2640750d971596b052495f2536db20
+F ext/rbu/rbufault.test 2d7f567b79d558f6e093c58808cab4354f8a174e3802f69e7790a9689b3c09f8
+F ext/rbu/rbufault2.test 06e735c002c17802d93debca41f59b027e7429db7de17f2a81318ecfd3c651d4
+F ext/rbu/rbufault3.test e0052ccba428ffdd2bb989d3ae84716f058ec5ab5f7196c64ba407b9d23c7255
+F ext/rbu/rbufault4.test 03d2849c3df7d7bd14a622e789ff049e5080edd34a79cd432e01204db2a5930a
+F ext/rbu/rbufts.test 0ae8d1da191c75bd776b86e24456db0fb6e97b7c944259fae5407ea55d23c31d
+F ext/rbu/rbumulti.test 5fb139058f37ddc5a113c5b93238de915b769b7792de41b44c983bc7c18cf5b9
+F ext/rbu/rbuprogress.test 04614ff8820bab9c1ec1b7dbec1edc4b45474421d4fe7abbd2a879a9c02884f9
+F ext/rbu/rburesume.test dbdc4ca504e9c76375a69e5f0d91205db967dcc509a5166ca80231f8fda49eb1
+F ext/rbu/rbusave.test f4190a1a86fccf84f723af5c93813365ae33feda35845ba107b59683d1cdd926
+F ext/rbu/rbusplit.test b37e7b40b38760881dc9c854bd40b4744c6b6cd74990754eca3bda0f407051e8
+F ext/rbu/rbutemplimit.test 7f408f49b90fa0a720d7599f3aec74a3c85e6cd78e56fdf726ce00af9147a341
+F ext/rbu/rbuvacuum.test 55e101e90168c2b31df6c9638fe73dc7f7cc666b6142266d1563697d79f73534
+F ext/rbu/rbuvacuum2.test 0a7669bbabdaeed915f02f59f33fe20e13d4932ba2086fe00a82064d9424c80b
+F ext/rbu/sqlite3rbu.c 71f8c09948d09ec9c5a8dbe7127e8ef61ef0853e698b2650be2485ac7b9c75c8
F ext/rbu/sqlite3rbu.h b42bcd4d8357268c6c39ab2a60b29c091e89328fa8cc49c8fac5ab8d007e79b2
F ext/rbu/test_rbu.c baa23eb28457580673d2175e5f0c29ced0cd320ee819b13ad362398c53b96e90
F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
@@ -356,11 +358,11 @@ F ext/repair/sqlite3_checker.c.in 4a5a3af3f450fe503e5a2985e98516dc2a6b9ad247449e
F ext/repair/sqlite3_checker.tcl a9a2caa9660567257c177a91124d8c0dccdfa341e25c51e6da7f1fd9e601eafa
F ext/repair/test/README.md 34b2f542cf5be7bffe479242b33ee3492cea30711e447cc4a1a86cb5915f419e
F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc78249442da72ff3f8297398a69
-F ext/repair/test/checkindex01.test 6945d0ffc0c1dc993b2ce88036b26e0f5d6fcc65da70fc9df27c2647bb358b0f
+F ext/repair/test/checkindex01.test b530f141413b587c9eb78ff734de6bb79bc3515c335096108c12c01bddbadcec
F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
-F ext/rtree/geopoly.c 415a8ca5dfab54eea779e0bf31a859afb0b869a5147a726df4aec4b57c1bad57
-F ext/rtree/rtree.c 6cc2e673cf1e9ea1619f13ab990f12389dfb951b131acbc2fbe164cee8992a20
+F ext/rtree/geopoly.c d56ff997f2646b03be742eb85e8206f779d777f3a282fe0da576780ca0e11f20
+F ext/rtree/rtree.c 7125183bf6c37b8b8ee1a04d2b0fe258531fd31650fdd050ed041817f1943d17
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
F ext/rtree/rtree1.test 309afc04d4287542b2cd74f933296832cc681c7b014d9405cb329b62053a5349
F ext/rtree/rtree2.test 5f25b01acd03470067a2d52783b2eb0a50bf836803d4342d20ca39e541220fe2
@@ -369,9 +371,9 @@ F ext/rtree/rtree4.test 304de65d484540111b896827e4261815e5dca4ce28eeecd58be648cd
F ext/rtree/rtree5.test 49c9041d713d54560b315c2c7ef7207ee287eba1b20f8266968a06f2e55d3142
F ext/rtree/rtree6.test 593e0d36510d5ac1d1fb39b018274ff17604fe8fdca8cf1f8e16559cea1477f4
F ext/rtree/rtree7.test c8fb2e555b128dd0f0bdb520c61380014f497f8a23c40f2e820acc9f9e4fdce5
-F ext/rtree/rtree8.test 924926d7c64ac59fcca0809de472d9dd73c612f54daae1cf992bdd7dac90305b
+F ext/rtree/rtree8.test 2d99006a1386663978c9e1df167554671e4f711c419175b39f332719deb1ce0e
F ext/rtree/rtree9.test c646f12c8c1c68ef015c6c043d86a0c42488e2e68ed1bb1b0771a7ca246cbabf
-F ext/rtree/rtreeA.test 20623ca337ca3bd7e008cc9fb49e44dbe97f1a80b238e10a12bb4afcd0da3776
+F ext/rtree/rtreeA.test ed2f1be9c06dde0b1ab93a95dd9e87eeaa02db2d30bcb4b9179b69ee3dc3319b
F ext/rtree/rtreeB.test 4cec297f8e5c588654bbf3c6ed0903f10612be8a2878055dd25faf8c71758bc9
F ext/rtree/rtreeC.test 128928549d22b65c381ab1366760d08703cd75e34f6a7a506ece38f9330b7282
F ext/rtree/rtreeD.test fe46aa7f012e137bd58294409b16c0d43976c3bb92c8f710481e577c4a1100dc
@@ -381,15 +383,17 @@ F ext/rtree/rtreeG.test 1b9ca6e3effb48f4161edaa463ddeaa8fca4b2526d084f9cbf5dbe4e
F ext/rtree/rtreeH.test aa08cc4fa8005b4c67446c7110205055b4d6da90e760e6f44b82dfa4cdf8d87a
F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195
F ext/rtree/rtree_util.tcl db734b4c5e75fed6acc56d9701f2235345acfdec750b5fc7b587936f5f6bceed
-F ext/rtree/rtreecheck.test 4d29103d1e16fcbf90135d1c637b833688492b063b2971dfb5dc6ba76555cfee
+F ext/rtree/rtreecheck.test d67d5b3e9e45bfa8cd90734e8e9302144ac415b8e9176c6f02d4f92892ee8a35
F ext/rtree/rtreeconnect.test 225ad3fcb483d36cbee423a25052a6bbae762c9576ae9268332360c68c170d3d
-F ext/rtree/sqlite3rtree.h 9c5777af3d2921c7b4ae4954e8e5697502289d28
+F ext/rtree/sqlite3rtree.h 03c8db3261e435fbddcfc961471795cbf12b24e03001d0015b2636b0f3881373
F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
F ext/rtree/util/randomshape.tcl 54ee03d0d4a1c621806f7f44d5b78d2db8fac26e0e8687c36c4bd0203b27dbff
F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
-F ext/rtree/visual01.txt 17c3afefc208c375607aa82242e97fa79c316e539bcd0b7b3e59344c69445d05
+F ext/rtree/visual01.txt e9c2564083bcd30ec51b07f881bffbf0e12b50a3f6fced0c222c5c1d2f94ac66
F ext/session/changeset.c 4ccbaa4531944c24584bf6a61ba3a39c62b6267a
-F ext/session/session1.test 4532116484f525110eb4cfff7030c59354c0cde9def4d109466b0df2b35ad5cc
+F ext/session/changesetfuzz.c 255826ee367781ec4c29a36c7c63e9ee6387dc03a8346cf240feb8d597958b0e
+F ext/session/changesetfuzz1.test 2e1b90d888fbf0eea5e1bd2f1e527a48cc85f8e0ff75df1ec4e320b21f580b3a
+F ext/session/session1.test 0b2f88995832ea040ae8e83a1ad4afa99c00b85c779d213da73a95ea4113233e
F ext/session/session2.test 284de45abae4cc1082bc52012ee81521d5ac58e0
F ext/session/session3.test ce9ce3dfa489473987f899e9f6a0f2db9bde3479
F ext/session/session4.test 6778997065b44d99c51ff9cece047ff9244a32856b328735ae27ddef68979c40
@@ -399,31 +403,32 @@ F ext/session/session8.test 8e194b3f655d861ca36de5d4de53f702751bab3b
F ext/session/session9.test 5409d90d8141881d08285ed1c2c0d8d10fb92069
F ext/session/sessionA.test 1feeab0b8e03527f08f2f1defb442da25480138f
F ext/session/sessionB.test 886252dcb7e692e62ef7e357456200912e367823
-F ext/session/sessionC.test 97556f5164ac29f2344b24bd7de6a3a35a95c390
-F ext/session/sessionD.test d3617e29aa15c9413aee5286d99587633245d58d2ad28f3f331c822735418a22
-F ext/session/sessionE.test 0a616c4ad8fd2c05f23217ebb6212ef80b7fef30f5f086a6633a081f93e84637
-F ext/session/sessionF.test c2f178d4dfd723a5fd94a730ea2ccb44c669e3ce
-F ext/session/sessionG.test 3edde849c4071078d92bd682c836186f6e4e5a3fb6bcf3fc1de1a7caa5e4427d
-F ext/session/sessionH.test 332b60e4c2e0a680105e11936201cabe378216f307e2747803cea56fa7d9ebae
-F ext/session/session_common.tcl ee925e0d233677e45e395fb1f559b84068ce7baa8aa1034441739d3e87ee249c
+F ext/session/sessionC.test f8a5508bc059ae646e5ec9bdbca66ad24bc92fe99fda5790ac57e1f59fce2fdf
+F ext/session/sessionD.test 4f91d0ca8afc4c3969c72c9f0b5ea9527e21de29039937d0d973f821e8470724
+F ext/session/sessionE.test b2010949c9d7415306f64e3c2072ddabc4b8250c98478d3c0c4d064bce83111d
+F ext/session/sessionF.test d37ed800881e742c208df443537bf29aa49fd56eac520d0f0c6df3e6320f3401
+F ext/session/sessionG.test 3828b944cd1285f4379340fd36f8b64c464fc84df6ff3ccbc95578fd87140b9c
+F ext/session/sessionH.test a417559f29a7e775950fc5fc82b3d01256a7cbe793ddf1180df234df823d56e2
+F ext/session/session_common.tcl 29ec9910aca1e996ca1c8531b8cecabf96eb576aa53de65a8ff03d848b9a2a8b
F ext/session/session_speed_test.c edc1f96fd5e0e4b16eb03e2a73041013d59e8723
F ext/session/sessionat.test efe88965e74ff1bc2af9c310b28358c02d420c1fb2705cc7a28f0c1cc142c3ec
F ext/session/sessiondiff.test ad13dd65664bae26744e1f18eb3cbd5588349b7e9118851d8f9364248d67bcec
F ext/session/sessionfault.test da273f2712b6411e85e71465a1733b8501dbf6f7
-F ext/session/sessionfault2.test 555a8504de03d59b369ef20209585da5aeb2671dedabc4584e9ffe6269689185
-F ext/session/sessionrebase.test 4e1bcfd26fd8ed8ac571746f56cceeb45184f4d65490ea0d405227cfc8a9cba8
-F ext/session/sessionstat1.test 41cd97c2e48619a41cdf8ae749e1b25f34719de638689221aa43971be693bf4e
-F ext/session/sessionwor.test 2f3744236dc8b170a695b7d8ddc8c743c7e79fdc
-F ext/session/sqlite3session.c 2d29bbd888599b94b2c8b31ff433675e008273a4d225b336508b18e6187fec1d
-F ext/session/sqlite3session.h c01820d5b6e73e86d88008f4d1c1c7dfb83422963018292b864028a0400ceccf
-F ext/session/test_session.c dba36c6c0153b22501112d3e8882b5c946cf617c955153b6712bd2f8ba1428c0
+F ext/session/sessionfault2.test dd593f80b6b4786f7adfe83c5939620bc505559770cc181332da26f29cddd7bb
+F ext/session/sessioninvert.test ae1a003a9ab1f8d64227dbb5c3a4c97e65b561b01e7b2953cf48683fb2724169
+F ext/session/sessionrebase.test ccfa716b23bd1d3b03217ee58cfd90c78d4b99f53e6a9a2f05e82363b9142810
+F ext/session/sessionstat1.test 218d351cf9fcd6648f125a26b607b140310160184723c2666091b54450a68fb5
+F ext/session/sessionwor.test 07f0b304dc4df5454906069140bf6ec67edcaa3c548f3683354003cf2c22b64a
+F ext/session/sqlite3session.c dbd6f7a89c1236d8e7b58f4e217391670ce91b9e6f85c16ba02832674ef0cf3c
+F ext/session/sqlite3session.h 05351d2f50a1203fdffbeb590fdbbc796c9a6bfcd0c9b26cf6db3854e3eb4294
+F ext/session/test_session.c 98797aba475a799376c9a42214f2d1debf2d0c3cb657d9c8bbf4f70bf3fb4aec
F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
F ext/userauth/userauth.c f81aa5a3ecacf406f170c62a144405858f6f6de51dbdc0920134e629edbe2648
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
-F main.mk 1db6df4bff24ed6684917e3fe311ce28f5924d6417c698fe4326f7cadf02df31
+F main.mk eeaa279fa6acdcfa6555058548075569a06f891fd67f5901b1e7700d18052fda
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -435,37 +440,37 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
-F src/alter.c 70dd115eb1f949f69f61773733dc89d6494915ec6a736f259c7a7de4aeb51726
+F src/alter.c f886160da189e4e99093cd5a2aca625652cc9b027d5100b87f81c175d1056387
F src/analyze.c 3dc6b98cf007b005af89df165c966baaa48e8124f38c87b4d2b276fe7f0b9eb9
-F src/attach.c 4bd5b92633671d3e8ce431153ebb1893b50335818423b5373f3f27969f79769a
-F src/auth.c 32a5bbe3b755169ab6c66311c5225a3cd4f75a46c041f7fb117e0cbb68055114
+F src/attach.c 92b51739a885da8bd84bc9a05485f1e48148bce5c15432f059b45af98fff75cd
+F src/auth.c 0fac71038875693a937e506bceb492c5f136dd7b1249fbd4ae70b4e8da14f9df
F src/backup.c 78d3cecfbe28230a3a9a1793e2ead609f469be43e8f486ca996006be551857ab
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
-F src/btree.c 3f5e1a03db871e627bf5da21092bf7434ecfc5c5980bbd7d45eba13341340173
+F src/btree.c ba7c7eef4461790f37c309936bfc5d0d6ba9b194b02d3c8ff1fd53b420ea6d3b
F src/btree.h febb2e817be499570b7a2e32a9bbb4b607a9234f6b84bb9ae84916d4806e96f2
F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96
-F src/build.c 0b3d422770877d74ee6d54f4c122d82c48f7d04ee3bfb91702e402de7f5c45ac
-F src/callback.c 36caff1e7eb7deb58572d59c41cee8f064a11d00297616995c5050ea0cfc1288
+F src/build.c 127d33ad57b455a9339e9fabff41284c8b030cc6247ca7a2a6c0ad7abfc1ce85
+F src/callback.c 789bd33d188146f66c0dd8306472a72d1c05f71924b24a91caf6bd45cf9aba73
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
-F src/ctime.c b157b01081f92442f8b0218ddb93ddce8ebddad36dbddeecfdd771561dd4f387
+F src/ctime.c 109e58d00f62e8e71ee1eb5944ac18b90171c928ab2e082e058056e1137cc20b
F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957
-F src/dbpage.c 4aa7f26198934dbd002e69418220eae3dbc71b010bbac32bd78faf86b52ce6c3
-F src/dbstat.c edabb82611143727511a45ca0859b8cd037851ebe756ae3db289859dd18b6f91
-F src/delete.c 107e28d3ef8bd72fd11953374ca9107cd74e8b09c3ded076a6048742d26ce7d2
-F src/expr.c d8da79a5cb19bbded56181337a221ead5f4ad3cbf0fbcb5da2156abefab566cd
+F src/dbpage.c 135eb3b5e74f9ef74bde5cec2571192c90c86984fa534c88bf4a055076fa19b7
+F src/dbstat.c 3c8bd4e77f0244fd2bd7cc90acf116ad2f8e82d70e536637f35ac2bc99b726f9
+F src/delete.c f7938125847e8ef485448db5fbad29acb2991381a02887dd854c1617315ab9fb
+F src/expr.c 9aacc0b72348ba90010b672dcbbbe2fa56e1182043bc917a3a147b2bc57a5497
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
-F src/fkey.c f59253c0be4b1e9dfcb073b6d6d6ab83090ae50c08b5c113b76013c4b157cd6a
+F src/fkey.c 972a4ba14296bef2303a0abbad1e3d82bc3c61f9e6ce4e8e9528bdee68748812
F src/func.c 7c288b4ce309b5a8b8473514b88e1f8e69a80134509a8c0db8e39c858e367e7f
-F src/global.c 9bf034fd560bdd514715170ed8460bb7f823cec113f0569ef3f18a20c7ccd128
-F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a
+F src/global.c 8291eee0782b83124de14ec0389ec9fd6ae1873358a6b0d9469fe17a46ad803b
+F src/hash.c 931ec82d7e070654a8facb42549bbb3a25720171d73ba94c3d3160580d01ef1f
F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4
F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
-F src/insert.c c723716f0de7aa0a679300f7d3541c89645f4a9882161cecdb3093fc07f8cc4b
+F src/insert.c 6b81aae27b196925d8ff78824f4bbd435d6a40cd38dc324685e21735bb402109
F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e
-F src/loadext.c 30b140d0e5031924c56f802760506c0a235ced0dff9f3d95119aa86df12856e2
-F src/main.c 6275ece0699a957c4709a7ebe29476f132adbe459d18a6b497e234e4669abf91
+F src/loadext.c 9050dd153b5583804184be9c9dee9ebb554178d6db1f8ac280899e8aad9060e6
+F src/main.c 4cfb3913cc9e65d3ac649b1785ac753fc225d29425d5437e012f7eac0cefe0eb
F src/malloc.c 07295435093ce354c6d9063ac05a2eeae28bd251d2e63c48b3d67c12c76f7e18
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
@@ -485,33 +490,33 @@ F src/os.c 8aeb0b0f40f8f5b0da03fe49706695adaf42d2f516ab95abc72e86c245e119de
F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
-F src/os_unix.c 7cfd67db0e2f926243f646db7ec1caa33ca9bee45799b0160ddfcd6ccfc175d2
-F src/os_win.c 070cdbb400097c6cda54aa005356095afdc2f3ee691d17192c54724ef146a971
+F src/os_unix.c f6e91b8fd82af7afbfd073c4974ad6cdb8e62d9f65ceddb45167835a0567fdc0
+F src/os_win.c 85d9e532d0444ab6c16d7431490c2e279e282aa0917b0e988996b1ae0de5c5a0
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
-F src/pager.c a0d8f686ef64549ad5b356fd30429bd9ee7a06dd42b4d6faa096352ff26b1c5b
-F src/pager.h ecc554a55bc55d1c4ba5e17137b72e238e00bd81e72ff2662d8b9c8c10ae3963
-F src/parse.y 4118dbf9c37c410e5c4775c033b1aaf67ac8ff7965df7a4bb429dd5db2dbe374
-F src/pcache.c 135ef0bc6fb2e3b7178d49ab5c9176254c8a691832c1bceb1156b2fbdd0869bd
-F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170
-F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880
-F src/pragma.c 79abc65c08d2754048efee3ba99fe91863dfeab0ba699a4439fa5053ec87cf36
-F src/pragma.h fb46b1e663128f6827979ad8ebddb55be2a0276ea923c47adeac02144207a682
-F src/prepare.c f8e260d940a0e08494c0f30744521b2f832d7263eca9d02b050cea0ba144b097
+F src/pager.c 75e0f3cfa3962c714f519f8a3d1e67ecca1c91de0e010a036b988e40ce9e4c73
+F src/pager.h 217921e81eb5fe455caa5cda96061959706bcdd29ddb57166198645ef7822ac3
+F src/parse.y 6840fe7c0b5eb4dd25ee5d075213bc8255ed4c0678d71bfb6744d0520d91c179
+F src/pcache.c 696a01f1a6370c1b50a09c15972bc3bee3333f8fcd1f2da8e9a76b1b062c59ee
+F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
+F src/pcache1.c bf9fcea656dce1cd2cca6b77a1d1d3552050d55a31c98bf0d9f405930a83bc95
+F src/pragma.c 4e056f042683b99c4ea0db395f68d051b1a95833ab40951c40d3ef7e1fee1354
+F src/pragma.h fdd03d78a7497f74a3f652909f945328480089189526841ae829ce7313d98d13
+F src/prepare.c f81f8d707e583192c28fea0b2e19385415b7d188123b23f49b038076408d7a69
F src/printf.c 0f1177cf1dd4d7827bf64d840768514ec76409abecaca9e8b577dbd065150381
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
-F src/resolve.c 352c6af1a99441206ff62a6f7429dbf537827f42c428639695220b9c8639e33b
+F src/resolve.c 4cfc44def0f0690ceaab8f6481f5d76284d7f9509aab6e218a679b4836a54614
F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93
-F src/select.c 0671309c245ecb2b75d8b33948cbcf039325468aaedc13f37c8c4f3f62f48d5f
-F src/shell.c.in 6e0aad854be738a5d0368940459399be211e9ac43aebe92bb9ed46cfe38d0e1f
-F src/sqlite.h.in 4b4c2f2daeeed4412ba9d81bc78092c69831fe6eda4f0ae5bf951da51a8dccec
+F src/select.c 61e867a906f140b73baf4ce7a201ad6dcba30820969f5618ee40e9a0d32c6f5f
+F src/shell.c.in 482e23a370cbe5b0d4c73a0f0f5fce34f7caa08a14a8d75e12f0225c4e14915c
+F src/sqlite.h.in cce9feede1c1c03923c091b4bbbd081dd77aaf92024cc2cdbf65f712c2f668c3
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
-F src/sqlite3ext.h 305adca1b5da4a33ce2db5bd236935768e951d5651bfe5560ed55cfcdbce6a63
-F src/sqliteInt.h 489bda7e69087742c4724bc85c21778703e0ee5cc463b4d89c0092ae8034896a
+F src/sqlite3ext.h 960f1b86c3610fa23cb6a267572a97dcf286e77aa0dd3b9b23292ffaa1ea8683
+F src/sqliteInt.h 1161f7579cdd6217737a66517ef27f4016426603eff492e9b31f45a7d7d4c61f
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
F src/tclsqlite.c e72862a271348d779672b45a730c33fd0c535e630ff927e8ce4a0c908d1d28c6
-F src/test1.c 31c491ccb536bd9916a084e732ffe783b3c8973f2586d5a56aed0e3a9701dfff
+F src/test1.c 5390e5afb31fed61f72d0be0cb1b322d198a6e03fc13ff245ae76d17b4dcf2e9
F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6
@@ -526,7 +531,7 @@ F src/test_backup.c bf5da90c9926df0a4b941f2d92825a01bbe090a0
F src/test_bestindex.c 78809f11026f18a93fcfd798d9479cba37e1201c830260bf1edc674b2fa9b857
F src/test_blob.c ae4a0620b478548afb67963095a7417cd06a4ec0a56adb453542203bfdcb31ce
F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274
-F src/test_config.c 6c3f341ece48020c4ddbce055643a91c653283b3a6853c46ea18d22e5c72847d
+F src/test_config.c 5ebafbcd5c75ac1c16bb0c8fe926dc325cc03e780943a88ca50e0d9a4fc4d2f5
F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f
F src/test_demovfs.c a0c3bdd45ed044115c2c9f7779e56eafff18741e
F src/test_devsym.c 1960abbb234b97e9b920f07e99503fc04b443f62bbc3c6ff2c2cea2133e3b8a2
@@ -534,8 +539,8 @@ F src/test_fs.c 35a2f7dd8a915900873386331386d9ba1ae1b5026d74fd20c2807bc76221f291
F src/test_func.c d12d805953bcb3bb19f71d29cdc93383b7b7a3369504d2b7e398a1bd77376294
F src/test_hexio.c 1d4469ca61ab202a1fcec6543f584d2407205e8d
F src/test_init.c 4413c211a94b62157ca4c145b3f27c497f03c664
-F src/test_intarray.c 988fc61cb0ff539f4172c0d95f15287c92516f64
-F src/test_intarray.h f3b7672f5d1056eac563c0d6ea8480a660b1475c
+F src/test_intarray.c 39b4181662a0f33a427748d87218e7578d913e683dc27eab7098bb41617cac71
+F src/test_intarray.h d57ae92f420cda25e22790dac474d60961bd0c500cbaa3338a05152d4a669ef7
F src/test_journal.c 619f2aa10e0d7a5f87c0f06825bc61dfce1c6b9c7f3ad990fb13de6c3b8874a3
F src/test_loadext.c 337056bae59f80b9eb00ba82088b39d0f4fe6dfd
F src/test_malloc.c dec0aa821b230773aeb3dd11d652c1193f7cedb18a20b25659bc672288115242
@@ -543,7 +548,7 @@ F src/test_md5.c 7268e1e8c399d4a5e181b64ac20e1e6f3bc4dd9fc87abac02db145a3d951fa8
F src/test_multiplex.c e054459f7633f3ff8ce1245da724f9a8be189e4e
F src/test_multiplex.h 5436d03f2d0501d04f3ed50a75819e190495b635
F src/test_mutex.c 7f4337ba23ee6b1d2ec81c189653608cb069926a
-F src/test_onefile.c 416f87a28d6d673352d33fc4b1c7d39db878e50f
+F src/test_onefile.c f31e52e891c5fef6709b9fcef54ce660648a34172423a9cbdf4cbce3ba0049f4
F src/test_osinst.c 98ef31ff03d55497829ca0f6c74a9f4e1aa48690
F src/test_pcache.c a5cd24730cb43c5b18629043314548c9169abb00
F src/test_quota.c 6cb9297115b551f433a9ad1741817a9831abed99
@@ -564,33 +569,33 @@ F src/test_windirent.h 90dfbe95442c9762357fe128dc7ae3dc199d006de93eb33ba3972e0a9
F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394ba3f
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
-F src/tokenize.c 9f55961518f77793edd56eee860ecf035d4370ebbb0726ad2f6cada6637fd16b
-F src/treeview.c e7a7f90552bb418533cdd0309b5eb71d4effa50165b880fc8c2001e613577e5f
+F src/tokenize.c 9e781e1ca80eefe7b5d6a9e2cd5c678c847da55fd6f093781fad7950934d4c83
+F src/treeview.c 7b12ac059de54c939b6eb0dbffc9410c29c80d2470cee5cbe07d5ff9ea2d9253
F src/trigger.c d3d78568f37fb2e6cdcc2d1e7b60156f15b0b600adec55b83c5d42f6cad250bd
-F src/update.c 0c9714a1dc954c261d7251dbf51067bf041f0a9a6003ba34999705e9e4ef03a3
+F src/update.c 1816d56c1bca1ba4e0ef98cac2f49be62858e9df1dc08844c7067eb41cc44274
F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4
F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157
-F src/vacuum.c 36e7d21a20c0bf6ef4ef7c399d192b5239410b7c4d3c1070fba4e30810d0b855
-F src/vdbe.c b1b2142469a4eb177e712827f7c1ee376e41381eed870938d1494c13f55bf2e7
+F src/vacuum.c 836cadc922de866c849e23a75f93d344cdc143d388339305d09a3fed27e8798d
+F src/vdbe.c 005e691ea4c7d51e6c1a69d9389aeb34700884c85f51681817ddea3fdc2fc39b
F src/vdbe.h 5081dcc497777efe5e9ebe7330d283a044a005e4bdda2e2e984f03bf89a0d907
-F src/vdbeInt.h f1f35f70460698d8f5a2bdef1001114babf318e2983a067804e2ae077d8e9827
-F src/vdbeapi.c 2ba821c5929a2769e4b217dd85843479c718b8989d414723ec8af0616a83d611
-F src/vdbeaux.c 9fe7760a6b9739f21f3e19ad5364330b0f681998fc52c32358243b0060423474
+F src/vdbeInt.h 437e6c6af679fdf157867eb83a8adc6cf5145d6774453c2214cfd0bd01d92980
+F src/vdbeapi.c ecccfce6f614c33a95952efeec969d163e8349eac314ee2b7b163eda921b5eb0
+F src/vdbeaux.c f547901b1aa9e2d81c63f06893f633648e434180666a827aacb547d7d6c8a601
F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191
-F src/vdbemem.c 81329ab760e4ec0162119d9cd10193e0303c45c5935bb20c7ae9139d44dd6641
+F src/vdbemem.c 7b3305bc4a5139f4536ac9b5f61da0f915e49d2e3fdfa87dfdfa9d7aba8bc1e9
F src/vdbesort.c 90aad5a92608f2dd771c96749beabdb562c9d881131a860a7a5bccf66dc3be7f
F src/vdbetrace.c 79d6dbbc479267b255a7de8080eee6e729928a0ef93ed9b0bfa5618875b48392
-F src/vtab.c 8665561f244c137a2d17b5c3e5910d7303054fe841c5d510e53f23beb0089594
+F src/vtab.c 70188a745dc4e57d26e942681ff4b2912b7c8249ad5de3f60f0677b4337bcfaa
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c 3f4f653daf234fe713edbcbca3fec2350417d159d28801feabc702a22c4e213f
F src/wal.h 606292549f5a7be50b6227bd685fa76e3a4affad71bb8ac5ce4cb5c79f6a176a
-F src/walker.c ba7225773931760cf60bf22f34d0cce2588df7ce5ce0f215a52eb88234b55ac4
-F src/where.c 2019126801437944c38cc62a99491e98591460b7cc07ab57eb66165f710a289b
-F src/whereInt.h b90ef9b9707ef750eab2a7a080c48fb4900315033274689def32d0cf5a81ebe4
-F src/wherecode.c cf6d3ac7b428102c1ebbff8758cf932ce38a31ed7704960010b6a90a9849b1f5
-F src/whereexpr.c 0f496c579f3c95aebb3d3e223ec6571d97dfd598140656c90ca93046bdfeaf69
-F src/window.c 4b503da928dace3e845b891381a4d98eeb8c5744313ae3643df8d8d21fdcca65
+F src/walker.c fb94aadc9099ff9c6506d0a8b88d51266005bcaa265403f3d7caf732a562eb66
+F src/where.c 3818e8a736a05d2cb194e64399af707e367fbcc5c251d785804d02eaf121288e
+F src/whereInt.h f125f29fca80890768e0b2caa14f95db74b2dacd3a122a168f97aa7b64d6968f
+F src/wherecode.c c45f03aefc2266b990df0fc4d7acc4e27f56f881f4fc0fc355b7cbc4d7189da5
+F src/whereexpr.c 491f0894ad9903750cdecb7894437a0cabdffdd88f574d2b1c9ac85d14fe4b9c
+F src/window.c 6550e2850ebced51100ef83d49b00a1cf03f81a482dafedafb0320df647ed8fc
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
@@ -598,19 +603,20 @@ F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/aggnested.test 18b00de006597e960a6b27ccec51474ac66cf1070a87c1933e5694dc02190ef1
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
F test/all.test 2ecb8bbd52416642e41c9081182a8df05d42c75637afd4488aace78cc4b69e13
-F test/alter.test 99e72759d48d6531ac2a9f346b4a9b5fe8f89c67a0fa5e916a3990d3b1fe9d09
-F test/alter2.test 7ea05c7d92ac99349a802ef7ada17294dd647060
+F test/alter.test 93dee7c0ff9106fbd53a8bbf519107904b884050a99c4565412c58c37d68c802
+F test/alter2.test a966ccfcddf9ce0a4e0e6ff1aca9e6e7948e0e242cd7e43fc091948521807687
F test/alter3.test 4d79934d812eaeacc6f22781a080f8cfe012fdc3
F test/alter4.test 7e93a21fe131e1dfeb317e90056856f96b10381fc7fe3a05e765569a23400433
F test/alterauth.test 63442ba61ceb0c1eeb63aac1f4f5cebfa509d352276059d27106ae256bafc959
-F test/altercol.test 53fb5e218c9296afc160f2c4fcbeaf42bd0604815d9b3896a7d2eec583ad8704
-F test/alterlegacy.test e7c07d605c2a85e7d1696c89e6bf64dfc932fc6d9320fe8708c8f5fc0b524d41
-F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
+F test/alterauth2.test c0a1ddf5b93d93cb0d15ba7acaf0c5c6fb515bbe861ede75b2d3fabad33b6499
+F test/altercol.test 313ed080ed61691c52cd87053129889f71582d6d0efebdd5f3edad2a98c66874
+F test/alterlegacy.test 82022721ce0de29cedc9a7af63bc9fcc078b0ee000f8283b4b6ea9c3eab2f44b
+F test/altermalloc.test 167a47de41b5c638f5f5c6efb59784002b196fff70f98d9b4ed3cd74a3fb80c9
F test/altermalloc2.test fa7b1c1139ea39b8dec407cf1feb032ca8e0076bd429574969b619175ad0174b
-F test/altertab.test 3b830144c18ae00abd2a27e3d2851c8bb1ee8fe655fa16d8a5971066dc71b58a
-F test/altertab2.test 159fd5f7b23ddc841fe678f579f9b1b8e69f44296f3ff75d1b4c155d37a59832
+F test/altertab.test 17e46baa6b2234048c91891a303141afceca4da95a36ee1a0a9fec6ccef1f4da
+F test/altertab2.test 0d64de5632ca5de13b023839cfe5b8952d029e4622befcea1433adaa93883220
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
-F test/analyze.test b3a9c67d00e1df7588a5b7be9a0292899f94fe8cac1f94a017277474ca2e59df
+F test/analyze.test 7168c8bffa5d5cbc53c05b7e9c7fcdd24b365a1bc5046ce80c45efa3c02e6b7c
F test/analyze3.test ff62d9029e6deb2c914490c6b00caf7fae47cc85cdc046e4a0d0a4d4b87c71d8
F test/analyze4.test cdf88f3f72b0f0643a1ff6c730fc5af1e42464d47478d9fbac84c333f72c014e
F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4
@@ -634,21 +640,21 @@ F test/atof1.test ff0b0156fd705b67c506e1f2bfe9e26102bea9bd
F test/atomic.test 065a453dde33c77ff586d91ccaa6ed419829d492dbb1a5694b8a09f3f9d7d061
F test/atomic2.test b6863b4aa552543874f80b42fb3063f1c8c2e3d8e56b6562f00a3cc347b5c1da
F test/atrc.c ec92d56d8fbed9eb3e11aaf1ab98cf7dd59e69dae31f128013f1d97e54e7dfed
-F test/attach.test f4b8918ba2f3e88e6883b8452340545f10a1388af808343c37fc5c577be8281c
+F test/attach.test 21bce8681f780a8d631a5ec7ecd0d849bfe84611257b038ae4ffeccc609d8a4e
F test/attach2.test 256bd240da1835fb8408dd59fb7ef71f8358c7a756c46662434d11d07ba3a0ce
F test/attach3.test c59d92791070c59272e00183b7353eeb94915976
F test/attach4.test 53bf502f17647c6d6c5add46dda6bac8b6f4665c
-F test/attachmalloc.test 3a4bfca9545bfe906a8d2e622de10fbac5b711b0
+F test/attachmalloc.test 12c4f028e570acf9e0a4b0b7fe6f536e21f3d5ebddcece423603d0569beaf438
F test/auth.test 3310d9c08e928beca42d3eadaaf53cef619d9d275f598565a3758a21ce63138e
F test/auth2.test 9eb7fce9f34bf1f50d3f366fb3e606be5a2000a1
F test/auth3.test db21405b95257c24d29273b6b31d0efc59e1d337e3d5804ba2d1fd4897b1ae49
F test/autoanalyze1.test b9cc3f32a990fa56669b668d237c6d53e983554ae80c0604992e18869a0b2dec
-F test/autoinc.test 9d202b7dce6571e52b744138eff12610214501acd635abdd72d18736cd06fd22
+F test/autoinc.test 381f494fefa90acd999933829e2934efb6b40906db9d6a39e822e3f7b4c8bf61
F test/autoindex1.test a09958fa756129af10b6582bcbf3cbdf11e305e027b393f393caef801159dee0
F test/autoindex2.test 12ef578928102baaa0dc23ad397601a2f4ecb0df
F test/autoindex3.test 2dd997d6590438b53e4f715f9278aa91c9299cf3f81246a0915269c35beb790e
F test/autoindex4.test 49d3cd791a9baa16fb461d7ea3de80d019a819cf
-F test/autoindex5.test 5f0135dc3b266277b8c1904624439097d8e8020dd7197eda13fda23c35c21a05
+F test/autoindex5.test 4a0eb6c7c7ae456d97a2061d4c8d6380946272c5c91d91507c1feb1af3dc7cce
F test/autovacuum.test 0831cd34e14695d297187f7f6519265e3121c5b0a1720e548e86829e796129e9
F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4
F test/avtrans.test b7dc25459ecbd86c6fa9c606ee3068f59d81e225118617dcf2bbb6ded2ade89e
@@ -665,8 +671,8 @@ F test/bc_common.tcl b5e42d80305be95697e6370e015af571e5333a1c
F test/bestindex1.test 852170bddbb21daa121fabcc274640ff83d7d8705912e8b5fe7ed2c5a9a9224a
F test/bestindex2.test 9a0ccd320b6525eec3a706aae6cdab7e1b7b5abca75027e39f39f755e76e5928
F test/bestindex3.test 001788a114ad96d81d5154fe77c7f1e26e84b3a2b5635ca29e4f96f6decc534e
-F test/bestindex4.test 4cb5ff7dbaebadb87d366f51969271778423b455
-F test/bestindex5.test 412b42f8036b28d8b2f3534d89389ad946a4b1a65a12263f51936f7424296f1b
+F test/bestindex4.test 038e3d0789332f3f1d61474f9bbc9c6d08c6bd1783a978f31f38ad82688de601
+F test/bestindex5.test 67c1166131bb59f9e47c00118f7d432ca5491e6cae6ca3f87ca9db20103a78f9
F test/bestindex6.test d856a9bb63d927493575823eed44053bc36251e241aa364e54d0f2a2d302e1d4
F test/between.test 34d375fb5ce1ae283ffe82b6b233e9f38e84fc6c
F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59
@@ -694,9 +700,9 @@ F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de
F test/cacheflush.test af25bb1509df04c1da10e38d8f322d66eceedf61
F test/cachespill.test 895997f84a25b323b166aecb69baab2d6380ea98f9e0bcc688c4493c535cfab9
F test/capi2.test 34a1a9a96d543a2ec2c209696b11b164444f57253b1f2cba1c2e53fadede6c7b
-F test/capi3.test 36f5c859c91a9bb0075d6ddcfcf2476cad629b09f7bfd135776fb94b06c04706
+F test/capi3.test 3910a73c38ac76d69778dd9eb481ab7cd6ed59117fc047b4f6056a5c72529de1
F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4
-F test/capi3c.test 7ebed1d8fa2f3190149d556fe8cff5a006be62af437c5c4640db614470126098
+F test/capi3c.test 54e2dc0c8fd7c34ad1590d1be6864397da2438c95a9f5aee2f8fbc60c112e44b
F test/capi3d.test 485048dc5cd07bc68011e4917ad035ad6047ab82
F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe
F test/cast.test 5ceb920718d280b61163500a7d29e0e0a86458b1cbd92d96f962c9d970aa3857
@@ -722,11 +728,11 @@ F test/conflict.test 029faa2d81a0d1cafb5f88614beb663d972c01db
F test/conflict2.test bb0b94cf7196c64a3cbd815c66d3ee98c2fecd9c
F test/conflict3.test a83db76a6c3503b2fa057c7bfb08c318d8a422202d8bc5b86226e078e5b49ff9
F test/contrib01.test 2a1cbc0f2f48955d7d073f725765da6fbceda6b4
-F test/corrupt.test 141c39ea650c1365e85a49e402fa05cb9617fb97
-F test/corrupt2.test fdfdffab9bc37d6d173f56ffb82472206f11dd4a68caad9360ac4db2eddb34c8
+F test/corrupt.test d7cb0300e4a297147b6a05e92a1684bc8973635c3bcaa3d66e983c9cbdbf47a3
+F test/corrupt2.test a7f95356d19a4e8bf9423622ad865cabf48ae49dad40eb7a17a0b39f1cdd6948
F test/corrupt3.test f95d7bf78109e0b84eb285a787ce91a3fd6a2dd7d0cb55882abff3bdc081a57e
F test/corrupt4.test 8d1d86b850fcc43e417450454f2044e52d55778a
-F test/corrupt5.test 8ead52af76006f3286e9396cb41898018ccea107
+F test/corrupt5.test 387be3250795e2a86e6234745558b80efb248a357d0cd8e53bce75c7463f545d
F test/corrupt6.test fc6a891716139665dae0073b6945e3670bf92568
F test/corrupt7.test b036f94bda4b0b23a2919bf717046ce9ecca4543
F test/corrupt8.test 2399dfe40d2c0c63af86706e30f3e6302a8d0516
@@ -739,18 +745,18 @@ F test/corruptE.test 82ccf4f8f543fdbedd4aa42c709cb077f7374c62
F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4
F test/corruptG.test adf79b669cbfd19e28c8191a610d083ae53a6d51
F test/corruptH.test 79801d97ec5c2f9f3c87739aa1ec2eb786f96454
-F test/corruptI.test 075fe1d75aa1d84e2949be56b6264376c41502e4
+F test/corruptI.test a17bbf54fdde78d43cf3cc34b0057719fd4a173a3d824285b67dc5257c064c7b
F test/corruptJ.test 4d5ccc4bf959464229a836d60142831ef76a5aa4
-F test/corruptK.test 91550557849244a9904f4e090052e3f2c1c3f1106840d58b00ffaa3a8c2d3fc0
+F test/corruptK.test 5ef338c560ca4dfb7360828da16f1829be4deba3b378cafdc7a1cdaf027eb5c4
F test/cost.test b37db8a10d467a69e71a9f3d40bbb266c2f587742b37c6912f6e3f7185a0e216
F test/count.test cb2e0f934c6eb33670044520748d2ecccd46259c
-F test/countofview.test 2d0ce23daca1bada0522c3d62e0e0c0d69ec4e0fc41df2bcd662a5e11169b9c9
+F test/countofview.test e3d4cd6900e4e4f074968ab24b8b87d3671cd624961bef40fd3a6b8f574343cf
F test/coveridxscan.test 5ec98719a2e2914e8908dc75f7247d9b54a26df04625f846ac7900d5483f7296
F test/crash.test fb9dc4a02dcba30d4aa5c2c226f98b220b2b959f
F test/crash2.test 5b14d4eb58b880e231361d3b609b216acda86651
F test/crash3.test 8f5de9d32ab9ab95475a9efe7f47a940aa889418
F test/crash4.test fe2821baf37168dc59dd733dcf7dba2a401487bc
-F test/crash5.test 05dd3aa9dbb751a22d5cdaf22a9c49b6667aa219
+F test/crash5.test f14ff37eddc41991be4eb63568f86caa306fd9962a0ae3750db8836777bb7aae
F test/crash6.test 4c56f1e40d0291e1110790a99807aa875b1647ba
F test/crash7.test 1a194c4900a255258cf94b7fcbfd29536db572df
F test/crash8.test 64366e459c28dd62edfb7ad87253a409c7533b92d16fcc479a6a8131bdcc3100
@@ -758,7 +764,7 @@ F test/crashM.test d95f59046fa749b0d0822edf18a717788c8f318d
F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
F test/createtab.test b5de160630b209c4b8925bdcbbaf48cc90b67fe8
F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c
-F test/csv01.test 6e1445b3207d574cff22fc41a8e549dfcf2466ee90546ada97d22a90fa89eb58
+F test/csv01.test 4a92840619ef435b905e6d3f35cd0644df23225d7b7967d7940b40f06d6a90a6
F test/ctime.test 78749e6c9a5f0010d67985be80788f841e3cd2da18114e2ed6010399a7d807f3
F test/cursorhint.test 7bc346788390475e77a345da2b92270d04d35856
F test/cursorhint2.test 6f3aa9cb19e7418967a10ec6905209bcbb5968054da855fc36c8beee9ae9c42f
@@ -766,10 +772,12 @@ F test/dataversion1.test 6e5e86ac681f0782e766ebcb56c019ae001522d114e0e111e5ebf68
F test/date.test 9b73bbeb1b82d9c1f44dec5cf563bf7da58d2373
F test/date2.test 74c234bece1b016e94dd4ef9c8cc7a199a8806c0e2291cab7ba64bace6350b10
F test/dbfuzz.c 73047c920d6210e5912c87cdffd9a1c281d4252e
-F test/dbpage.test dbf50a4d361f9e45a979432c727506065113124478a7d2db12074fa655e65d6c
-F test/dbstatus.test c15fa97f743dac7ce996814c84b56317e138895ee15ce27f15b608aa6924c90a
+F test/dbfuzz2-seed1.db e6225c6f3d7b63f9c5b6867146a5f329d997ab105bee64644dc2b3a2f2aebaee
+F test/dbfuzz2.c 652f85bac1770e927da139db513234a3eba308f72ac2f8b32f0093d7d19def70
+F test/dbpage.test 650234ba683b9d82b899c6c51439819787e7609f17a0cc40e0080a7b6443bc38
+F test/dbstatus.test cd83aa623b8aab477269bc94cf8aa90c1e195a144561dd04a1620770aaa8524e
F test/dbstatus2.test f5fe0afed3fa45e57cfa70d1147606c20d2ba23feac78e9a172f2fe8ab5b78ef
-F test/default.test 0cb49b1c315a0d81c81d775e407f66906a2a604d
+F test/default.test 3e46c421eebefd2787c2f96673efabf792d360f3a1d5073918cbe450ce672a62
F test/delete.test 31832b0c45ecb51a54348c68db173be462985901e6ed7f403d6d7a8f70ab4ef0
F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa
F test/delete3.test 555e84a00a99230b7d049d477a324a631126a6ab
@@ -792,10 +800,10 @@ F test/e_delete.test ab39084f26ae1f033c940b70ebdbbd523dc4962e
F test/e_droptrigger.test 3cd080807622c13e5bbb61fc9a57bd7754da2412
F test/e_dropview.test 21ce09c361227ddbc9819a5608ee2700c276bdd5
F test/e_expr.test ca8896601ade1e27c6559614c7f32c63d44636fdfa720436a160f09b8bf66c89
-F test/e_fkey.test 9778696ef9fceacebed8d482d02b47287981faaedf6f73db563ea8a7afb546da
-F test/e_fts3.test 8cf40550bb088a6aa187c818c00fabe26ef82900a4cd5c66b427ccafe28bedaa
+F test/e_fkey.test 2febb2084aef9b0186782421c07bc9d377abf067c9cb4efd49d9647ae31f5afe
+F test/e_fts3.test 17ba7c373aba4d4f5696ba147ee23fd1a1ef70782af050e03e262ca187c5ee07
F test/e_insert.test f02f7f17852b2163732c6611d193f84fc67bc641fb4882c77a464076e5eba80e
-F test/e_reindex.test 2bebf7b393e519198b7c654407221cf171a439b8
+F test/e_reindex.test 2b0e29344497d9a8a999453a003cb476b6b1d2eef2d6c120f83c2d3a429f3164
F test/e_resolve.test a61751c368b109db73df0f20fc75fb47e166b1d8
F test/e_select.test c5a669b4d63217aa10094ba737ba3ddd07bd439d4bc7a5b798f6ea32511cbe7c
F test/e_select2.test aceb80ab927d46fba5ce7586ebabf23e2bb0604f
@@ -826,7 +834,7 @@ F test/fallocate.test 07416bd593a116d5893cb244f45a94d5c6fe030561df3bd972e6135f81
F test/filectrl.test 6e871c2d35dead1d9a88e176e8d2ca094fec6bb3
F test/filefmt.test f393e80c4b8d493b7a7f8f3809a8425bbf4292af1f5140f01cb1427798a2bbd4
F test/fkey1.test d11dbb8a93ead9b5c46ae5d02da016d61245d47662fb2d844c99214f6163f768
-F test/fkey2.test 6206484a0eba570902a1a4d86489df24d0265f6994daebf851861d8f0cf4a27b
+F test/fkey2.test d35d1c81e7569bdd2b872e91750f7098117d2e8291369f70b7e3d50a0e523dc2
F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49
F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d
F test/fkey5.test 24dd28eb3d9f1b5a174f47e9899ace5facb08373a4223593c8c631e6cf9f7d5a
@@ -889,21 +897,21 @@ F test/fts3am.test 218aa6ba0dfc50c7c16b2022aac5c6be593d08d8
F test/fts3an.test a49ccadc07a2f7d646ec1b81bc09da2d85a85b18
F test/fts3ao.test 266989148fec6d9f1bb6c5382f7aa3dcea0e9cd444576e28dd2b9287ac7dd220
F test/fts3atoken.test 4b4c16fdcfc972f2cdbba212375a060a86ccf5f1
-F test/fts3auto.test b981fea19b132b4e6878f50d7c1f369b28f68eb9
+F test/fts3auto.test 19097050a3ca7ab7a43b2be967cb3dfd8ddf841dfdc4eac88deb172ad2f209f2
F test/fts3aux1.test 7a170e172afdbceb67f5baa05941fd4fbf56af42f61daa3d140f4b4bf4cb68f6
F test/fts3aux2.test 7ae2b2c13aefdf4169279a27a5f51780ce57f6ba
F test/fts3b.test c15c4a9d04e210d0be67e54ce6a87b927168fbf9c1e3faec8c1a732c366fd491
F test/fts3c.test fc723a9cf10b397fdfc2b32e73c53c8b1ec02958
F test/fts3comp1.test a0f5b16a2df44dd0b15751787130af2183167c0c
F test/fts3conf.test c84bbaec81281c1788aa545ac6e78a6bd6cde2bdbbce2da261690e3659f5a76b
-F test/fts3corrupt.test 2710b77983cc7789295ddbffea52c1d3b7506dbb
-F test/fts3corrupt2.test 6d96efae2f8a6af3eeaf283aba437e6d0e5447ba
-F test/fts3corrupt3.test 56e0ee83e90b57f5f3644cb7d1b36a067b7b8b19cdf0dedce45e5e13cf752f65
-F test/fts3corrupt4.test 98022cbacbd6ddc4708f210768f5684f041f50ce330c461f2631752492611d96
-F test/fts3cov.test 9c3681325b9a850bca8dd75cc29dde73e9a87972bb75204e97d826f13c7181f9
-F test/fts3d.test d3e9c8fb75135ada06bf3bab4f9666224965d708
-F test/fts3defer.test 0be4440b73a2e651fc1e472066686d6ada4b9963
-F test/fts3defer2.test c540f5f5c2840f70c68fd9b597df817ec7170468
+F test/fts3corrupt.test 46b9ddda7f6588fd5a5b1f4bb4fc0618dc45010e7dddb8a3a188baf3197177ae
+F test/fts3corrupt2.test bf55c3fa0b0dc8ea1c0fe5543623bd27714585da6a129038fd6999fe3b0d25f3
+F test/fts3corrupt3.test 0d5b69a0998b4adf868cc301fc78f3d0707745f1d984ce044c205cdb764b491f
+F test/fts3corrupt4.test a27259f4f25d60b4eca481d050b3cfee97eddb0d937d38f231408c5239066e11
+F test/fts3cov.test cb932743da52a1c79a1ab8983e26c8121cf02263d6ff16e1f642e6f9b8348338
+F test/fts3d.test 2bd8c97bcb9975f2334147173b4872505b6a41359a4f9068960a36afe07a679f
+F test/fts3defer.test f4c20e4c7153d20a98ee49ee5f3faef624fefc9a067f8d8d629db380c4d9f1de
+F test/fts3defer2.test 3da52ca2114e300e9971eee2f0cc1a2e5f27e6a9ee67957d49e63e41fdfcc0e7
F test/fts3defer3.test dd53fc13223c6d8264a98244e9b19abd35ed71cd
F test/fts3drop.test 1b906e293d6773812587b3dc458cb9e8f3f0c297
F test/fts3e.test 1f6c6ac9cc8b772ca256e6b22aaeed50c9350851
@@ -917,37 +925,37 @@ F test/fts3fault2.test 6a17a11d8034b1c4eca9f3091649273d56c49ff049e2173df8060f943
F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641
F test/fts3join.test 949b4f5ae3ae9cc2423cb865d711e32476bdb205ab2be923fdf48246e4a44166
F test/fts3malloc.test b0e4c133b8d61d4f6d112d8110f8320e9e453ef6
-F test/fts3matchinfo.test ce864e0bd92429df8008f31cf557269ba172482a
-F test/fts3misc.test ba03a83b831555cfd18c6c862b24b70a53ce7497fe55077f7c4b7c9ce83c2eed
+F test/fts3matchinfo.test aa66cc50615578b30f6df9984819ae5b702511cf8a94251ec7c594096a703a4a
+F test/fts3misc.test 0b20083efab36a42804bf8017a003f72f963c46163403dae7256493367d2f9d3
F test/fts3near.test 7e3354d46f155a822b59c0e957fd2a70c1d7e905
F test/fts3offsets.test b85fd382abdc78ebce721d8117bd552dfb75094c
F test/fts3prefix.test fa794eaab0bdae466494947b0b153d7844478ab2
F test/fts3prefix2.test e1f0a822ca661dced7f12ce392e14eaf65609dce
-F test/fts3query.test ca5dffabdfe9aef2ebcc89e02ce515898f86f8c30a365283831c53e0e08e5821
+F test/fts3query.test ca033ff2ebcc22c69d89032fb0bc1850997d31e7e60ecd26440796ba1654e78f
F test/fts3rank.test cd99bc83a3c923c8d52afd90d86979cf05fc41849f892faeac3988055ef37b99
F test/fts3rnd.test 1320d8826a845e38a96e769562bf83d7a92a15d0
F test/fts3shared.test 57e26a801f21027b7530da77db54286a6fe4997e
-F test/fts3snippet.test 01a4231816e03a0660ae53ba2404fe69012fe0db
+F test/fts3snippet.test 8cf586fe4b6878192602a81a665448aacbbad80ade0867bb5299d40e73584311
F test/fts3sort.test ed34c716a11cc2009a35210e84ad5f9c102362ca
F test/fts3tok1.test a663f4cac22a9505400bc22aacb818d7055240409c28729669ea7d4cc2120d15
F test/fts3tok_err.test 52273cd193b9036282f7bacb43da78c6be87418d
F test/fts3varint.test 752c08ed5d32c5d7dc211b056f4ed68a76b7e36e
F test/fts4aa.test 10aac8e9d62c7357590acfabe3fad01e9a9ce1cb
-F test/fts4check.test c3056eab9524232e4c9bdcd119912947e07bcc1c
+F test/fts4check.test 6259f856604445d7b684c9b306b2efb6346834c3f50e8fc4a59a2ca6d5319ad0
F test/fts4content.test 1518195a9f92b711d94419f76409a31cc78755854fb0abb1da2b74b9e0cf843e
F test/fts4docid.test e33c383cfbdff0284685604d256f347a18fdbf01
-F test/fts4growth.test e5390da74619cacc389711bac9349640b32c4f9a
+F test/fts4growth.test 289833c34ad45a5e6e6133b53b6a71647231fb89d36ddcb8d9c87211b6721d7f
F test/fts4growth2.test 13ad4e76451af6e6906c95cdc725d01b00044269
F test/fts4incr.test 4e353a0bd886ea984e56fce9e77724fc923b8d0d
F test/fts4langid.test 2168ba330af34f8a1c8832de0aab4c4b6fa195a16419c9c0c8aad59ceb6ff714
F test/fts4lastrowid.test 185835895948d5325c7710649824042373b2203149abe8024a9319d25234dfd7
-F test/fts4merge.test 10b55f410fade8691a455210b0b9302ef178a4f06fba0ad1941801caab82f5a9
+F test/fts4merge.test 1096e30b58ad616bd502141bfe5bfe4c3a518df89e958d41a5ed1ce322369b9c
F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891
F test/fts4merge3.test 8d9ccb4a3d41c4c617a149d6c4b13ad02de797d0
F test/fts4merge4.test d895b1057a7798b67e03455d0fa50e9ea836c47b
F test/fts4noti.test 5553d7bb2e20bf4a06b23e849352efc022ce6309
F test/fts4onepass.test d69ddc4ee3415e40b0c5d1d0408488a87614d4f63ba9c44f3e52db541d6b7cc7
-F test/fts4opt.test fd6a11684b965e1999564ae763797b7fb9e34c96
+F test/fts4opt.test 0fd0cc84000743ff2a883b9b84b4a5be07249f0ba790c8848a757164cdd46b2a
F test/fts4unicode.test ceca76422abc251818cb25dabe33d3c3970da5f7c90e1540f190824e6b3a7c95
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
F test/func.test 09dda479bcfc568f99f3070413e9672a8eeedc1be9c5d819bf55d4788c2583b7
@@ -961,14 +969,15 @@ F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1
F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1
F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c31
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
-F test/fuzz_malloc.test 5b257a7652d8ee90b22e9cf80d9dbea31a4f3e6fed1d33de57b24b1bdb211d79
-F test/fuzzcheck.c 8074a35ed4ec3735a5e144b7e0e9123d9821a92281756c1a40d43e302dd79243
+F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2
+F test/fuzzcheck.c fda41c0e4e667fae96b002410bb19cece7a33314264ed6bbc6d012909ee9fd58
F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
F test/fuzzdata4.db b502c7d5498261715812dd8b3c2005bad08b3a26e6489414bd13926cd3e42ed2
F test/fuzzdata5.db e35f64af17ec48926481cfaf3b3855e436bd40d1cfe2d59a9474cb4b748a52a5
F test/fuzzdata6.db 92a80e4afc172c24f662a10a612d188fb272de4a9bd19e017927c95f737de6d7
+F test/fuzzdata7.db a1bf54eb455e9772942abae1b2d1cf1e3d3659f0e5dd14f00792fd01411ae8ef
F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8
F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14
F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
@@ -992,16 +1001,16 @@ F test/incrblob.test c9b96afc292aeff43d6687bcb09b0280aa599822
F test/incrblob2.test a494c9e848560039a23974b9119cfc2cf3ad3bd15cc2694ee6367ae537ef8f1f
F test/incrblob3.test d8d036fde015d4a159cd3cbae9d29003b37227a4
F test/incrblob4.test 21a52a6843a56cdcce968c6a86b72a7066d0e6ba
-F test/incrblob_err.test 69f9247fed50278d48ea710d1a8f9cdb09e4c0b8
+F test/incrblob_err.test 89372a28f1d98254f03fed705f9efcd34ef61a674df16d2dbb4726944a2de5e9
F test/incrblobfault.test 74dd8ac108304cea0b4a0df6df63a1567e558758
F test/incrcorrupt.test 6c567fbf870aa9e91866fe52ce6f200cd548939a
-F test/incrvacuum.test b729aab1d4983037da57e66c20dfd7458561a85626dcf824f60175e35f4ce152
+F test/incrvacuum.test 2aaee202b1f230e55779f70d155f6ba67bbdff8481d650214d256ab0f97d4a2b
F test/incrvacuum2.test 7d26cfda66c7e55898d196de54ac4ec7d86a4e3d
F test/incrvacuum3.test 75256fb1377e7c39ef2de62bfc42bbff67be295a
F test/incrvacuum_ioerr.test 6ae2f783424e47a0033304808fe27789cf93e635
-F test/index.test fe3c7a1aad82af92623747e9c3f3aa94ccd51238
+F test/index.test df4cddf4435314a948237fdfa9acee67de21f7bebc789beab4b89b575b4f6a70
F test/index2.test f835d5e13ca163bd78c4459ca15fd2e4ed487407
-F test/index3.test 81bc47890b8abfb181bc35f8d10b56c069803386
+F test/index3.test 51685f39345462b84fcf77eb8537af847fdf438cc96b05c45d6aaca4e473ade0
F test/index4.test ab92e736d5946840236cd61ac3191f91a7856bf6
F test/index5.test 8621491915800ec274609e42e02a97d67e9b13e7
F test/index6.test d07ea75b8c21f125c6f325522e8df8c05c91e9251ec923a31d0582b2ba4a617d
@@ -1010,7 +1019,7 @@ F test/index8.test bc2e3db70e8e62459aaa1bd7e4a9b39664f8f9d7
F test/index9.test 0aa3e509dddf81f93380396e40e9bb386904c1054924ba8fa9bcdfe85a8e7721
F test/indexedby.test a52c8c6abfae4fbfb51d99440de4ca1840dbacc606b05e29328a2a8ba7cd914e
F test/indexexpr1.test 635261197bcdc19b9b2c59bbfa7227d525c00e9587faddb2d293c44d287ce60e
-F test/indexexpr2.test 08551aa8956a91582979e17b6d369f321a5cb6ed6d3e952925a3e54e9e7de216
+F test/indexexpr2.test fc994dcd4b3da932d4add8e65ed7ca08166d541e00a46874cfacd98dfb93a31b
F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
F test/insert.test 5604b1ff5675cc84c34a5b315792b958f48c32edccc0dafcc81d3b776270b70a
@@ -1020,7 +1029,7 @@ F test/insert4.test 46bead5f39e181850ee56adcf49d3a3157c460c52249211714612ac89fe3
F test/insert5.test 394f96728d1258f406fe5f5aeb0aaf29487c39a6
F test/instr.test 9a8802f28437d8ade53fedfc47b2ca599b4e48ba
F test/instrfault.test 0f870b218ea17cd477bb19ed330eecdb460dd53a
-F test/intarray.test 46d95b457916638c5d8b1af21fb174804b3acf8b
+F test/intarray.test 8319986182af37c8eb4879c6bfe9cf0074e9d43b193a4c728a0efa3417c53fb7
F test/interrupt.test 16ea879ec728cb76414c148c5f24afd5d1f91054
F test/interrupt2.test e4408ca770a6feafbadb0801e54a0dcd1a8d108d
F test/intpkey.test ac71107a49a06492b69b82aafaf225400598d3c8
@@ -1052,12 +1061,13 @@ F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
F test/kvtest.c 94da54bb66aae7a54e47cf7e4ea4acecc0f217560f79ad3abfcc0361d6d557ba
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
+F test/lemon-test01.y 58b764610fd934e189ffbb0bbfa33d171b9cb06019b55bdc04d090d6767e11d7
F test/like.test 11cfd7d4ef8625389df9efc46735ff0b0b41d5e62047ef0f3bc24c380d28a7a6
F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da
-F test/like3.test cf0ff2d06c9d8456283aeff405b911642298441206306aeaeaa93973233b1195
+F test/like3.test 430691e6057e11a59e934be74c06b85605b80061d45af5714d52886a811efeb7
F test/limit.test 0c99a27a87b14c646a9d583c7c89fd06c352663e
F test/limit2.test 9409b033284642a859fafc95f29a5a6a557bd57c1f0d7c3f554bd64ed69df77e
-F test/loadext.test d077450695ddb5c1ea3ad7d48e5f5850fe732ad9
+F test/loadext.test faa4f6eed07a5aac35d57fdd7bc07f8fc82464cfd327567c10cf0ba3c86cde04
F test/loadext2.test 0408380b57adca04004247179837a18e866a74f7
F test/lock.test be4fe08118fb988fed741f429b7dd5d65e1c90db
F test/lock2.test 5242d8ac4e2d59c403aebff606af449b455aceff
@@ -1093,6 +1103,7 @@ F test/mallocK.test 1f4b5efbf61715ab79b20b38739ff4b3d110ceb53f54e5db6da1f01c0837
F test/mallocL.test fb311ff80afddf3b1a75e52289081f4754d901dc
F test/mallocM.test 78bbe9d3da84a5c679123cdb40d7b2010b18fc46e13897e4f253c6ba6fbff134
F test/malloc_common.tcl aac62499b76be719fac31e7a3e54a7fd53272e7f
+F test/malloctraceviewer.tcl b7a54595270c1d201abf1c3f3d461f27eaf24cdef623ad08a0fe5e411264c8a9
F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e
F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f
F test/memdb.test c1f2a343ad14398d5d6debda6ea33e80d0dafcc7
@@ -1104,16 +1115,16 @@ F test/minmax.test 6751e87b409fe11b02e70a306d846fa544e25a41
F test/minmax2.test dae92964ac87c1d2ef978c582e81a95e11c00f1cbef68980bfb2abaf10315063
F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354
F test/minmax4.test 936941484ebdceb8adec7c86b6cd9b6e5e897c1f
-F test/misc1.test 704ea2cc7e7b9deb622b37953f0e77d0879826e8c3bfc1d7a691528035405061
+F test/misc1.test c8cfd1c3f842b3341fda9d81a96236d5c76ca89973aeff3fe50bac6fefcfc421
F test/misc2.test 00d7de54eda90e237fc9a38b9e5ccc769ebf6d4d
F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d
-F test/misc4.test 0d8be3466adf123a7791a66ba2bc8e8d229e87f3
-F test/misc5.test 60e1fc758a93cacd19eb2fafcd1d40d150a05047546c7a92389c98047d621901
+F test/misc4.test 10cd6addb2fa9093df4751a1b92b50440175dd5468a6ec84d0386e78f087db0e
+F test/misc5.test c4aeaa0fa28faa08f2485309c38db4719e6cd1364215d5687a5b96d340a3fa58
F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
-F test/misc7.test 349855706310f0de6b91645d199f6874f518627fd057743fa4e3689b60d06efc
+F test/misc7.test 10d639a5e0fdf1bd51ad42be705393a38780ad71b6957110035a4e6c1e5e7f40
F test/misc8.test 8fb0f31d7a8aed484d759773ab8ad12ec746a477f4a67394a4af0e677494c3ca
F test/misuse.test 9e7f78402005e833af71dcab32d048003869eca5abcaccc985d4f8dc1d86bcc7
-F test/mjournal.test 9d86e697dcbc5da2c4e8caba9b176b5765fe65e80c88c278b8c09a917e436795
+F test/mjournal.test 28a08d5cb5fb5b5702a46e19176e45e964e0800d1f894677169e79f34030e152
F test/mmap1.test fb04e0c10492455007624ade884ca0c8852ff3e4e11d95408f9709ca2ef7f626
F test/mmap2.test 9d6dd9ddb4ad2379f29cc78f38ce1e63ed418022
F test/mmap3.test b3c297e78e6a8520aafcc1a8f140535594c9086e
@@ -1129,11 +1140,11 @@ F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
F test/nan.test 437d40e6d0778b050d7750726c0cbd2c9936b81962926e8f8c48ca698f00f4d1
F test/nockpt.test 8c43b25af63b0bd620cf1b003529e37b6f1dc53bd22690e96a1bd73f78dde53a
F test/nolock.test f196cf8b8fbea4e2ca345140a2b3f3b0da45c76e
-F test/normalize.test 1dedf653ca33b0b55fd0c7967d2861a51f1801a7aa899a02d4c0d7adfcd5acdc
+F test/normalize.test 6a80564d2000702b5919ed2c1069fef0f95762142bc96a71b4c124a845165713
F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf
F test/notify2.test 2ecabaa1305083856b7c39cf32816b612740c161
F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934
-F test/notnull.test b6999231221df3534827e45e2005dd7a815fdd5f2c2e1afb9be21ead410816f8
+F test/notnull.test a37b663d5bb728d66fc182016613fb8e4a0a4bbf3d75b8876a7527f7d4ed3f18
F test/null.test 0dcce4f04284ec66108c503327ad6d224c0752b3
F test/numcast.test 5d126f7f581432e86a90d1e35cac625164aec4a1
F test/numindex1.test 20a5450d4b056e48cd5db30e659f13347a099823
@@ -1152,10 +1163,10 @@ F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da
F test/orderby8.test 23ef1a5d72bd3adcc2f65561c654295d1b8047bd
F test/orderby9.test 87fb9548debcc2cd141c5299002dd94672fa76a3
F test/oserror.test e7b3416be4b9d5dd2fe0b42dd394daaddbb6c83eeec1f0e47b120b53e0ad3ace
-F test/ossfuzz.c c4c4547e2c92ac52f10038b073a03248251a23c1c559728f63a18aeca0e79f03
+F test/ossfuzz.c 273eaea2d65b70d77ea4f01404114b9e0244488943f768dc39458c72bd722e0e
F test/ossshell.c f125c5bd16e537a2549aa579b328dd1c59905e7ab1338dfc210e755bb7b69f17
F test/ovfl.test 199c482696defceacee8c8e0e0ef36da62726b2f
-F test/pager1.test a32ce299ed01ffb06e84a3af467ae1f3389786b316f40c4359f442c79144736b
+F test/pager1.test 1e9ee778bdeaf4f7f09997d029cdaca6a42dfc2092edafe4f5e590acbf1eab13
F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71
F test/pager3.test 4e9a83d6ca0838d7c602c9eb93d1357562d9059c1e02ffb138a8271020838370
F test/pager4.test a122e9e6925d5b23b31e3dfef8c6a44bbf19590e
@@ -1164,19 +1175,19 @@ F test/pagerfault2.test caf4c7facb914fd3b03a17b31ae2b180c8d6ca1f
F test/pagerfault3.test 1003fcda009bf48a8e22a516e193b6ef0dd1bbd8
F test/pageropt.test 84e4cc5cbca285357f7906e99b21be4f2bf5abc0
F test/pagesize.test 5769fc62d8c890a83a503f67d47508dfdc543305
-F test/parser1.test 391b9bf9a229547a129c61ac345ed1a6f5eb1854
+F test/parser1.test 6ccdf5e459a5dc4673d3273dc311a7e9742ca952dd0551a6a6320d27035ce4b3
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
-F test/permutations.test f6d25d2f978e6bb4d6aa08db82ec10d635c47e88b79f96d79d16860425dc6a8b
+F test/permutations.test cf0b4e498db1d0143c19641d4420df7cc27fab2c95ed0abd2c7c5753beab25b8
F test/pg_common.tcl 301ac19c1a52fd55166d26db929b3b89165c634d52b5f8ad76ea8cb06960db30
-F test/pragma.test 7c8cfc328a1717a95663cf8edb06c52ddfeaf97bb0aee69ae7457132e8d39e7d
+F test/pragma.test c267bf02742c823a191960895b3d52933cebd7beee26757d1ed694f213fcd867
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
-F test/pragma3.test 14c12bc5352b1e100e0b6b44f371053a81ccf8ed
-F test/pragma4.test 3046501bee2f652dc2a4f9c87781e2741361d6864439c8381aba6c3b774b335c
+F test/pragma3.test 8300aa9c63cff1027006ca34bf413a148abbd6dcd471fa9a1ded322fe18c0df9
+F test/pragma4.test 52d8186f9e8d09b87189432cdd401dfa66d0b32445e837fa19046c8ae7621b0e
F test/pragma5.test 824ce6ced5d6b7ec71abe37fc6005ff836fe39d638273dc5192b39864b9ee983
F test/pragmafault.test 275edaf3161771d37de60e5c2b412627ac94cef11739236bec12ed1258b240f8
-F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc
+F test/printf.test a3e559bc9d922e7fe44e9d05c6965fee34fe3bc28300a4248c6a063425246ffd
F test/printf2.test 30b5dd0b4b992dc5626496846ecce17ff592cacbcb11c3e589f3ac4d7e129dae
F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
@@ -1194,8 +1205,8 @@ F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
F test/regexp2.test 40e894223b3d6672655481493f1be12012f2b33c
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
-F test/releasetest.tcl c5b474f9880073fc3b69729ee05d5284653a9ee101af572204917d9dcb1d9015 x
-F test/resetdb.test 684a6ffde5a5141bba79f3101981cc38dcfc3403f61e643b7b3aa68bef0b8408
+F test/releasetest.tcl b290d538ffcb2ff711f09eadc7396c1a42580f3fb078605471dc8875ca0b4d1e x
+F test/resetdb.test 373a9eb8fcbd58bf87affec6a88c6353038f98a5d25be5ab75a0b9636c462a36
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa
F test/rollback2.test bc868d57899dc6972e2b4483faae0e03365a0556941474eec487ae21d8d38bb6
@@ -1252,19 +1263,19 @@ F test/server1.test c2b00864514a68a0e6fd518659dc95d0050307a357a08969872bef027d78
F test/session.test 78fa2365e93d3663a6e933f86e7afc395adf18be
F test/sessionfuzz-data1.db 1f8d5def831f19b1c74571037f0d53a588ea49a6c4ca2a028fc0c27ef896dbcb
F test/sessionfuzz.c b0fcdcf757451957e17396a3af5171f1fdf9b2babc81da9fa35675df46c4729a
-F test/shared.test 1da9dbad400cee0d93f252ccf76e1ae007a63746
+F test/shared.test 1826673eb5eb745fb91a3bdac99a7737057742ae38dcb0fe076a384d6727578b
F test/shared2.test 03eb4a8d372e290107d34b6ce1809919a698e879
F test/shared3.test ab693f9b6e156b8bfb2a0ad94f29fe69602a5d38
F test/shared4.test c75f476804e76e26bf6fa0e7b421fb0ca7d07558
F test/shared6.test 866bb4982c45ce216c61ded5e8fde4e7e2f3ffa9
F test/shared7.test a81e99f83e6c51b02ac99c96fb3a2a7b5978c956
-F test/shared8.test 00a07bf5e1337ecf72e94542bdefdc330d7a2538
+F test/shared8.test 933ed7d71f598bb6c7a8c192a3cd30f2562fdccf514df383798599c34ffa672f
F test/shared9.test 5f2a8f79b4d6c7d107a01ffa1ed05ae7e6333e21
F test/sharedA.test 49d87ec54ab640fbbc3786ee3c01de94aaa482a3a9f834ad3fe92770eb69e281
F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
-F test/shell1.test 707c03fbd07ac506cfb6fa09da4ee22e2b50453c3db2f404694116eb990168f3
+F test/shell1.test d2bf5daeb6f449f0169c9ef3094db17a16a02199c5dcf1a635a3e79b07eb0edd
F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b
F test/shell3.test ac8c2b744014c3e9a0e26bfd829ab65f00923dc1a91ffd044863e9423cc91494
F test/shell4.test 89ad573879a745974ff2df20ff97c5d6ffffbd5d
@@ -1282,11 +1293,11 @@ F test/skipscan3.test ec5bab3f81c7038b43450e7b3062e04a198bdbb5
F test/skipscan5.test 67817a4b6857c47e0e33ba3e506da6f23ef68de2
F test/skipscan6.test 0b4cd1b4ac9f84d91454df513c99a4932fa07e8f27b8049bea605068b3e34ac7
F test/snapshot.test a504f2e7009f512ef66c719f0ea1c55a556bdaf1e1312c80a04d46fc1a3e9632
-F test/snapshot2.test 4fc84a0121e882d6980333bf14dfc1143dfb94f5afbb909c084977a945b45beb
-F test/snapshot3.test d6ec952e437e5c06a293d0f5ec1be1b45771d46d93bccfb3818ca2617dcb11e7
-F test/snapshot4.test 0f7e6bd6f1370d112ee820c541d0dd0e7b8ab4ea77429e65106d81c9ad2185a6
+F test/snapshot2.test 8d6ff5dd9cc503f6e12d408a30409c3f9c653507b24408d9cd7195931c89bc54
+F test/snapshot3.test 8744313270c55f6e18574283553d3c5c5fe4c5970585663613a0e75c151e599b
+F test/snapshot4.test d4e9347ef2fcabc491fc893506c7bbaf334da3be111d6eb4f3a97cc623b78322
F test/snapshot_fault.test 508ae6f211d4991e9ff3b5080aeb0a179bf6755138aabeac4bca8083044d895a
-F test/snapshot_up.test 93fec2d847ec12e3bae0f6486da2abc965a606e099e4e870454045f5f56f71ba
+F test/snapshot_up.test a0a29c4cf33475fcef07c3f8e64af795e24ab91b4cc68295863402a393cdd41c
F test/soak.test 18944cf21b94a7fe0df02016a6ee1e9632bc4e8d095a0cb49d95e15d5cca2d5c
F test/softheap1.test 843cd84db9891b2d01b9ab64cef3e9020f98d087
F test/sort.test c2adc635c2564241fefec0b3a68391ef6868fd3b
@@ -1325,26 +1336,26 @@ F test/subtype1.test 7fe09496352f97053af1437150751be2d0a0cae8
F test/superlock.test ec94f0556b6488d97f71c79f9061ae08d9ab8f12
F test/swarmvtab.test 9a3fd5ab3e9b3c976ad1b3d7646aab725114f2ac26b59395d0778b33bab6cdaf
F test/swarmvtab2.test c948cb2fdfc5b01d85e8f6d6504854202dc1a0782ab2a0ed61538f27cbd0aa5c
-F test/swarmvtab3.test 6cb664669630fcec4102a09333e52068734858fd2761eee3b0465c14cdbcee29
-F test/swarmvtabfault.test 00aec54665909490f5c383f3cae3b5d18bd97c12490b429ff8752a3027acfa42
+F test/swarmvtab3.test 247aa38b6ebd2b99db2075847ae47e789ac34f1c2ab5c720dfcffd990004c544
+F test/swarmvtabfault.test 8a67a9f27c61073a47990829e92bc0c64420a807cb642b15a25f6c788210ed95
F test/symlink.test 0d816670325536b8973ec08d32b45136baddb80bd45fd178e0ce7a9e8153f3e7
F test/sync.test 89539f4973c010eda5638407e71ca7fddbcd8e0594f4c9980229f804d4333092
F test/sync2.test 8f9f7d4f6d5be8ca8941a8dadcc4299e558cb6a1ff653a9469146c7a76ef2039
F test/syscall.test a39d9a36f852ae6e4800f861bc2f2e83f68bbc2112d9399931ecfadeabd2d69d
F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04
-F test/tabfunc01.test c47171c36b3d411df2bd49719dcaa5d034f8d277477fd41d253940723b969a51
-F test/table.test b708f3e5fa2542fa51dfab21fc07b36ea445cb2f
-F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
+F test/tabfunc01.test 54300134f76db817685194d2f0e63e3fbf7380b45e0d426e00a9aee752497cfb
+F test/table.test eb3463b7add9f16a5bb836badf118cf391b809d09fdccd1f79684600d07ec132
+F test/tableapi.test ecbcc29c4ab62c1912c3717c48ea5c5e59f7d64e4a91034e6148bd2b82f177f4
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
F test/tclsqlite.test dca8aa30d84175e7d8c8fc43d3ffa11fa56e23fbdac2679d03833a0f326edf34
F test/tempdb.test 4cdaa23ddd8acb4d79cbb1b68ccdfd09b0537aaba909ca69a876157c2a2cbd08
-F test/tempdb2.test 4749545409c6d7438b435c3f05cdd139cf4145a954a6908d19e3443ffd8724b3
+F test/tempdb2.test 2479226e4cb96f4c663eccd2d12c077cf6bda29ca5cc69a8a58a06127105dd62
F test/tempfault.test 0c0d349c9a99bf5f374655742577f8712c647900
F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
F test/temptable2.test d2940417496e2b9548e01d09990763fbe88c316504033256d51493e1f1a5ce6a
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
-F test/tester.tcl d5138d226cc2aaacb6934cdd79acaa5edd17cad862482895b833bbf62c49aca0
+F test/tester.tcl fa5656391e3b477508abe12b3b81f019b2e71397399ab38a2f32d8d7f3bf8e56
F test/thread001.test b61a29dd87cf669f5f6ac96124a7c97d71b0c80d9012746072055877055cf9ef
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@ -1514,14 +1525,14 @@ F test/trigger3.test aa640bb2bbb03edd5ff69c055117ea088f121945
F test/trigger4.test 74700b76ebf3947b2f7a92405141eb2cf2a5d359
F test/trigger5.test 619391a3e9fc194081d22cefd830d811e7badf83
F test/trigger6.test 0e411654f122552da6590f0b4e6f781048a4a9b9
-F test/trigger7.test 93cfa9b48ab9104b2b3d87bc544ac8021405643e36f23ee84635fbfaf9b8fef5
+F test/trigger7.test e7ce54bfda67a88d778aea42544e151c465547a7e617127b6914c2221a6d53c1
F test/trigger8.test 30cb0530bd7c4728055420e3f739aa00412eafa4
F test/trigger9.test 2226ec795a33b0460ab5cf8891e9054cc7edef41
-F test/triggerA.test fe5597f47ee21bacb4936dc827994ed94161e332
+F test/triggerA.test 837be862d8721f903dba3f3ceff05b32e0bee5214cf6ea3da5fadf12d3650e9d
F test/triggerB.test 56780c031b454abac2340dbb3b71ac5c56c3d7fe
F test/triggerC.test 302d8995f5ffe63bbc15053abb3ef7a39cf5a092
F test/triggerD.test 8e7f3921a92a5797d472732108109e44575fa650
-F test/triggerE.test d9e9b364dfd527c84ac0de53045406325487feecb32888d482eca64421a50d99
+F test/triggerE.test ede2e4bce4ba802337bd69d39447fa04a938e06d84a8bfc53c76850fc36ed86d
F test/triggerF.test 6a8c22bd058cf467f0c7d112afe87f7a8c579c0c4681b914b8f19020f48528a4
F test/triggerG.test d5caeef6144ede2426dd13211fd72248241ff2ebc68e12a4c0bf30f5faa21499
F test/tt3_checkpoint.c 9e75cf7c1c364f52e1c47fd0f14c4340a9db0fe1
@@ -1532,8 +1543,8 @@ F test/tt3_vacuum.c 1753f45917699c9c1f66b64c717a717c9379f776
F test/types.test bf816ce73c7dfcfe26b700c19f97ef4050d194ff
F test/types2.test 1aeb81976841a91eef292723649b5c4fe3bc3cac
F test/types3.test 99e009491a54f4dc02c06bdbc0c5eea56ae3e25a
-F test/unionvtab.test 595fb601de00188ca5e7c6dbe266c17a0faf234cf434ce85eccec1a929ef9baf
-F test/unionvtabfault.test 26b6854d5aef9005cd630513025690bff1b7378ae9c97b81e2a3cbe84eee0f58
+F test/unionvtab.test 5ae0f0b4f302a4c6bb310b64386f9ac6a4c1c271c08f31cc7c5d92722e2b2729
+F test/unionvtabfault.test e8759f3d14fb938ce9657e2342db34aeac0fb9bc1692b0d1ebb0069630151d06
F test/unique.test 93f8b2ef5ea51b9495f8d6493429b1fd0f465264
F test/unique2.test 3674e9f2a3f1fbbfd4772ac74b7a97090d0f77d2
F test/unixexcl.test d936ba2b06794018e136418addd59a2354eeae97
@@ -1558,7 +1569,7 @@ F test/vacuummem.test 7b42abb3208bd82dd23a7536588396f295a314f2
F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
F test/view.test 71e1bf4c0e2e0d37c84d7db5b33cd47eb4a7662c19d93ede4112b350b186f61f
-F test/vtab1.test 8f91b9538d1404c3932293a588c4344218a0c94792d4289bb55e41020e7b3fff
+F test/vtab1.test 60b4f70aafa6078d6fdfc11417af3bd216d7ef5eafce16707a6ca3dae5166d20
F test/vtab2.test 14d4ab26cee13ba6cf5c5601b158e4f57552d3b055cdd9406cf7f711e9c84082
F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e
F test/vtab4.test 8e73ed268f3d596bc3590f45fc948fb40f28e9c3
@@ -1577,7 +1588,7 @@ F test/vtabH.test 3cf9aa1c1c4381b3b3ac33f933376f06fbb99d2294a83c79b7562d3ed87be4
F test/vtabI.test 751b07636700dbdea328e4265b6077ccd6811a3f
F test/vtabJ.test d7b73675708cf63cfcb9d443bb451fc01a028347275b7311e51f9fdf3ca6757f
F test/vtab_alter.test 736e66fb5ec7b4fee58229aa3ada2f27ec58bc58c00edae4836890c3784c6783
-F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
+F test/vtab_err.test dcc8b7b9cb67522b3fe7a272c73856829dae4ab7fdb30399aea1b6981bda2b65
F test/vtab_shared.test 5253bff2355a9a3f014c15337da7e177ab0ef8ad
F test/wal.test 613efec03e517e1775d86b993a54877d2e29a477
F test/wal2.test 155b9efa999bdb38ce1cd729b9a4fcdbffd6b88be27f039bad1d2929d287d918
@@ -1585,7 +1596,7 @@ F test/wal3.test 2a93004bc0fb2b5c29888964024695bade278ab2
F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c
F test/wal5.test 9c11da7aeccd83a46d79a556ad11a18d3cb15aa9
F test/wal6.test b602704e4b066199bc89d91ca9000f335dcf4572
-F test/wal64k.test 163655ecd2cb8afef4737cac2a40fdd2eeaf20b8
+F test/wal64k.test 2a525c0f45d709bae3765c71045ccec5df7d100ccbd3a7860fdba46c9addb965
F test/wal7.test 2ae8f427d240099cc4b2dfef63cff44e2a68a1bd
F test/wal8.test d9df3fba4caad5854ed69ed673c68482514203c8
F test/wal9.test 378e76a9ad09cd9bee06c172ad3547b0129a6750
@@ -1636,22 +1647,22 @@ F test/whereL.test 0a19fc44cd1122040f56c934f1b14d0ca85bde28f270268a428dd9796ea06
F test/wherefault.test 1374c3aa198388925246475f84ad4cd5f9528864
F test/wherelfault.test 9012e4ef5259058b771606616bd007af5d154e64cc25fa9fd4170f6411db44e3
F test/wherelimit.test 592081800806d297dd7449b1030c863d2883d6d42901837ccd2e5a9bd962edb0
-F test/wherelimit2.test be78ba3aa1831c6358fd7d5b9809bfd520f0c2a7d63a295e8f182e140ff137c3
+F test/wherelimit2.test 9bf0aa56cca40ea0e4c5e2915341355a2bbc0859ec4ce1589197fe2a9d94635f
F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2aeee74
F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
-F test/window1.test 474bef1a6ac291755e51d1f9458dc11117c1870ac5e08b4d3938649b215f8334
+F test/window1.test 02e481ac48c445b43bab7b3cf1e4115165b5127a1aa29e14f5372922c836f1a4
F test/window2.tcl 9bfa842d8a62b0d36dc8c1b5972206393c43847433c6d75940b87fec93ce3143
F test/window2.test 8e6d2a1b9f54dfebee1cde961c8590cd87b4db45c50f44947a211e1b63c2a05e
F test/window3.tcl 577a3b1ff913208e5248c04dab9df17fd760ce159a752789e26d0cb4a5f91823
F test/window3.test e274b7f8952ca4ed25996e0e45c047192b066e0aaff2a822d4293c8c4f1d8d98
F test/window4.tcl 511425f6b0abf9b953df54cc9c7295cc7c25d78f4ed6f7a74b094eec0120eccb
F test/window4.test c5d6bf3403e4ade2f19df2afe4c16f29fb817c392c6c1c8017edb7165c191a62
-F test/window5.test 8187f46597c90b73e8f96659e893353cbda337479cc582f7a488eab351ba08d3
-F test/window6.test 7574778c79cae89f1781df237bf9ff5063886deca91a36efc53934315f0e7612
-F test/windowfault.test 23abad97b72c6f609002255ddd41ef5c8922408f918f9b98ad6005ab316e482f
+F test/window5.test d328dd18221217c49c144181975eea17339eaeaf0e9aa558cee3afb84652821e
+F test/window6.test 5eae4ae7a590ccf1e605880969ca0bad3955616ac91cad3031baea38748badb3
+F test/windowfault.test 12ceb6bbb355d13e8fcd88c5731a57256dfdf77b9a7ae20842a76fcd4623df5b
F test/with1.test 2465d98ffce80d00553ac7135697c18b0369275b6ecc750daa2af320b8c812ca
F test/with2.test e0030e2f0267a910d6c0e4f46f2dfe941c1cc0d4f659ba69b3597728e7e8f1ab
F test/with3.test 5e8ce2c585170bbbc0544e2a01a4941fa0be173ba5265e5c92eb588cd99a232d
@@ -1659,7 +1670,7 @@ F test/with4.test 257be66c0c67fee1defbbac0f685c3465e2cad037f21ce65f23f86084f1982
F test/withM.test 693b61765f2b387b5e3e24a4536e2e82de15ff64
F test/without_rowid1.test 533add9100255e4cc430d371b3ecfb79f11f956b86c3a1b9d34413bf8e482d8f
F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
-F test/without_rowid3.test e1bb85362d9b7b63ea2b93c433bb2923fff8badb98e463474365531c1cd5f880
+F test/without_rowid3.test ea4b59dd1b0d7f5f5e4b7cca978cdb905752a9d7c57dc4344a591dba765a3691
F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a
F test/without_rowid5.test 89b1c587bd92a0590e440da33e7666bf4891572a
F test/without_rowid6.test 1f99644e6508447fb050f73697350c7ceca3392e
@@ -1667,8 +1678,8 @@ F test/wordcount.c d721a4b6fae93e6e33449700bce1686bc23257c27425bc3ef1599dc912ade
F test/writecrash.test f1da7f7adfe8d7f09ea79b42e5ca6dcc41102f27f8e334ad71539501ddd910cc
F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa
F test/zerodamage.test 9c41628db7e8d9e8a0181e59ea5f189df311a9f6ce99cc376dc461f66db6f8dc
-F test/zipfile.test a61f6ba6dbaaf4983849df84a31df140c7ddd1362e2fa9ecd3cdf5cd123b7f18
-F test/zipfile2.test 8a18965530258140ce301b2c2f4245bc505ffead2e17a97fa34c7ace379ea5e0
+F test/zipfile.test b3b558639f7a103e095713ad0f57fec1fce1b7d60c8054df5789b98f7547a395
+F test/zipfile2.test 9903388a602a3834189857a985106ff95c3bba6a3969e0134127df991889db5d
F test/zipfilefault.test 44d4d7a7f7cca7521d569d7f71026b241d65a6b1757aa409c1a168827edbbc2c
F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5
F tool/GetTclKit.bat 8995df40c4209808b31f24de0b58f90930239a234f7591e3675d45bfbb990c5d
@@ -1684,11 +1695,11 @@ F tool/fast_vacuum.c 5ba0d6f5963a0a63bdc42840f678bad75b2ebce1
F tool/fragck.tcl 5265a95126abcf6ab357f7efa544787e5963f439
F tool/fuzzershell.c e1d90a03ca790d7c331c2aae08ca46ff435f1ae1faa6cb9cc48f4687c18fdc6e
F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
-F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
+F tool/genfkey.test b6afd7b825d797a1e1274f519ab5695373552ecad5cd373530c63533638a5a4f
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f
F tool/lemon.c 60d1e1eb0f7ebae709f68f1472d77fbf291c5345cd98ff417219da7e74fd09e9
-F tool/lempar.c 6020ce61dd7a536a3866952eb1e616c7e8b14b8f623368ed5a98f0639cedf048
+F tool/lempar.c 452f12d40229847634a160e5666b6c4ec4392fd81941c3443861b48d497054cc
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca
@@ -1701,7 +1712,7 @@ F tool/mkmsvcmin.tcl cad0c7b54d7dd92bc87d59f36d4cc4f070eb2e625f14159dc2f5c4204e6
F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
F tool/mkopcodeh.tcl 352a4319c0ad869eb26442bf7c3b015aa15594c21f1cce5a6420dbe999367c21
F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa
-F tool/mkpragmatab.tcl 8b9b448b5eb7222d4e3f7afb3c678596784180d319eb4e01c842887ed8213b85
+F tool/mkpragmatab.tcl a1334e70a08fdf5de32cd0093613212bb11ac8f880487540987175c536ac335f
F tool/mkshellc.tcl 1f45770aea226ac093a9c72f718efbb88a2a2833409ec2e1c4cecae4202626f5
F tool/mksourceid.c d458f9004c837bee87a6382228ac20d3eae3c49ea3b0a5aace936f8b60748d3b
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
@@ -1733,7 +1744,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 579d7e4e42c30a963781654c87d2868823120b55d59e16ca77b0edbab0218713
+F tool/sqldiff.c 7b9b7238284f02131dbb8f21a4e862409bff728045c5473139d28c67ac87580e
F tool/sqlite3_analyzer.c.in 7eeaae8b0d7577662acaabbb11107af0659d1b41bc1dfdd4d91422de27127968
F tool/sqltclsh.c.in 1bcc2e9da58fadf17b0bf6a50e68c1159e602ce057210b655d50bad5aaaef898
F tool/sqltclsh.tcl 862f4cf1418df5e1315b5db3b5ebe88969e2a784525af5fbf9596592f14ed848
@@ -1745,7 +1756,7 @@ F tool/varint.c 5d94cb5003db9dbbcbcc5df08d66f16071aee003
F tool/vdbe-compress.tcl 5926c71f9c12d2ab73ef35c29376e756eb68361c
F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
-F tool/warnings.sh 8a4acea31e0f9c562949a2d767329533c0930d699ea19c6704c0ca0aa9154068
+F tool/warnings.sh 09311479bdc290e20ec8e35a3d1b14b096bbd96222277cfd6274c3a99b3d012f
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
F vsixtest/App.xaml b76d3b48860e7454775c47ea38ffea9c4abe3e85
F vsixtest/App.xaml.cpp c465147f50871165c60ca16955219f6c5812d6d8
@@ -1768,11 +1779,11 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 8d09ce5d738bb00c4524c663ec69555fe917ac733d58b06a302675ce7fe33fca
-R 00cfcd9deda5635c7483df5f9218a978
+P 23684cb841ac2cb0d69e5470253bd96feb733762a7553b952a08470834fe85fa
+R dcc394af10af6094607f56a6086fb748
T +bgcolor * #d0c0ff
T +sym-release *
-T +sym-version-3.25.3 *
+T +sym-version-3.26.0 *
U drh
-Z d2b8ccce3c6c80bcf2a7dfd041b6e7a9
+Z 560a5decbb241d53eb97e72267b6e6e8
# Remove this line to create a well-formed manifest.
diff --git a/chromium/third_party/sqlite/src/manifest.uuid b/chromium/third_party/sqlite/src/manifest.uuid
index 8b7d03cd5ea..166b1b3d3af 100644
--- a/chromium/third_party/sqlite/src/manifest.uuid
+++ b/chromium/third_party/sqlite/src/manifest.uuid
@@ -1 +1 @@
-89e099fbe5e13c33e683bef07361231ca525b88f7907be7092058007b75036f2
+bf8c1b2b7a5960c282e543b9c293686dccff272512d08865f4600fb58238b4f9
diff --git a/chromium/third_party/sqlite/src/src/alter.c b/chromium/third_party/sqlite/src/src/alter.c
index b505b736ff6..fcddc40d0c5 100644
--- a/chromium/third_party/sqlite/src/src/alter.c
+++ b/chromium/third_party/sqlite/src/src/alter.c
@@ -667,10 +667,16 @@ static void renameTokenCheckAll(Parse *pParse, void *pPtr){
#endif
/*
-** Add a new RenameToken object mapping parse tree element pPtr into
-** token *pToken to the Parse object currently under construction.
+** Remember that the parser tree element pPtr was created using
+** the token pToken.
**
-** Return a copy of pPtr.
+** In other words, construct a new RenameToken object and add it
+** to the list of RenameToken objects currently being built up
+** in pParse->pRename.
+**
+** The pPtr argument is returned so that this routine can be used
+** with tail recursion in tokenExpr() routine, for a small performance
+** improvement.
*/
void *sqlite3RenameTokenMap(Parse *pParse, void *pPtr, Token *pToken){
RenameToken *pNew;
@@ -803,7 +809,7 @@ static int renameColumnExprCb(Walker *pWalker, Expr *pExpr){
renameTokenFind(pWalker->pParse, p, (void*)pExpr);
}else if( pExpr->op==TK_COLUMN
&& pExpr->iColumn==p->iCol
- && p->pTab==pExpr->pTab
+ && p->pTab==pExpr->y.pTab
){
renameTokenFind(pWalker->pParse, p, (void*)pExpr);
}
@@ -1061,9 +1067,14 @@ static int renameResolveTrigger(Parse *pParse, const char *zDb){
db->aDb[sqlite3SchemaToIndex(db, pNew->pTabSchema)].zDbSName
);
pParse->eTriggerOp = pNew->op;
+ /* ALWAYS() because if the table of the trigger does not exist, the
+ ** error would have been hit before this point */
+ if( ALWAYS(pParse->pTriggerTab) ){
+ rc = sqlite3ViewGetColumnNames(pParse, pParse->pTriggerTab);
+ }
/* Resolve symbols in WHEN clause */
- if( pNew->pWhen ){
+ if( rc==SQLITE_OK && pNew->pWhen ){
rc = sqlite3ResolveExprNames(&sNC, pNew->pWhen);
}
@@ -1177,15 +1188,8 @@ static void renameParseCleanup(Parse *pParse){
** into zNew. The name should be quoted if bQuote is true.
**
** This function is used internally by the ALTER TABLE RENAME COLUMN command.
-** Though accessible to application code, it is not intended for use by
-** applications. The existance of this function, and the way it works,
-** is subject to change without notice.
-**
-** If any of the parameters are out-of-bounds, then simply return NULL.
-** An out-of-bounds parameter can only occur when the application calls
-** this function directly. The parameters will always be well-formed when
-** this routine is invoked by the bytecode for a legitimate ALTER TABLE
-** statement.
+** It is only accessible to SQL created using sqlite3NestedParse(). It is
+** not reachable from ordinary SQL passed into sqlite3_prepare().
*/
static void renameColumnFunc(
sqlite3_context *context,
@@ -1341,8 +1345,8 @@ renameColumnFunc_done:
*/
static int renameTableExprCb(Walker *pWalker, Expr *pExpr){
RenameCtx *p = pWalker->u.pRename;
- if( pExpr->op==TK_COLUMN && p->pTab==pExpr->pTab ){
- renameTokenFind(pWalker->pParse, p, (void*)&pExpr->pTab);
+ if( pExpr->op==TK_COLUMN && p->pTab==pExpr->y.pTab ){
+ renameTokenFind(pWalker->pParse, p, (void*)&pExpr->y.pTab);
}
return WRC_Continue;
}
@@ -1439,7 +1443,7 @@ static void renameTableFunc(
}else{
/* Modify any FK definitions to point to the new table. */
#ifndef SQLITE_OMIT_FOREIGN_KEY
- if( db->flags & SQLITE_ForeignKeys ){
+ if( isLegacy==0 || (db->flags & SQLITE_ForeignKeys) ){
FKey *pFKey;
for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){
if( sqlite3_stricmp(pFKey->zTo, zOld)==0 ){
@@ -1593,9 +1597,9 @@ static void renameTableTest(
*/
void sqlite3AlterFunctions(void){
static FuncDef aAlterTableFuncs[] = {
- FUNCTION(sqlite_rename_column, 9, 0, 0, renameColumnFunc),
- FUNCTION(sqlite_rename_table, 7, 0, 0, renameTableFunc),
- FUNCTION(sqlite_rename_test, 5, 0, 0, renameTableTest),
+ INTERNAL_FUNCTION(sqlite_rename_column, 9, renameColumnFunc),
+ INTERNAL_FUNCTION(sqlite_rename_table, 7, renameTableFunc),
+ INTERNAL_FUNCTION(sqlite_rename_test, 5, renameTableTest),
};
sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs));
}
diff --git a/chromium/third_party/sqlite/src/src/attach.c b/chromium/third_party/sqlite/src/src/attach.c
index 19c75833071..fcb05046de2 100644
--- a/chromium/third_party/sqlite/src/src/attach.c
+++ b/chromium/third_party/sqlite/src/src/attach.c
@@ -100,7 +100,7 @@ static void attachFunc(
if( pNew->pBt ) sqlite3BtreeClose(pNew->pBt);
pNew->pBt = 0;
pNew->pSchema = 0;
- rc = sqlite3BtreeOpen(pVfs, "x", db, &pNew->pBt, 0, SQLITE_OPEN_MAIN_DB);
+ rc = sqlite3BtreeOpen(pVfs, "x\0", db, &pNew->pBt, 0, SQLITE_OPEN_MAIN_DB);
}else{
/* This is a real ATTACH
**
diff --git a/chromium/third_party/sqlite/src/src/auth.c b/chromium/third_party/sqlite/src/src/auth.c
index 5d4ad89911e..ccf4981d5f6 100644
--- a/chromium/third_party/sqlite/src/src/auth.c
+++ b/chromium/third_party/sqlite/src/src/auth.c
@@ -151,6 +151,7 @@ void sqlite3AuthRead(
int iCol; /* Index of column in table */
assert( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER );
+ assert( !IN_RENAME_OBJECT || db->xAuth==0 );
if( db->xAuth==0 ) return;
iDb = sqlite3SchemaToIndex(pParse->db, pSchema);
if( iDb<0 ){
@@ -207,6 +208,7 @@ int sqlite3AuthCheck(
/* Don't do any authorization checks if the database is initialising
** or if the parser is being invoked from within sqlite3_declare_vtab.
*/
+ assert( !IN_RENAME_OBJECT || db->xAuth==0 );
if( db->init.busy || IN_SPECIAL_PARSE ){
return SQLITE_OK;
}
diff --git a/chromium/third_party/sqlite/src/src/btree.c b/chromium/third_party/sqlite/src/src/btree.c
index 3fa8f88f146..62f4bd9db1d 100644
--- a/chromium/third_party/sqlite/src/src/btree.c
+++ b/chromium/third_party/sqlite/src/src/btree.c
@@ -992,6 +992,13 @@ static void ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent, int *pRC){
*pRC = rc;
return;
}
+ if( ((char*)sqlite3PagerGetExtra(pDbPage))[0]!=0 ){
+ /* The first byte of the extra data is the MemPage.isInit byte.
+ ** If that byte is set, it means this page is also being used
+ ** as a btree page. */
+ *pRC = SQLITE_CORRUPT_BKPT;
+ goto ptrmap_exit;
+ }
offset = PTRMAP_PTROFFSET(iPtrmap, key);
if( offset<0 ){
*pRC = SQLITE_CORRUPT_BKPT;
@@ -1357,7 +1364,12 @@ static void ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell, int *pRC){
assert( pCell!=0 );
pPage->xParseCell(pPage, pCell, &info);
if( info.nLocal<info.nPayload ){
- Pgno ovfl = get4byte(&pCell[info.nSize-4]);
+ Pgno ovfl;
+ if( SQLITE_WITHIN(pPage->aDataEnd, pCell, pCell+info.nLocal) ){
+ *pRC = SQLITE_CORRUPT_BKPT;
+ return;
+ }
+ ovfl = get4byte(&pCell[info.nSize-4]);
ptrmapPut(pPage->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno, pRC);
}
}
@@ -3152,7 +3164,7 @@ static int lockBtree(BtShared *pBt){
pageSize-usableSize);
return rc;
}
- if( (pBt->db->flags & SQLITE_WriteSchema)==0 && nPage>nPageFile ){
+ if( sqlite3WritableSchema(pBt->db)==0 && nPage>nPageFile ){
rc = SQLITE_CORRUPT_BKPT;
goto page1_init_failed;
}
@@ -3626,6 +3638,7 @@ static int relocatePage(
eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE );
assert( sqlite3_mutex_held(pBt->mutex) );
assert( pDbPage->pBt==pBt );
+ if( iDbPage<3 ) return SQLITE_CORRUPT_BKPT;
/* Move page iDbPage from its current location to page number iFreePage */
TRACE(("AUTOVACUUM: Moving %d to free page %d (ptr page %d type %d)\n",
@@ -4811,9 +4824,6 @@ static int accessPayload(
/* Need to read this page properly. It contains some of the
** range of data that is being read (eOp==0) or written (eOp!=0).
*/
-#ifdef SQLITE_DIRECT_OVERFLOW_READ
- sqlite3_file *fd; /* File from which to do direct overflow read */
-#endif
int a = amt;
if( a + offset > ovflSize ){
a = ovflSize - offset;
@@ -4824,7 +4834,7 @@ static int accessPayload(
**
** 1) this is a read operation, and
** 2) data is required from the start of this overflow page, and
- ** 3) there is no open write-transaction, and
+ ** 3) there are no dirty pages in the page-cache
** 4) the database is file-backed, and
** 5) the page is not in the WAL file
** 6) at least 4 bytes have already been read into the output buffer
@@ -4835,11 +4845,10 @@ static int accessPayload(
*/
if( eOp==0 /* (1) */
&& offset==0 /* (2) */
- && pBt->inTransaction==TRANS_READ /* (3) */
- && (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (4) */
- && 0==sqlite3PagerUseWal(pBt->pPager, nextPage) /* (5) */
+ && sqlite3PagerDirectReadOk(pBt->pPager, nextPage) /* (3,4,5) */
&& &pBuf[-4]>=pBufStart /* (6) */
){
+ sqlite3_file *fd = sqlite3PagerFile(pBt->pPager);
u8 aSave[4];
u8 *aWrite = &pBuf[-4];
assert( aWrite>=pBufStart ); /* due to (6) */
diff --git a/chromium/third_party/sqlite/src/src/build.c b/chromium/third_party/sqlite/src/src/build.c
index b1206e1127b..806c89f439b 100644
--- a/chromium/third_party/sqlite/src/src/build.c
+++ b/chromium/third_party/sqlite/src/src/build.c
@@ -356,17 +356,15 @@ Table *sqlite3LocateTable(
if( p==0 ){
const char *zMsg = flags & LOCATE_VIEW ? "no such view" : "no such table";
#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( sqlite3FindDbName(db, zDbase)<1 ){
- /* If zName is the not the name of a table in the schema created using
- ** CREATE, then check to see if it is the name of an virtual table that
- ** can be an eponymous virtual table. */
- Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName);
- if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
- pMod = sqlite3PragmaVtabRegister(db, zName);
- }
- if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){
- return pMod->pEpoTab;
- }
+ /* If zName is the not the name of a table in the schema created using
+ ** CREATE, then check to see if it is the name of an virtual table that
+ ** can be an eponymous virtual table. */
+ Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName);
+ if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
+ pMod = sqlite3PragmaVtabRegister(db, zName);
+ }
+ if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){
+ return pMod->pEpoTab;
}
#endif
if( (flags & LOCATE_NOERR)==0 ){
@@ -546,17 +544,22 @@ void sqlite3ResetOneSchema(sqlite3 *db, int iDb){
void sqlite3ResetAllSchemasOfConnection(sqlite3 *db){
int i;
sqlite3BtreeEnterAll(db);
- assert( db->nSchemaLock==0 );
for(i=0; i<db->nDb; i++){
Db *pDb = &db->aDb[i];
if( pDb->pSchema ){
- sqlite3SchemaClear(pDb->pSchema);
+ if( db->nSchemaLock==0 ){
+ sqlite3SchemaClear(pDb->pSchema);
+ }else{
+ DbSetProperty(db, i, DB_ResetWanted);
+ }
}
}
db->mDbFlags &= ~(DBFLAG_SchemaChange|DBFLAG_SchemaKnownOk);
sqlite3VtabUnlockList(db);
sqlite3BtreeLeaveAll(db);
- sqlite3CollapseDatabaseArray(db);
+ if( db->nSchemaLock==0 ){
+ sqlite3CollapseDatabaseArray(db);
+ }
}
/*
@@ -633,6 +636,12 @@ static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){
/* Delete the Table structure itself.
*/
+#ifdef SQLITE_ENABLE_NORMALIZE
+ if( pTable->pColHash ){
+ sqlite3HashClear(pTable->pColHash);
+ sqlite3_free(pTable->pColHash);
+ }
+#endif
sqlite3DeleteColumnNames(db, pTable);
sqlite3DbFree(db, pTable->zName);
sqlite3DbFree(db, pTable->zColAff);
@@ -792,6 +801,20 @@ int sqlite3TwoPartName(
}
/*
+** True if PRAGMA writable_schema is ON
+*/
+int sqlite3WritableSchema(sqlite3 *db){
+ testcase( (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))==0 );
+ testcase( (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))==
+ SQLITE_WriteSchema );
+ testcase( (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))==
+ SQLITE_Defensive );
+ testcase( (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))==
+ (SQLITE_WriteSchema|SQLITE_Defensive) );
+ return (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))==SQLITE_WriteSchema;
+}
+
+/*
** This routine is used to check if the UTF-8 string zName is a legal
** unqualified name for a new schema object (table, index, view or
** trigger). All names are legal except those that begin with the string
@@ -800,7 +823,7 @@ int sqlite3TwoPartName(
*/
int sqlite3CheckObjectName(Parse *pParse, const char *zName){
if( !pParse->db->init.busy && pParse->nested==0
- && (pParse->db->flags & SQLITE_WriteSchema)==0
+ && sqlite3WritableSchema(pParse->db)==0
&& 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", zName);
return SQLITE_ERROR;
@@ -1876,6 +1899,36 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
recomputeColumnsNotIndexed(pPk);
}
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/*
+** Return true if zName is a shadow table name in the current database
+** connection.
+**
+** zName is temporarily modified while this routine is running, but is
+** restored to its original value prior to this routine returning.
+*/
+static int isShadowTableName(sqlite3 *db, char *zName){
+ char *zTail; /* Pointer to the last "_" in zName */
+ Table *pTab; /* Table that zName is a shadow of */
+ Module *pMod; /* Module for the virtual table */
+
+ zTail = strrchr(zName, '_');
+ if( zTail==0 ) return 0;
+ *zTail = 0;
+ pTab = sqlite3FindTable(db, zName, 0);
+ *zTail = '_';
+ if( pTab==0 ) return 0;
+ if( !IsVirtual(pTab) ) return 0;
+ pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->azModuleArg[0]);
+ if( pMod==0 ) return 0;
+ if( pMod->pModule->iVersion<3 ) return 0;
+ if( pMod->pModule->xShadowName==0 ) return 0;
+ return pMod->pModule->xShadowName(zTail+1);
+}
+#else
+# define isShadowTableName(x,y) 0
+#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
+
/*
** This routine is called to report the final ")" that terminates
** a CREATE TABLE statement.
@@ -1915,6 +1968,10 @@ void sqlite3EndTable(
p = pParse->pNewTable;
if( p==0 ) return;
+ if( pSelect==0 && isShadowTableName(db, p->zName) ){
+ p->tabFlags |= TF_Shadow;
+ }
+
/* If the db->init.busy is 1 it means we are reading the SQL off the
** "sqlite_master" or "sqlite_temp_master" table on the disk.
** So do not write to the disk again. Extract the root page number
@@ -2422,7 +2479,7 @@ void sqlite3RootPageMoved(sqlite3 *db, int iDb, int iFrom, int iTo){
static void destroyRootPage(Parse *pParse, int iTable, int iDb){
Vdbe *v = sqlite3GetVdbe(pParse);
int r1 = sqlite3GetTempReg(pParse);
- assert( iTable>1 );
+ if( iTable<2 ) sqlite3ErrorMsg(pParse, "corrupt schema");
sqlite3VdbeAddOp3(v, OP_Destroy, iTable, r1, iDb);
sqlite3MayAbort(pParse);
#ifndef SQLITE_OMIT_AUTOVACUUM
diff --git a/chromium/third_party/sqlite/src/src/callback.c b/chromium/third_party/sqlite/src/src/callback.c
index 7c42d93bed7..3d55b286736 100644
--- a/chromium/third_party/sqlite/src/src/callback.c
+++ b/chromium/third_party/sqlite/src/src/callback.c
@@ -295,6 +295,21 @@ static FuncDef *functionSearch(
}
return 0;
}
+#ifdef SQLITE_ENABLE_NORMALIZE
+FuncDef *sqlite3FunctionSearchN(
+ int h, /* Hash of the name */
+ const char *zFunc, /* Name of function */
+ int nFunc /* Length of the name */
+){
+ FuncDef *p;
+ for(p=sqlite3BuiltinFunctions.a[h]; p; p=p->u.pHash){
+ if( sqlite3StrNICmp(p->zName, zFunc, nFunc)==0 ){
+ return p;
+ }
+ }
+ return 0;
+}
+#endif /* SQLITE_ENABLE_NORMALIZE */
/*
** Insert a new FuncDef into a FuncDefHash hash table.
@@ -308,7 +323,7 @@ void sqlite3InsertBuiltinFuncs(
FuncDef *pOther;
const char *zName = aDef[i].zName;
int nName = sqlite3Strlen30(zName);
- int h = (zName[0] + nName) % SQLITE_FUNC_HASH_SZ;
+ int h = SQLITE_FUNC_HASH(zName[0], nName);
assert( zName[0]>='a' && zName[0]<='z' );
pOther = functionSearch(h, zName);
if( pOther ){
@@ -387,7 +402,7 @@ FuncDef *sqlite3FindFunction(
*/
if( !createFlag && (pBest==0 || (db->mDbFlags & DBFLAG_PreferBuiltin)!=0) ){
bestScore = 0;
- h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % SQLITE_FUNC_HASH_SZ;
+ h = SQLITE_FUNC_HASH(sqlite3UpperToLower[(u8)zName[0]], nName);
p = functionSearch(h, zName);
while( p ){
int score = matchQuality(p, nArg, enc);
diff --git a/chromium/third_party/sqlite/src/src/ctime.c b/chromium/third_party/sqlite/src/src/ctime.c
index aae082cadca..d783de6d0c1 100644
--- a/chromium/third_party/sqlite/src/src/ctime.c
+++ b/chromium/third_party/sqlite/src/src/ctime.c
@@ -235,6 +235,9 @@ static const char * const sqlite3azCompileOpt[] = {
#if SQLITE_ENABLE_FTS5
"ENABLE_FTS5",
#endif
+#if SQLITE_ENABLE_GEOPOLY
+ "ENABLE_GEOPOLY",
+#endif
#if SQLITE_ENABLE_HIDDEN_COLUMNS
"ENABLE_HIDDEN_COLUMNS",
#endif
@@ -265,6 +268,9 @@ static const char * const sqlite3azCompileOpt[] = {
#if SQLITE_ENABLE_MULTIPLEX
"ENABLE_MULTIPLEX",
#endif
+#if SQLITE_ENABLE_NORMALIZE
+ "ENABLE_NORMALIZE",
+#endif
#if SQLITE_ENABLE_NULL_TRIM
"ENABLE_NULL_TRIM",
#endif
diff --git a/chromium/third_party/sqlite/src/src/dbpage.c b/chromium/third_party/sqlite/src/src/dbpage.c
index 66d0b97c94f..6c86b2b4d3d 100644
--- a/chromium/third_party/sqlite/src/src/dbpage.c
+++ b/chromium/third_party/sqlite/src/src/dbpage.c
@@ -119,9 +119,8 @@ static int dbpageBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
if( p->iColumn!=DBPAGE_COLUMN_SCHEMA ) continue;
if( p->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
if( !p->usable ){
- /* No solution. Use the default SQLITE_BIG_DBL cost */
- pIdxInfo->estimatedRows = 0x7fffffff;
- return SQLITE_OK;
+ /* No solution. */
+ return SQLITE_CONSTRAINT;
}
iPlan = 2;
pIdxInfo->aConstraintUsage[i].argvIndex = 1;
@@ -313,6 +312,10 @@ static int dbpageUpdate(
Pager *pPager;
int szPage;
+ if( pTab->db->flags & SQLITE_Defensive ){
+ zErr = "read-only";
+ goto update_fail;
+ }
if( argc==1 ){
zErr = "cannot delete";
goto update_fail;
@@ -403,6 +406,7 @@ int sqlite3DbpageRegister(sqlite3 *db){
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
+ 0 /* xShadowName */
};
return sqlite3_create_module(db, "sqlite_dbpage", &dbpage_module, 0);
}
diff --git a/chromium/third_party/sqlite/src/src/dbstat.c b/chromium/third_party/sqlite/src/src/dbstat.c
index 7e7450e3648..73ab7d926e2 100644
--- a/chromium/third_party/sqlite/src/src/dbstat.c
+++ b/chromium/third_party/sqlite/src/src/dbstat.c
@@ -194,17 +194,15 @@ static int statDisconnect(sqlite3_vtab *pVtab){
static int statBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
int i;
- pIdxInfo->estimatedCost = 1.0e6; /* Initial cost estimate */
-
/* Look for a valid schema=? constraint. If found, change the idxNum to
** 1 and request the value of that constraint be sent to xFilter. And
** lower the cost estimate to encourage the constrained version to be
** used.
*/
for(i=0; i<pIdxInfo->nConstraint; i++){
- if( pIdxInfo->aConstraint[i].usable==0 ) continue;
- if( pIdxInfo->aConstraint[i].op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
if( pIdxInfo->aConstraint[i].iColumn!=10 ) continue;
+ if( pIdxInfo->aConstraint[i].usable==0 ) return SQLITE_CONSTRAINT;
+ if( pIdxInfo->aConstraint[i].op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
pIdxInfo->idxNum = 1;
pIdxInfo->estimatedCost = 1.0;
pIdxInfo->aConstraintUsage[i].argvIndex = 1;
@@ -254,7 +252,7 @@ static int statOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
return SQLITE_OK;
}
-static void statClearPage(StatPage *p){
+static void statClearCells(StatPage *p){
int i;
if( p->aCell ){
for(i=0; i<p->nCell; i++){
@@ -262,6 +260,12 @@ static void statClearPage(StatPage *p){
}
sqlite3_free(p->aCell);
}
+ p->nCell = 0;
+ p->aCell = 0;
+}
+
+static void statClearPage(StatPage *p){
+ statClearCells(p);
sqlite3PagerUnref(p->pPg);
sqlite3_free(p->zPath);
memset(p, 0, sizeof(StatPage));
@@ -324,22 +328,33 @@ static int statDecodePage(Btree *pBt, StatPage *p){
u8 *aHdr = &aData[p->iPgno==1 ? 100 : 0];
p->flags = aHdr[0];
+ if( p->flags==0x0A || p->flags==0x0D ){
+ isLeaf = 1;
+ nHdr = 8;
+ }else if( p->flags==0x05 || p->flags==0x02 ){
+ isLeaf = 0;
+ nHdr = 12;
+ }else{
+ goto statPageIsCorrupt;
+ }
+ if( p->iPgno==1 ) nHdr += 100;
p->nCell = get2byte(&aHdr[3]);
p->nMxPayload = 0;
-
- isLeaf = (p->flags==0x0A || p->flags==0x0D);
- nHdr = 12 - isLeaf*4 + (p->iPgno==1)*100;
+ szPage = sqlite3BtreeGetPageSize(pBt);
nUnused = get2byte(&aHdr[5]) - nHdr - 2*p->nCell;
nUnused += (int)aHdr[7];
iOff = get2byte(&aHdr[1]);
while( iOff ){
+ int iNext;
+ if( iOff>=szPage ) goto statPageIsCorrupt;
nUnused += get2byte(&aData[iOff+2]);
- iOff = get2byte(&aData[iOff]);
+ iNext = get2byte(&aData[iOff]);
+ if( iNext<iOff+4 && iNext>0 ) goto statPageIsCorrupt;
+ iOff = iNext;
}
p->nUnused = nUnused;
p->iRightChildPg = isLeaf ? 0 : sqlite3Get4byte(&aHdr[8]);
- szPage = sqlite3BtreeGetPageSize(pBt);
if( p->nCell ){
int i; /* Used to iterate through cells */
@@ -356,6 +371,7 @@ static int statDecodePage(Btree *pBt, StatPage *p){
StatCell *pCell = &p->aCell[i];
iOff = get2byte(&aData[nHdr+i*2]);
+ if( iOff<nHdr || iOff>=szPage ) goto statPageIsCorrupt;
if( !isLeaf ){
pCell->iChildPg = sqlite3Get4byte(&aData[iOff]);
iOff += 4;
@@ -372,13 +388,14 @@ static int statDecodePage(Btree *pBt, StatPage *p){
}
if( nPayload>(u32)p->nMxPayload ) p->nMxPayload = nPayload;
getLocalPayload(nUsable, p->flags, nPayload, &nLocal);
+ if( nLocal<0 ) goto statPageIsCorrupt;
pCell->nLocal = nLocal;
- assert( nLocal>=0 );
assert( nPayload>=(u32)nLocal );
assert( nLocal<=(nUsable-35) );
if( nPayload>(u32)nLocal ){
int j;
int nOvfl = ((nPayload - nLocal) + nUsable-4 - 1) / (nUsable - 4);
+ if( iOff+nLocal>nUsable ) goto statPageIsCorrupt;
pCell->nLastOvfl = (nPayload-nLocal) - (nOvfl-1) * (nUsable-4);
pCell->nOvfl = nOvfl;
pCell->aOvfl = sqlite3_malloc64(sizeof(u32)*nOvfl);
@@ -402,6 +419,11 @@ static int statDecodePage(Btree *pBt, StatPage *p){
}
return SQLITE_OK;
+
+statPageIsCorrupt:
+ p->flags = 0;
+ statClearCells(p);
+ return SQLITE_OK;
}
/*
@@ -697,6 +719,7 @@ int sqlite3DbstatRegister(sqlite3 *db){
0, /* xSavepoint */
0, /* xRelease */
0, /* xRollbackTo */
+ 0 /* xShadowName */
};
return sqlite3_create_module(db, "dbstat", &dbstat_module, 0);
}
diff --git a/chromium/third_party/sqlite/src/src/delete.c b/chromium/third_party/sqlite/src/src/delete.c
index 988a7940c69..69135c226e9 100644
--- a/chromium/third_party/sqlite/src/src/delete.c
+++ b/chromium/third_party/sqlite/src/src/delete.c
@@ -44,32 +44,49 @@ Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
return pTab;
}
+/* Return true if table pTab is read-only.
+**
+** A table is read-only if any of the following are true:
+**
+** 1) It is a virtual table and no implementation of the xUpdate method
+** has been provided
+**
+** 2) It is a system table (i.e. sqlite_master), this call is not
+** part of a nested parse and writable_schema pragma has not
+** been specified
+**
+** 3) The table is a shadow table, the database connection is in
+** defensive mode, and the current sqlite3_prepare()
+** is for a top-level SQL statement.
+*/
+static int tabIsReadOnly(Parse *pParse, Table *pTab){
+ sqlite3 *db;
+ if( IsVirtual(pTab) ){
+ return sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0;
+ }
+ if( (pTab->tabFlags & (TF_Readonly|TF_Shadow))==0 ) return 0;
+ db = pParse->db;
+ if( (pTab->tabFlags & TF_Readonly)!=0 ){
+ return sqlite3WritableSchema(db)==0 && pParse->nested==0;
+ }
+ assert( pTab->tabFlags & TF_Shadow );
+ return (db->flags & SQLITE_Defensive)!=0
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ && db->pVtabCtx==0
+#endif
+ && db->nVdbeExec==0;
+}
+
/*
** Check to make sure the given table is writable. If it is not
** writable, generate an error message and return 1. If it is
** writable return 0;
*/
int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
- /* A table is not writable under the following circumstances:
- **
- ** 1) It is a virtual table and no implementation of the xUpdate method
- ** has been provided, or
- ** 2) It is a system table (i.e. sqlite_master), this call is not
- ** part of a nested parse and writable_schema pragma has not
- ** been specified.
- **
- ** In either case leave an error message in pParse and return non-zero.
- */
- if( ( IsVirtual(pTab)
- && sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0 )
- || ( (pTab->tabFlags & TF_Readonly)!=0
- && (pParse->db->flags & SQLITE_WriteSchema)==0
- && pParse->nested==0 )
- ){
+ if( tabIsReadOnly(pParse, pTab) ){
sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName);
return 1;
}
-
#ifndef SQLITE_OMIT_VIEW
if( !viewOk && pTab->pSelect ){
sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName);
diff --git a/chromium/third_party/sqlite/src/src/expr.c b/chromium/third_party/sqlite/src/src/expr.c
index 657ff7ababa..c61528288ba 100644
--- a/chromium/third_party/sqlite/src/src/expr.c
+++ b/chromium/third_party/sqlite/src/src/expr.c
@@ -58,8 +58,8 @@ char sqlite3ExprAffinity(Expr *pExpr){
return sqlite3AffinityType(pExpr->u.zToken, 0);
}
#endif
- if( (op==TK_AGG_COLUMN || op==TK_COLUMN) && pExpr->pTab ){
- return sqlite3TableColumnAffinity(pExpr->pTab, pExpr->iColumn);
+ if( (op==TK_AGG_COLUMN || op==TK_COLUMN) && pExpr->y.pTab ){
+ return sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
}
if( op==TK_SELECT_COLUMN ){
assert( pExpr->pLeft->flags&EP_xIsSelect );
@@ -141,15 +141,15 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
while( p ){
int op = p->op;
if( p->flags & EP_Generic ) break;
- if( (op==TK_AGG_COLUMN || op==TK_COLUMN
- || op==TK_REGISTER || op==TK_TRIGGER)
- && p->pTab!=0
+ if( op==TK_REGISTER ) op = p->op2;
+ if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_TRIGGER)
+ && p->y.pTab!=0
){
- /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally
+ /* op==TK_REGISTER && p->y.pTab!=0 happens when pExpr was originally
** a TK_COLUMN but was previously evaluated and cached in a register */
int j = p->iColumn;
if( j>=0 ){
- const char *zColl = p->pTab->aCol[j].zColl;
+ const char *zColl = p->y.pTab->aCol[j].zColl;
pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
}
break;
@@ -158,7 +158,7 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
p = p->pLeft;
continue;
}
- if( op==TK_COLLATE || (op==TK_REGISTER && p->op2==TK_COLLATE) ){
+ if( op==TK_COLLATE ){
pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
break;
}
@@ -1052,6 +1052,10 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
assert( p!=0 );
/* Sanity check: Assert that the IntValue is non-negative if it exists */
assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 );
+
+ assert( !ExprHasProperty(p, EP_WinFunc) || p->y.pWin!=0 || db->mallocFailed );
+ assert( p->op!=TK_FUNCTION || ExprHasProperty(p, EP_TokenOnly|EP_Reduced)
+ || p->y.pWin==0 || ExprHasProperty(p, EP_WinFunc) );
#ifdef SQLITE_DEBUG
if( ExprHasProperty(p, EP_Leaf) && !ExprHasProperty(p, EP_TokenOnly) ){
assert( p->pLeft==0 );
@@ -1070,8 +1074,9 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
}else{
sqlite3ExprListDelete(db, p->x.pList);
}
- if( !ExprHasProperty(p, EP_Reduced) ){
- sqlite3WindowDelete(db, p->pWin);
+ if( ExprHasProperty(p, EP_WinFunc) ){
+ assert( p->op==TK_FUNCTION );
+ sqlite3WindowDelete(db, p->y.pWin);
}
}
if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken);
@@ -1135,7 +1140,7 @@ static int dupedExprStructSize(Expr *p, int flags){
assert( (0xfff & (EP_Reduced|EP_TokenOnly))==0 );
if( 0==flags || p->op==TK_SELECT_COLUMN
#ifndef SQLITE_OMIT_WINDOWFUNC
- || p->pWin
+ || ExprHasProperty(p, EP_WinFunc)
#endif
){
nSize = EXPR_FULLSIZE;
@@ -1162,7 +1167,7 @@ static int dupedExprStructSize(Expr *p, int flags){
static int dupedExprNodeSize(Expr *p, int flags){
int nByte = dupedExprStructSize(p, flags) & 0xfff;
if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){
- nByte += sqlite3Strlen30(p->u.zToken)+1;
+ nByte += sqlite3Strlen30NN(p->u.zToken)+1;
}
return ROUND8(nByte);
}
@@ -1265,22 +1270,24 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
}
/* Fill in pNew->pLeft and pNew->pRight. */
- zAlloc += dupedExprNodeSize(p, dupFlags);
- if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly) ){
+ if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly|EP_WinFunc) ){
+ zAlloc += dupedExprNodeSize(p, dupFlags);
if( !ExprHasProperty(pNew, EP_TokenOnly|EP_Leaf) ){
pNew->pLeft = p->pLeft ?
exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc) : 0;
pNew->pRight = p->pRight ?
exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc) : 0;
}
- }else{
#ifndef SQLITE_OMIT_WINDOWFUNC
- if( ExprHasProperty(p, EP_Reduced|EP_TokenOnly) ){
- pNew->pWin = 0;
- }else{
- pNew->pWin = sqlite3WindowDup(db, pNew, p->pWin);
+ if( ExprHasProperty(p, EP_WinFunc) ){
+ pNew->y.pWin = sqlite3WindowDup(db, pNew, p->y.pWin);
+ assert( ExprHasProperty(pNew, EP_WinFunc) );
}
#endif /* SQLITE_OMIT_WINDOWFUNC */
+ if( pzBuffer ){
+ *pzBuffer = zAlloc;
+ }
+ }else{
if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){
if( pNew->op==TK_SELECT_COLUMN ){
pNew->pLeft = p->pLeft;
@@ -1292,9 +1299,6 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
pNew->pRight = sqlite3ExprDup(db, p->pRight, 0);
}
}
- if( pzBuffer ){
- *pzBuffer = zAlloc;
- }
}
return pNew;
}
@@ -2089,8 +2093,8 @@ int sqlite3ExprCanBeNull(const Expr *p){
return 0;
case TK_COLUMN:
return ExprHasProperty(p, EP_CanBeNull) ||
- p->pTab==0 || /* Reference to column of index on expression */
- (p->iColumn>=0 && p->pTab->aCol[p->iColumn].notNull==0);
+ p->y.pTab==0 || /* Reference to column of index on expression */
+ (p->iColumn>=0 && p->y.pTab->aCol[p->iColumn].notNull==0);
default:
return 1;
}
@@ -2145,6 +2149,14 @@ int sqlite3IsRowid(const char *z){
if( sqlite3StrICmp(z, "OID")==0 ) return 1;
return 0;
}
+#ifdef SQLITE_ENABLE_NORMALIZE
+int sqlite3IsRowidN(const char *z, int n){
+ if( sqlite3StrNICmp(z, "_ROWID_", n)==0 ) return 1;
+ if( sqlite3StrNICmp(z, "ROWID", n)==0 ) return 1;
+ if( sqlite3StrNICmp(z, "OID", n)==0 ) return 1;
+ return 0;
+}
+#endif
/*
** pX is the RHS of an IN operator. If pX is a SELECT statement
@@ -3378,7 +3390,7 @@ expr_code_doover:
** constant.
*/
int iReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft,target);
- int aff = sqlite3TableColumnAffinity(pExpr->pTab, pExpr->iColumn);
+ int aff = sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
if( aff!=SQLITE_AFF_BLOB ){
static const char zAff[] = "B\000C\000D\000E";
assert( SQLITE_AFF_BLOB=='A' );
@@ -3402,7 +3414,7 @@ expr_code_doover:
iTab = pParse->iSelfTab - 1;
}
}
- return sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,
+ return sqlite3ExprCodeGetColumn(pParse, pExpr->y.pTab,
pExpr->iColumn, iTab, target,
pExpr->op2);
}
@@ -3616,8 +3628,8 @@ expr_code_doover:
CollSeq *pColl = 0; /* A collating sequence */
#ifndef SQLITE_OMIT_WINDOWFUNC
- if( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) && pExpr->pWin ){
- return pExpr->pWin->regResult;
+ if( ExprHasProperty(pExpr, EP_WinFunc) ){
+ return pExpr->y.pWin->regResult;
}
#endif
@@ -3860,7 +3872,7 @@ expr_code_doover:
** p1==1 -> old.a p1==4 -> new.a
** p1==2 -> old.b p1==5 -> new.b
*/
- Table *pTab = pExpr->pTab;
+ Table *pTab = pExpr->y.pTab;
int p1 = pExpr->iTable * (pTab->nCol+1) + 1 + pExpr->iColumn;
assert( pExpr->iTable==0 || pExpr->iTable==1 );
@@ -3871,7 +3883,7 @@ expr_code_doover:
sqlite3VdbeAddOp2(v, OP_Param, p1, target);
VdbeComment((v, "r[%d]=%s.%s", target,
(pExpr->iTable ? "new" : "old"),
- (pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName)
+ (pExpr->iColumn<0 ? "rowid" : pExpr->y.pTab->aCol[pExpr->iColumn].zName)
));
#ifndef SQLITE_OMIT_FLOATING_POINT
@@ -4710,7 +4722,7 @@ int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){
}
return 2;
}
- if( pA->op!=pB->op ){
+ if( pA->op!=pB->op || pA->op==TK_RAISE ){
if( pA->op==TK_COLLATE && sqlite3ExprCompare(pParse, pA->pLeft,pB,iTab)<2 ){
return 1;
}
@@ -4722,6 +4734,20 @@ int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){
if( pA->op!=TK_COLUMN && pA->op!=TK_AGG_COLUMN && pA->u.zToken ){
if( pA->op==TK_FUNCTION ){
if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2;
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ /* Justification for the assert():
+ ** window functions have p->op==TK_FUNCTION but aggregate functions
+ ** have p->op==TK_AGG_FUNCTION. So any comparison between an aggregate
+ ** function and a window function should have failed before reaching
+ ** this point. And, it is not possible to have a window function and
+ ** a scalar function with the same name and number of arguments. So
+ ** if we reach this point, either A and B both window functions or
+ ** neither are a window functions. */
+ assert( ExprHasProperty(pA,EP_WinFunc)==ExprHasProperty(pB,EP_WinFunc) );
+ if( ExprHasProperty(pA,EP_WinFunc) ){
+ if( sqlite3WindowCompare(pParse,pA->y.pWin,pB->y.pWin)!=0 ) return 2;
+ }
+#endif
}else if( pA->op==TK_COLLATE ){
if( sqlite3_stricmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2;
}else if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){
@@ -4729,33 +4755,20 @@ int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){
}
}
if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
- if( ALWAYS((combinedFlags & EP_TokenOnly)==0) ){
+ if( (combinedFlags & EP_TokenOnly)==0 ){
if( combinedFlags & EP_xIsSelect ) return 2;
if( (combinedFlags & EP_FixedCol)==0
&& sqlite3ExprCompare(pParse, pA->pLeft, pB->pLeft, iTab) ) return 2;
if( sqlite3ExprCompare(pParse, pA->pRight, pB->pRight, iTab) ) return 2;
if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2;
- assert( (combinedFlags & EP_Reduced)==0 );
- if( pA->op!=TK_STRING && pA->op!=TK_TRUEFALSE ){
+ if( pA->op!=TK_STRING
+ && pA->op!=TK_TRUEFALSE
+ && (combinedFlags & EP_Reduced)==0
+ ){
if( pA->iColumn!=pB->iColumn ) return 2;
if( pA->iTable!=pB->iTable
&& (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2;
}
-#ifndef SQLITE_OMIT_WINDOWFUNC
- /* Justification for the assert():
- ** window functions have p->op==TK_FUNCTION but aggregate functions
- ** have p->op==TK_AGG_FUNCTION. So any comparison between an aggregate
- ** function and a window function should have failed before reaching
- ** this point. And, it is not possible to have a window function and
- ** a scalar function with the same name and number of arguments. So
- ** if we reach this point, either A and B both window functions or
- ** neither are a window functions. */
- assert( (pA->pWin==0)==(pB->pWin==0) );
-
- if( pA->pWin!=0 ){
- if( sqlite3WindowCompare(pParse,pA->pWin,pB->pWin)!=0 ) return 2;
- }
-#endif
}
return 0;
}
@@ -4896,8 +4909,8 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
testcase( pExpr->op==TK_LE );
testcase( pExpr->op==TK_GT );
testcase( pExpr->op==TK_GE );
- if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->pTab))
- || (pExpr->pRight->op==TK_COLUMN && IsVirtual(pExpr->pRight->pTab))
+ if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->y.pTab))
+ || (pExpr->pRight->op==TK_COLUMN && IsVirtual(pExpr->pRight->y.pTab))
){
return WRC_Prune;
}
@@ -5128,7 +5141,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
&& (k = addAggInfoColumn(pParse->db, pAggInfo))>=0
){
pCol = &pAggInfo->aCol[k];
- pCol->pTab = pExpr->pTab;
+ pCol->pTab = pExpr->y.pTab;
pCol->iTable = pExpr->iTable;
pCol->iColumn = pExpr->iColumn;
pCol->iMem = ++pParse->nMem;
diff --git a/chromium/third_party/sqlite/src/src/fkey.c b/chromium/third_party/sqlite/src/src/fkey.c
index 4dafd9e88fd..b9aad0c9658 100644
--- a/chromium/third_party/sqlite/src/src/fkey.c
+++ b/chromium/third_party/sqlite/src/src/fkey.c
@@ -502,7 +502,7 @@ static Expr *exprTableColumn(
){
Expr *pExpr = sqlite3Expr(db, TK_COLUMN, 0);
if( pExpr ){
- pExpr->pTab = pTab;
+ pExpr->y.pTab = pTab;
pExpr->iTable = iCursor;
pExpr->iColumn = iCol;
}
@@ -602,8 +602,11 @@ static void fkScanChildren(
** NOT( $current_a==a AND $current_b==b AND ... )
**
** The first form is used for rowid tables. The second form is used
- ** for WITHOUT ROWID tables. In the second form, the primary key is
- ** (a,b,...)
+ ** for WITHOUT ROWID tables. In the second form, the *parent* key is
+ ** (a,b,...). Either the parent or primary key could be used to
+ ** uniquely identify the current row, but the parent key is more convenient
+ ** as the required values have already been loaded into registers
+ ** by the caller.
*/
if( pTab==pFKey->pFrom && nIncr>0 ){
Expr *pNe; /* Expression (pLeft != pRight) */
@@ -617,12 +620,12 @@ static void fkScanChildren(
Expr *pEq, *pAll = 0;
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
assert( pIdx!=0 );
- for(i=0; i<pPk->nKeyCol; i++){
+ for(i=0; i<pIdx->nKeyCol; i++){
i16 iCol = pIdx->aiColumn[i];
assert( iCol>=0 );
pLeft = exprTableRegister(pParse, pTab, regData, iCol);
- pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, iCol);
- pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight);
+ pRight = sqlite3Expr(db, TK_ID, pTab->aCol[iCol].zName);
+ pEq = sqlite3PExpr(pParse, TK_IS, pLeft, pRight);
pAll = sqlite3ExprAnd(db, pAll, pEq);
}
pNe = sqlite3PExpr(pParse, TK_NOT, pAll, 0);
diff --git a/chromium/third_party/sqlite/src/src/global.c b/chromium/third_party/sqlite/src/src/global.c
index 626487a019b..8011df7e564 100644
--- a/chromium/third_party/sqlite/src/src/global.c
+++ b/chromium/third_party/sqlite/src/src/global.c
@@ -240,6 +240,7 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
0, /* xTestCallback */
#endif
0, /* bLocaltimeFault */
+ 0, /* bInternalFunctions */
0x7ffffffe, /* iOnceResetThreshold */
SQLITE_DEFAULT_SORTERREF_SIZE /* szSorterRef */
};
diff --git a/chromium/third_party/sqlite/src/src/hash.c b/chromium/third_party/sqlite/src/src/hash.c
index 1f0ef154f35..04f67f67d27 100644
--- a/chromium/third_party/sqlite/src/src/hash.c
+++ b/chromium/third_party/sqlite/src/src/hash.c
@@ -64,6 +64,20 @@ static unsigned int strHash(const char *z){
}
return h;
}
+#ifdef SQLITE_ENABLE_NORMALIZE
+static unsigned int strHashN(const char *z, int n){
+ unsigned int h = 0;
+ int i;
+ for(i=0; i<n; i++){
+ /* Knuth multiplicative hashing. (Sorting & Searching, p. 510).
+ ** 0x9e3779b1 is 2654435761 which is the closest prime number to
+ ** (2**32)*golden_ratio, where golden_ratio = (sqrt(5) - 1)/2. */
+ h += sqlite3UpperToLower[z[i]];
+ h *= 0x9e3779b1;
+ }
+ return h;
+}
+#endif /* SQLITE_ENABLE_NORMALIZE */
/* Link pNew element into the hash table pH. If pEntry!=0 then also
@@ -175,6 +189,40 @@ static HashElem *findElementWithHash(
}
return &nullElement;
}
+#ifdef SQLITE_ENABLE_NORMALIZE
+static HashElem *findElementWithHashN(
+ const Hash *pH, /* The pH to be searched */
+ const char *pKey, /* The key we are searching for */
+ int nKey, /* Number of key bytes to use */
+ unsigned int *pHash /* Write the hash value here */
+){
+ HashElem *elem; /* Used to loop thru the element list */
+ int count; /* Number of elements left to test */
+ unsigned int h; /* The computed hash */
+ static HashElem nullElement = { 0, 0, 0, 0 };
+
+ if( pH->ht ){ /*OPTIMIZATION-IF-TRUE*/
+ struct _ht *pEntry;
+ h = strHashN(pKey, nKey) % pH->htsize;
+ pEntry = &pH->ht[h];
+ elem = pEntry->chain;
+ count = pEntry->count;
+ }else{
+ h = 0;
+ elem = pH->first;
+ count = pH->count;
+ }
+ if( pHash ) *pHash = h;
+ while( count-- ){
+ assert( elem!=0 );
+ if( sqlite3StrNICmp(elem->pKey,pKey,nKey)==0 ){
+ return elem;
+ }
+ elem = elem->next;
+ }
+ return &nullElement;
+}
+#endif /* SQLITE_ENABLE_NORMALIZE */
/* Remove a single entry from the hash table given a pointer to that
** element and a hash on the element's key.
@@ -219,6 +267,14 @@ void *sqlite3HashFind(const Hash *pH, const char *pKey){
assert( pKey!=0 );
return findElementWithHash(pH, pKey, 0)->data;
}
+#ifdef SQLITE_ENABLE_NORMALIZE
+void *sqlite3HashFindN(const Hash *pH, const char *pKey, int nKey){
+ assert( pH!=0 );
+ assert( pKey!=0 );
+ assert( nKey>=0 );
+ return findElementWithHashN(pH, pKey, nKey, 0)->data;
+}
+#endif /* SQLITE_ENABLE_NORMALIZE */
/* Insert an element into the hash table pH. The key is pKey
** and the data is "data".
diff --git a/chromium/third_party/sqlite/src/src/insert.c b/chromium/third_party/sqlite/src/src/insert.c
index 6d1121eaa19..cd2eec12864 100644
--- a/chromium/third_party/sqlite/src/src/insert.c
+++ b/chromium/third_party/sqlite/src/src/insert.c
@@ -146,7 +146,8 @@ void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){
}while( i>=0 && zColAff[i]==SQLITE_AFF_BLOB );
pTab->zColAff = zColAff;
}
- i = sqlite3Strlen30(zColAff);
+ assert( zColAff!=0 );
+ i = sqlite3Strlen30NN(zColAff);
if( i ){
if( iReg ){
sqlite3VdbeAddOp4(v, OP_Affinity, iReg, i, 0, zColAff, i);
@@ -1126,14 +1127,15 @@ insert_cleanup:
#endif
/*
-** Meanings of bits in of pWalker->eCode for checkConstraintUnchanged()
+** Meanings of bits in of pWalker->eCode for
+** sqlite3ExprReferencesUpdatedColumn()
*/
#define CKCNSTRNT_COLUMN 0x01 /* CHECK constraint uses a changing column */
#define CKCNSTRNT_ROWID 0x02 /* CHECK constraint references the ROWID */
-/* This is the Walker callback from checkConstraintUnchanged(). Set
-** bit 0x01 of pWalker->eCode if
-** pWalker->eCode to 0 if this expression node references any of the
+/* This is the Walker callback from sqlite3ExprReferencesUpdatedColumn().
+* Set bit 0x01 of pWalker->eCode if pWalker->eCode to 0 and if this
+** expression node references any of the
** columns that are being modifed by an UPDATE statement.
*/
static int checkConstraintExprNode(Walker *pWalker, Expr *pExpr){
@@ -1155,12 +1157,21 @@ static int checkConstraintExprNode(Walker *pWalker, Expr *pExpr){
** only columns that are modified by the UPDATE are those for which
** aiChng[i]>=0, and also the ROWID is modified if chngRowid is true.
**
-** Return true if CHECK constraint pExpr does not use any of the
+** Return true if CHECK constraint pExpr uses any of the
** changing columns (or the rowid if it is changing). In other words,
-** return true if this CHECK constraint can be skipped when validating
+** return true if this CHECK constraint must be validated for
** the new row in the UPDATE statement.
+**
+** 2018-09-15: pExpr might also be an expression for an index-on-expressions.
+** The operation of this routine is the same - return true if an only if
+** the expression uses one or more of columns identified by the second and
+** third arguments.
*/
-static int checkConstraintUnchanged(Expr *pExpr, int *aiChng, int chngRowid){
+int sqlite3ExprReferencesUpdatedColumn(
+ Expr *pExpr, /* The expression to be checked */
+ int *aiChng, /* aiChng[x]>=0 if column x changed by the UPDATE */
+ int chngRowid /* True if UPDATE changes the rowid */
+){
Walker w;
memset(&w, 0, sizeof(w));
w.eCode = 0;
@@ -1175,7 +1186,7 @@ static int checkConstraintUnchanged(Expr *pExpr, int *aiChng, int chngRowid){
testcase( w.eCode==CKCNSTRNT_COLUMN );
testcase( w.eCode==CKCNSTRNT_ROWID );
testcase( w.eCode==(CKCNSTRNT_ROWID|CKCNSTRNT_COLUMN) );
- return !w.eCode;
+ return w.eCode!=0;
}
/*
@@ -1381,7 +1392,13 @@ void sqlite3GenerateConstraintChecks(
for(i=0; i<pCheck->nExpr; i++){
int allOk;
Expr *pExpr = pCheck->a[i].pExpr;
- if( aiChng && checkConstraintUnchanged(pExpr, aiChng, pkChng) ) continue;
+ if( aiChng
+ && !sqlite3ExprReferencesUpdatedColumn(pExpr, aiChng, pkChng)
+ ){
+ /* The check constraints do not reference any of the columns being
+ ** updated so there is no point it verifying the check constraint */
+ continue;
+ }
allOk = sqlite3VdbeMakeLabel(v);
sqlite3VdbeVerifyAbortable(v, onError);
sqlite3ExprIfTrue(pParse, pExpr, allOk, SQLITE_JUMPIFNULL);
diff --git a/chromium/third_party/sqlite/src/src/loadext.c b/chromium/third_party/sqlite/src/src/loadext.c
index 5f4987209a8..142a89a52e7 100644
--- a/chromium/third_party/sqlite/src/src/loadext.c
+++ b/chromium/third_party/sqlite/src/src/loadext.c
@@ -84,6 +84,7 @@
# define sqlite3_declare_vtab 0
# define sqlite3_vtab_config 0
# define sqlite3_vtab_on_conflict 0
+# define sqlite3_vtab_collation 0
#endif
#ifdef SQLITE_OMIT_SHARED_CACHE
@@ -451,7 +452,13 @@ static const sqlite3_api_routines sqlite3Apis = {
sqlite3_str_length,
sqlite3_str_value,
/* Version 3.25.0 and later */
- sqlite3_create_window_function
+ sqlite3_create_window_function,
+ /* Version 3.26.0 and later */
+#ifdef SQLITE_ENABLE_NORMALIZE
+ sqlite3_normalized_sql
+#else
+ 0
+#endif
};
/*
diff --git a/chromium/third_party/sqlite/src/src/main.c b/chromium/third_party/sqlite/src/src/main.c
index f070fed3398..478428ac27c 100644
--- a/chromium/third_party/sqlite/src/src/main.c
+++ b/chromium/third_party/sqlite/src/src/main.c
@@ -835,6 +835,7 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){
{ SQLITE_DBCONFIG_ENABLE_QPSG, SQLITE_EnableQPSG },
{ SQLITE_DBCONFIG_TRIGGER_EQP, SQLITE_TriggerEQP },
{ SQLITE_DBCONFIG_RESET_DATABASE, SQLITE_ResetDatabase },
+ { SQLITE_DBCONFIG_DEFENSIVE, SQLITE_Defensive },
};
unsigned int i;
rc = SQLITE_ERROR; /* IMP: R-42790-23372 */
@@ -3062,6 +3063,9 @@ static int openDatabase(
#if defined(SQLITE_ENABLE_QPSG)
| SQLITE_EnableQPSG
#endif
+#if defined(SQLITE_DEFAULT_DEFENSIVE)
+ | SQLITE_Defensive
+#endif
;
sqlite3HashInit(&db->aCollSeq);
#ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -3957,15 +3961,26 @@ int sqlite3_test_control(int op, ...){
/* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, int onoff);
**
- ** If parameter onoff is non-zero, configure the wrappers so that all
- ** subsequent calls to localtime() and variants fail. If onoff is zero,
- ** undo this setting.
+ ** If parameter onoff is non-zero, subsequent calls to localtime()
+ ** and its variants fail. If onoff is zero, undo this setting.
*/
case SQLITE_TESTCTRL_LOCALTIME_FAULT: {
sqlite3GlobalConfig.bLocaltimeFault = va_arg(ap, int);
break;
}
+ /* sqlite3_test_control(SQLITE_TESTCTRL_INTERNAL_FUNCS, int onoff);
+ **
+ ** If parameter onoff is non-zero, internal-use-only SQL functions
+ ** are visible to ordinary SQL. This is useful for testing but is
+ ** unsafe because invalid parameters to those internal-use-only functions
+ ** can result in crashes or segfaults.
+ */
+ case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS: {
+ sqlite3GlobalConfig.bInternalFunctions = va_arg(ap, int);
+ break;
+ }
+
/* sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, int);
**
** Set or clear a flag that indicates that the database file is always well-
diff --git a/chromium/third_party/sqlite/src/src/os_unix.c b/chromium/third_party/sqlite/src/src/os_unix.c
index 96802e62d7c..d0736e0a63d 100644
--- a/chromium/third_party/sqlite/src/src/os_unix.c
+++ b/chromium/third_party/sqlite/src/src/os_unix.c
@@ -136,12 +136,10 @@
#define SQLITE_FSFLAGS_IS_MSDOS 0x1
/*
-** If we are to be thread-safe, include the pthreads header and define
-** the SQLITE_UNIX_THREADS macro.
+** If we are to be thread-safe, include the pthreads header.
*/
#if SQLITE_THREADSAFE
# include <pthread.h>
-# define SQLITE_UNIX_THREADS 1
#endif
/*
@@ -1119,8 +1117,7 @@ struct unixFileId {
/*
** An instance of the following structure is allocated for each open
-** inode. Or, on LinuxThreads, there is one of these structures for
-** each inode opened by each thread.
+** inode.
**
** A single inode can have multiple file descriptors, so each unixFile
** structure contains a pointer to an instance of this object and this
@@ -1166,13 +1163,16 @@ struct unixInodeInfo {
/*
** A lists of all unixInodeInfo objects.
+**
+** Must hold unixBigLock in order to read or write this variable.
*/
static unixInodeInfo *inodeList = 0; /* All unixInodeInfo objects */
#ifdef SQLITE_DEBUG
/*
-** True if the inode mutex is held, or not. Used only within assert()
-** to help verify correct mutex usage.
+** True if the inode mutex (on the unixFile.pFileMutex field) is held, or not.
+** This routine is used only within assert() to help verify correct mutex
+** usage.
*/
int unixFileMutexHeld(unixFile *pFile){
assert( pFile->pInode );
@@ -1300,8 +1300,8 @@ static void closePendingFds(unixFile *pFile){
/*
** Release a unixInodeInfo structure previously allocated by findInodeInfo().
**
-** The mutex entered using the unixEnterMutex() function must be held
-** when this function is called.
+** The global mutex must be held when this routine is called, but the mutex
+** on the inode being deleted must NOT be held.
*/
static void releaseInodeInfo(unixFile *pFile){
unixInodeInfo *pInode = pFile->pInode;
@@ -1336,8 +1336,7 @@ static void releaseInodeInfo(unixFile *pFile){
** describes that file descriptor. Create a new one if necessary. The
** return value might be uninitialized if an error occurs.
**
-** The mutex entered using the unixEnterMutex() function must be held
-** when this function is called.
+** The global mutex must held when calling this routine.
**
** Return an appropriate error code.
*/
@@ -1398,6 +1397,7 @@ static int findInodeInfo(
#else
fileId.ino = (u64)statbuf.st_ino;
#endif
+ assert( unixMutexHeld() );
pInode = inodeList;
while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){
pInode = pInode->pNext;
@@ -1417,6 +1417,7 @@ static int findInodeInfo(
}
}
pInode->nRef = 1;
+ assert( unixMutexHeld() );
pInode->pNext = inodeList;
pInode->pPrev = 0;
if( inodeList ) inodeList->pPrev = pInode;
@@ -4220,18 +4221,18 @@ static int unixGetpagesize(void){
**
** The following fields are read-only after the object is created:
**
-** fid
+** hShm
** zFilename
**
-** Either unixShmNode.mutex must be held or unixShmNode.nRef==0 and
+** Either unixShmNode.pShmMutex must be held or unixShmNode.nRef==0 and
** unixMutexHeld() is true when reading or writing any other field
** in this structure.
*/
struct unixShmNode {
unixInodeInfo *pInode; /* unixInodeInfo that owns this SHM node */
- sqlite3_mutex *mutex; /* Mutex to access this object */
+ sqlite3_mutex *pShmMutex; /* Mutex to access this object */
char *zFilename; /* Name of the mmapped file */
- int h; /* Open file descriptor */
+ int hShm; /* Open file descriptor */
int szRegion; /* Size of shared-memory regions */
u16 nRegion; /* Size of array apRegion */
u8 isReadonly; /* True if read-only */
@@ -4253,16 +4254,16 @@ struct unixShmNode {
** The following fields are initialized when this object is created and
** are read-only thereafter:
**
-** unixShm.pFile
+** unixShm.pShmNode
** unixShm.id
**
-** All other fields are read/write. The unixShm.pFile->mutex must be held
-** while accessing any read/write fields.
+** All other fields are read/write. The unixShm.pShmNode->pShmMutex must
+** be held while accessing any read/write fields.
*/
struct unixShm {
unixShmNode *pShmNode; /* The underlying unixShmNode object */
unixShm *pNext; /* Next unixShm with the same unixShmNode */
- u8 hasMutex; /* True if holding the unixShmNode mutex */
+ u8 hasMutex; /* True if holding the unixShmNode->pShmMutex */
u8 id; /* Id of this connection within its unixShmNode */
u16 sharedMask; /* Mask of shared locks held */
u16 exclMask; /* Mask of exclusive locks held */
@@ -4292,7 +4293,8 @@ static int unixShmSystemLock(
/* Access to the unixShmNode object is serialized by the caller */
pShmNode = pFile->pInode->pShmNode;
- assert( pShmNode->nRef==0 || sqlite3_mutex_held(pShmNode->mutex) );
+ assert( pShmNode->nRef==0 || sqlite3_mutex_held(pShmNode->pShmMutex) );
+ assert( pShmNode->nRef>0 || unixMutexHeld() );
/* Shared locks never span more than one byte */
assert( n==1 || lockType!=F_RDLCK );
@@ -4300,13 +4302,13 @@ static int unixShmSystemLock(
/* Locks are within range */
assert( n>=1 && n<=SQLITE_SHM_NLOCK );
- if( pShmNode->h>=0 ){
+ if( pShmNode->hShm>=0 ){
/* Initialize the locking parameters */
f.l_type = lockType;
f.l_whence = SEEK_SET;
f.l_start = ofst;
f.l_len = n;
- rc = osSetPosixAdvisoryLock(pShmNode->h, &f, pFile);
+ rc = osSetPosixAdvisoryLock(pShmNode->hShm, &f, pFile);
rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
}
@@ -4378,18 +4380,18 @@ static void unixShmPurge(unixFile *pFd){
int nShmPerMap = unixShmRegionPerMap();
int i;
assert( p->pInode==pFd->pInode );
- sqlite3_mutex_free(p->mutex);
+ sqlite3_mutex_free(p->pShmMutex);
for(i=0; i<p->nRegion; i+=nShmPerMap){
- if( p->h>=0 ){
+ if( p->hShm>=0 ){
osMunmap(p->apRegion[i], p->szRegion);
}else{
sqlite3_free(p->apRegion[i]);
}
}
sqlite3_free(p->apRegion);
- if( p->h>=0 ){
- robust_close(pFd, p->h, __LINE__);
- p->h = -1;
+ if( p->hShm>=0 ){
+ robust_close(pFd, p->hShm, __LINE__);
+ p->hShm = -1;
}
p->pInode->pShmNode = 0;
sqlite3_free(p);
@@ -4431,7 +4433,7 @@ static int unixLockSharedMemory(unixFile *pDbFd, unixShmNode *pShmNode){
lock.l_start = UNIX_SHM_DMS;
lock.l_len = 1;
lock.l_type = F_WRLCK;
- if( osFcntl(pShmNode->h, F_GETLK, &lock)!=0 ) {
+ if( osFcntl(pShmNode->hShm, F_GETLK, &lock)!=0 ) {
rc = SQLITE_IOERR_LOCK;
}else if( lock.l_type==F_UNLCK ){
if( pShmNode->isReadonly ){
@@ -4439,7 +4441,12 @@ static int unixLockSharedMemory(unixFile *pDbFd, unixShmNode *pShmNode){
rc = SQLITE_READONLY_CANTINIT;
}else{
rc = unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1);
- if( rc==SQLITE_OK && robust_ftruncate(pShmNode->h, 0) ){
+ /* The first connection to attach must truncate the -shm file. We
+ ** truncate to 3 bytes (an arbitrary small number, less than the
+ ** -shm header size) rather than 0 as a system debugging aid, to
+ ** help detect if a -shm file truncation is legitimate or is the work
+ ** or a rogue process. */
+ if( rc==SQLITE_OK && robust_ftruncate(pShmNode->hShm, 3) ){
rc = unixLogError(SQLITE_IOERR_SHMOPEN,"ftruncate",pShmNode->zFilename);
}
}
@@ -4545,12 +4552,12 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
sqlite3_snprintf(nShmFilename, zShm, "%s-shm", zBasePath);
sqlite3FileSuffix3(pDbFd->zPath, zShm);
#endif
- pShmNode->h = -1;
+ pShmNode->hShm = -1;
pDbFd->pInode->pShmNode = pShmNode;
pShmNode->pInode = pDbFd->pInode;
if( sqlite3GlobalConfig.bCoreMutex ){
- pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
- if( pShmNode->mutex==0 ){
+ pShmNode->pShmMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
+ if( pShmNode->pShmMutex==0 ){
rc = SQLITE_NOMEM_BKPT;
goto shm_open_err;
}
@@ -4558,11 +4565,11 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
if( pInode->bProcessLock==0 ){
if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){
- pShmNode->h = robust_open(zShm, O_RDWR|O_CREAT, (sStat.st_mode&0777));
+ pShmNode->hShm = robust_open(zShm, O_RDWR|O_CREAT,(sStat.st_mode&0777));
}
- if( pShmNode->h<0 ){
- pShmNode->h = robust_open(zShm, O_RDONLY, (sStat.st_mode&0777));
- if( pShmNode->h<0 ){
+ if( pShmNode->hShm<0 ){
+ pShmNode->hShm = robust_open(zShm, O_RDONLY, (sStat.st_mode&0777));
+ if( pShmNode->hShm<0 ){
rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShm);
goto shm_open_err;
}
@@ -4573,7 +4580,7 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
** is owned by the same user that owns the original database. Otherwise,
** the original owner will not be able to connect.
*/
- robustFchown(pShmNode->h, sStat.st_uid, sStat.st_gid);
+ robustFchown(pShmNode->hShm, sStat.st_uid, sStat.st_gid);
rc = unixLockSharedMemory(pDbFd, pShmNode);
if( rc!=SQLITE_OK && rc!=SQLITE_READONLY_CANTINIT ) goto shm_open_err;
@@ -4593,13 +4600,13 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
** the cover of the unixEnterMutex() mutex and the pointer from the
** new (struct unixShm) object to the pShmNode has been set. All that is
** left to do is to link the new object into the linked list starting
- ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex
- ** mutex.
+ ** at pShmNode->pFirst. This must be done while holding the
+ ** pShmNode->pShmMutex.
*/
- sqlite3_mutex_enter(pShmNode->mutex);
+ sqlite3_mutex_enter(pShmNode->pShmMutex);
p->pNext = pShmNode->pFirst;
pShmNode->pFirst = p;
- sqlite3_mutex_leave(pShmNode->mutex);
+ sqlite3_mutex_leave(pShmNode->pShmMutex);
return rc;
/* Jump here on any error */
@@ -4651,7 +4658,7 @@ static int unixShmMap(
p = pDbFd->pShm;
pShmNode = p->pShmNode;
- sqlite3_mutex_enter(pShmNode->mutex);
+ sqlite3_mutex_enter(pShmNode->pShmMutex);
if( pShmNode->isUnlocked ){
rc = unixLockSharedMemory(pDbFd, pShmNode);
if( rc!=SQLITE_OK ) goto shmpage_out;
@@ -4659,8 +4666,8 @@ static int unixShmMap(
}
assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
assert( pShmNode->pInode==pDbFd->pInode );
- assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 );
- assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 );
+ assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 );
+ assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 );
/* Minimum number of regions required to be mapped. */
nReqRegion = ((iRegion+nShmPerMap) / nShmPerMap) * nShmPerMap;
@@ -4672,12 +4679,12 @@ static int unixShmMap(
pShmNode->szRegion = szRegion;
- if( pShmNode->h>=0 ){
+ if( pShmNode->hShm>=0 ){
/* The requested region is not mapped into this processes address space.
** Check to see if it has been allocated (i.e. if the wal-index file is
** large enough to contain the requested region).
*/
- if( osFstat(pShmNode->h, &sStat) ){
+ if( osFstat(pShmNode->hShm, &sStat) ){
rc = SQLITE_IOERR_SHMSIZE;
goto shmpage_out;
}
@@ -4705,7 +4712,7 @@ static int unixShmMap(
assert( (nByte % pgsz)==0 );
for(iPg=(sStat.st_size/pgsz); iPg<(nByte/pgsz); iPg++){
int x = 0;
- if( seekAndWriteFd(pShmNode->h, iPg*pgsz + pgsz-1, "", 1, &x)!=1 ){
+ if( seekAndWriteFd(pShmNode->hShm, iPg*pgsz + pgsz-1,"",1,&x)!=1 ){
const char *zFile = pShmNode->zFilename;
rc = unixLogError(SQLITE_IOERR_SHMSIZE, "write", zFile);
goto shmpage_out;
@@ -4728,22 +4735,22 @@ static int unixShmMap(
int nMap = szRegion*nShmPerMap;
int i;
void *pMem;
- if( pShmNode->h>=0 ){
+ if( pShmNode->hShm>=0 ){
pMem = osMmap(0, nMap,
pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE,
- MAP_SHARED, pShmNode->h, szRegion*(i64)pShmNode->nRegion
+ MAP_SHARED, pShmNode->hShm, szRegion*(i64)pShmNode->nRegion
);
if( pMem==MAP_FAILED ){
rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename);
goto shmpage_out;
}
}else{
- pMem = sqlite3_malloc64(szRegion);
+ pMem = sqlite3_malloc64(nMap);
if( pMem==0 ){
rc = SQLITE_NOMEM_BKPT;
goto shmpage_out;
}
- memset(pMem, 0, szRegion);
+ memset(pMem, 0, nMap);
}
for(i=0; i<nShmPerMap; i++){
@@ -4760,7 +4767,7 @@ shmpage_out:
*pp = 0;
}
if( pShmNode->isReadonly && rc==SQLITE_OK ) rc = SQLITE_READONLY;
- sqlite3_mutex_leave(pShmNode->mutex);
+ sqlite3_mutex_leave(pShmNode->pShmMutex);
return rc;
}
@@ -4794,12 +4801,12 @@ static int unixShmLock(
|| flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED)
|| flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
- assert( pShmNode->h>=0 || pDbFd->pInode->bProcessLock==1 );
- assert( pShmNode->h<0 || pDbFd->pInode->bProcessLock==0 );
+ assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 );
+ assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 );
mask = (1<<(ofst+n)) - (1<<ofst);
assert( n>1 || mask==(1<<ofst) );
- sqlite3_mutex_enter(pShmNode->mutex);
+ sqlite3_mutex_enter(pShmNode->pShmMutex);
if( flags & SQLITE_SHM_UNLOCK ){
u16 allMask = 0; /* Mask of locks held by siblings */
@@ -4872,7 +4879,7 @@ static int unixShmLock(
}
}
}
- sqlite3_mutex_leave(pShmNode->mutex);
+ sqlite3_mutex_leave(pShmNode->pShmMutex);
OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n",
p->id, osGetpid(0), p->sharedMask, p->exclMask));
return rc;
@@ -4922,14 +4929,14 @@ static int unixShmUnmap(
/* Remove connection p from the set of connections associated
** with pShmNode */
- sqlite3_mutex_enter(pShmNode->mutex);
+ sqlite3_mutex_enter(pShmNode->pShmMutex);
for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
*pp = p->pNext;
/* Free the connection p */
sqlite3_free(p);
pDbFd->pShm = 0;
- sqlite3_mutex_leave(pShmNode->mutex);
+ sqlite3_mutex_leave(pShmNode->pShmMutex);
/* If pShmNode->nRef has reached 0, then close the underlying
** shared-memory file, too */
@@ -4938,7 +4945,7 @@ static int unixShmUnmap(
assert( pShmNode->nRef>0 );
pShmNode->nRef--;
if( pShmNode->nRef==0 ){
- if( deleteFlag && pShmNode->h>=0 ){
+ if( deleteFlag && pShmNode->hShm>=0 ){
osUnlink(pShmNode->zFilename);
}
unixShmPurge(pDbFd);
diff --git a/chromium/third_party/sqlite/src/src/os_win.c b/chromium/third_party/sqlite/src/src/os_win.c
index 5cd28a20e42..76743781a01 100644
--- a/chromium/third_party/sqlite/src/src/os_win.c
+++ b/chromium/third_party/sqlite/src/src/os_win.c
@@ -284,8 +284,7 @@ struct winFile {
int nFetchOut; /* Number of outstanding xFetch references */
HANDLE hMap; /* Handle for accessing memory mapping */
void *pMapRegion; /* Area memory mapped */
- sqlite3_int64 mmapSize; /* Usable size of mapped region */
- sqlite3_int64 mmapSizeActual; /* Actual size of mapped region */
+ sqlite3_int64 mmapSize; /* Size of mapped region */
sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */
#endif
};
@@ -2906,7 +2905,26 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
DWORD lastErrno;
#if SQLITE_MAX_MMAP_SIZE>0
sqlite3_int64 oldMmapSize;
- if( pFile->nFetchOut>0 ) return SQLITE_OK;
+ if( pFile->nFetchOut>0 ){
+ /* File truncation is a no-op if there are outstanding memory mapped
+ ** pages. This is because truncating the file means temporarily unmapping
+ ** the file, and that might delete memory out from under existing cursors.
+ **
+ ** This can result in incremental vacuum not truncating the file,
+ ** if there is an active read cursor when the incremental vacuum occurs.
+ ** No real harm comes of this - the database file is not corrupted,
+ ** though some folks might complain that the file is bigger than it
+ ** needs to be.
+ **
+ ** The only feasible work-around is to defer the truncation until after
+ ** all references to memory-mapped content are closed. That is doable,
+ ** but involves adding a few branches in the common write code path which
+ ** could slow down normal operations slightly. Hence, we have decided for
+ ** now to simply make trancations a no-op if there are pending reads. We
+ ** can maybe revisit this decision in the future.
+ */
+ return SQLITE_OK;
+ }
#endif
assert( pFile );
@@ -4335,9 +4353,9 @@ shmpage_out:
static int winUnmapfile(winFile *pFile){
assert( pFile!=0 );
OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, hMap=%p, pMapRegion=%p, "
- "mmapSize=%lld, mmapSizeActual=%lld, mmapSizeMax=%lld\n",
+ "mmapSize=%lld, mmapSizeMax=%lld\n",
osGetCurrentProcessId(), pFile, pFile->hMap, pFile->pMapRegion,
- pFile->mmapSize, pFile->mmapSizeActual, pFile->mmapSizeMax));
+ pFile->mmapSize, pFile->mmapSizeMax));
if( pFile->pMapRegion ){
if( !osUnmapViewOfFile(pFile->pMapRegion) ){
pFile->lastErrno = osGetLastError();
@@ -4349,7 +4367,6 @@ static int winUnmapfile(winFile *pFile){
}
pFile->pMapRegion = 0;
pFile->mmapSize = 0;
- pFile->mmapSizeActual = 0;
}
if( pFile->hMap!=NULL ){
if( !osCloseHandle(pFile->hMap) ){
@@ -4460,7 +4477,6 @@ static int winMapfile(winFile *pFd, sqlite3_int64 nByte){
}
pFd->pMapRegion = pNew;
pFd->mmapSize = nMap;
- pFd->mmapSizeActual = nMap;
}
OSTRACE(("MAP-FILE pid=%lu, pFile=%p, rc=SQLITE_OK\n",
@@ -5262,7 +5278,6 @@ static int winOpen(
pFile->hMap = NULL;
pFile->pMapRegion = 0;
pFile->mmapSize = 0;
- pFile->mmapSizeActual = 0;
pFile->mmapSizeMax = sqlite3GlobalConfig.szMmap;
#endif
diff --git a/chromium/third_party/sqlite/src/src/pager.c b/chromium/third_party/sqlite/src/src/pager.c
index 24f40514174..771330e9ab2 100644
--- a/chromium/third_party/sqlite/src/src/pager.c
+++ b/chromium/third_party/sqlite/src/src/pager.c
@@ -825,19 +825,30 @@ static const unsigned char aJournalMagic[] = {
*/
#define isOpen(pFd) ((pFd)->pMethods!=0)
+#ifdef SQLITE_DIRECT_OVERFLOW_READ
/*
-** Return true if this pager uses a write-ahead log to read page pgno.
-** Return false if the pager reads pgno directly from the database.
+** Return true if page pgno can be read directly from the database file
+** by the b-tree layer. This is the case if:
+**
+** * the database file is open,
+** * there are no dirty pages in the cache, and
+** * the desired page is not currently in the wal file.
*/
-#if !defined(SQLITE_OMIT_WAL) && defined(SQLITE_DIRECT_OVERFLOW_READ)
-int sqlite3PagerUseWal(Pager *pPager, Pgno pgno){
- u32 iRead = 0;
- int rc;
- if( pPager->pWal==0 ) return 0;
- rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iRead);
- return rc || iRead;
+int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){
+ if( pPager->fd->pMethods==0 ) return 0;
+ if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0;
+#ifndef SQLITE_OMIT_WAL
+ if( pPager->pWal ){
+ u32 iRead = 0;
+ int rc;
+ rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iRead);
+ return (rc==SQLITE_OK && iRead==0);
+ }
+#endif
+ return 1;
}
#endif
+
#ifndef SQLITE_OMIT_WAL
# define pagerUseWal(x) ((x)->pWal!=0)
#else
@@ -7021,7 +7032,11 @@ void sqlite3PagerSetCodec(
void (*xCodecFree)(void*),
void *pCodec
){
- if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec);
+ if( pPager->xCodecFree ){
+ pPager->xCodecFree(pPager->pCodec);
+ }else{
+ pager_reset(pPager);
+ }
pPager->xCodec = pPager->memDb ? 0 : xCodec;
pPager->xCodecSizeChng = xCodecSizeChng;
pPager->xCodecFree = xCodecFree;
diff --git a/chromium/third_party/sqlite/src/src/pager.h b/chromium/third_party/sqlite/src/src/pager.h
index e51c2606a39..80e6ad43663 100644
--- a/chromium/third_party/sqlite/src/src/pager.h
+++ b/chromium/third_party/sqlite/src/src/pager.h
@@ -179,9 +179,6 @@ int sqlite3PagerSharedLock(Pager *pPager);
int sqlite3PagerWalCallback(Pager *pPager);
int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
int sqlite3PagerCloseWal(Pager *pPager, sqlite3*);
-# ifdef SQLITE_DIRECT_OVERFLOW_READ
- int sqlite3PagerUseWal(Pager *pPager, Pgno);
-# endif
# ifdef SQLITE_ENABLE_SNAPSHOT
int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot);
int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot);
@@ -189,8 +186,10 @@ int sqlite3PagerSharedLock(Pager *pPager);
int sqlite3PagerSnapshotCheck(Pager *pPager, sqlite3_snapshot *pSnapshot);
void sqlite3PagerSnapshotUnlock(Pager *pPager);
# endif
-#else
-# define sqlite3PagerUseWal(x,y) 0
+#endif
+
+#ifdef SQLITE_DIRECT_OVERFLOW_READ
+ int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno);
#endif
#ifdef SQLITE_ENABLE_ZIPVFS
diff --git a/chromium/third_party/sqlite/src/src/parse.y b/chromium/third_party/sqlite/src/src/parse.y
index e0f8c646206..cd38ebf51b5 100644
--- a/chromium/third_party/sqlite/src/src/parse.y
+++ b/chromium/third_party/sqlite/src/src/parse.y
@@ -941,13 +941,10 @@ idlist(A) ::= nm(Y).
p->pLeft = p->pRight = 0;
p->x.pList = 0;
p->pAggInfo = 0;
- p->pTab = 0;
+ p->y.pTab = 0;
p->op2 = 0;
p->iTable = 0;
p->iColumn = 0;
-#ifndef SQLITE_OMIT_WINDOWFUNC
- p->pWin = 0;
-#endif
p->u.zToken = (char*)&p[1];
memcpy(p->u.zToken, t.z, t.n);
p->u.zToken[t.n] = 0;
diff --git a/chromium/third_party/sqlite/src/src/pcache.c b/chromium/third_party/sqlite/src/src/pcache.c
index d5e8711f471..d690931578c 100644
--- a/chromium/third_party/sqlite/src/src/pcache.c
+++ b/chromium/third_party/sqlite/src/src/pcache.c
@@ -32,7 +32,7 @@
** The PCache.pSynced variable is used to optimize searching for a dirty
** page to eject from the cache mid-transaction. It is better to eject
** a page that does not require a journal sync than one that does.
-** Therefore, pSynced is maintained to that it *almost* always points
+** Therefore, pSynced is maintained so that it *almost* always points
** to either the oldest page in the pDirty/pDirtyTail list that has a
** clear PGHDR_NEED_SYNC flag or to a page that is older than this one
** (so that the right page to eject can be found by following pDirtyPrev
@@ -856,6 +856,15 @@ int sqlite3PCachePercentDirty(PCache *pCache){
return nCache ? (int)(((i64)nDirty * 100) / nCache) : 0;
}
+#ifdef SQLITE_DIRECT_OVERFLOW_READ
+/*
+** Return true if there are one or more dirty pages in the cache. Else false.
+*/
+int sqlite3PCacheIsDirty(PCache *pCache){
+ return (pCache->pDirty!=0);
+}
+#endif
+
#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG)
/*
** For all dirty pages currently in the cache, invoke the specified
diff --git a/chromium/third_party/sqlite/src/src/pcache.h b/chromium/third_party/sqlite/src/src/pcache.h
index 8aadd023e11..d6cb43971c4 100644
--- a/chromium/third_party/sqlite/src/src/pcache.h
+++ b/chromium/third_party/sqlite/src/src/pcache.h
@@ -183,4 +183,8 @@ int sqlite3HeaderSizePcache1(void);
/* Number of dirty pages as a percentage of the configured cache size */
int sqlite3PCachePercentDirty(PCache*);
+#ifdef SQLITE_DIRECT_OVERFLOW_READ
+int sqlite3PCacheIsDirty(PCache *pCache);
+#endif
+
#endif /* _PCACHE_H_ */
diff --git a/chromium/third_party/sqlite/src/src/pcache1.c b/chromium/third_party/sqlite/src/src/pcache1.c
index 2692bd6ac9d..1986b22ca61 100644
--- a/chromium/third_party/sqlite/src/src/pcache1.c
+++ b/chromium/third_party/sqlite/src/src/pcache1.c
@@ -105,7 +105,8 @@ struct PgHdr1 {
};
/*
-** A page is pinned if it is no on the LRU list
+** A page is pinned if it is not on the LRU list. To be "pinned" means
+** that the page is in active use and must not be deallocated.
*/
#define PAGE_IS_PINNED(p) ((p)->pLruNext==0)
#define PAGE_IS_UNPINNED(p) ((p)->pLruNext!=0)
@@ -166,6 +167,7 @@ struct PCache1 {
unsigned int nMax; /* Configured "cache_size" value */
unsigned int n90pct; /* nMax*9/10 */
unsigned int iMaxKey; /* Largest key seen since xTruncate() */
+ unsigned int nPurgeableDummy; /* pnPurgeable points here when not used*/
/* Hash table of all pages. The following variables may only be accessed
** when the accessor is holding the PGroup mutex.
@@ -779,8 +781,7 @@ static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){
pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
pCache->pnPurgeable = &pGroup->nPurgeable;
}else{
- static unsigned int dummyCurrentPage;
- pCache->pnPurgeable = &dummyCurrentPage;
+ pCache->pnPurgeable = &pCache->nPurgeableDummy;
}
pcache1LeaveMutex(pGroup);
if( pCache->nHash==0 ){
diff --git a/chromium/third_party/sqlite/src/src/pragma.c b/chromium/third_party/sqlite/src/src/pragma.c
index 472fca7ee69..40b600752da 100644
--- a/chromium/third_party/sqlite/src/src/pragma.c
+++ b/chromium/third_party/sqlite/src/src/pragma.c
@@ -1058,7 +1058,7 @@ void sqlite3Pragma(
setPragmaResultColumnNames(v, pPragma);
returnSingleInt(v, (db->flags & pPragma->iArg)!=0 );
}else{
- int mask = pPragma->iArg; /* Mask of bits to set or clear. */
+ u64 mask = pPragma->iArg; /* Mask of bits to set or clear. */
if( db->autoCommit==0 ){
/* Foreign key support may not be enabled or disabled while not
** in auto-commit mode. */
@@ -1107,15 +1107,17 @@ void sqlite3Pragma(
Table *pTab;
pTab = sqlite3LocateTable(pParse, LOCATE_NOERR, zRight, zDb);
if( pTab ){
+ int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
int i, k;
int nHidden = 0;
Column *pCol;
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
- pParse->nMem = 6;
- sqlite3CodeVerifySchema(pParse, iDb);
+ pParse->nMem = 7;
+ sqlite3CodeVerifySchema(pParse, iTabDb);
sqlite3ViewGetColumnNames(pParse, pTab);
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
- if( IsHiddenColumn(pCol) ){
+ int isHidden = IsHiddenColumn(pCol);
+ if( isHidden && pPragma->iArg==0 ){
nHidden++;
continue;
}
@@ -1127,13 +1129,14 @@ void sqlite3Pragma(
for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){}
}
assert( pCol->pDflt==0 || pCol->pDflt->op==TK_SPAN );
- sqlite3VdbeMultiLoad(v, 1, "issisi",
+ sqlite3VdbeMultiLoad(v, 1, pPragma->iArg ? "issisii" : "issisi",
i-nHidden,
pCol->zName,
sqlite3ColumnType(pCol,""),
pCol->notNull ? 1 : 0,
pCol->pDflt ? pCol->pDflt->u.zToken : 0,
- k);
+ k,
+ isHidden);
}
}
}
@@ -1171,6 +1174,7 @@ void sqlite3Pragma(
Table *pTab;
pIdx = sqlite3FindIndex(db, zRight, zDb);
if( pIdx ){
+ int iIdxDb = sqlite3SchemaToIndex(db, pIdx->pSchema);
int i;
int mx;
if( pPragma->iArg ){
@@ -1183,7 +1187,7 @@ void sqlite3Pragma(
pParse->nMem = 3;
}
pTab = pIdx->pTable;
- sqlite3CodeVerifySchema(pParse, iDb);
+ sqlite3CodeVerifySchema(pParse, iIdxDb);
assert( pParse->nMem<=pPragma->nPragCName );
for(i=0; i<mx; i++){
i16 cnum = pIdx->aiColumn[i];
@@ -1207,8 +1211,9 @@ void sqlite3Pragma(
int i;
pTab = sqlite3FindTable(db, zRight, zDb);
if( pTab ){
+ int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
pParse->nMem = 5;
- sqlite3CodeVerifySchema(pParse, iDb);
+ sqlite3CodeVerifySchema(pParse, iTabDb);
for(pIdx=pTab->pIndex, i=0; pIdx; pIdx=pIdx->pNext, i++){
const char *azOrigin[] = { "c", "u", "pk" };
sqlite3VdbeMultiLoad(v, 1, "isisi",
@@ -1255,6 +1260,7 @@ void sqlite3Pragma(
pParse->nMem = 2;
for(i=0; i<SQLITE_FUNC_HASH_SZ; i++){
for(p=sqlite3BuiltinFunctions.a[i]; p; p=p->u.pHash ){
+ if( p->funcFlags & SQLITE_FUNC_INTERNAL ) continue;
sqlite3VdbeMultiLoad(v, 1, "si", p->zName, 1);
}
}
@@ -1296,9 +1302,10 @@ void sqlite3Pragma(
if( pTab ){
pFK = pTab->pFKey;
if( pFK ){
+ int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
int i = 0;
pParse->nMem = 8;
- sqlite3CodeVerifySchema(pParse, iDb);
+ sqlite3CodeVerifySchema(pParse, iTabDb);
while(pFK){
int j;
for(j=0; j<pFK->nCol; j++){
@@ -1343,9 +1350,9 @@ void sqlite3Pragma(
pParse->nMem += 4;
regKey = ++pParse->nMem;
regRow = ++pParse->nMem;
- sqlite3CodeVerifySchema(pParse, iDb);
k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash);
while( k ){
+ int iTabDb;
if( zRight ){
pTab = sqlite3LocateTable(pParse, 0, zRight, zDb);
k = 0;
@@ -1354,21 +1361,23 @@ void sqlite3Pragma(
k = sqliteHashNext(k);
}
if( pTab==0 || pTab->pFKey==0 ) continue;
- sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
+ iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+ sqlite3CodeVerifySchema(pParse, iTabDb);
+ sqlite3TableLock(pParse, iTabDb, pTab->tnum, 0, pTab->zName);
if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow;
- sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead);
+ sqlite3OpenTable(pParse, 0, iTabDb, pTab, OP_OpenRead);
sqlite3VdbeLoadString(v, regResult, pTab->zName);
for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
pParent = sqlite3FindTable(db, pFK->zTo, zDb);
if( pParent==0 ) continue;
pIdx = 0;
- sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName);
+ sqlite3TableLock(pParse, iTabDb, pParent->tnum, 0, pParent->zName);
x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0);
if( x==0 ){
if( pIdx==0 ){
- sqlite3OpenTable(pParse, i, iDb, pParent, OP_OpenRead);
+ sqlite3OpenTable(pParse, i, iTabDb, pParent, OP_OpenRead);
}else{
- sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iDb);
+ sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iTabDb);
sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
}
}else{
@@ -2137,12 +2146,24 @@ void sqlite3Pragma(
#endif
#ifdef SQLITE_HAS_CODEC
+ /* Pragma iArg
+ ** ---------- ------
+ ** key 0
+ ** rekey 1
+ ** hexkey 2
+ ** hexrekey 3
+ ** textkey 4
+ ** textrekey 5
+ */
case PragTyp_KEY: {
- if( zRight ) sqlite3_key_v2(db, zDb, zRight, sqlite3Strlen30(zRight));
- break;
- }
- case PragTyp_REKEY: {
- if( zRight ) sqlite3_rekey_v2(db, zDb, zRight, sqlite3Strlen30(zRight));
+ if( zRight ){
+ int n = pPragma->iArg<4 ? sqlite3Strlen30(zRight) : -1;
+ if( (pPragma->iArg & 1)==0 ){
+ sqlite3_key_v2(db, zDb, zRight, n);
+ }else{
+ sqlite3_rekey_v2(db, zDb, zRight, n);
+ }
+ }
break;
}
case PragTyp_HEXKEY: {
@@ -2154,7 +2175,7 @@ void sqlite3Pragma(
iByte = (iByte<<4) + sqlite3HexToInt(zRight[i]);
if( (i&1)!=0 ) zKey[i/2] = iByte;
}
- if( (zLeft[3] & 0xf)==0xb ){
+ if( (pPragma->iArg & 1)==0 ){
sqlite3_key_v2(db, zDb, zKey, i/2);
}else{
sqlite3_rekey_v2(db, zDb, zKey, i/2);
@@ -2484,7 +2505,8 @@ static const sqlite3_module pragmaVtabModule = {
0, /* xRename - rename the table */
0, /* xSavepoint */
0, /* xRelease */
- 0 /* xRollbackTo */
+ 0, /* xRollbackTo */
+ 0 /* xShadowName */
};
/*
diff --git a/chromium/third_party/sqlite/src/src/pragma.h b/chromium/third_party/sqlite/src/src/pragma.h
index 970092f1cd8..dd10e0f77f2 100644
--- a/chromium/third_party/sqlite/src/src/pragma.h
+++ b/chromium/third_party/sqlite/src/src/pragma.h
@@ -49,10 +49,9 @@
#define PragTyp_ACTIVATE_EXTENSIONS 41
#define PragTyp_HEXKEY 42
#define PragTyp_KEY 43
-#define PragTyp_REKEY 44
-#define PragTyp_LOCK_STATUS 45
-#define PragTyp_PARSER_TRACE 46
-#define PragTyp_STATS 47
+#define PragTyp_LOCK_STATUS 44
+#define PragTyp_PARSER_TRACE 45
+#define PragTyp_STATS 46
/* Property flags associated with various pragma. */
#define PragFlg_NeedSchema 0x01 /* Force schema load before running */
@@ -69,58 +68,57 @@
** result column is different from the name of the pragma
*/
static const char *const pragCName[] = {
- /* 0 */ "cache_size", /* Used by: default_cache_size */
- /* 1 */ "cid", /* Used by: table_info */
- /* 2 */ "name",
- /* 3 */ "type",
- /* 4 */ "notnull",
- /* 5 */ "dflt_value",
- /* 6 */ "pk",
- /* 7 */ "tbl", /* Used by: stats */
- /* 8 */ "idx",
- /* 9 */ "wdth",
- /* 10 */ "hght",
- /* 11 */ "flgs",
- /* 12 */ "seqno", /* Used by: index_info */
- /* 13 */ "cid",
- /* 14 */ "name",
+ /* 0 */ "id", /* Used by: foreign_key_list */
+ /* 1 */ "seq",
+ /* 2 */ "table",
+ /* 3 */ "from",
+ /* 4 */ "to",
+ /* 5 */ "on_update",
+ /* 6 */ "on_delete",
+ /* 7 */ "match",
+ /* 8 */ "cid", /* Used by: table_xinfo */
+ /* 9 */ "name",
+ /* 10 */ "type",
+ /* 11 */ "notnull",
+ /* 12 */ "dflt_value",
+ /* 13 */ "pk",
+ /* 14 */ "hidden",
+ /* table_info reuses 8 */
/* 15 */ "seqno", /* Used by: index_xinfo */
- /* 16 */ "cid",
- /* 17 */ "name",
- /* 18 */ "desc",
- /* 19 */ "coll",
- /* 20 */ "key",
- /* 21 */ "seq", /* Used by: index_list */
- /* 22 */ "name",
- /* 23 */ "unique",
- /* 24 */ "origin",
- /* 25 */ "partial",
- /* 26 */ "seq", /* Used by: database_list */
- /* 27 */ "name",
- /* 28 */ "file",
- /* 29 */ "name", /* Used by: function_list */
- /* 30 */ "builtin",
- /* 31 */ "name", /* Used by: module_list pragma_list */
- /* 32 */ "seq", /* Used by: collation_list */
- /* 33 */ "name",
- /* 34 */ "id", /* Used by: foreign_key_list */
- /* 35 */ "seq",
- /* 36 */ "table",
- /* 37 */ "from",
- /* 38 */ "to",
- /* 39 */ "on_update",
- /* 40 */ "on_delete",
- /* 41 */ "match",
- /* 42 */ "table", /* Used by: foreign_key_check */
- /* 43 */ "rowid",
- /* 44 */ "parent",
- /* 45 */ "fkid",
- /* 46 */ "busy", /* Used by: wal_checkpoint */
- /* 47 */ "log",
- /* 48 */ "checkpointed",
- /* 49 */ "timeout", /* Used by: busy_timeout */
- /* 50 */ "database", /* Used by: lock_status */
- /* 51 */ "status",
+ /* 16 */ "cid",
+ /* 17 */ "name",
+ /* 18 */ "desc",
+ /* 19 */ "coll",
+ /* 20 */ "key",
+ /* 21 */ "tbl", /* Used by: stats */
+ /* 22 */ "idx",
+ /* 23 */ "wdth",
+ /* 24 */ "hght",
+ /* 25 */ "flgs",
+ /* 26 */ "seq", /* Used by: index_list */
+ /* 27 */ "name",
+ /* 28 */ "unique",
+ /* 29 */ "origin",
+ /* 30 */ "partial",
+ /* 31 */ "table", /* Used by: foreign_key_check */
+ /* 32 */ "rowid",
+ /* 33 */ "parent",
+ /* 34 */ "fkid",
+ /* index_info reuses 15 */
+ /* 35 */ "seq", /* Used by: database_list */
+ /* 36 */ "name",
+ /* 37 */ "file",
+ /* 38 */ "busy", /* Used by: wal_checkpoint */
+ /* 39 */ "log",
+ /* 40 */ "checkpointed",
+ /* 41 */ "name", /* Used by: function_list */
+ /* 42 */ "builtin",
+ /* collation_list reuses 26 */
+ /* 43 */ "database", /* Used by: lock_status */
+ /* 44 */ "status",
+ /* 45 */ "cache_size", /* Used by: default_cache_size */
+ /* module_list pragma_list reuses 9 */
+ /* 46 */ "timeout", /* Used by: busy_timeout */
};
/* Definitions of all built-in pragmas */
@@ -130,7 +128,7 @@ typedef struct PragmaName {
u8 mPragFlg; /* Zero or more PragFlg_XXX values */
u8 iPragCName; /* Start of column names in pragCName[] */
u8 nPragCName; /* Num of col names. 0 means use pragma name */
- u32 iArg; /* Extra argument */
+ u64 iArg; /* Extra argument */
} PragmaName;
static const PragmaName aPragmaName[] = {
#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
@@ -171,7 +169,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "busy_timeout",
/* ePragTyp: */ PragTyp_BUSY_TIMEOUT,
/* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 49, 1,
+ /* ColNames: */ 46, 1,
/* iArg: */ 0 },
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
{/* zName: */ "cache_size",
@@ -208,7 +206,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "collation_list",
/* ePragTyp: */ PragTyp_COLLATION_LIST,
/* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 32, 2,
+ /* ColNames: */ 26, 2,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS)
@@ -243,14 +241,14 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "database_list",
/* ePragTyp: */ PragTyp_DATABASE_LIST,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0,
- /* ColNames: */ 26, 3,
+ /* ColNames: */ 35, 3,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
{/* zName: */ "default_cache_size",
/* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
- /* ColNames: */ 0, 1,
+ /* ColNames: */ 45, 1,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
@@ -280,14 +278,14 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "foreign_key_check",
/* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0,
- /* ColNames: */ 42, 4,
+ /* ColNames: */ 31, 4,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FOREIGN_KEY)
{/* zName: */ "foreign_key_list",
/* ePragTyp: */ PragTyp_FOREIGN_KEY_LIST,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
- /* ColNames: */ 34, 8,
+ /* ColNames: */ 0, 8,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
@@ -323,7 +321,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "function_list",
/* ePragTyp: */ PragTyp_FUNCTION_LIST,
/* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 29, 2,
+ /* ColNames: */ 41, 2,
/* iArg: */ 0 },
#endif
#endif
@@ -332,12 +330,12 @@ static const PragmaName aPragmaName[] = {
/* ePragTyp: */ PragTyp_HEXKEY,
/* ePragFlg: */ 0,
/* ColNames: */ 0, 0,
- /* iArg: */ 0 },
+ /* iArg: */ 2 },
{/* zName: */ "hexrekey",
/* ePragTyp: */ PragTyp_HEXKEY,
/* ePragFlg: */ 0,
/* ColNames: */ 0, 0,
- /* iArg: */ 0 },
+ /* iArg: */ 3 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
#if !defined(SQLITE_OMIT_CHECK)
@@ -359,12 +357,12 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "index_info",
/* ePragTyp: */ PragTyp_INDEX_INFO,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
- /* ColNames: */ 12, 3,
+ /* ColNames: */ 15, 3,
/* iArg: */ 0 },
{/* zName: */ "index_list",
/* ePragTyp: */ PragTyp_INDEX_LIST,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
- /* ColNames: */ 21, 5,
+ /* ColNames: */ 26, 5,
/* iArg: */ 0 },
{/* zName: */ "index_xinfo",
/* ePragTyp: */ PragTyp_INDEX_INFO,
@@ -421,7 +419,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "lock_status",
/* ePragTyp: */ PragTyp_LOCK_STATUS,
/* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 50, 2,
+ /* ColNames: */ 43, 2,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
@@ -447,7 +445,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "module_list",
/* ePragTyp: */ PragTyp_MODULE_LIST,
/* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 31, 1,
+ /* ColNames: */ 9, 1,
/* iArg: */ 0 },
#endif
#endif
@@ -480,7 +478,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "pragma_list",
/* ePragTyp: */ PragTyp_PRAGMA_LIST,
/* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 31, 1,
+ /* ColNames: */ 9, 1,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
@@ -511,10 +509,10 @@ static const PragmaName aPragmaName[] = {
#endif
#if defined(SQLITE_HAS_CODEC)
{/* zName: */ "rekey",
- /* ePragTyp: */ PragTyp_REKEY,
+ /* ePragTyp: */ PragTyp_KEY,
/* ePragFlg: */ 0,
/* ColNames: */ 0, 0,
- /* iArg: */ 0 },
+ /* iArg: */ 1 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
{/* zName: */ "reverse_unordered_selects",
@@ -567,7 +565,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "stats",
/* ePragTyp: */ PragTyp_STATS,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
- /* ColNames: */ 7, 5,
+ /* ColNames: */ 21, 5,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
@@ -581,8 +579,13 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "table_info",
/* ePragTyp: */ PragTyp_TABLE_INFO,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
- /* ColNames: */ 1, 6,
+ /* ColNames: */ 8, 6,
/* iArg: */ 0 },
+ {/* zName: */ "table_xinfo",
+ /* ePragTyp: */ PragTyp_TABLE_INFO,
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
+ /* ColNames: */ 8, 7,
+ /* iArg: */ 1 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
{/* zName: */ "temp_store",
@@ -596,6 +599,18 @@ static const PragmaName aPragmaName[] = {
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
#endif
+#if defined(SQLITE_HAS_CODEC)
+ {/* zName: */ "textkey",
+ /* ePragTyp: */ PragTyp_KEY,
+ /* ePragFlg: */ 0,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 4 },
+ {/* zName: */ "textrekey",
+ /* ePragTyp: */ PragTyp_KEY,
+ /* ePragFlg: */ 0,
+ /* ColNames: */ 0, 0,
+ /* iArg: */ 5 },
+#endif
{/* zName: */ "threads",
/* ePragTyp: */ PragTyp_THREADS,
/* ePragFlg: */ PragFlg_Result0,
@@ -646,7 +661,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "wal_checkpoint",
/* ePragTyp: */ PragTyp_WAL_CHECKPOINT,
/* ePragFlg: */ PragFlg_NeedSchema,
- /* ColNames: */ 46, 3,
+ /* ColNames: */ 38, 3,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
@@ -654,7 +669,7 @@ static const PragmaName aPragmaName[] = {
/* ePragTyp: */ PragTyp_FLAG,
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
/* ColNames: */ 0, 0,
- /* iArg: */ SQLITE_WriteSchema },
+ /* iArg: */ SQLITE_WriteSchema|SQLITE_NoSchemaError },
#endif
};
-/* Number of pragmas: 61 on by default, 78 total. */
+/* Number of pragmas: 63 on by default, 82 total. */
diff --git a/chromium/third_party/sqlite/src/src/prepare.c b/chromium/third_party/sqlite/src/src/prepare.c
index 76a7611ebd8..fe098cfa092 100644
--- a/chromium/third_party/sqlite/src/src/prepare.c
+++ b/chromium/third_party/sqlite/src/src/prepare.c
@@ -327,8 +327,8 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
rc = SQLITE_NOMEM_BKPT;
sqlite3ResetAllSchemasOfConnection(db);
}
- if( rc==SQLITE_OK || (db->flags&SQLITE_WriteSchema)){
- /* Black magic: If the SQLITE_WriteSchema flag is set, then consider
+ if( rc==SQLITE_OK || (db->flags&SQLITE_NoSchemaError)){
+ /* Black magic: If the SQLITE_NoSchemaError flag is set, then consider
** the schema loaded, even if errors occurred. In this situation the
** current sqlite3_prepare() operation will fail, but the following one
** will attempt to compile the supplied statement against whatever subset
@@ -709,6 +709,294 @@ static int sqlite3LockAndPrepare(
return rc;
}
+#ifdef SQLITE_ENABLE_NORMALIZE
+/*
+** Checks if the specified token is a table, column, or function name,
+** based on the databases associated with the statement being prepared.
+** If the function fails, zero is returned and pRc is filled with the
+** error code.
+*/
+static int shouldTreatAsIdentifier(
+ sqlite3 *db, /* Database handle. */
+ const char *zToken, /* Pointer to start of token to be checked */
+ int nToken, /* Length of token to be checked */
+ int *pRc /* Pointer to error code upon failure */
+){
+ int bFound = 0; /* Non-zero if token is an identifier name. */
+ int i, j; /* Database and column loop indexes. */
+ Schema *pSchema; /* Schema for current database. */
+ Hash *pHash; /* Hash table of tables for current database. */
+ HashElem *e; /* Hash element for hash table iteration. */
+ Table *pTab; /* Database table for columns being checked. */
+
+ if( sqlite3IsRowidN(zToken, nToken) ){
+ return 1;
+ }
+ if( nToken>0 ){
+ int hash = SQLITE_FUNC_HASH(sqlite3UpperToLower[(u8)zToken[0]], nToken);
+ if( sqlite3FunctionSearchN(hash, zToken, nToken) ) return 1;
+ }
+ assert( db!=0 );
+ sqlite3_mutex_enter(db->mutex);
+ sqlite3BtreeEnterAll(db);
+ for(i=0; i<db->nDb; i++){
+ pHash = &db->aFunc;
+ if( sqlite3HashFindN(pHash, zToken, nToken) ){
+ bFound = 1;
+ break;
+ }
+ pSchema = db->aDb[i].pSchema;
+ if( pSchema==0 ) continue;
+ pHash = &pSchema->tblHash;
+ if( sqlite3HashFindN(pHash, zToken, nToken) ){
+ bFound = 1;
+ break;
+ }
+ for(e=sqliteHashFirst(pHash); e; e=sqliteHashNext(e)){
+ pTab = sqliteHashData(e);
+ if( pTab==0 ) continue;
+ pHash = pTab->pColHash;
+ if( pHash==0 ){
+ pTab->pColHash = pHash = sqlite3_malloc(sizeof(Hash));
+ if( pHash ){
+ sqlite3HashInit(pHash);
+ for(j=0; j<pTab->nCol; j++){
+ Column *pCol = &pTab->aCol[j];
+ sqlite3HashInsert(pHash, pCol->zName, pCol);
+ }
+ }else{
+ *pRc = SQLITE_NOMEM_BKPT;
+ bFound = 0;
+ goto done;
+ }
+ }
+ if( pHash && sqlite3HashFindN(pHash, zToken, nToken) ){
+ bFound = 1;
+ goto done;
+ }
+ }
+ }
+done:
+ sqlite3BtreeLeaveAll(db);
+ sqlite3_mutex_leave(db->mutex);
+ return bFound;
+}
+
+/*
+** Attempt to estimate the final output buffer size needed for the fully
+** normalized version of the specified SQL string. This should take into
+** account any potential expansion that could occur (e.g. via IN clauses
+** being expanded, etc). This size returned is the total number of bytes
+** including the NUL terminator.
+*/
+static int estimateNormalizedSize(
+ const char *zSql, /* The original SQL string */
+ int nSql, /* Length of original SQL string */
+ u8 prepFlags /* The flags passed to sqlite3_prepare_v3() */
+){
+ int nOut = nSql + 4;
+ const char *z = zSql;
+ while( nOut<nSql*5 ){
+ while( z[0]!=0 && z[0]!='I' && z[0]!='i' ){ z++; }
+ if( z[0]==0 ) break;
+ z++;
+ if( z[0]!='N' && z[0]!='n' ) break;
+ z++;
+ while( sqlite3Isspace(z[0]) ){ z++; }
+ if( z[0]!='(' ) break;
+ z++;
+ nOut += 5; /* ?,?,? */
+ }
+ return nOut;
+}
+
+/*
+** Copy the current token into the output buffer while dealing with quoted
+** identifiers. By default, all letters will be converted into lowercase.
+** If the bUpper flag is set, uppercase will be used. The piOut argument
+** will be used to update the target index into the output string.
+*/
+static void copyNormalizedToken(
+ const char *zSql, /* The original SQL string */
+ int iIn, /* Current index into the original SQL string */
+ int nToken, /* Number of bytes in the current token */
+ int tokenFlags, /* Flags returned by the tokenizer */
+ char *zOut, /* The output string */
+ int *piOut /* Pointer to target index into the output string */
+){
+ int bQuoted = tokenFlags & SQLITE_TOKEN_QUOTED;
+ int bKeyword = tokenFlags & SQLITE_TOKEN_KEYWORD;
+ int j = *piOut, k = 0;
+ for(; k<nToken; k++){
+ if( bQuoted ){
+ if( k==0 && iIn>0 ){
+ zOut[j++] = '"';
+ continue;
+ }else if( k==nToken-1 ){
+ zOut[j++] = '"';
+ continue;
+ }
+ }
+ if( bKeyword ){
+ zOut[j++] = sqlite3Toupper(zSql[iIn+k]);
+ }else{
+ zOut[j++] = sqlite3Tolower(zSql[iIn+k]);
+ }
+ }
+ *piOut = j;
+}
+
+/*
+** Perform normalization of the SQL contained in the prepared statement and
+** store the result in the zNormSql field. The schema for the associated
+** databases are consulted while performing the normalization in order to
+** determine if a token appears to be an identifier. All identifiers are
+** left intact in the normalized SQL and all literals are replaced with a
+** single '?'.
+*/
+void sqlite3Normalize(
+ Vdbe *pVdbe, /* VM being reprepared */
+ const char *zSql, /* The original SQL string */
+ int nSql, /* Size of the input string in bytes */
+ u8 prepFlags /* The flags passed to sqlite3_prepare_v3() */
+){
+ sqlite3 *db; /* Database handle. */
+ char *z; /* The output string */
+ int nZ; /* Size of the output string in bytes */
+ int i; /* Next character to read from zSql[] */
+ int j; /* Next character to fill in on z[] */
+ int tokenType = 0; /* Type of the next token */
+ int prevTokenType = 0; /* Type of the previous token, except spaces */
+ int n; /* Size of the next token */
+ int nParen = 0; /* Nesting level of parenthesis */
+ Hash inHash; /* Table of parenthesis levels to output index. */
+
+ db = sqlite3VdbeDb(pVdbe);
+ assert( db!=0 );
+ assert( pVdbe->zNormSql==0 );
+ if( zSql==0 ) return;
+ nZ = estimateNormalizedSize(zSql, nSql, prepFlags);
+ z = sqlite3DbMallocRawNN(db, nZ);
+ if( z==0 ) return;
+ sqlite3HashInit(&inHash);
+ for(i=j=0; i<nSql && zSql[i]; i+=n){
+ int flags = 0;
+ if( tokenType!=TK_SPACE ) prevTokenType = tokenType;
+ n = sqlite3GetTokenNormalized((unsigned char*)zSql+i, &tokenType, &flags);
+ switch( tokenType ){
+ case TK_SPACE: {
+ break;
+ }
+ case TK_ILLEGAL: {
+ sqlite3DbFree(db, z);
+ sqlite3HashClear(&inHash);
+ return;
+ }
+ case TK_STRING:
+ case TK_INTEGER:
+ case TK_FLOAT:
+ case TK_VARIABLE:
+ case TK_BLOB: {
+ z[j++] = '?';
+ break;
+ }
+ case TK_LP:
+ case TK_RP: {
+ if( tokenType==TK_LP ){
+ nParen++;
+ if( prevTokenType==TK_IN ){
+ assert( nParen<nSql );
+ sqlite3HashInsert(&inHash, zSql+nParen, SQLITE_INT_TO_PTR(j));
+ }
+ }else{
+ int jj;
+ assert( nParen<nSql );
+ jj = SQLITE_PTR_TO_INT(sqlite3HashFind(&inHash, zSql+nParen));
+ if( jj>0 ){
+ sqlite3HashInsert(&inHash, zSql+nParen, 0);
+ assert( jj+6<nZ );
+ memcpy(z+jj+1, "?,?,?", 5);
+ j = jj+6;
+ assert( nZ-1-j>=0 );
+ assert( nZ-1-j<nZ );
+ memset(z+j, 0, nZ-1-j);
+ }
+ nParen--;
+ }
+ assert( nParen>=0 );
+ /* Fall through */
+ }
+ case TK_MINUS:
+ case TK_SEMI:
+ case TK_PLUS:
+ case TK_STAR:
+ case TK_SLASH:
+ case TK_REM:
+ case TK_EQ:
+ case TK_LE:
+ case TK_NE:
+ case TK_LSHIFT:
+ case TK_LT:
+ case TK_RSHIFT:
+ case TK_GT:
+ case TK_GE:
+ case TK_BITOR:
+ case TK_CONCAT:
+ case TK_COMMA:
+ case TK_BITAND:
+ case TK_BITNOT:
+ case TK_DOT:
+ case TK_IN:
+ case TK_IS:
+ case TK_NOT:
+ case TK_NULL:
+ case TK_ID: {
+ if( tokenType==TK_NULL ){
+ if( prevTokenType==TK_IS || prevTokenType==TK_NOT ){
+ /* NULL is a keyword in this case, not a literal value */
+ }else{
+ /* Here the NULL is a literal value */
+ z[j++] = '?';
+ break;
+ }
+ }
+ if( j>0 && sqlite3IsIdChar(z[j-1]) && sqlite3IsIdChar(zSql[i]) ){
+ z[j++] = ' ';
+ }
+ if( tokenType==TK_ID ){
+ int i2 = i, n2 = n, rc = SQLITE_OK;
+ if( nParen>0 ){
+ assert( nParen<nSql );
+ sqlite3HashInsert(&inHash, zSql+nParen, 0);
+ }
+ if( flags&SQLITE_TOKEN_QUOTED ){ i2++; n2-=2; }
+ if( shouldTreatAsIdentifier(db, zSql+i2, n2, &rc)==0 ){
+ if( rc!=SQLITE_OK ){
+ sqlite3DbFree(db, z);
+ sqlite3HashClear(&inHash);
+ return;
+ }
+ if( sqlite3_keyword_check(zSql+i2, n2)==0 ){
+ z[j++] = '?';
+ break;
+ }
+ }
+ }
+ copyNormalizedToken(zSql, i, n, flags, z, &j);
+ break;
+ }
+ }
+ }
+ assert( j<nZ && "one" );
+ while( j>0 && z[j-1]==' ' ){ j--; }
+ if( j>0 && z[j-1]!=';' ){ z[j++] = ';'; }
+ z[j] = 0;
+ assert( j<nZ && "two" );
+ pVdbe->zNormSql = z;
+ sqlite3HashClear(&inHash);
+}
+#endif /* SQLITE_ENABLE_NORMALIZE */
+
/*
** Rerun the compilation of a statement after a schema change.
**
diff --git a/chromium/third_party/sqlite/src/src/resolve.c b/chromium/third_party/sqlite/src/src/resolve.c
index 090a4b02a20..9d03e075d2b 100644
--- a/chromium/third_party/sqlite/src/src/resolve.c
+++ b/chromium/third_party/sqlite/src/src/resolve.c
@@ -159,7 +159,7 @@ int sqlite3MatchSpanName(
** (even if X is implied).
** pExpr->iTable Set to the cursor number for the table obtained
** from pSrcList.
-** pExpr->pTab Points to the Table structure of X.Y (even if
+** pExpr->y.pTab Points to the Table structure of X.Y (even if
** X and/or Y are implied.)
** pExpr->iColumn Set to the column number within the table.
** pExpr->op Set to TK_COLUMN.
@@ -203,7 +203,6 @@ static int lookupName(
/* Initialize the node to no-match */
pExpr->iTable = -1;
- pExpr->pTab = 0;
ExprSetVVAProperty(pExpr, EP_NoReduce);
/* Translate the schema name in zDb into a pointer to the corresponding
@@ -265,7 +264,7 @@ static int lookupName(
continue;
}
if( IN_RENAME_OBJECT && pItem->zAlias ){
- sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->pTab);
+ sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->y.pTab);
}
}
if( 0==(cntTab++) ){
@@ -291,13 +290,13 @@ static int lookupName(
}
if( pMatch ){
pExpr->iTable = pMatch->iCursor;
- pExpr->pTab = pMatch->pTab;
+ pExpr->y.pTab = pMatch->pTab;
/* RIGHT JOIN not (yet) supported */
assert( (pMatch->fg.jointype & JT_RIGHT)==0 );
if( (pMatch->fg.jointype & JT_LEFT)!=0 ){
ExprSetProperty(pExpr, EP_CanBeNull);
}
- pSchema = pExpr->pTab->pSchema;
+ pSchema = pExpr->y.pTab->pSchema;
}
} /* if( pSrcList ) */
@@ -354,7 +353,7 @@ static int lookupName(
testcase( iCol==(-1) );
if( IN_RENAME_OBJECT ){
pExpr->iColumn = iCol;
- pExpr->pTab = pTab;
+ pExpr->y.pTab = pTab;
eNewExprOp = TK_COLUMN;
}else{
pExpr->iTable = pNC->uNC.pUpsert->regData + iCol;
@@ -376,7 +375,7 @@ static int lookupName(
testcase( iCol==32 );
pParse->newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol));
}
- pExpr->pTab = pTab;
+ pExpr->y.pTab = pTab;
pExpr->iColumn = (i16)iCol;
eNewExprOp = TK_TRIGGER;
#endif /* SQLITE_OMIT_TRIGGER */
@@ -476,7 +475,7 @@ static int lookupName(
assert( pExpr->op==TK_ID );
if( ExprHasProperty(pExpr,EP_DblQuoted) ){
pExpr->op = TK_STRING;
- pExpr->pTab = 0;
+ pExpr->y.pTab = 0;
return WRC_Prune;
}
if( sqlite3ExprIdToTrueFalse(pExpr) ){
@@ -554,9 +553,9 @@ Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSrc, int iCol){
Expr *p = sqlite3ExprAlloc(db, TK_COLUMN, 0, 0);
if( p ){
struct SrcList_item *pItem = &pSrc->a[iSrc];
- p->pTab = pItem->pTab;
+ p->y.pTab = pItem->pTab;
p->iTable = pItem->iCursor;
- if( p->pTab->iPKey==iCol ){
+ if( p->y.pTab->iPKey==iCol ){
p->iColumn = -1;
}else{
p->iColumn = (ynVar)iCol;
@@ -646,7 +645,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
pItem = pSrcList->a;
assert( HasRowid(pItem->pTab) && pItem->pTab->pSelect==0 );
pExpr->op = TK_COLUMN;
- pExpr->pTab = pItem->pTab;
+ pExpr->y.pTab = pItem->pTab;
pExpr->iTable = pItem->iCursor;
pExpr->iColumn = -1;
pExpr->affinity = SQLITE_AFF_INTEGER;
@@ -690,9 +689,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
zColumn = pRight->u.zToken;
if( IN_RENAME_OBJECT ){
sqlite3RenameTokenRemap(pParse, (void*)pExpr, (void*)pRight);
- }
- if( IN_RENAME_OBJECT ){
- sqlite3RenameTokenRemap(pParse, (void*)&pExpr->pTab, (void*)pLeft);
+ sqlite3RenameTokenRemap(pParse, (void*)&pExpr->y.pTab, (void*)pLeft);
}
}
return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr);
@@ -774,6 +771,15 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
notValid(pParse, pNC, "non-deterministic functions",
NC_IdxExpr|NC_PartIdx);
}
+ if( (pDef->funcFlags & SQLITE_FUNC_INTERNAL)!=0
+ && pParse->nested==0
+ && sqlite3Config.bInternalFunctions==0
+ ){
+ /* Internal-use-only functions are disallowed unless the
+ ** SQL is being compiled using sqlite3NestedParse() */
+ no_such_func = 1;
+ pDef = 0;
+ }
}
if( 0==IN_RENAME_OBJECT ){
@@ -782,18 +788,18 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|| (pDef->xValue==0 && pDef->xInverse==0)
|| (pDef->xValue && pDef->xInverse && pDef->xSFunc && pDef->xFinalize)
);
- if( pDef && pDef->xValue==0 && pExpr->pWin ){
+ if( pDef && pDef->xValue==0 && ExprHasProperty(pExpr, EP_WinFunc) ){
sqlite3ErrorMsg(pParse,
"%.*s() may not be used as a window function", nId, zId
);
pNC->nErr++;
}else if(
(is_agg && (pNC->ncFlags & NC_AllowAgg)==0)
- || (is_agg && (pDef->funcFlags & SQLITE_FUNC_WINDOW) && !pExpr->pWin)
- || (is_agg && pExpr->pWin && (pNC->ncFlags & NC_AllowWin)==0)
+ || (is_agg && (pDef->funcFlags&SQLITE_FUNC_WINDOW) && !pExpr->y.pWin)
+ || (is_agg && pExpr->y.pWin && (pNC->ncFlags & NC_AllowWin)==0)
){
const char *zType;
- if( (pDef->funcFlags & SQLITE_FUNC_WINDOW) || pExpr->pWin ){
+ if( (pDef->funcFlags & SQLITE_FUNC_WINDOW) || pExpr->y.pWin ){
zType = "window";
}else{
zType = "aggregate";
@@ -823,7 +829,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
}
if( is_agg ){
#ifndef SQLITE_OMIT_WINDOWFUNC
- pNC->ncFlags &= ~(pExpr->pWin ? NC_AllowWin : NC_AllowAgg);
+ pNC->ncFlags &= ~(pExpr->y.pWin ? NC_AllowWin : NC_AllowAgg);
#else
pNC->ncFlags &= ~NC_AllowAgg;
#endif
@@ -832,17 +838,17 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
sqlite3WalkExprList(pWalker, pList);
if( is_agg ){
#ifndef SQLITE_OMIT_WINDOWFUNC
- if( pExpr->pWin ){
+ if( pExpr->y.pWin ){
Select *pSel = pNC->pWinSelect;
- sqlite3WalkExprList(pWalker, pExpr->pWin->pPartition);
- sqlite3WalkExprList(pWalker, pExpr->pWin->pOrderBy);
- sqlite3WalkExpr(pWalker, pExpr->pWin->pFilter);
- sqlite3WindowUpdate(pParse, pSel->pWinDefn, pExpr->pWin, pDef);
+ sqlite3WalkExprList(pWalker, pExpr->y.pWin->pPartition);
+ sqlite3WalkExprList(pWalker, pExpr->y.pWin->pOrderBy);
+ sqlite3WalkExpr(pWalker, pExpr->y.pWin->pFilter);
+ sqlite3WindowUpdate(pParse, pSel->pWinDefn, pExpr->y.pWin, pDef);
if( 0==pSel->pWin
- || 0==sqlite3WindowCompare(pParse, pSel->pWin, pExpr->pWin)
+ || 0==sqlite3WindowCompare(pParse, pSel->pWin, pExpr->y.pWin)
){
- pExpr->pWin->pNextWin = pSel->pWin;
- pSel->pWin = pExpr->pWin;
+ pExpr->y.pWin->pNextWin = pSel->pWin;
+ pSel->pWin = pExpr->y.pWin;
}
pNC->ncFlags |= NC_AllowWin;
}else
@@ -1265,13 +1271,13 @@ static int resolveOrderGroupBy(
for(j=0; j<pSelect->pEList->nExpr; j++){
if( sqlite3ExprCompare(0, pE, pSelect->pEList->a[j].pExpr, -1)==0 ){
#ifndef SQLITE_OMIT_WINDOWFUNC
- if( pE->pWin ){
+ if( ExprHasProperty(pE, EP_WinFunc) ){
/* Since this window function is being changed into a reference
** to the same window function the result set, remove the instance
** of this window function from the Select.pWin list. */
Window **pp;
for(pp=&pSelect->pWin; *pp; pp=&(*pp)->pNextWin){
- if( *pp==pE->pWin ){
+ if( *pp==pE->y.pWin ){
*pp = (*pp)->pNextWin;
}
}
diff --git a/chromium/third_party/sqlite/src/src/select.c b/chromium/third_party/sqlite/src/src/select.c
index db1c896c356..fab4df68fa1 100644
--- a/chromium/third_party/sqlite/src/src/select.c
+++ b/chromium/third_party/sqlite/src/src/select.c
@@ -803,7 +803,7 @@ static void selectExprDefer(
struct ExprList_item *pItem = &pEList->a[i];
if( pItem->u.x.iOrderByCol==0 ){
Expr *pExpr = pItem->pExpr;
- Table *pTab = pExpr->pTab;
+ Table *pTab = pExpr->y.pTab;
if( pExpr->op==TK_COLUMN && pExpr->iColumn>=0 && pTab && !IsVirtual(pTab)
&& (pTab->aCol[pExpr->iColumn].colFlags & COLFLAG_SORTERREF)
){
@@ -826,12 +826,12 @@ static void selectExprDefer(
Expr *pNew = sqlite3PExpr(pParse, TK_COLUMN, 0, 0);
if( pNew ){
pNew->iTable = pExpr->iTable;
- pNew->pTab = pExpr->pTab;
+ pNew->y.pTab = pExpr->y.pTab;
pNew->iColumn = pPk ? pPk->aiColumn[k] : -1;
pExtra = sqlite3ExprListAppend(pParse, pExtra, pNew);
}
}
- pSort->aDefer[nDefer].pTab = pExpr->pTab;
+ pSort->aDefer[nDefer].pTab = pExpr->y.pTab;
pSort->aDefer[nDefer].iCsr = pExpr->iTable;
pSort->aDefer[nDefer].nKey = nKey;
nDefer++;
@@ -1680,7 +1680,7 @@ static const char *columnTypeImpl(
break;
}
- assert( pTab && pExpr->pTab==pTab );
+ assert( pTab && pExpr->y.pTab==pTab );
if( pS ){
/* The "table" is actually a sub-select or a view in the FROM clause
** of the SELECT statement. Return the declaration type and origin
@@ -1865,7 +1865,7 @@ static void generateColumnNames(
assert( p!=0 );
assert( p->op!=TK_AGG_COLUMN ); /* Agg processing has not run yet */
- assert( p->op!=TK_COLUMN || p->pTab!=0 ); /* Covering idx not yet coded */
+ assert( p->op!=TK_COLUMN || p->y.pTab!=0 ); /* Covering idx not yet coded */
if( pEList->a[i].zName ){
/* An AS clause always takes first priority */
char *zName = pEList->a[i].zName;
@@ -1873,7 +1873,7 @@ static void generateColumnNames(
}else if( srcName && p->op==TK_COLUMN ){
char *zCol;
int iCol = p->iColumn;
- pTab = p->pTab;
+ pTab = p->y.pTab;
assert( pTab!=0 );
if( iCol<0 ) iCol = pTab->iPKey;
assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
@@ -1964,7 +1964,7 @@ int sqlite3ColumnsFromExprList(
if( pColExpr->op==TK_COLUMN ){
/* For columns use the column name name */
int iCol = pColExpr->iColumn;
- Table *pTab = pColExpr->pTab;
+ Table *pTab = pColExpr->y.pTab;
assert( pTab!=0 );
if( iCol<0 ) iCol = pTab->iPKey;
zName = iCol>=0 ? pTab->aCol[iCol].zName : "rowid";
@@ -5464,14 +5464,19 @@ static struct SrcList_item *isSelfJoinView(
){
struct SrcList_item *pItem;
for(pItem = pTabList->a; pItem<pThis; pItem++){
+ Select *pS1;
if( pItem->pSelect==0 ) continue;
if( pItem->fg.viaCoroutine ) continue;
if( pItem->zName==0 ) continue;
if( sqlite3_stricmp(pItem->zDatabase, pThis->zDatabase)!=0 ) continue;
if( sqlite3_stricmp(pItem->zName, pThis->zName)!=0 ) continue;
- if( sqlite3ExprCompare(0,
- pThis->pSelect->pWhere, pItem->pSelect->pWhere, -1)
- ){
+ pS1 = pItem->pSelect;
+ if( pThis->pSelect->selId!=pS1->selId ){
+ /* The query flattener left two different CTE tables with identical
+ ** names in the same FROM clause. */
+ continue;
+ }
+ if( sqlite3ExprCompare(0, pThis->pSelect->pWhere, pS1->pWhere, -1) ){
/* The view was modified by some other optimization such as
** pushDownWhereTerms() */
continue;
diff --git a/chromium/third_party/sqlite/src/src/shell.c.in b/chromium/third_party/sqlite/src/src/shell.c.in
index 28d3d82a420..b13551dc61f 100644
--- a/chromium/third_party/sqlite/src/src/shell.c.in
+++ b/chromium/third_party/sqlite/src/src/shell.c.in
@@ -1059,11 +1059,12 @@ struct ShellState {
/* Allowed values for ShellState.openMode
*/
-#define SHELL_OPEN_UNSPEC 0 /* No open-mode specified */
-#define SHELL_OPEN_NORMAL 1 /* Normal database file */
-#define SHELL_OPEN_APPENDVFS 2 /* Use appendvfs */
-#define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */
-#define SHELL_OPEN_READONLY 4 /* Open a normal database read-only */
+#define SHELL_OPEN_UNSPEC 0 /* No open-mode specified */
+#define SHELL_OPEN_NORMAL 1 /* Normal database file */
+#define SHELL_OPEN_APPENDVFS 2 /* Use appendvfs */
+#define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */
+#define SHELL_OPEN_READONLY 4 /* Open a normal database read-only */
+#define SHELL_OPEN_DESERIALIZE 5 /* Open using sqlite3_deserialize() */
/*
** These are the allowed shellFlgs values
@@ -1273,7 +1274,7 @@ static void editFunc(
if( bBin ){
sqlite3_result_blob64(context, p, sz, sqlite3_free);
}else{
- int i, j;
+ sqlite3_int64 i, j;
if( hasCRNL ){
/* If the original contains \r\n then do no conversions back to \n */
j = sz;
@@ -3335,137 +3336,238 @@ static int run_schema_dump_query(
}
/*
-** Text of a help message
+** Text of help messages.
+**
+** The help text for each individual command begins with a line that starts
+** with ".". Subsequent lines are supplimental information.
+**
+** There must be two or more spaces between the end of the command and the
+** start of the description of what that command does.
*/
-static char zHelp[] =
+static const char *(azHelp[]) = {
#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
- ".archive ... Manage SQL archives: \".archive --help\" for details\n"
+ ".archive ... Manage SQL archives",
+ " Each command must have exactly one of the following options:",
+ " -c, --create Create a new archive",
+ " -u, --update Update or add files to an existing archive",
+ " -t, --list List contents of archive",
+ " -x, --extract Extract files from archive",
+ " Optional arguments:",
+ " -v, --verbose Print each filename as it is processed",
+ " -f FILE, --file FILE Operate on archive FILE (default is current db)",
+ " -a FILE, --append FILE Operate on FILE opened using the apndvfs VFS",
+ " -C DIR, --directory DIR Change to directory DIR to read/extract files",
+ " -n, --dryrun Show the SQL that would have occurred",
+ " Examples:",
+ " .ar -cf archive.sar foo bar # Create archive.sar from files foo and bar",
+ " .ar -tf archive.sar # List members of archive.sar",
+ " .ar -xvf archive.sar # Verbosely extract files from archive.sar",
+ " See also:",
+ " http://sqlite.org/cli.html#sqlar_archive_support",
#endif
#ifndef SQLITE_OMIT_AUTHORIZATION
- ".auth ON|OFF Show authorizer callbacks\n"
+ ".auth ON|OFF Show authorizer callbacks",
#endif
- ".backup ?DB? FILE Backup DB (default \"main\") to FILE\n"
- " Add \"--append\" to open using appendvfs.\n"
- ".bail on|off Stop after hitting an error. Default OFF\n"
- ".binary on|off Turn binary output on or off. Default OFF\n"
- ".cd DIRECTORY Change the working directory to DIRECTORY\n"
- ".changes on|off Show number of rows changed by SQL\n"
- ".check GLOB Fail if output since .testcase does not match\n"
- ".clone NEWDB Clone data into NEWDB from the existing database\n"
- ".databases List names and files of attached databases\n"
- ".dbconfig ?op? ?val? List or change sqlite3_db_config() options\n"
- ".dbinfo ?DB? Show status information about the database\n"
- ".dump ?TABLE? ... Dump the database in an SQL text format\n"
- " If TABLE specified, only dump tables matching\n"
- " LIKE pattern TABLE.\n"
- ".echo on|off Turn command echo on or off\n"
- ".eqp on|off|full Enable or disable automatic EXPLAIN QUERY PLAN\n"
- ".excel Display the output of next command in a spreadsheet\n"
- ".exit Exit this program\n"
- ".expert EXPERIMENTAL. Suggest indexes for specified queries\n"
+ ".backup ?DB? FILE Backup DB (default \"main\") to FILE",
+ " --append Use the appendvfs",
+ ".bail on|off Stop after hitting an error. Default OFF",
+ ".binary on|off Turn binary output on or off. Default OFF",
+ ".cd DIRECTORY Change the working directory to DIRECTORY",
+ ".changes on|off Show number of rows changed by SQL",
+ ".check GLOB Fail if output since .testcase does not match",
+ ".clone NEWDB Clone data into NEWDB from the existing database",
+ ".databases List names and files of attached databases",
+ ".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
+ ".dbinfo ?DB? Show status information about the database",
+ ".dump ?TABLE? ... Render all database content as SQL",
+ " Options:",
+ " --preserve-rowids Include ROWID values in the output",
+ " --newlines Allow unescaped newline characters in output",
+ " TABLE is LIKE pattern for the tables to dump",
+ ".echo on|off Turn command echo on or off",
+ ".eqp on|off|full Enable or disable automatic EXPLAIN QUERY PLAN",
+ ".excel Display the output of next command in a spreadsheet",
+ ".exit ?CODE? Exit this program with return-code CODE",
+ ".expert EXPERIMENTAL. Suggest indexes for specified queries",
/* Because explain mode comes on automatically now, the ".explain" mode
** is removed from the help screen. It is still supported for legacy, however */
-/*".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic\n"*/
- ".fullschema ?--indent? Show schema and the content of sqlite_stat tables\n"
- ".headers on|off Turn display of headers on or off\n"
- ".help Show this message\n"
- ".import FILE TABLE Import data from FILE into TABLE\n"
+/*".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic",*/
+ ".fullschema ?--indent? Show schema and the content of sqlite_stat tables",
+ ".headers on|off Turn display of headers on or off",
+ ".help ?-all? ?PATTERN? Show help text for PATTERN",
+ ".import FILE TABLE Import data from FILE into TABLE",
#ifndef SQLITE_OMIT_TEST_CONTROL
- ".imposter INDEX TABLE Create imposter table TABLE on index INDEX\n"
+ ".imposter INDEX TABLE Create imposter table TABLE on index INDEX",
#endif
- ".indexes ?TABLE? Show names of all indexes\n"
- " If TABLE specified, only show indexes for tables\n"
- " matching LIKE pattern TABLE.\n"
+ ".indexes ?TABLE? Show names of indexes",
+ " If TABLE is specified, only show indexes for",
+ " tables matching TABLE using the LIKE operator.",
#ifdef SQLITE_ENABLE_IOTRACE
- ".iotrace FILE Enable I/O diagnostic logging to FILE\n"
+ ".iotrace FILE Enable I/O diagnostic logging to FILE",
#endif
- ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT\n"
- ".lint OPTIONS Report potential schema issues. Options:\n"
- " fkey-indexes Find missing foreign key indexes\n"
+ ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT",
+ ".lint OPTIONS Report potential schema issues.",
+ " Options:",
+ " fkey-indexes Find missing foreign key indexes",
#ifndef SQLITE_OMIT_LOAD_EXTENSION
- ".load FILE ?ENTRY? Load an extension library\n"
+ ".load FILE ?ENTRY? Load an extension library",
#endif
- ".log FILE|off Turn logging on or off. FILE can be stderr/stdout\n"
- ".mode MODE ?TABLE? Set output mode where MODE is one of:\n"
- " ascii Columns/rows delimited by 0x1F and 0x1E\n"
- " csv Comma-separated values\n"
- " column Left-aligned columns. (See .width)\n"
- " html HTML <table> code\n"
- " insert SQL insert statements for TABLE\n"
- " line One value per line\n"
- " list Values delimited by \"|\"\n"
- " quote Escape answers as for SQL\n"
- " tabs Tab-separated values\n"
- " tcl TCL list elements\n"
- ".nullvalue STRING Use STRING in place of NULL values\n"
- ".once (-e|-x|FILE) Output for the next SQL command only to FILE\n"
- " or invoke system text editor (-e) or spreadsheet (-x)\n"
- " on the output.\n"
- ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE\n"
- " The --new option starts with an empty file\n"
- " Other options: --readonly --append --zip\n"
- ".output ?FILE? Send output to FILE or stdout\n"
- ".print STRING... Print literal STRING\n"
- ".prompt MAIN CONTINUE Replace the standard prompts\n"
- ".quit Exit this program\n"
- ".read FILENAME Execute SQL in FILENAME\n"
- ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n"
- ".save FILE Write in-memory database into FILE\n"
- ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off\n"
- ".schema ?PATTERN? Show the CREATE statements matching PATTERN\n"
- " Add --indent for pretty-printing\n"
- ".selftest ?--init? Run tests defined in the SELFTEST table\n"
- ".separator COL ?ROW? Change the column separator and optionally the row\n"
- " separator for both the output mode and .import\n"
+ ".log FILE|off Turn logging on or off. FILE can be stderr/stdout",
+ ".mode MODE ?TABLE? Set output mode",
+ " MODE is one of:",
+ " ascii Columns/rows delimited by 0x1F and 0x1E",
+ " csv Comma-separated values",
+ " column Left-aligned columns. (See .width)",
+ " html HTML <table> code",
+ " insert SQL insert statements for TABLE",
+ " line One value per line",
+ " list Values delimited by \"|\"",
+ " quote Escape answers as for SQL",
+ " tabs Tab-separated values",
+ " tcl TCL list elements",
+ ".nullvalue STRING Use STRING in place of NULL values",
+ ".once (-e|-x|FILE) Output for the next SQL command only to FILE",
+ " If FILE begins with '|' then open as a pipe",
+ " Other options:",
+ " -e Invoke system text editor",
+ " -x Open in a spreadsheet",
+ ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE",
+ " Options:",
+ " --append Use appendvfs to append database to the end of FILE",
+#ifdef SQLITE_ENABLE_DESERIALIZE
+ " --deserialize Load into memory useing sqlite3_deserialize()",
+#endif
+ " --new Initialize FILE to an empty database",
+ " --readonly Open FILE readonly",
+ " --zip FILE is a ZIP archive",
+ ".output ?FILE? Send output to FILE or stdout if FILE is omitted",
+ " If FILE begins with '|' then open it as a pipe.",
+ ".print STRING... Print literal STRING",
+ ".prompt MAIN CONTINUE Replace the standard prompts",
+ ".quit Exit this program",
+ ".read FILE Read input from FILE",
+ ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE",
+ ".save FILE Write in-memory database into FILE",
+ ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off",
+ ".schema ?PATTERN? Show the CREATE statements matching PATTERN",
+ " Options:",
+ " --indent Try to pretty-print the schema",
+ ".selftest ?OPTIONS? Run tests defined in the SELFTEST table",
+ " Options:",
+ " --init Create a new SELFTEST table",
+ " -v Verbose output",
+ ".separator COL ?ROW? Change the column and row separators",
#if defined(SQLITE_ENABLE_SESSION)
- ".session CMD ... Create or control sessions\n"
+ ".session ?NAME? CMD ... Create or control sessions",
+ " Subcommands:",
+ " attach TABLE Attach TABLE",
+ " changeset FILE Write a changeset into FILE",
+ " close Close one session",
+ " enable ?BOOLEAN? Set or query the enable bit",
+ " filter GLOB... Reject tables matching GLOBs",
+ " indirect ?BOOLEAN? Mark or query the indirect status",
+ " isempty Query whether the session is empty",
+ " list List currently open session names",
+ " open DB NAME Open a new session on DB",
+ " patchset FILE Write a patchset into FILE",
+ " If ?NAME? is omitted, the first defined session is used.",
#endif
- ".sha3sum ?OPTIONS...? Compute a SHA3 hash of database content\n"
+ ".sha3sum ... Compute a SHA3 hash of database content",
+ " Options:",
+ " --schema Also hash the sqlite_master table",
+ " --sha3-224 Use the sha3-224 algorithm",
+ " --sha3-256 Use the sha3-256 algorithm. This is the default.",
+ " --sha3-384 Use the sha3-384 algorithm",
+ " --sha3-512 Use the sha3-512 algorithm",
+ " Any other argument is a LIKE pattern for tables to hash",
#ifndef SQLITE_NOHAVE_SYSTEM
- ".shell CMD ARGS... Run CMD ARGS... in a system shell\n"
+ ".shell CMD ARGS... Run CMD ARGS... in a system shell",
#endif
- ".show Show the current values for various settings\n"
- ".stats ?on|off? Show stats or turn stats on or off\n"
+ ".show Show the current values for various settings",
+ ".stats ?on|off? Show stats or turn stats on or off",
#ifndef SQLITE_NOHAVE_SYSTEM
- ".system CMD ARGS... Run CMD ARGS... in a system shell\n"
+ ".system CMD ARGS... Run CMD ARGS... in a system shell",
#endif
- ".tables ?TABLE? List names of tables\n"
- " If TABLE specified, only list tables matching\n"
- " LIKE pattern TABLE.\n"
- ".testcase NAME Begin redirecting output to 'testcase-out.txt'\n"
- ".timeout MS Try opening locked tables for MS milliseconds\n"
- ".timer on|off Turn SQL timer on or off\n"
- ".trace FILE|off Output each SQL statement as it is run\n"
- ".vfsinfo ?AUX? Information about the top-level VFS\n"
- ".vfslist List all available VFSes\n"
- ".vfsname ?AUX? Print the name of the VFS stack\n"
- ".width NUM1 NUM2 ... Set column widths for \"column\" mode\n"
- " Negative values right-justify\n"
-;
+ ".tables ?TABLE? List names of tables matching LIKE pattern TABLE",
+ ".testcase NAME Begin redirecting output to 'testcase-out.txt'",
+ ".timeout MS Try opening locked tables for MS milliseconds",
+ ".timer on|off Turn SQL timer on or off",
+ ".trace FILE|off Output each SQL statement as it is run",
+ ".vfsinfo ?AUX? Information about the top-level VFS",
+ ".vfslist List all available VFSes",
+ ".vfsname ?AUX? Print the name of the VFS stack",
+ ".width NUM1 NUM2 ... Set column widths for \"column\" mode",
+ " Negative values right-justify",
+};
-#if defined(SQLITE_ENABLE_SESSION)
/*
-** Print help information for the ".sessions" command
-*/
-void session_help(ShellState *p){
- raw_printf(p->out,
- ".session ?NAME? SUBCOMMAND ?ARGS...?\n"
- "If ?NAME? is omitted, the first defined session is used.\n"
- "Subcommands:\n"
- " attach TABLE Attach TABLE\n"
- " changeset FILE Write a changeset into FILE\n"
- " close Close one session\n"
- " enable ?BOOLEAN? Set or query the enable bit\n"
- " filter GLOB... Reject tables matching GLOBs\n"
- " indirect ?BOOLEAN? Mark or query the indirect status\n"
- " isempty Query whether the session is empty\n"
- " list List currently open session names\n"
- " open DB NAME Open a new session on DB\n"
- " patchset FILE Write a patchset into FILE\n"
- );
+** Output help text.
+**
+** zPattern describes the set of commands for which help text is provided.
+** If zPattern is NULL, then show all commands, but only give a one-line
+** description of each.
+**
+** Return the number of matches.
+*/
+static int showHelp(FILE *out, const char *zPattern){
+ int i = 0;
+ int j = 0;
+ int n = 0;
+ char *zPat;
+ if( zPattern==0
+ || zPattern[0]=='0'
+ || strcmp(zPattern,"-a")==0
+ || strcmp(zPattern,"-all")==0
+ ){
+ /* Show all commands, but only one line per command */
+ if( zPattern==0 ) zPattern = "";
+ for(i=0; i<ArraySize(azHelp); i++){
+ if( azHelp[i][0]=='.' || zPattern[0] ){
+ utf8_printf(out, "%s\n", azHelp[i]);
+ n++;
+ }
+ }
+ }else{
+ /* Look for commands that for which zPattern is an exact prefix */
+ zPat = sqlite3_mprintf(".%s*", zPattern);
+ for(i=0; i<ArraySize(azHelp); i++){
+ if( sqlite3_strglob(zPat, azHelp[i])==0 ){
+ utf8_printf(out, "%s\n", azHelp[i]);
+ j = i+1;
+ n++;
+ }
+ }
+ sqlite3_free(zPat);
+ if( n ){
+ if( n==1 ){
+ /* when zPattern is a prefix of exactly one command, then include the
+ ** details of that command, which should begin at offset j */
+ while( j<ArraySize(azHelp)-1 && azHelp[j][0]!='.' ){
+ utf8_printf(out, "%s\n", azHelp[j]);
+ j++;
+ }
+ }
+ return n;
+ }
+ /* Look for commands that contain zPattern anywhere. Show the complete
+ ** text of all commands that match. */
+ zPat = sqlite3_mprintf("%%%s%%", zPattern);
+ for(i=0; i<ArraySize(azHelp); i++){
+ if( azHelp[i][0]=='.' ) j = i;
+ if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){
+ utf8_printf(out, "%s\n", azHelp[j]);
+ while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]!='.' ){
+ j++;
+ utf8_printf(out, "%s\n", azHelp[j]);
+ }
+ i = j;
+ n++;
+ }
+ }
+ sqlite3_free(zPat);
+ }
+ return n;
}
-#endif
-
/* Forward reference */
static int process_input(ShellState *p, FILE *in);
@@ -3495,7 +3597,7 @@ static char *readFile(const char *zName, int *pnByte){
nIn = ftell(in);
rewind(in);
pBuf = sqlite3_malloc64( nIn+1 );
- if( pBuf==0 ) return 0;
+ if( pBuf==0 ){ fclose(in); return 0; }
nRead = fread(pBuf, nIn, 1, in);
fclose(in);
if( nRead!=1 ){
@@ -3575,6 +3677,11 @@ int deduceDatabaseType(const char *zName, int dfltZip){
return SHELL_OPEN_NORMAL;
}
}
+ n = fread(zBuf, 16, 1, f);
+ if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){
+ fclose(f);
+ return SHELL_OPEN_NORMAL;
+ }
fseek(f, -25, SEEK_END);
n = fread(zBuf, 25, 1, f);
if( n==1 && memcmp(zBuf, "Start-Of-SQLite3-", 17)==0 ){
@@ -3626,6 +3733,10 @@ static void open_db(ShellState *p, int openFlags){
SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, "apndvfs");
break;
}
+ case SHELL_OPEN_DESERIALIZE: {
+ sqlite3_open(0, &p->db);
+ break;
+ }
case SHELL_OPEN_ZIPFILE: {
sqlite3_open(":memory:", &p->db);
break;
@@ -3675,6 +3786,18 @@ static void open_db(ShellState *p, int openFlags){
sqlite3_exec(p->db, zSql, 0, 0, 0);
sqlite3_free(zSql);
}
+#ifdef SQLITE_ENABLE_DESERIALIZE
+ else if( p->openMode==SHELL_OPEN_DESERIALIZE ){
+ int nData = 0;
+ unsigned char *aData = (unsigned char*)readFile(p->zDbFilename, &nData);
+ int rc = sqlite3_deserialize(p->db, "main", aData, nData, nData,
+ SQLITE_DESERIALIZE_RESIZEABLE |
+ SQLITE_DESERIALIZE_FREEONCLOSE);
+ if( rc ){
+ utf8_printf(stderr, "Error: sqlite3_deserialize() returns %d\n", rc);
+ }
+ }
+#endif
}
}
@@ -4879,6 +5002,7 @@ static void shellPreparePrintf(
char *z;
va_start(ap, zFmt);
z = sqlite3_vmprintf(zFmt, ap);
+ va_end(ap);
if( z==0 ){
*pRc = SQLITE_NOMEM;
}else{
@@ -4941,32 +5065,7 @@ struct ArCommand {
** Print a usage message for the .ar command to stderr and return SQLITE_ERROR.
*/
static int arUsage(FILE *f){
- raw_printf(f,
-"\n"
-"Usage: .ar [OPTION...] [FILE...]\n"
-"The .ar command manages sqlar archives.\n"
-"\n"
-"Examples:\n"
-" .ar -cf archive.sar foo bar # Create archive.sar from files foo and bar\n"
-" .ar -tf archive.sar # List members of archive.sar\n"
-" .ar -xvf archive.sar # Verbosely extract files from archive.sar\n"
-"\n"
-"Each command line must feature exactly one command option:\n"
-" -c, --create Create a new archive\n"
-" -u, --update Update or add files to an existing archive\n"
-" -t, --list List contents of archive\n"
-" -x, --extract Extract files from archive\n"
-"\n"
-"And zero or more optional options:\n"
-" -v, --verbose Print each filename as it is processed\n"
-" -f FILE, --file FILE Operate on archive FILE (default is current db)\n"
-" -a FILE, --append FILE Operate on FILE opened using the apndvfs VFS\n"
-" -C DIR, --directory DIR Change to directory DIR to read/extract files\n"
-" -n, --dryrun Show the SQL that would have occurred\n"
-"\n"
-"See also: http://sqlite.org/cli.html#sqlar_archive_support\n"
-"\n"
-);
+ showHelp(f,"archive");
return SQLITE_ERROR;
}
@@ -5073,6 +5172,7 @@ static int arParseCommand(
struct ArSwitch *pEnd = &aSwitch[nSwitch];
if( nArg<=1 ){
+ utf8_printf(stderr, "Wrong number of arguments. Usage:\n");
return arUsage(stderr);
}else{
char *z = azArg[1];
@@ -5844,7 +5944,10 @@ static int do_meta_command(char *zLine, ShellState *p){
}else
if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){
- static const struct DbConfigChoices {const char *zName; int op;} aDbConfig[] = {
+ static const struct DbConfigChoices {
+ const char *zName;
+ int op;
+ } aDbConfig[] = {
{ "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY },
{ "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER },
{ "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
@@ -5853,6 +5956,7 @@ static int do_meta_command(char *zLine, ShellState *p){
{ "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG },
{ "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP },
{ "reset_database", SQLITE_DBCONFIG_RESET_DATABASE },
+ { "defensive", SQLITE_DBCONFIG_DEFENSIVE },
};
int ii, v;
open_db(p, 0);
@@ -6091,7 +6195,14 @@ static int do_meta_command(char *zLine, ShellState *p){
}else
if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
- utf8_printf(p->out, "%s", zHelp);
+ if( nArg>=2 ){
+ n = showHelp(p->out, azArg[1]);
+ if( n==0 ){
+ utf8_printf(p->out, "Nothing matches '%s'\n", azArg[1]);
+ }
+ }else{
+ showHelp(p->out, 0);
+ }
}else
if( c=='i' && strncmp(azArg[0], "import", n)==0 ){
@@ -6568,6 +6679,10 @@ static int do_meta_command(char *zLine, ShellState *p){
p->openMode = SHELL_OPEN_APPENDVFS;
}else if( optionMatch(z, "readonly") ){
p->openMode = SHELL_OPEN_READONLY;
+#ifdef SQLITE_ENABLE_DESERIALIZE
+ }else if( optionMatch(z, "deserialize") ){
+ p->openMode = SHELL_OPEN_DESERIALIZE;
+#endif
}else if( z[0]=='-' ){
utf8_printf(stderr, "unknown option: %s\n", z);
rc = 1;
@@ -7095,7 +7210,7 @@ static int do_meta_command(char *zLine, ShellState *p){
}else
/* If no command name matches, show a syntax error */
session_syntax_error:
- session_help(p);
+ showHelp(p->out, "session");
}else
#endif
@@ -7562,6 +7677,7 @@ static int do_meta_command(char *zLine, ShellState *p){
{ "byteorder", SQLITE_TESTCTRL_BYTEORDER, "" },
/*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, "" }, */
{ "imposter", SQLITE_TESTCTRL_IMPOSTER, "SCHEMA ON/OFF ROOTPAGE"},
+ { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, "BOOLEAN" },
{ "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN" },
{ "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN" },
{ "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK" },
@@ -7656,6 +7772,7 @@ static int do_meta_command(char *zLine, ShellState *p){
/* sqlite3_test_control(int, int) */
case SQLITE_TESTCTRL_ASSERT:
case SQLITE_TESTCTRL_ALWAYS:
+ case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS:
if( nArg==3 ){
int opt = booleanValue(azArg[2]);
rc2 = sqlite3_test_control(testctrl, opt);
@@ -7950,7 +8067,7 @@ static int line_is_command_terminator(const char *zLine){
** user-friendly, but it does seem to work.
*/
#ifdef SQLITE_OMIT_COMPLETE
-int sqlite3_complete(const char *zSql){ return 1; }
+#define sqlite3_complete(x) 1
#endif
/*
@@ -8546,6 +8663,10 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
#endif
}else if( strcmp(z,"-append")==0 ){
data.openMode = SHELL_OPEN_APPENDVFS;
+#ifdef SQLITE_ENABLE_DESERIALIZE
+ }else if( strcmp(z,"-deserialize")==0 ){
+ data.openMode = SHELL_OPEN_DESERIALIZE;
+#endif
}else if( strcmp(z,"-readonly")==0 ){
data.openMode = SHELL_OPEN_READONLY;
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
@@ -8641,6 +8762,10 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
#endif
}else if( strcmp(z,"-append")==0 ){
data.openMode = SHELL_OPEN_APPENDVFS;
+#ifdef SQLITE_ENABLE_DESERIALIZE
+ }else if( strcmp(z,"-deserialize")==0 ){
+ data.openMode = SHELL_OPEN_DESERIALIZE;
+#endif
}else if( strcmp(z,"-readonly")==0 ){
data.openMode = SHELL_OPEN_READONLY;
}else if( strcmp(z,"-ascii")==0 ){
@@ -8785,7 +8910,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
*/
if( stdin_is_interactive ){
char *zHome;
- char *zHistory = 0;
+ char *zHistory;
int nHistory;
printf(
"SQLite version %s %.19s\n" /*extra-version-info*/
@@ -8798,8 +8923,10 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
printf(".\nUse \".open FILENAME\" to reopen on a "
"persistent database.\n");
}
- zHome = find_home_dir(0);
- if( zHome ){
+ zHistory = getenv("SQLITE_HISTORY");
+ if( zHistory ){
+ zHistory = strdup(zHistory);
+ }else if( (zHome = find_home_dir(0))!=0 ){
nHistory = strlen30(zHome) + 20;
if( (zHistory = malloc(nHistory))!=0 ){
sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome);
diff --git a/chromium/third_party/sqlite/src/src/sqlite.h.in b/chromium/third_party/sqlite/src/src/sqlite.h.in
index 620f10e631c..11622a49697 100644
--- a/chromium/third_party/sqlite/src/src/sqlite.h.in
+++ b/chromium/third_party/sqlite/src/src/sqlite.h.in
@@ -2017,6 +2017,7 @@ struct sqlite3_mem_methods {
** is invoked.
**
** <dl>
+** [[SQLITE_DBCONFIG_LOOKASIDE]]
** <dt>SQLITE_DBCONFIG_LOOKASIDE</dt>
** <dd> ^This option takes three additional arguments that determine the
** [lookaside memory allocator] configuration for the [database connection].
@@ -2039,6 +2040,7 @@ struct sqlite3_mem_methods {
** memory is in use leaves the configuration unchanged and returns
** [SQLITE_BUSY].)^</dd>
**
+** [[SQLITE_DBCONFIG_ENABLE_FKEY]]
** <dt>SQLITE_DBCONFIG_ENABLE_FKEY</dt>
** <dd> ^This option is used to enable or disable the enforcement of
** [foreign key constraints]. There should be two additional arguments.
@@ -2049,6 +2051,7 @@ struct sqlite3_mem_methods {
** following this call. The second parameter may be a NULL pointer, in
** which case the FK enforcement setting is not reported back. </dd>
**
+** [[SQLITE_DBCONFIG_ENABLE_TRIGGER]]
** <dt>SQLITE_DBCONFIG_ENABLE_TRIGGER</dt>
** <dd> ^This option is used to enable or disable [CREATE TRIGGER | triggers].
** There should be two additional arguments.
@@ -2059,6 +2062,7 @@ struct sqlite3_mem_methods {
** following this call. The second parameter may be a NULL pointer, in
** which case the trigger setting is not reported back. </dd>
**
+** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]]
** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt>
** <dd> ^This option is used to enable or disable the two-argument
** version of the [fts3_tokenizer()] function which is part of the
@@ -2072,6 +2076,7 @@ struct sqlite3_mem_methods {
** following this call. The second parameter may be a NULL pointer, in
** which case the new setting is not reported back. </dd>
**
+** [[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION]]
** <dt>SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION</dt>
** <dd> ^This option is used to enable or disable the [sqlite3_load_extension()]
** interface independently of the [load_extension()] SQL function.
@@ -2089,7 +2094,7 @@ struct sqlite3_mem_methods {
** be a NULL pointer, in which case the new setting is not reported back.
** </dd>
**
-** <dt>SQLITE_DBCONFIG_MAINDBNAME</dt>
+** [[SQLITE_DBCONFIG_MAINDBNAME]] <dt>SQLITE_DBCONFIG_MAINDBNAME</dt>
** <dd> ^This option is used to change the name of the "main" database
** schema. ^The sole argument is a pointer to a constant UTF8 string
** which will become the new schema name in place of "main". ^SQLite
@@ -2098,6 +2103,7 @@ struct sqlite3_mem_methods {
** until after the database connection closes.
** </dd>
**
+** [[SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE]]
** <dt>SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE</dt>
** <dd> Usually, when a database in wal mode is closed or detached from a
** database handle, SQLite checks if this will mean that there are now no
@@ -2111,7 +2117,7 @@ struct sqlite3_mem_methods {
** have been disabled - 0 if they are not disabled, 1 if they are.
** </dd>
**
-** <dt>SQLITE_DBCONFIG_ENABLE_QPSG</dt>
+** [[SQLITE_DBCONFIG_ENABLE_QPSG]] <dt>SQLITE_DBCONFIG_ENABLE_QPSG</dt>
** <dd>^(The SQLITE_DBCONFIG_ENABLE_QPSG option activates or deactivates
** the [query planner stability guarantee] (QPSG). When the QPSG is active,
** a single SQL query statement will always use the same algorithm regardless
@@ -2127,7 +2133,7 @@ struct sqlite3_mem_methods {
** following this call.
** </dd>
**
-** <dt>SQLITE_DBCONFIG_TRIGGER_EQP</dt>
+** [[SQLITE_DBCONFIG_TRIGGER_EQP]] <dt>SQLITE_DBCONFIG_TRIGGER_EQP</dt>
** <dd> By default, the output of EXPLAIN QUERY PLAN commands does not
** include output for any operations performed by trigger programs. This
** option is used to set or clear (the default) a flag that governs this
@@ -2139,7 +2145,7 @@ struct sqlite3_mem_methods {
** it is not disabled, 1 if it is.
** </dd>
**
-** <dt>SQLITE_DBCONFIG_RESET_DATABASE</dt>
+** [[SQLITE_DBCONFIG_RESET_DATABASE]] <dt>SQLITE_DBCONFIG_RESET_DATABASE</dt>
** <dd> Set the SQLITE_DBCONFIG_RESET_DATABASE flag and then run
** [VACUUM] in order to reset a database back to an empty database
** with no schema and no content. The following process works even for
@@ -2158,6 +2164,18 @@ struct sqlite3_mem_methods {
** Because resetting a database is destructive and irreversible, the
** process requires the use of this obscure API and multiple steps to help
** ensure that it does not happen by accident.
+**
+** [[SQLITE_DBCONFIG_DEFENSIVE]] <dt>SQLITE_DBCONFIG_DEFENSIVE</dt>
+** <dd>The SQLITE_DBCONFIG_DEFENSIVE option activates or deactivates the
+** "defensive" flag for a database connection. When the defensive
+** flag is enabled, language features that allow ordinary SQL to
+** deliberately corrupt the database file are disabled. The disabled
+** features include but are not limited to the following:
+** <ul>
+** <li> The [PRAGMA writable_schema=ON] statement.
+** <li> Writes to the [sqlite_dbpage] virtual table.
+** <li> Direct writes to [shadow tables].
+** </ul>
** </dd>
** </dl>
*/
@@ -2171,7 +2189,8 @@ struct sqlite3_mem_methods {
#define SQLITE_DBCONFIG_ENABLE_QPSG 1007 /* int int* */
#define SQLITE_DBCONFIG_TRIGGER_EQP 1008 /* int int* */
#define SQLITE_DBCONFIG_RESET_DATABASE 1009 /* int int* */
-#define SQLITE_DBCONFIG_MAX 1009 /* Largest DBCONFIG */
+#define SQLITE_DBCONFIG_DEFENSIVE 1010 /* int int* */
+#define SQLITE_DBCONFIG_MAX 1010 /* Largest DBCONFIG */
/*
** CAPI3REF: Enable Or Disable Extended Result Codes
@@ -3609,9 +3628,19 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
** on this hint by avoiding the use of [lookaside memory] so as not to
** deplete the limited store of lookaside memory. Future versions of
** SQLite may act on this hint differently.
+**
+** [[SQLITE_PREPARE_NORMALIZE]] ^(<dt>SQLITE_PREPARE_NORMALIZE</dt>
+** <dd>The SQLITE_PREPARE_NORMALIZE flag indicates that a normalized
+** representation of the SQL statement should be calculated and then
+** associated with the prepared statement, which can be obtained via
+** the [sqlite3_normalized_sql()] interface.)^ The semantics used to
+** normalize a SQL statement are unspecified and subject to change.
+** At a minimum, literal values will be replaced with suitable
+** placeholders.
** </dl>
*/
#define SQLITE_PREPARE_PERSISTENT 0x01
+#define SQLITE_PREPARE_NORMALIZE 0x02
/*
** CAPI3REF: Compiling An SQL Statement
@@ -3769,6 +3798,11 @@ int sqlite3_prepare16_v3(
** ^The sqlite3_expanded_sql(P) interface returns a pointer to a UTF-8
** string containing the SQL text of prepared statement P with
** [bound parameters] expanded.
+** ^The sqlite3_normalized_sql(P) interface returns a pointer to a UTF-8
+** string containing the normalized SQL text of prepared statement P. The
+** semantics used to normalize a SQL statement are unspecified and subject
+** to change. At a minimum, literal values will be replaced with suitable
+** placeholders.
**
** ^(For example, if a prepared statement is created using the SQL
** text "SELECT $abc,:xyz" and if parameter $abc is bound to integer 2345
@@ -3784,14 +3818,16 @@ int sqlite3_prepare16_v3(
** bound parameter expansions. ^The [SQLITE_OMIT_TRACE] compile-time
** option causes sqlite3_expanded_sql() to always return NULL.
**
-** ^The string returned by sqlite3_sql(P) is managed by SQLite and is
-** automatically freed when the prepared statement is finalized.
+** ^The strings returned by sqlite3_sql(P) and sqlite3_normalized_sql(P)
+** are managed by SQLite and are automatically freed when the prepared
+** statement is finalized.
** ^The string returned by sqlite3_expanded_sql(P), on the other hand,
** is obtained from [sqlite3_malloc()] and must be free by the application
** by passing it to [sqlite3_free()].
*/
const char *sqlite3_sql(sqlite3_stmt *pStmt);
char *sqlite3_expanded_sql(sqlite3_stmt *pStmt);
+const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt);
/*
** CAPI3REF: Determine If An SQL Statement Writes The Database
@@ -6281,6 +6317,9 @@ struct sqlite3_module {
int (*xSavepoint)(sqlite3_vtab *pVTab, int);
int (*xRelease)(sqlite3_vtab *pVTab, int);
int (*xRollbackTo)(sqlite3_vtab *pVTab, int);
+ /* The methods above are in versions 1 and 2 of the sqlite_module object.
+ ** Those below are for version 3 and greater. */
+ int (*xShadowName)(const char*);
};
/*
@@ -7203,6 +7242,7 @@ int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_OPTIMIZATIONS 15
#define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */
#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */
+#define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 17
#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
#define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */
#define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19
@@ -8638,6 +8678,7 @@ int sqlite3_vtab_config(sqlite3*, int op, ...);
** can use to customize and optimize their behavior.
**
** <dl>
+** [[SQLITE_VTAB_CONSTRAINT_SUPPORT]]
** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT
** <dd>Calls of the form
** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported,
diff --git a/chromium/third_party/sqlite/src/src/sqlite3ext.h b/chromium/third_party/sqlite/src/src/sqlite3ext.h
index ae34572f31f..eb606c7cfa5 100644
--- a/chromium/third_party/sqlite/src/src/sqlite3ext.h
+++ b/chromium/third_party/sqlite/src/src/sqlite3ext.h
@@ -310,12 +310,15 @@ struct sqlite3_api_routines {
int (*str_errcode)(sqlite3_str*);
int (*str_length)(sqlite3_str*);
char *(*str_value)(sqlite3_str*);
+ /* Version 3.25.0 and later */
int (*create_window_function)(sqlite3*,const char*,int,int,void*,
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*),
void (*xValue)(sqlite3_context*),
void (*xInv)(sqlite3_context*,int,sqlite3_value**),
void(*xDestroy)(void*));
+ /* Version 3.26.0 and later */
+ const char *(*normalized_sql)(sqlite3_stmt*);
};
/*
@@ -603,6 +606,8 @@ typedef int (*sqlite3_loadext_entry)(
#define sqlite3_str_value sqlite3_api->str_value
/* Version 3.25.0 and later */
#define sqlite3_create_window_function sqlite3_api->create_window_function
+/* Version 3.26.0 and later */
+#define sqlite3_normalized_sql sqlite3_api->normalized_sql
#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 0f6ef518639..44d1406110e 100644
--- a/chromium/third_party/sqlite/src/src/sqliteInt.h
+++ b/chromium/third_party/sqlite/src/src/sqliteInt.h
@@ -1305,12 +1305,14 @@ struct LookasideSlot {
** functions use a regular table table from hash.h.)
**
** Hash each FuncDef structure into one of the FuncDefHash.a[] slots.
-** Collisions are on the FuncDef.u.pHash chain.
+** Collisions are on the FuncDef.u.pHash chain. Use the SQLITE_FUNC_HASH()
+** macro to compute a hash on the function name.
*/
#define SQLITE_FUNC_HASH_SZ 23
struct FuncDefHash {
FuncDef *a[SQLITE_FUNC_HASH_SZ]; /* Hash table for functions */
};
+#define SQLITE_FUNC_HASH(C,L) (((C)+(L))%SQLITE_FUNC_HASH_SZ)
#ifdef SQLITE_USER_AUTHENTICATION
/*
@@ -1371,7 +1373,7 @@ struct sqlite3 {
Db *aDb; /* All backends */
int nDb; /* Number of backends currently in use */
u32 mDbFlags; /* flags recording internal state */
- u32 flags; /* flags settable by pragmas. See below */
+ u64 flags; /* flags settable by pragmas. See below */
i64 lastRowid; /* ROWID of most recent insert (see above) */
i64 szMmap; /* Default mmap_size setting */
u32 nSchemaLock; /* Do not reset the schema when non-zero */
@@ -1537,14 +1539,17 @@ struct sqlite3 {
#define SQLITE_TriggerEQP 0x01000000 /* Show trigger EXPLAIN QUERY PLAN */
#define SQLITE_ResetDatabase 0x02000000 /* Reset the database */
#define SQLITE_LegacyAlter 0x04000000 /* Legacy ALTER TABLE behaviour */
+#define SQLITE_NoSchemaError 0x08000000 /* Do not report schema parse errors*/
+#define SQLITE_Defensive 0x10000000 /* Input SQL is likely hostile */
/* Flags used only if debugging */
+#define HI(X) ((u64)(X)<<32)
#ifdef SQLITE_DEBUG
-#define SQLITE_SqlTrace 0x08000000 /* Debug print SQL as it executes */
-#define SQLITE_VdbeListing 0x10000000 /* Debug listings of VDBE programs */
-#define SQLITE_VdbeTrace 0x20000000 /* True to trace VDBE execution */
-#define SQLITE_VdbeAddopTrace 0x40000000 /* Trace sqlite3VdbeAddOp() calls */
-#define SQLITE_VdbeEQP 0x80000000 /* Debug EXPLAIN QUERY PLAN */
+#define SQLITE_SqlTrace HI(0x0001) /* Debug print SQL as it executes */
+#define SQLITE_VdbeListing HI(0x0002) /* Debug listings of VDBE progs */
+#define SQLITE_VdbeTrace HI(0x0004) /* True to trace VDBE execution */
+#define SQLITE_VdbeAddopTrace HI(0x0008) /* Trace sqlite3VdbeAddOp() calls */
+#define SQLITE_VdbeEQP HI(0x0010) /* Debug EXPLAIN QUERY PLAN */
#endif
/*
@@ -1678,8 +1683,9 @@ struct FuncDestructor {
** single query - might change over time */
#define SQLITE_FUNC_AFFINITY 0x4000 /* Built-in affinity() function */
#define SQLITE_FUNC_OFFSET 0x8000 /* Built-in sqlite_offset() function */
-#define SQLITE_FUNC_WINDOW 0x10000 /* Built-in window-only function */
-#define SQLITE_FUNC_WINDOW_SIZE 0x20000 /* Requires partition size as arg. */
+#define SQLITE_FUNC_WINDOW 0x00010000 /* Built-in window-only function */
+#define SQLITE_FUNC_WINDOW_SIZE 0x20000 /* Requires partition size as arg. */
+#define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */
/*
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
@@ -1755,10 +1761,13 @@ struct FuncDestructor {
#define AGGREGATE2(zName, nArg, arg, nc, xStep, xFinal, extraFlags) \
{nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|extraFlags, \
SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xFinal,0,#zName, {0}}
-
#define WAGGREGATE(zName, nArg, arg, nc, xStep, xFinal, xValue, xInverse, f) \
{nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|f, \
SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xValue,xInverse,#zName, {0}}
+#define INTERNAL_FUNCTION(zName, nArg, xFunc) \
+ {nArg, SQLITE_FUNC_INTERNAL|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \
+ 0, 0, xFunc, 0, 0, 0, #zName, {0} }
+
/*
** All current savepoints are stored in a linked list starting at
@@ -1943,6 +1952,9 @@ struct VTable {
struct Table {
char *zName; /* Name of the table or view */
Column *aCol; /* Information about each column */
+#ifdef SQLITE_ENABLE_NORMALIZE
+ Hash *pColHash; /* All columns indexed by name */
+#endif
Index *pIndex; /* List of SQL indexes on this table. */
Select *pSelect; /* NULL for tables. Points to definition if a view. */
FKey *pFKey; /* Linked list of all foreign keys in this table */
@@ -1993,6 +2005,7 @@ struct Table {
#define TF_StatsUsed 0x0100 /* Query planner decisions affected by
** Index.aiRowLogEst[] values */
#define TF_HasNotNull 0x0200 /* Contains NOT NULL constraints */
+#define TF_Shadow 0x0400 /* True for a shadow table */
/*
** Test to see whether or not a table is a virtual table. This is
@@ -2280,6 +2293,12 @@ struct IndexSample {
};
/*
+** Possible values to use within the flags argument to sqlite3GetToken().
+*/
+#define SQLITE_TOKEN_QUOTED 0x1 /* Token is a quoted identifier. */
+#define SQLITE_TOKEN_KEYWORD 0x2 /* Token is a keyword. */
+
+/*
** Each token coming out of the lexer is an instance of
** this structure. Tokens are also used as part of an expression.
**
@@ -2460,11 +2479,11 @@ struct Expr {
** TK_COLUMN: the value of p5 for OP_Column
** TK_AGG_FUNCTION: nesting depth */
AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
- Table *pTab; /* Table for TK_COLUMN expressions. Can be NULL
- ** for a column of an index on an expression */
-#ifndef SQLITE_OMIT_WINDOWFUNC
- Window *pWin; /* Window definition for window functions */
-#endif
+ union {
+ Table *pTab; /* TK_COLUMN: Table containing column. Can be NULL
+ ** for a column of an index on an expression */
+ Window *pWin; /* TK_FUNCTION: Window definition for the func */
+ } y;
};
/*
@@ -2494,6 +2513,7 @@ struct Expr {
#define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */
#define EP_Alias 0x400000 /* Is an alias for a result set column */
#define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */
+#define EP_WinFunc 0x1000000 /* TK_FUNCTION with Expr.y.pWin set */
/*
** The EP_Propagate mask is a set of properties that automatically propagate
@@ -3398,6 +3418,7 @@ struct Sqlite3Config {
int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */
#endif
int bLocaltimeFault; /* True to fail localtime() calls */
+ int bInternalFunctions; /* Internal SQL functions are visible */
int iOnceResetThreshold; /* When to reset OP_Once counters */
u32 szSorterRef; /* Min size in bytes to use sorter-refs */
};
@@ -3651,6 +3672,7 @@ int sqlite3IsIdChar(u8);
*/
int sqlite3StrICmp(const char*,const char*);
int sqlite3Strlen30(const char*);
+#define sqlite3Strlen30NN(C) (strlen(C)&0x3fffffff)
char *sqlite3ColumnType(Column*,char*);
#define sqlite3StrNICmp sqlite3_strnicmp
@@ -3767,6 +3789,7 @@ char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
void sqlite3TreeViewExpr(TreeView*, const Expr*, u8);
void sqlite3TreeViewBareExprList(TreeView*, const ExprList*, const char*);
void sqlite3TreeViewExprList(TreeView*, const ExprList*, u8, const char*);
+ void sqlite3TreeViewSrcList(TreeView*, const SrcList*);
void sqlite3TreeViewSelect(TreeView*, const Select*, u8);
void sqlite3TreeViewWith(TreeView*, const With*, u8);
#ifndef SQLITE_OMIT_WINDOWFUNC
@@ -3999,11 +4022,15 @@ int sqlite3ExprIsInteger(Expr*, int*);
int sqlite3ExprCanBeNull(const Expr*);
int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
int sqlite3IsRowid(const char*);
+#ifdef SQLITE_ENABLE_NORMALIZE
+int sqlite3IsRowidN(const char*, int);
+#endif
void sqlite3GenerateRowDelete(
Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8,int);
void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int);
int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int);
void sqlite3ResolvePartIdxLabel(Parse*,int);
+int sqlite3ExprReferencesUpdatedColumn(Expr*,int*,int);
void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int,
u8,u8,int,int*,int*,Upsert*);
#ifdef SQLITE_ENABLE_NULL_TRIM
@@ -4024,6 +4051,9 @@ ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int);
SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int);
IdList *sqlite3IdListDup(sqlite3*,IdList*);
Select *sqlite3SelectDup(sqlite3*,Select*,int);
+#ifdef SQLITE_ENABLE_NORMALIZE
+FuncDef *sqlite3FunctionSearchN(int,const char*,int);
+#endif
void sqlite3InsertBuiltinFuncs(FuncDef*,int);
FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,u8,u8);
void sqlite3RegisterBuiltinFunctions(void);
@@ -4181,6 +4211,7 @@ Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int);
Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
Expr *sqlite3ExprSkipCollate(Expr*);
int sqlite3CheckCollSeq(Parse *, CollSeq *);
+int sqlite3WritableSchema(sqlite3*);
int sqlite3CheckObjectName(Parse *, const char *);
void sqlite3VdbeSetChanges(sqlite3 *, int);
int sqlite3AddInt64(i64*,i64);
@@ -4227,6 +4258,9 @@ void sqlite3AlterFunctions(void);
void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*);
int sqlite3GetToken(const unsigned char *, int *);
+#ifdef SQLITE_ENABLE_NORMALIZE
+int sqlite3GetTokenNormalized(const unsigned char *, int *, int *);
+#endif
void sqlite3NestedParse(Parse*, const char*, ...);
void sqlite3ExpirePreparedStatements(sqlite3*, int);
int sqlite3CodeSubselect(Parse*, Expr *, int, int);
@@ -4384,6 +4418,9 @@ sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*);
int sqlite3VdbeParameterIndex(Vdbe*, const char*, int);
int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
void sqlite3ParserReset(Parse*);
+#ifdef SQLITE_ENABLE_NORMALIZE
+void sqlite3Normalize(Vdbe*, const char*, int, u8);
+#endif
int sqlite3Reprepare(Vdbe*);
void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
diff --git a/chromium/third_party/sqlite/src/src/test1.c b/chromium/third_party/sqlite/src/src/test1.c
index 1c9ebf822f3..5d6a01f319f 100644
--- a/chromium/third_party/sqlite/src/src/test1.c
+++ b/chromium/third_party/sqlite/src/src/test1.c
@@ -4218,6 +4218,7 @@ static int SQLITE_TCLAPI test_prepare_v2(
char *zCopy = 0; /* malloc() copy of zSql */
int bytes;
const char *zTail = 0;
+ const char **pzTail;
sqlite3_stmt *pStmt = 0;
char zBuf[50];
int rc;
@@ -4242,7 +4243,8 @@ static int SQLITE_TCLAPI test_prepare_v2(
zCopy = malloc(n);
memcpy(zCopy, zSql, n);
}
- rc = sqlite3_prepare_v2(db, zCopy, bytes, &pStmt, objc>=5 ? &zTail : 0);
+ pzTail = objc>=5 ? &zTail : 0;
+ rc = sqlite3_prepare_v2(db, zCopy, bytes, &pStmt, pzTail);
free(zCopy);
zTail = &zSql[(zTail - zCopy)];
@@ -4270,6 +4272,79 @@ static int SQLITE_TCLAPI test_prepare_v2(
}
/*
+** Usage: sqlite3_prepare_v3 DB sql bytes flags ?tailvar?
+**
+** Compile up to <bytes> bytes of the supplied SQL string <sql> using
+** database handle <DB> and flags <flags>. The parameter <tailval> is
+** the name of a global variable that is set to the unused portion of
+** <sql> (if any). A STMT handle is returned.
+*/
+static int SQLITE_TCLAPI test_prepare_v3(
+ void * clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+ sqlite3 *db;
+ const char *zSql;
+ char *zCopy = 0; /* malloc() copy of zSql */
+ int bytes, flags;
+ const char *zTail = 0;
+ const char **pzTail;
+ sqlite3_stmt *pStmt = 0;
+ char zBuf[50];
+ int rc;
+
+ if( objc!=6 && objc!=5 ){
+ Tcl_AppendResult(interp, "wrong # args: should be \"",
+ Tcl_GetString(objv[0]), " DB sql bytes flags tailvar", 0);
+ return TCL_ERROR;
+ }
+ if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
+ zSql = Tcl_GetString(objv[2]);
+ if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
+ if( Tcl_GetIntFromObj(interp, objv[4], &flags) ) return TCL_ERROR;
+
+ /* Instead of using zSql directly, make a copy into a buffer obtained
+ ** directly from malloc(). The idea is to make it easier for valgrind
+ ** to spot buffer overreads. */
+ if( bytes>=0 ){
+ zCopy = malloc(bytes);
+ memcpy(zCopy, zSql, bytes);
+ }else{
+ int n = (int)strlen(zSql) + 1;
+ zCopy = malloc(n);
+ memcpy(zCopy, zSql, n);
+ }
+ pzTail = objc>=6 ? &zTail : 0;
+ rc = sqlite3_prepare_v3(db, zCopy, bytes, (unsigned int)flags,&pStmt,pzTail);
+ free(zCopy);
+ zTail = &zSql[(zTail - zCopy)];
+
+ assert(rc==SQLITE_OK || pStmt==0);
+ Tcl_ResetResult(interp);
+ if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
+ if( rc==SQLITE_OK && zTail && objc>=6 ){
+ if( bytes>=0 ){
+ bytes = bytes - (int)(zTail-zSql);
+ }
+ Tcl_ObjSetVar2(interp, objv[5], 0, Tcl_NewStringObj(zTail, bytes), 0);
+ }
+ if( rc!=SQLITE_OK ){
+ assert( pStmt==0 );
+ sqlite3_snprintf(sizeof(zBuf), zBuf, "(%d) ", rc);
+ Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
+ return TCL_ERROR;
+ }
+
+ if( pStmt ){
+ if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
+ Tcl_AppendResult(interp, zBuf, 0);
+ }
+ return TCL_OK;
+}
+
+/*
** Usage: sqlite3_prepare_tkt3134 DB
**
** Generate a prepared statement for a zero-byte string as a test
@@ -4676,6 +4751,25 @@ static int SQLITE_TCLAPI test_ex_sql(
sqlite3_free(z);
return TCL_OK;
}
+#ifdef SQLITE_ENABLE_NORMALIZE
+static int SQLITE_TCLAPI test_norm_sql(
+ void * clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+ sqlite3_stmt *pStmt;
+
+ if( objc!=2 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "STMT");
+ return TCL_ERROR;
+ }
+
+ if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
+ Tcl_SetResult(interp, (char *)sqlite3_normalized_sql(pStmt), TCL_VOLATILE);
+ return TCL_OK;
+}
+#endif /* SQLITE_ENABLE_NORMALIZE */
/*
** Usage: sqlite3_column_count STMT
@@ -6235,7 +6329,7 @@ static int SQLITE_TCLAPI reset_prng_state(
/*
** tclcmd: database_may_be_corrupt
**
-** Indicate that database files might be corrupt. In other words, set the normal
+** Indicate that database files might be corrupt. In other words, set the normal
** state of operation.
*/
static int SQLITE_TCLAPI database_may_be_corrupt(
@@ -6250,8 +6344,9 @@ static int SQLITE_TCLAPI database_may_be_corrupt(
/*
** tclcmd: database_never_corrupt
**
-** Indicate that database files are always well-formed. This enables extra assert()
-** statements that test conditions that are always true for well-formed databases.
+** Indicate that database files are always well-formed. This enables
+** extra assert() statements that test conditions that are always true
+** for well-formed databases.
*/
static int SQLITE_TCLAPI database_never_corrupt(
ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
@@ -6617,9 +6712,10 @@ static int SQLITE_TCLAPI test_test_control(
const char *zName;
int i;
} aVerb[] = {
- { "SQLITE_TESTCTRL_LOCALTIME_FAULT", SQLITE_TESTCTRL_LOCALTIME_FAULT },
- { "SQLITE_TESTCTRL_SORTER_MMAP", SQLITE_TESTCTRL_SORTER_MMAP },
- { "SQLITE_TESTCTRL_IMPOSTER", SQLITE_TESTCTRL_IMPOSTER },
+ { "SQLITE_TESTCTRL_LOCALTIME_FAULT", SQLITE_TESTCTRL_LOCALTIME_FAULT },
+ { "SQLITE_TESTCTRL_SORTER_MMAP", SQLITE_TESTCTRL_SORTER_MMAP },
+ { "SQLITE_TESTCTRL_IMPOSTER", SQLITE_TESTCTRL_IMPOSTER },
+ { "SQLITE_TESTCTRL_INTERNAL_FUNCTIONS", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS},
};
int iVerb;
int iFlag;
@@ -6637,6 +6733,7 @@ static int SQLITE_TCLAPI test_test_control(
iFlag = aVerb[iVerb].i;
switch( iFlag ){
+ case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS:
case SQLITE_TESTCTRL_LOCALTIME_FAULT: {
int val;
if( objc!=3 ){
@@ -6644,7 +6741,7 @@ static int SQLITE_TCLAPI test_test_control(
return TCL_ERROR;
}
if( Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
- sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, val);
+ sqlite3_test_control(iFlag, val);
break;
}
@@ -7038,6 +7135,7 @@ static int SQLITE_TCLAPI tclLoadStaticExtensionCmd(
extern int sqlite3_closure_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_csv_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_eval_init(sqlite3*,char**,const sqlite3_api_routines*);
+ extern int sqlite3_explain_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_fileio_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_fuzzer_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_ieee_init(sqlite3*,char**,const sqlite3_api_routines*);
@@ -7062,6 +7160,7 @@ static int SQLITE_TCLAPI tclLoadStaticExtensionCmd(
{ "closure", sqlite3_closure_init },
{ "csv", sqlite3_csv_init },
{ "eval", sqlite3_eval_init },
+ { "explain", sqlite3_explain_init },
{ "fileio", sqlite3_fileio_init },
{ "fuzzer", sqlite3_fuzzer_init },
{ "ieee754", sqlite3_ieee_init },
@@ -7460,6 +7559,7 @@ static int SQLITE_TCLAPI test_sqlite3_db_config(
{ "QPSG", SQLITE_DBCONFIG_ENABLE_QPSG },
{ "TRIGGER_EQP", SQLITE_DBCONFIG_TRIGGER_EQP },
{ "RESET_DB", SQLITE_DBCONFIG_RESET_DATABASE },
+ { "DEFENSIVE", SQLITE_DBCONFIG_DEFENSIVE },
};
int i;
int v;
@@ -7644,6 +7744,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "sqlite3_prepare", test_prepare ,0 },
{ "sqlite3_prepare16", test_prepare16 ,0 },
{ "sqlite3_prepare_v2", test_prepare_v2 ,0 },
+ { "sqlite3_prepare_v3", test_prepare_v3 ,0 },
{ "sqlite3_prepare_tkt3134", test_prepare_tkt3134, 0},
{ "sqlite3_prepare16_v2", test_prepare16_v2 ,0 },
{ "sqlite3_finalize", test_finalize ,0 },
@@ -7655,6 +7756,9 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "sqlite3_step", test_step ,0 },
{ "sqlite3_sql", test_sql ,0 },
{ "sqlite3_expanded_sql", test_ex_sql ,0 },
+#ifdef SQLITE_ENABLE_NORMALIZE
+ { "sqlite3_normalized_sql", test_norm_sql ,0 },
+#endif
{ "sqlite3_next_stmt", test_next_stmt ,0 },
{ "sqlite3_stmt_readonly", test_stmt_readonly ,0 },
{ "sqlite3_stmt_busy", test_stmt_busy ,0 },
diff --git a/chromium/third_party/sqlite/src/src/test_config.c b/chromium/third_party/sqlite/src/src/test_config.c
index dd26913d1b0..55a99bb9911 100644
--- a/chromium/third_party/sqlite/src/src/test_config.c
+++ b/chromium/third_party/sqlite/src/src/test_config.c
@@ -124,7 +124,7 @@ static void set_options(Tcl_Interp *interp){
STRINGVALUE(SQLITE_MAX_WORKER_THREADS), TCL_GLOBAL_ONLY
);
-#if 1 /* def SQLITE_MEMDEBUG */
+#ifdef SQLITE_MEMDEBUG
Tcl_SetVar2(interp, "sqlite_options", "memdebug", "1", TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp, "sqlite_options", "memdebug", "0", TCL_GLOBAL_ONLY);
@@ -762,6 +762,12 @@ Tcl_SetVar2(interp, "sqlite_options", "mergesort", "1", TCL_GLOBAL_ONLY);
Tcl_SetVar2(interp, "sqlite_options", "uri_00_error", "0", TCL_GLOBAL_ONLY);
#endif
+#if defined(SQLITE_ENABLE_NORMALIZE)
+ Tcl_SetVar2(interp, "sqlite_options", "normalize", "1", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "normalize", "0", TCL_GLOBAL_ONLY);
+#endif
+
#ifdef SQLITE_OMIT_WINDOWFUNC
Tcl_SetVar2(interp, "sqlite_options", "windowfunc", "0", TCL_GLOBAL_ONLY);
#else
diff --git a/chromium/third_party/sqlite/src/src/test_intarray.c b/chromium/third_party/sqlite/src/src/test_intarray.c
index 1f7a49a3ed0..ee19b1d7202 100644
--- a/chromium/third_party/sqlite/src/src/test_intarray.c
+++ b/chromium/third_party/sqlite/src/src/test_intarray.c
@@ -13,6 +13,10 @@
** This file implements a read-only VIRTUAL TABLE that contains the
** content of a C-language array of integer values. See the corresponding
** header file for full details.
+**
+** This virtual table is used for internal testing of SQLite only. It is
+** not recommended for use in production. For a similar virtual table that
+** is production-ready, see the "carray" virtual table over in ext/misc.
*/
#include "test_intarray.h"
#include <string.h>
@@ -315,7 +319,6 @@ static int SQLITE_TCLAPI test_intarray_create(
rc = sqlite3_intarray_create(db, zName, &pArray);
#endif
if( rc!=SQLITE_OK ){
- assert( pArray==0 );
Tcl_AppendResult(interp, sqlite3ErrName(rc), (char*)0);
return TCL_ERROR;
}
diff --git a/chromium/third_party/sqlite/src/src/test_intarray.h b/chromium/third_party/sqlite/src/src/test_intarray.h
index cee55b5dae8..116e3bdc076 100644
--- a/chromium/third_party/sqlite/src/src/test_intarray.h
+++ b/chromium/third_party/sqlite/src/src/test_intarray.h
@@ -13,6 +13,10 @@
** This is the C-language interface definition for the "intarray" or
** integer array virtual table for SQLite.
**
+** This virtual table is used for internal testing of SQLite only. It is
+** not recommended for use in production. For a similar virtual table that
+** is production-ready, see the "carray" virtual table over in ext/misc.
+**
** The intarray virtual table is designed to facilitate using an
** array of integers as the right-hand side of an IN operator. So
** instead of doing a prepared statement like this:
@@ -72,7 +76,10 @@
** virtual table is dropped. Since the virtual tables are created in the
** TEMP database, they are automatically dropped when the database connection
** closes so the application does not normally need to take any special
-** action to free the intarray objects.
+** action to free the intarray objects. Because of the way virtual tables
+** work and the (somewhat goofy) way that the intarray virtual table is
+** implemented, it is not allowed to invoke sqlite3_intarray_create(D,N,P)
+** more than once with the same D and N values.
*/
#include "sqlite3.h"
#ifndef SQLITE_INTARRAY_H
diff --git a/chromium/third_party/sqlite/src/src/test_onefile.c b/chromium/third_party/sqlite/src/src/test_onefile.c
index 7a99e3e7f4c..554842d9931 100644
--- a/chromium/third_party/sqlite/src/src/test_onefile.c
+++ b/chromium/third_party/sqlite/src/src/test_onefile.c
@@ -560,6 +560,7 @@ static int fsCheckReservedLock(sqlite3_file *pFile, int *pResOut){
** File control method. For custom operations on an fs-file.
*/
static int fsFileControl(sqlite3_file *pFile, int op, void *pArg){
+ if( op==SQLITE_FCNTL_PRAGMA ) return SQLITE_NOTFOUND;
return SQLITE_OK;
}
diff --git a/chromium/third_party/sqlite/src/src/test_window.c b/chromium/third_party/sqlite/src/src/test_window.c
new file mode 100644
index 00000000000..dd2ca2f8215
--- /dev/null
+++ b/chromium/third_party/sqlite/src/src/test_window.c
@@ -0,0 +1,349 @@
+/*
+** 2018 June 17
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+*/
+
+#include "sqlite3.h"
+
+#ifdef SQLITE_TEST
+
+#include "sqliteInt.h"
+#include <tcl.h>
+
+extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb);
+extern const char *sqlite3ErrName(int);
+
+typedef struct TestWindow TestWindow;
+struct TestWindow {
+ Tcl_Obj *xStep;
+ Tcl_Obj *xFinal;
+ Tcl_Obj *xValue;
+ Tcl_Obj *xInverse;
+ Tcl_Interp *interp;
+};
+
+typedef struct TestWindowCtx TestWindowCtx;
+struct TestWindowCtx {
+ Tcl_Obj *pVal;
+};
+
+static void doTestWindowStep(
+ int bInverse,
+ sqlite3_context *ctx,
+ int nArg,
+ sqlite3_value **apArg
+){
+ int i;
+ TestWindow *p = (TestWindow*)sqlite3_user_data(ctx);
+ Tcl_Obj *pEval = Tcl_DuplicateObj(bInverse ? p->xInverse : p->xStep);
+ TestWindowCtx *pCtx = sqlite3_aggregate_context(ctx, sizeof(TestWindowCtx));
+
+ Tcl_IncrRefCount(pEval);
+ if( pCtx ){
+ const char *zResult;
+ int rc;
+ if( pCtx->pVal ){
+ Tcl_ListObjAppendElement(p->interp, pEval, Tcl_DuplicateObj(pCtx->pVal));
+ }else{
+ Tcl_ListObjAppendElement(p->interp, pEval, Tcl_NewStringObj("", -1));
+ }
+ for(i=0; i<nArg; i++){
+ Tcl_Obj *pArg;
+ pArg = Tcl_NewStringObj((const char*)sqlite3_value_text(apArg[i]), -1);
+ Tcl_ListObjAppendElement(p->interp, pEval, pArg);
+ }
+ rc = Tcl_EvalObjEx(p->interp, pEval, TCL_EVAL_GLOBAL);
+ if( rc!=TCL_OK ){
+ zResult = Tcl_GetStringResult(p->interp);
+ sqlite3_result_error(ctx, zResult, -1);
+ }else{
+ if( pCtx->pVal ) Tcl_DecrRefCount(pCtx->pVal);
+ pCtx->pVal = Tcl_DuplicateObj(Tcl_GetObjResult(p->interp));
+ Tcl_IncrRefCount(pCtx->pVal);
+ }
+ }
+ Tcl_DecrRefCount(pEval);
+}
+
+static void doTestWindowFinalize(int bValue, sqlite3_context *ctx){
+ TestWindow *p = (TestWindow*)sqlite3_user_data(ctx);
+ Tcl_Obj *pEval = Tcl_DuplicateObj(bValue ? p->xValue : p->xFinal);
+ TestWindowCtx *pCtx = sqlite3_aggregate_context(ctx, sizeof(TestWindowCtx));
+
+ Tcl_IncrRefCount(pEval);
+ if( pCtx ){
+ const char *zResult;
+ int rc;
+ if( pCtx->pVal ){
+ Tcl_ListObjAppendElement(p->interp, pEval, Tcl_DuplicateObj(pCtx->pVal));
+ }else{
+ Tcl_ListObjAppendElement(p->interp, pEval, Tcl_NewStringObj("", -1));
+ }
+
+ rc = Tcl_EvalObjEx(p->interp, pEval, TCL_EVAL_GLOBAL);
+ zResult = Tcl_GetStringResult(p->interp);
+ if( rc!=TCL_OK ){
+ sqlite3_result_error(ctx, zResult, -1);
+ }else{
+ sqlite3_result_text(ctx, zResult, -1, SQLITE_TRANSIENT);
+ }
+
+ if( bValue==0 ){
+ if( pCtx->pVal ) Tcl_DecrRefCount(pCtx->pVal);
+ pCtx->pVal = 0;
+ }
+ }
+ Tcl_DecrRefCount(pEval);
+}
+
+static void testWindowStep(
+ sqlite3_context *ctx,
+ int nArg,
+ sqlite3_value **apArg
+){
+ doTestWindowStep(0, ctx, nArg, apArg);
+}
+static void testWindowInverse(
+ sqlite3_context *ctx,
+ int nArg,
+ sqlite3_value **apArg
+){
+ doTestWindowStep(1, ctx, nArg, apArg);
+}
+
+static void testWindowFinal(sqlite3_context *ctx){
+ doTestWindowFinalize(0, ctx);
+}
+static void testWindowValue(sqlite3_context *ctx){
+ doTestWindowFinalize(1, ctx);
+}
+
+static void testWindowDestroy(void *pCtx){
+ ckfree(pCtx);
+}
+
+/*
+** Usage: sqlite3_create_window_function DB NAME XSTEP XFINAL XVALUE XINVERSE
+*/
+static int SQLITE_TCLAPI test_create_window(
+ void * clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+ TestWindow *pNew;
+ sqlite3 *db;
+ const char *zName;
+ int rc;
+
+ if( objc!=7 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "DB NAME XSTEP XFINAL XVALUE XINVERSE");
+ return TCL_ERROR;
+ }
+
+ if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
+ zName = Tcl_GetString(objv[2]);
+ pNew = (TestWindow*)ckalloc(sizeof(TestWindow));
+ memset(pNew, 0, sizeof(TestWindow));
+ pNew->xStep = Tcl_DuplicateObj(objv[3]);
+ pNew->xFinal = Tcl_DuplicateObj(objv[4]);
+ pNew->xValue = Tcl_DuplicateObj(objv[5]);
+ pNew->xInverse = Tcl_DuplicateObj(objv[6]);
+ pNew->interp = interp;
+
+ Tcl_IncrRefCount(pNew->xStep);
+ Tcl_IncrRefCount(pNew->xFinal);
+ Tcl_IncrRefCount(pNew->xValue);
+ Tcl_IncrRefCount(pNew->xInverse);
+
+ rc = sqlite3_create_window_function(db, zName, -1, SQLITE_UTF8, (void*)pNew,
+ testWindowStep, testWindowFinal, testWindowValue, testWindowInverse,
+ testWindowDestroy
+ );
+ if( rc!=SQLITE_OK ){
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
+ return TCL_ERROR;
+ }
+
+ return TCL_OK;
+}
+
+static int SQLITE_TCLAPI test_create_window_misuse(
+ void * clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+ sqlite3 *db;
+ int rc;
+
+ if( objc!=2 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "DB");
+ return TCL_ERROR;
+ }
+ if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
+
+ rc = sqlite3_create_window_function(db, "fff", -1, SQLITE_UTF8, 0,
+ 0, testWindowFinal, testWindowValue, testWindowInverse,
+ 0
+ );
+ if( rc!=SQLITE_MISUSE ) goto error;
+ rc = sqlite3_create_window_function(db, "fff", -1, SQLITE_UTF8, 0,
+ testWindowStep, 0, testWindowValue, testWindowInverse,
+ 0
+ );
+ if( rc!=SQLITE_MISUSE ) goto error;
+ rc = sqlite3_create_window_function(db, "fff", -1, SQLITE_UTF8, 0,
+ testWindowStep, testWindowFinal, 0, testWindowInverse,
+ 0
+ );
+ if( rc!=SQLITE_MISUSE ) goto error;
+ rc = sqlite3_create_window_function(db, "fff", -1, SQLITE_UTF8, 0,
+ testWindowStep, testWindowFinal, testWindowValue, 0,
+ 0
+ );
+ if( rc!=SQLITE_MISUSE ) goto error;
+
+ return TCL_OK;
+
+ error:
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("misuse test error", -1));
+ return TCL_ERROR;
+}
+
+/*
+** xStep for sumint().
+*/
+static void sumintStep(
+ sqlite3_context *ctx,
+ int nArg,
+ sqlite3_value *apArg[]
+){
+ sqlite3_int64 *pInt;
+
+ assert( nArg==1 );
+ if( sqlite3_value_type(apArg[0])!=SQLITE_INTEGER ){
+ sqlite3_result_error(ctx, "invalid argument", -1);
+ return;
+ }
+ pInt = (sqlite3_int64*)sqlite3_aggregate_context(ctx, sizeof(sqlite3_int64));
+ if( pInt ){
+ *pInt += sqlite3_value_int64(apArg[0]);
+ }
+}
+
+/*
+** xInverse for sumint().
+*/
+static void sumintInverse(
+ sqlite3_context *ctx,
+ int nArg,
+ sqlite3_value *apArg[]
+){
+ sqlite3_int64 *pInt;
+ pInt = (sqlite3_int64*)sqlite3_aggregate_context(ctx, sizeof(sqlite3_int64));
+ *pInt -= sqlite3_value_int64(apArg[0]);
+}
+
+/*
+** xFinal for sumint().
+*/
+static void sumintFinal(sqlite3_context *ctx){
+ sqlite3_int64 res = 0;
+ sqlite3_int64 *pInt;
+ pInt = (sqlite3_int64*)sqlite3_aggregate_context(ctx, 0);
+ if( pInt ) res = *pInt;
+ sqlite3_result_int64(ctx, res);
+}
+
+/*
+** xValue for sumint().
+*/
+static void sumintValue(sqlite3_context *ctx){
+ sqlite3_int64 res = 0;
+ sqlite3_int64 *pInt;
+ pInt = (sqlite3_int64*)sqlite3_aggregate_context(ctx, 0);
+ if( pInt ) res = *pInt;
+ sqlite3_result_int64(ctx, res);
+}
+
+static int SQLITE_TCLAPI test_create_sumint(
+ void * clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+ sqlite3 *db;
+ int rc;
+
+ if( objc!=2 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "DB");
+ return TCL_ERROR;
+ }
+ if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
+
+ rc = sqlite3_create_window_function(db, "sumint", 1, SQLITE_UTF8, 0,
+ sumintStep, sumintFinal, sumintValue, sumintInverse,
+ 0
+ );
+
+ if( rc!=SQLITE_OK ){
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+static int SQLITE_TCLAPI test_override_sum(
+ void * clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+ sqlite3 *db;
+ int rc;
+
+ if( objc!=2 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "DB");
+ return TCL_ERROR;
+ }
+ if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
+
+ rc = sqlite3_create_function(db, "sum", -1, SQLITE_UTF8, 0,
+ 0, sumintStep, sumintFinal
+ );
+
+ if( rc!=SQLITE_OK ){
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+int Sqlitetest_window_Init(Tcl_Interp *interp){
+ static struct {
+ char *zName;
+ Tcl_ObjCmdProc *xProc;
+ int clientData;
+ } aObjCmd[] = {
+ { "sqlite3_create_window_function", test_create_window, 0 },
+ { "test_create_window_function_misuse", test_create_window_misuse, 0 },
+ { "test_create_sumint", test_create_sumint, 0 },
+ { "test_override_sum", test_override_sum, 0 },
+ };
+ int i;
+ for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
+ ClientData c = (ClientData)SQLITE_INT_TO_PTR(aObjCmd[i].clientData);
+ Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, c, 0);
+ }
+ return TCL_OK;
+}
+#endif
diff --git a/chromium/third_party/sqlite/src/src/tokenize.c b/chromium/third_party/sqlite/src/src/tokenize.c
index 84047265f7a..4e56a487e54 100644
--- a/chromium/third_party/sqlite/src/src/tokenize.c
+++ b/chromium/third_party/sqlite/src/src/tokenize.c
@@ -545,6 +545,73 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){
return i;
}
+#ifdef SQLITE_ENABLE_NORMALIZE
+/*
+** Return the length (in bytes) of the token that begins at z[0].
+** Store the token type in *tokenType before returning. If flags has
+** SQLITE_TOKEN_NORMALIZE flag enabled, use the identifier token type
+** for keywords. Add SQLITE_TOKEN_QUOTED to flags if the token was
+** actually a quoted identifier. Add SQLITE_TOKEN_KEYWORD to flags
+** if the token was recognized as a keyword; this is useful when the
+** SQLITE_TOKEN_NORMALIZE flag is used, because it enables the caller
+** to differentiate between a keyword being treated as an identifier
+** (for normalization purposes) and an actual identifier.
+*/
+int sqlite3GetTokenNormalized(
+ const unsigned char *z,
+ int *tokenType,
+ int *flags
+){
+ int n;
+ unsigned char iClass = aiClass[*z];
+ if( iClass==CC_KYWD ){
+ int i;
+ for(i=1; aiClass[z[i]]<=CC_KYWD; i++){}
+ if( IdChar(z[i]) ){
+ /* This token started out using characters that can appear in keywords,
+ ** but z[i] is a character not allowed within keywords, so this must
+ ** be an identifier instead */
+ i++;
+ while( IdChar(z[i]) ){ i++; }
+ *tokenType = TK_ID;
+ return i;
+ }
+ *tokenType = TK_ID;
+ n = keywordCode((char*)z, i, tokenType);
+ /* If the token is no longer considered to be an identifier, then it is a
+ ** keyword of some kind. Make the token back into an identifier and then
+ ** set the SQLITE_TOKEN_KEYWORD flag. Several non-identifier tokens are
+ ** used verbatim, including IN, IS, NOT, and NULL. */
+ switch( *tokenType ){
+ case TK_ID: {
+ /* do nothing, handled by caller */
+ break;
+ }
+ case TK_IN:
+ case TK_IS:
+ case TK_NOT:
+ case TK_NULL: {
+ *flags |= SQLITE_TOKEN_KEYWORD;
+ break;
+ }
+ default: {
+ *tokenType = TK_ID;
+ *flags |= SQLITE_TOKEN_KEYWORD;
+ break;
+ }
+ }
+ }else{
+ n = sqlite3GetToken(z, tokenType);
+ /* If the token is considered to be an identifier and the character class
+ ** of the first character is a quote, set the SQLITE_TOKEN_QUOTED flag. */
+ if( *tokenType==TK_ID && (iClass==CC_QUOTE || iClass==CC_QUOTE2) ){
+ *flags |= SQLITE_TOKEN_QUOTED;
+ }
+ }
+ return n;
+}
+#endif /* SQLITE_ENABLE_NORMALIZE */
+
/*
** Run the parser on the given SQL string. The parser structure is
** passed in. An SQLITE_ status code is returned. If an error occurs
diff --git a/chromium/third_party/sqlite/src/src/treeview.c b/chromium/third_party/sqlite/src/src/treeview.c
index 4b6ea4fe470..e7483dde25f 100644
--- a/chromium/third_party/sqlite/src/src/treeview.c
+++ b/chromium/third_party/sqlite/src/src/treeview.c
@@ -121,6 +121,42 @@ void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 moreToFollow){
}
}
+/*
+** Generate a human-readable description of a SrcList object.
+*/
+void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc){
+ int i;
+ for(i=0; i<pSrc->nSrc; i++){
+ const struct SrcList_item *pItem = &pSrc->a[i];
+ StrAccum x;
+ char zLine[100];
+ sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
+ sqlite3_str_appendf(&x, "{%d,*}", pItem->iCursor);
+ if( pItem->zDatabase ){
+ sqlite3_str_appendf(&x, " %s.%s", pItem->zDatabase, pItem->zName);
+ }else if( pItem->zName ){
+ sqlite3_str_appendf(&x, " %s", pItem->zName);
+ }
+ if( pItem->pTab ){
+ sqlite3_str_appendf(&x, " tabname=%Q", pItem->pTab->zName);
+ }
+ if( pItem->zAlias ){
+ sqlite3_str_appendf(&x, " (AS %s)", pItem->zAlias);
+ }
+ if( pItem->fg.jointype & JT_LEFT ){
+ sqlite3_str_appendf(&x, " LEFT-JOIN");
+ }
+ sqlite3StrAccumFinish(&x);
+ sqlite3TreeViewItem(pView, zLine, i<pSrc->nSrc-1);
+ if( pItem->pSelect ){
+ sqlite3TreeViewSelect(pView, pItem->pSelect, 0);
+ }
+ if( pItem->fg.isTabFunc ){
+ sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:");
+ }
+ sqlite3TreeViewPop(pView);
+ }
+}
/*
** Generate a human-readable description of a Select object.
@@ -175,39 +211,9 @@ void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
}
#endif
if( p->pSrc && p->pSrc->nSrc ){
- int i;
pView = sqlite3TreeViewPush(pView, (n--)>0);
sqlite3TreeViewLine(pView, "FROM");
- for(i=0; i<p->pSrc->nSrc; i++){
- struct SrcList_item *pItem = &p->pSrc->a[i];
- StrAccum x;
- char zLine[100];
- sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
- sqlite3_str_appendf(&x, "{%d,*}", pItem->iCursor);
- if( pItem->zDatabase ){
- sqlite3_str_appendf(&x, " %s.%s", pItem->zDatabase, pItem->zName);
- }else if( pItem->zName ){
- sqlite3_str_appendf(&x, " %s", pItem->zName);
- }
- if( pItem->pTab ){
- sqlite3_str_appendf(&x, " tabname=%Q", pItem->pTab->zName);
- }
- if( pItem->zAlias ){
- sqlite3_str_appendf(&x, " (AS %s)", pItem->zAlias);
- }
- if( pItem->fg.jointype & JT_LEFT ){
- sqlite3_str_appendf(&x, " LEFT-JOIN");
- }
- sqlite3StrAccumFinish(&x);
- sqlite3TreeViewItem(pView, zLine, i<p->pSrc->nSrc-1);
- if( pItem->pSelect ){
- sqlite3TreeViewSelect(pView, pItem->pSelect, 0);
- }
- if( pItem->fg.isTabFunc ){
- sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:");
- }
- sqlite3TreeViewPop(pView);
- }
+ sqlite3TreeViewSrcList(pView, p->pSrc);
sqlite3TreeViewPop(pView);
}
if( p->pWhere ){
@@ -497,7 +503,7 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
}else{
pFarg = pExpr->x.pList;
#ifndef SQLITE_OMIT_WINDOWFUNC
- pWin = pExpr->pWin;
+ pWin = pExpr->y.pWin;
#else
pWin = 0;
#endif
diff --git a/chromium/third_party/sqlite/src/src/update.c b/chromium/third_party/sqlite/src/src/update.c
index 73b973be076..b328d3b229b 100644
--- a/chromium/third_party/sqlite/src/src/update.c
+++ b/chromium/third_party/sqlite/src/src/update.c
@@ -80,6 +80,57 @@ void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
}
/*
+** Check to see if column iCol of index pIdx references any of the
+** columns defined by aXRef and chngRowid. Return true if it does
+** and false if not. This is an optimization. False-positives are a
+** performance degradation, but false-negatives can result in a corrupt
+** index and incorrect answers.
+**
+** aXRef[j] will be non-negative if column j of the original table is
+** being updated. chngRowid will be true if the rowid of the table is
+** being updated.
+*/
+static int indexColumnIsBeingUpdated(
+ Index *pIdx, /* The index to check */
+ int iCol, /* Which column of the index to check */
+ int *aXRef, /* aXRef[j]>=0 if column j is being updated */
+ int chngRowid /* true if the rowid is being updated */
+){
+ i16 iIdxCol = pIdx->aiColumn[iCol];
+ assert( iIdxCol!=XN_ROWID ); /* Cannot index rowid */
+ if( iIdxCol>=0 ){
+ return aXRef[iIdxCol]>=0;
+ }
+ assert( iIdxCol==XN_EXPR );
+ assert( pIdx->aColExpr!=0 );
+ assert( pIdx->aColExpr->a[iCol].pExpr!=0 );
+ return sqlite3ExprReferencesUpdatedColumn(pIdx->aColExpr->a[iCol].pExpr,
+ aXRef,chngRowid);
+}
+
+/*
+** Check to see if index pIdx is a partial index whose conditional
+** expression might change values due to an UPDATE. Return true if
+** the index is subject to change and false if the index is guaranteed
+** to be unchanged. This is an optimization. False-positives are a
+** performance degradation, but false-negatives can result in a corrupt
+** index and incorrect answers.
+**
+** aXRef[j] will be non-negative if column j of the original table is
+** being updated. chngRowid will be true if the rowid of the table is
+** being updated.
+*/
+static int indexWhereClauseMightChange(
+ Index *pIdx, /* The index to check */
+ int *aXRef, /* aXRef[j]>=0 if column j is being updated */
+ int chngRowid /* true if the rowid is being updated */
+){
+ if( pIdx->pPartIdxWhere==0 ) return 0;
+ return sqlite3ExprReferencesUpdatedColumn(pIdx->pPartIdxWhere,
+ aXRef, chngRowid);
+}
+
+/*
** Process an UPDATE statement.
**
** UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL;
@@ -302,19 +353,18 @@ void sqlite3Update(
/* There is one entry in the aRegIdx[] array for each index on the table
** being updated. Fill in aRegIdx[] with a register number that will hold
** the key for accessing each index.
- **
- ** FIXME: Be smarter about omitting indexes that use expressions.
*/
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
int reg;
- if( chngKey || hasFK>1 || pIdx->pPartIdxWhere || pIdx==pPk ){
+ if( chngKey || hasFK>1 || pIdx==pPk
+ || indexWhereClauseMightChange(pIdx,aXRef,chngRowid)
+ ){
reg = ++pParse->nMem;
pParse->nMem += pIdx->nColumn;
}else{
reg = 0;
for(i=0; i<pIdx->nKeyCol; i++){
- i16 iIdxCol = pIdx->aiColumn[i];
- if( iIdxCol<0 || aXRef[iIdxCol]>=0 ){
+ if( indexColumnIsBeingUpdated(pIdx, i, aXRef, chngRowid) ){
reg = ++pParse->nMem;
pParse->nMem += pIdx->nColumn;
if( (onError==OE_Replace)
diff --git a/chromium/third_party/sqlite/src/src/vacuum.c b/chromium/third_party/sqlite/src/src/vacuum.c
index 2d863445b8f..6ee545d18fc 100644
--- a/chromium/third_party/sqlite/src/src/vacuum.c
+++ b/chromium/third_party/sqlite/src/src/vacuum.c
@@ -166,7 +166,8 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
saved_mTrace = db->mTrace;
db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks;
db->mDbFlags |= DBFLAG_PreferBuiltin | DBFLAG_Vacuum;
- db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder | SQLITE_CountRows);
+ db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder
+ | SQLITE_Defensive | SQLITE_CountRows);
db->mTrace = 0;
zDbMain = db->aDb[iDb].zDbSName;
diff --git a/chromium/third_party/sqlite/src/src/vdbe.c b/chromium/third_party/sqlite/src/src/vdbe.c
index 04cc2afa6e6..ae2ff53d5e2 100644
--- a/chromium/third_party/sqlite/src/src/vdbe.c
+++ b/chromium/third_party/sqlite/src/src/vdbe.c
@@ -2894,17 +2894,25 @@ case OP_MakeRecord: {
if( nVarint<sqlite3VarintLen(nHdr) ) nHdr++;
}
nByte = nHdr+nData;
- if( nByte+nZero>db->aLimit[SQLITE_LIMIT_LENGTH] ){
- goto too_big;
- }
/* Make sure the output register has a buffer large enough to store
** the new record. The output register (pOp->p3) is not allowed to
** be one of the input registers (because the following call to
** sqlite3VdbeMemClearAndResize() could clobber the value before it is used).
*/
- if( sqlite3VdbeMemClearAndResize(pOut, (int)nByte) ){
- goto no_mem;
+ if( nByte+nZero<=pOut->szMalloc ){
+ /* The output register is already large enough to hold the record.
+ ** No error checks or buffer enlargement is required */
+ pOut->z = pOut->zMalloc;
+ }else{
+ /* Need to make sure that the output is not too big and then enlarge
+ ** the output register to hold the full result */
+ if( nByte+nZero>db->aLimit[SQLITE_LIMIT_LENGTH] ){
+ goto too_big;
+ }
+ if( sqlite3VdbeMemClearAndResize(pOut, (int)nByte) ){
+ goto no_mem;
+ }
}
zNewRecord = (u8 *)pOut->z;
@@ -5760,7 +5768,7 @@ case OP_ParseSchema: {
{
zMaster = MASTER_NAME;
initData.db = db;
- initData.iDb = pOp->p1;
+ initData.iDb = iDb;
initData.pzErrMsg = &p->zErrMsg;
initData.mInitFlags = 0;
zSql = sqlite3MPrintf(db,
diff --git a/chromium/third_party/sqlite/src/src/vdbeInt.h b/chromium/third_party/sqlite/src/src/vdbeInt.h
index ed0aecbc169..23c5b37cb47 100644
--- a/chromium/third_party/sqlite/src/src/vdbeInt.h
+++ b/chromium/third_party/sqlite/src/src/vdbeInt.h
@@ -406,6 +406,9 @@ struct Vdbe {
yDbMask lockMask; /* Subset of btreeMask that requires a lock */
u32 aCounter[7]; /* Counters used by sqlite3_stmt_status() */
char *zSql; /* Text of the SQL statement that generated this */
+#ifdef SQLITE_ENABLE_NORMALIZE
+ char *zNormSql; /* Normalization of the associated SQL statement */
+#endif
void *pFree; /* Free this when deleting the vdbe */
VdbeFrame *pFrame; /* Parent frame */
VdbeFrame *pDelFrame; /* List of frame objects to free on VM reset */
@@ -468,7 +471,9 @@ int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
int sqlite3VdbeIdxKeyCompare(sqlite3*,VdbeCursor*,UnpackedRecord*,int*);
int sqlite3VdbeIdxRowid(sqlite3*, BtCursor*, i64*);
int sqlite3VdbeExec(Vdbe*);
+#ifndef SQLITE_OMIT_EXPLAIN
int sqlite3VdbeList(Vdbe*);
+#endif
int sqlite3VdbeHalt(Vdbe*);
int sqlite3VdbeChangeEncoding(Mem *, int);
int sqlite3VdbeMemTooBig(Mem*);
@@ -507,7 +512,9 @@ int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
#ifndef SQLITE_OMIT_WINDOWFUNC
int sqlite3VdbeMemAggValue(Mem*, Mem*, FuncDef*);
#endif
+#ifndef SQLITE_OMIT_EXPLAIN
const char *sqlite3OpcodeName(int);
+#endif
int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
int sqlite3VdbeMemClearAndResize(Mem *pMem, int n);
int sqlite3VdbeCloseStatement(Vdbe *, int);
diff --git a/chromium/third_party/sqlite/src/src/vdbeapi.c b/chromium/third_party/sqlite/src/src/vdbeapi.c
index 9acb608e0b0..7cc7b1bdbf3 100644
--- a/chromium/third_party/sqlite/src/src/vdbeapi.c
+++ b/chromium/third_party/sqlite/src/src/vdbeapi.c
@@ -1702,6 +1702,16 @@ char *sqlite3_expanded_sql(sqlite3_stmt *pStmt){
#endif
}
+#ifdef SQLITE_ENABLE_NORMALIZE
+/*
+** Return the normalized SQL associated with a prepared statement.
+*/
+const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt){
+ Vdbe *p = (Vdbe *)pStmt;
+ return p ? p->zNormSql : 0;
+}
+#endif /* SQLITE_ENABLE_NORMALIZE */
+
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
/*
** Allocate and populate an UnpackedRecord structure based on the serialized
diff --git a/chromium/third_party/sqlite/src/src/vdbeaux.c b/chromium/third_party/sqlite/src/src/vdbeaux.c
index f23de9bb0d9..15a095ff6e7 100644
--- a/chromium/third_party/sqlite/src/src/vdbeaux.c
+++ b/chromium/third_party/sqlite/src/src/vdbeaux.c
@@ -64,6 +64,13 @@ void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, u8 prepFlags){
}
assert( p->zSql==0 );
p->zSql = sqlite3DbStrNDup(p->db, z, n);
+#ifdef SQLITE_ENABLE_NORMALIZE
+ assert( p->zNormSql==0 );
+ if( p->zSql && (prepFlags & SQLITE_PREPARE_NORMALIZE)!=0 ){
+ sqlite3Normalize(p, p->zSql, n, prepFlags);
+ assert( p->zNormSql!=0 || p->db->mallocFailed );
+ }
+#endif
}
/*
@@ -85,6 +92,11 @@ void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){
zTmp = pA->zSql;
pA->zSql = pB->zSql;
pB->zSql = zTmp;
+#ifdef SQLITE_ENABLE_NORMALIZE
+ zTmp = pA->zNormSql;
+ pA->zNormSql = pB->zNormSql;
+ pB->zNormSql = zTmp;
+#endif
pB->expmask = pA->expmask;
pB->prepFlags = pA->prepFlags;
memcpy(pB->aCounter, pA->aCounter, sizeof(pB->aCounter));
@@ -3156,6 +3168,9 @@ void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
vdbeFreeOpArray(db, p->aOp, p->nOp);
sqlite3DbFree(db, p->aColName);
sqlite3DbFree(db, p->zSql);
+#ifdef SQLITE_ENABLE_NORMALIZE
+ sqlite3DbFree(db, p->zNormSql);
+#endif
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
{
int i;
@@ -4152,12 +4167,12 @@ int sqlite3VdbeRecordCompareWithSkip(
}else{
idx1 = getVarint32(aKey1, szHdr1);
d1 = szHdr1;
- if( d1>(unsigned)nKey1 ){
- pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
- return 0; /* Corruption */
- }
i = 0;
}
+ if( d1>(unsigned)nKey1 ){
+ pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
+ return 0; /* Corruption */
+ }
VVA_ONLY( mem1.szMalloc = 0; ) /* Only needed by assert() statements */
assert( pPKey2->pKeyInfo->nAllField>=pPKey2->nField
diff --git a/chromium/third_party/sqlite/src/src/vdbemem.c b/chromium/third_party/sqlite/src/src/vdbemem.c
index c527800c3f7..04c8f9440e9 100644
--- a/chromium/third_party/sqlite/src/src/vdbemem.c
+++ b/chromium/third_party/sqlite/src/src/vdbemem.c
@@ -377,7 +377,8 @@ int sqlite3VdbeMemStringify(Mem *pMem, u8 enc, u8 bForce){
assert( fg & MEM_Real );
sqlite3_snprintf(nByte, pMem->z, "%!.15g", pMem->u.r);
}
- pMem->n = sqlite3Strlen30(pMem->z);
+ assert( pMem->z!=0 );
+ pMem->n = sqlite3Strlen30NN(pMem->z);
pMem->enc = SQLITE_UTF8;
pMem->flags |= MEM_Str|MEM_Term;
if( bForce ) pMem->flags &= ~(MEM_Int|MEM_Real);
diff --git a/chromium/third_party/sqlite/src/src/vtab.c b/chromium/third_party/sqlite/src/src/vtab.c
index 82a194cf118..0062984b3fd 100644
--- a/chromium/third_party/sqlite/src/src/vtab.c
+++ b/chromium/third_party/sqlite/src/src/vtab.c
@@ -328,7 +328,6 @@ void sqlite3VtabBeginParse(
Token *pModuleName, /* Name of the module for the virtual table */
int ifNotExists /* No error if the table already exists */
){
- int iDb; /* The database the table is being created in */
Table *pTable; /* The new virtual table */
sqlite3 *db; /* Database connection */
@@ -338,8 +337,6 @@ void sqlite3VtabBeginParse(
assert( 0==pTable->pIndex );
db = pParse->db;
- iDb = sqlite3SchemaToIndex(db, pTable->pSchema);
- assert( iDb>=0 );
assert( pTable->nModuleArg==0 );
addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName));
@@ -359,6 +356,8 @@ void sqlite3VtabBeginParse(
** The second call, to obtain permission to create the table, is made now.
*/
if( pTable->azModuleArg ){
+ int iDb = sqlite3SchemaToIndex(db, pTable->pSchema);
+ assert( iDb>=0 ); /* The database the table is being created in */
sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName,
pTable->azModuleArg[0], pParse->db->aDb[iDb].zDbSName);
}
@@ -1053,7 +1052,7 @@ FuncDef *sqlite3VtabOverloadFunction(
/* Check to see the left operand is a column in a virtual table */
if( NEVER(pExpr==0) ) return pDef;
if( pExpr->op!=TK_COLUMN ) return pDef;
- pTab = pExpr->pTab;
+ pTab = pExpr->y.pTab;
if( pTab==0 ) return pDef;
if( !IsVirtual(pTab) ) return pDef;
pVtab = sqlite3GetVTable(db, pTab)->pVtab;
diff --git a/chromium/third_party/sqlite/src/src/walker.c b/chromium/third_party/sqlite/src/src/walker.c
index 7bb5884ded3..3d36a8cabf9 100644
--- a/chromium/third_party/sqlite/src/src/walker.c
+++ b/chromium/third_party/sqlite/src/src/walker.c
@@ -55,8 +55,8 @@ static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){
if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
}
#ifndef SQLITE_OMIT_WINDOWFUNC
- if( !ExprHasProperty(pExpr, EP_Reduced) && pExpr->pWin ){
- Window *pWin = pExpr->pWin;
+ if( ExprHasProperty(pExpr, EP_WinFunc) ){
+ Window *pWin = pExpr->y.pWin;
if( sqlite3WalkExprList(pWalker, pWin->pPartition) ) return WRC_Abort;
if( sqlite3WalkExprList(pWalker, pWin->pOrderBy) ) return WRC_Abort;
if( sqlite3WalkExpr(pWalker, pWin->pFilter) ) return WRC_Abort;
diff --git a/chromium/third_party/sqlite/src/src/where.c b/chromium/third_party/sqlite/src/src/where.c
index d97922b19bc..0a264cf14f1 100644
--- a/chromium/third_party/sqlite/src/src/where.c
+++ b/chromium/third_party/sqlite/src/src/where.c
@@ -854,7 +854,6 @@ static void constructAutomaticIndex(
translateColumnToCopy(pParse, addrTop, pLevel->iTabCur,
pTabItem->regResult, 1);
sqlite3VdbeGoto(v, addrTop);
- pTabItem->fg.viaCoroutine = 0;
}else{
sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); VdbeCoverage(v);
}
@@ -1032,9 +1031,11 @@ static sqlite3_index_info *allocateIndexInfo(
** method of the virtual table with the sqlite3_index_info object that
** comes in as the 3rd argument to this function.
**
-** If an error occurs, pParse is populated with an error message and a
-** non-zero value is returned. Otherwise, 0 is returned and the output
-** part of the sqlite3_index_info structure is left populated.
+** If an error occurs, pParse is populated with an error message and an
+** appropriate error code is returned. A return of SQLITE_CONSTRAINT from
+** xBestIndex is not considered an error. SQLITE_CONSTRAINT indicates that
+** the current configuration of "unusable" flags in sqlite3_index_info can
+** not result in a valid plan.
**
** Whether or not an error is returned, it is the responsibility of the
** caller to eventually free p->idxStr if p->needToFreeIdxStr indicates
@@ -1048,7 +1049,7 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
rc = pVtab->pModule->xBestIndex(pVtab, p);
TRACE_IDX_OUTPUTS(p);
- if( rc!=SQLITE_OK ){
+ if( rc!=SQLITE_OK && rc!=SQLITE_CONSTRAINT ){
if( rc==SQLITE_NOMEM ){
sqlite3OomFault(pParse->db);
}else if( !pVtab->zErrMsg ){
@@ -1059,19 +1060,7 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
}
sqlite3_free(pVtab->zErrMsg);
pVtab->zErrMsg = 0;
-
-#if 0
- /* This error is now caught by the caller.
- ** Search for "xBestIndex malfunction" below */
- for(i=0; i<p->nConstraint; i++){
- if( !p->aConstraint[i].usable && p->aConstraintUsage[i].argvIndex>0 ){
- sqlite3ErrorMsg(pParse,
- "table %s: xBestIndex returned an invalid plan", pTab->zName);
- }
- }
-#endif
-
- return pParse->nErr;
+ return rc;
}
#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */
@@ -2126,6 +2115,14 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
sqlite3 *db = pWInfo->pParse->db;
int rc;
+ /* Stop the search once we hit the query planner search limit */
+ if( pBuilder->iPlanLimit==0 ){
+ WHERETRACE(0xffffffff,("=== query planner search limit reached ===\n"));
+ if( pBuilder->pOrSet ) pBuilder->pOrSet->n = 0;
+ return SQLITE_DONE;
+ }
+ pBuilder->iPlanLimit--;
+
/* If pBuilder->pOrSet is defined, then only keep track of the costs
** and prereqs.
*/
@@ -3136,7 +3133,17 @@ static int whereLoopAddVirtualOne(
/* Invoke the virtual table xBestIndex() method */
rc = vtabBestIndex(pParse, pSrc->pTab, pIdxInfo);
- if( rc ) return rc;
+ if( rc ){
+ if( rc==SQLITE_CONSTRAINT ){
+ /* If the xBestIndex method returns SQLITE_CONSTRAINT, that means
+ ** that the particular combination of parameters provided is unusable.
+ ** Make no entries in the loop table.
+ */
+ WHERETRACE(0xffff, (" ^^^^--- non-viable plan rejected!\n"));
+ return SQLITE_OK;
+ }
+ return rc;
+ }
mxTerm = -1;
assert( pNew->nLSlot>=nConstraint );
@@ -3532,9 +3539,11 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
/* Loop over the tables in the join, from left to right */
pNew = pBuilder->pNew;
whereLoopInit(pNew);
+ pBuilder->iPlanLimit = SQLITE_QUERY_PLANNER_LIMIT;
for(iTab=0, pItem=pTabList->a; pItem<pEnd; iTab++, pItem++){
Bitmask mUnusable = 0;
pNew->iTab = iTab;
+ pBuilder->iPlanLimit += SQLITE_QUERY_PLANNER_LIMIT_INCR;
pNew->maskSelf = sqlite3WhereGetMask(&pWInfo->sMaskSet, pItem->iCursor);
if( ((pItem->fg.jointype|priorJointype) & (JT_LEFT|JT_CROSS))!=0 ){
/* This condition is true when pItem is the FROM clause term on the
@@ -3560,7 +3569,15 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
rc = whereLoopAddOr(pBuilder, mPrereq, mUnusable);
}
mPrior |= pNew->maskSelf;
- if( rc || db->mallocFailed ) break;
+ if( rc || db->mallocFailed ){
+ if( rc==SQLITE_DONE ){
+ /* We hit the query planner search limit set by iPlanLimit */
+ sqlite3_log(SQLITE_WARNING, "abbreviated query algorithm search");
+ rc = SQLITE_OK;
+ }else{
+ break;
+ }
+ }
}
whereLoopClear(db, pNew);
diff --git a/chromium/third_party/sqlite/src/src/whereInt.h b/chromium/third_party/sqlite/src/src/whereInt.h
index 86c47290f17..6925e39e1d2 100644
--- a/chromium/third_party/sqlite/src/src/whereInt.h
+++ b/chromium/third_party/sqlite/src/src/whereInt.h
@@ -402,12 +402,33 @@ struct WhereLoopBuilder {
int nRecValid; /* Number of valid fields currently in pRec */
#endif
unsigned int bldFlags; /* SQLITE_BLDF_* flags */
+ unsigned int iPlanLimit; /* Search limiter */
};
/* Allowed values for WhereLoopBuider.bldFlags */
#define SQLITE_BLDF_INDEXED 0x0001 /* An index is used */
#define SQLITE_BLDF_UNIQUE 0x0002 /* All keys of a UNIQUE index used */
+/* The WhereLoopBuilder.iPlanLimit is used to limit the number of
+** index+constraint combinations the query planner will consider for a
+** particular query. If this parameter is unlimited, then certain
+** pathological queries can spend excess time in the sqlite3WhereBegin()
+** routine. The limit is high enough that is should not impact real-world
+** queries.
+**
+** SQLITE_QUERY_PLANNER_LIMIT is the baseline limit. The limit is
+** increased by SQLITE_QUERY_PLANNER_LIMIT_INCR before each term of the FROM
+** clause is processed, so that every table in a join is guaranteed to be
+** able to propose a some index+constraint combinations even if the initial
+** baseline limit was exhausted by prior tables of the join.
+*/
+#ifndef SQLITE_QUERY_PLANNER_LIMIT
+# define SQLITE_QUERY_PLANNER_LIMIT 20000
+#endif
+#ifndef SQLITE_QUERY_PLANNER_LIMIT_INCR
+# define SQLITE_QUERY_PLANNER_LIMIT_INCR 1000
+#endif
+
/*
** The WHERE clause processing routine has two halves. The
** first part does the start of the WHERE loop and the second
diff --git a/chromium/third_party/sqlite/src/src/wherecode.c b/chromium/third_party/sqlite/src/src/wherecode.c
index 3fab79cf99d..bbd738b8edd 100644
--- a/chromium/third_party/sqlite/src/src/wherecode.c
+++ b/chromium/third_party/sqlite/src/src/wherecode.c
@@ -1117,7 +1117,7 @@ static int whereIndexExprTransNode(Walker *p, Expr *pExpr){
pExpr->op = TK_COLUMN;
pExpr->iTable = pX->iIdxCur;
pExpr->iColumn = pX->iIdxCol;
- pExpr->pTab = 0;
+ pExpr->y.pTab = 0;
return WRC_Prune;
}else{
return WRC_Continue;
diff --git a/chromium/third_party/sqlite/src/src/whereexpr.c b/chromium/third_party/sqlite/src/src/whereexpr.c
index f4ce4471c67..e91f1d72165 100644
--- a/chromium/third_party/sqlite/src/src/whereexpr.c
+++ b/chromium/third_party/sqlite/src/src/whereexpr.c
@@ -281,7 +281,7 @@ static int isLikeOrGlob(
){
if( pLeft->op!=TK_COLUMN
|| sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT
- || IsVirtual(pLeft->pTab) /* Value might be numeric */
+ || IsVirtual(pLeft->y.pTab) /* Value might be numeric */
){
sqlite3ExprDelete(db, pPrefix);
sqlite3ValueFree(pVal);
@@ -382,7 +382,7 @@ static int isAuxiliaryVtabOperator(
** MATCH(expression,vtab_column)
*/
pCol = pList->a[1].pExpr;
- if( pCol->op==TK_COLUMN && IsVirtual(pCol->pTab) ){
+ if( pCol->op==TK_COLUMN && IsVirtual(pCol->y.pTab) ){
for(i=0; i<ArraySize(aOp); i++){
if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){
*peOp2 = aOp[i].eOp2;
@@ -404,12 +404,12 @@ static int isAuxiliaryVtabOperator(
** with function names in an arbitrary case.
*/
pCol = pList->a[0].pExpr;
- if( pCol->op==TK_COLUMN && IsVirtual(pCol->pTab) ){
+ if( pCol->op==TK_COLUMN && IsVirtual(pCol->y.pTab) ){
sqlite3_vtab *pVtab;
sqlite3_module *pMod;
void (*xNotUsed)(sqlite3_context*,int,sqlite3_value**);
void *pNotUsed;
- pVtab = sqlite3GetVTable(db, pCol->pTab)->pVtab;
+ pVtab = sqlite3GetVTable(db, pCol->y.pTab)->pVtab;
assert( pVtab!=0 );
assert( pVtab->pModule!=0 );
pMod = (sqlite3_module *)pVtab->pModule;
@@ -427,10 +427,10 @@ static int isAuxiliaryVtabOperator(
int res = 0;
Expr *pLeft = pExpr->pLeft;
Expr *pRight = pExpr->pRight;
- if( pLeft->op==TK_COLUMN && IsVirtual(pLeft->pTab) ){
+ if( pLeft->op==TK_COLUMN && IsVirtual(pLeft->y.pTab) ){
res++;
}
- if( pRight && pRight->op==TK_COLUMN && IsVirtual(pRight->pTab) ){
+ if( pRight && pRight->op==TK_COLUMN && IsVirtual(pRight->y.pTab) ){
res++;
SWAP(Expr*, pLeft, pRight);
}
@@ -1574,6 +1574,7 @@ void sqlite3WhereTabFuncArgs(
pArgs = pItem->u1.pFuncArg;
if( pArgs==0 ) return;
for(j=k=0; j<pArgs->nExpr; j++){
+ Expr *pRhs;
while( k<pTab->nCol && (pTab->aCol[k].colFlags & COLFLAG_HIDDEN)==0 ){k++;}
if( k>=pTab->nCol ){
sqlite3ErrorMsg(pParse, "too many arguments on %s() - max %d",
@@ -1584,9 +1585,10 @@ void sqlite3WhereTabFuncArgs(
if( pColRef==0 ) return;
pColRef->iTable = pItem->iCursor;
pColRef->iColumn = k++;
- pColRef->pTab = pTab;
- pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef,
- sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0));
+ pColRef->y.pTab = pTab;
+ pRhs = sqlite3PExpr(pParse, TK_UPLUS,
+ sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0), 0);
+ pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, pRhs);
whereClauseInsert(pWC, pTerm, TERM_DYNAMIC);
}
}
diff --git a/chromium/third_party/sqlite/src/src/window.c b/chromium/third_party/sqlite/src/src/window.c
index bf02a0dec9f..ec3d55cef7e 100644
--- a/chromium/third_party/sqlite/src/src/window.c
+++ b/chromium/third_party/sqlite/src/src/window.c
@@ -624,12 +624,12 @@ static int selectWindowRewriteExprCb(Walker *pWalker, Expr *pExpr){
switch( pExpr->op ){
case TK_FUNCTION:
- if( pExpr->pWin==0 ){
+ if( !ExprHasProperty(pExpr, EP_WinFunc) ){
break;
}else{
Window *pWin;
for(pWin=p->pWin; pWin; pWin=pWin->pNextWin){
- if( pExpr->pWin==pWin ){
+ if( pExpr->y.pWin==pWin ){
assert( pWin->pOwner==pExpr );
return WRC_Prune;
}
@@ -746,7 +746,7 @@ static ExprList *exprListAppendList(
*/
int sqlite3WindowRewrite(Parse *pParse, Select *p){
int rc = SQLITE_OK;
- if( p->pWin ){
+ if( p->pWin && p->pPrior==0 ){
Vdbe *v = sqlite3GetVdbe(pParse);
sqlite3 *db = pParse->db;
Select *pSub = 0; /* The subquery */
@@ -959,11 +959,13 @@ windowAllocErr:
*/
void sqlite3WindowAttach(Parse *pParse, Expr *p, Window *pWin){
if( p ){
+ assert( p->op==TK_FUNCTION );
/* This routine is only called for the parser. If pWin was not
** allocated due to an OOM, then the parser would fail before ever
** invoking this routine */
if( ALWAYS(pWin) ){
- p->pWin = pWin;
+ p->y.pWin = pWin;
+ ExprSetProperty(p, EP_WinFunc);
pWin->pOwner = p;
if( p->flags & EP_Distinct ){
sqlite3ErrorMsg(pParse,
@@ -2126,7 +2128,7 @@ static void windowCodeDefaultStep(
*/
Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p){
Window *pNew = 0;
- if( p ){
+ if( ALWAYS(p) ){
pNew = sqlite3DbMallocZero(db, sizeof(Window));
if( pNew ){
pNew->zName = sqlite3DbStrDup(db, p->zName);
diff --git a/chromium/third_party/sqlite/src/tool/genfkey.test b/chromium/third_party/sqlite/src/tool/genfkey.test
index 2c52acdef8b..732043e116c 100644
--- a/chromium/third_party/sqlite/src/tool/genfkey.test
+++ b/chromium/third_party/sqlite/src/tool/genfkey.test
@@ -351,4 +351,3 @@ do_test genfkey-6.7 {
SELECT * FROM child;
}
} {1 1}
-
diff --git a/chromium/third_party/sqlite/src/tool/lempar.c b/chromium/third_party/sqlite/src/tool/lempar.c
index ce485e9f15b..2ea791518f7 100644
--- a/chromium/third_party/sqlite/src/tool/lempar.c
+++ b/chromium/third_party/sqlite/src/tool/lempar.c
@@ -23,6 +23,7 @@
** input grammar file:
*/
#include <stdio.h>
+#include <assert.h>
/************ Begin %include sections from the grammar ************************/
%%
/**************** End of %include directives **********************************/
@@ -987,10 +988,9 @@ void Parse(
yymajor = YYNOCODE;
}else{
while( yypParser->yytos >= yypParser->yystack
- && yymx != YYERRORSYMBOL
&& (yyact = yy_find_reduce_action(
yypParser->yytos->stateno,
- YYERRORSYMBOL)) >= YY_MIN_REDUCE
+ YYERRORSYMBOL)) > YY_MAX_SHIFTREDUCE
){
yy_pop_parser_stack(yypParser);
}
diff --git a/chromium/third_party/sqlite/src/tool/mkpragmatab.tcl b/chromium/third_party/sqlite/src/tool/mkpragmatab.tcl
index 6ed2dfc8e84..c67e3102e7e 100644
--- a/chromium/third_party/sqlite/src/tool/mkpragmatab.tcl
+++ b/chromium/third_party/sqlite/src/tool/mkpragmatab.tcl
@@ -120,7 +120,7 @@ set pragma_def {
NAME: writable_schema
TYPE: FLAG
- ARG: SQLITE_WriteSchema
+ ARG: SQLITE_WriteSchema|SQLITE_NoSchemaError
IF: !defined(SQLITE_OMIT_FLAG_PRAGMAS)
NAME: read_uncommitted
@@ -220,9 +220,17 @@ set pragma_def {
NAME: table_info
FLAG: NeedSchema Result1 SchemaOpt
+ ARG: 0
COLS: cid name type notnull dflt_value pk
IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
+ NAME: table_xinfo
+ TYPE: TABLE_INFO
+ FLAG: NeedSchema Result1 SchemaOpt
+ ARG: 1
+ COLS: cid name type notnull dflt_value pk hidden
+ IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
+
NAME: stats
FLAG: NeedSchema Result0 SchemaReq
COLS: tbl idx wdth hght flgs
@@ -359,16 +367,33 @@ set pragma_def {
IF: defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
NAME: key
+ TYPE: KEY
+ ARG: 0
IF: defined(SQLITE_HAS_CODEC)
NAME: rekey
+ TYPE: KEY
+ ARG: 1
IF: defined(SQLITE_HAS_CODEC)
NAME: hexkey
+ TYPE: HEXKEY
+ ARG: 2
IF: defined(SQLITE_HAS_CODEC)
NAME: hexrekey
TYPE: HEXKEY
+ ARG: 3
+ IF: defined(SQLITE_HAS_CODEC)
+
+ NAME: textkey
+ TYPE: KEY
+ ARG: 4
+ IF: defined(SQLITE_HAS_CODEC)
+
+ NAME: textrekey
+ TYPE: KEY
+ ARG: 5
IF: defined(SQLITE_HAS_CODEC)
NAME: activate_extensions
@@ -414,20 +439,20 @@ set cols {}
set cols_list {}
set arg 0
proc record_one {} {
- global name type if arg allbyname typebyif flags cols allcols
+ global name type if arg allbyname typebyif flags cols all_cols
global cols_list colUsedBy
if {$name==""} return
if {$cols!=""} {
- if {![info exists allcols($cols)]} {
+ if {![info exists all_cols($cols)]} {
+ set all_cols($cols) 1
lappend cols_list $cols
- set allcols($cols) [llength $cols_list]
}
- set cx $allcols($cols)
+ set cx $cols
lappend colUsedBy($cols) $name
} else {
set cx 0
}
- set allbyname($name) [list $type $arg $if $flags $cx]
+ set allbyname($name) [list $type $arg $if $flags $cols]
set name {}
set type {}
set if {}
@@ -509,6 +534,13 @@ foreach f [lsort [array names allflags]] {
set fv [expr {$fv*2}]
}
+# Sort the column lists so that longer column lists occur first
+#
+proc colscmp {a b} {
+ return [expr {[llength $b] - [llength $a]}]
+}
+set cols_list [lsort -command colscmp $cols_list]
+
# Generate the array of column names used by pragmas that act like
# queries.
#
@@ -517,10 +549,23 @@ puts $fd "** or that return single-column results where the name of the"
puts $fd "** result column is different from the name of the pragma\n*/"
puts $fd "static const char *const pragCName\[\] = {"
set offset 0
+set allcollist {}
foreach cols $cols_list {
- set cols_offset($allcols($cols)) $offset
+ set n [llength $cols]
+ set limit [expr {[llength $allcollist] - $n}]
+ for {set i 0} {$i<$limit} {incr i} {
+ set sublist [lrange $allcollist $i [expr {$i+$n-1}]]
+ if {$sublist==$cols} {
+ puts $fd [format "%27s/* $colUsedBy($cols) reuses $i */" ""]
+ set cols_offset($cols) $i
+ break
+ }
+ }
+ if {$i<$limit} continue
+ set cols_offset($cols) $offset
set ub " /* Used by: $colUsedBy($cols) */"
foreach c $cols {
+ lappend allcollist $c
puts $fd [format " /* %3d */ %-14s%s" $offset \"$c\", $ub]
set ub ""
incr offset
@@ -538,7 +583,7 @@ puts $fd " u8 mPragFlg; /* Zero or more PragFlg_XXX values */"
puts $fd { u8 iPragCName; /* Start of column names in pragCName[] */}
puts $fd " u8 nPragCName; \
/* Num of col names. 0 means use pragma name */"
-puts $fd " u32 iArg; /* Extra argument */"
+puts $fd " u64 iArg; /* Extra argument */"
puts $fd "\175 PragmaName;"
puts $fd "static const PragmaName aPragmaName\[\] = \173"
@@ -546,12 +591,12 @@ set current_if {}
set spacer [format { %26s } {}]
foreach name $allnames {
foreach {type arg if flag cx} $allbyname($name) break
- if {$cx==0} {
+ if {$cx==0 || $cx==""} {
set cy 0
set nx 0
} else {
set cy $cols_offset($cx)
- set nx [llength [lindex $cols_list [expr {$cx-1}]]]
+ set nx [llength $cx]
}
if {$if!=$current_if} {
if {$current_if!=""} {
diff --git a/chromium/third_party/sqlite/src/tool/sqldiff.c b/chromium/third_party/sqlite/src/tool/sqldiff.c
index d398ae08ab5..ed3d5335679 100644
--- a/chromium/third_party/sqlite/src/tool/sqldiff.c
+++ b/chromium/third_party/sqlite/src/tool/sqldiff.c
@@ -1493,8 +1493,8 @@ static void putsVarint(FILE *out, sqlite3_uint64 v){
/*
** Write an SQLite value onto out.
*/
-static void putValue(FILE *out, sqlite3_value *pVal){
- int iDType = sqlite3_value_type(pVal);
+static void putValue(FILE *out, sqlite3_stmt *pStmt, int k){
+ int iDType = sqlite3_column_type(pStmt, k);
sqlite3_int64 iX;
double rX;
sqlite3_uint64 uX;
@@ -1503,24 +1503,24 @@ static void putValue(FILE *out, sqlite3_value *pVal){
putc(iDType, out);
switch( iDType ){
case SQLITE_INTEGER:
- iX = sqlite3_value_int64(pVal);
+ iX = sqlite3_column_int64(pStmt, k);
memcpy(&uX, &iX, 8);
for(j=56; j>=0; j-=8) putc((uX>>j)&0xff, out);
break;
case SQLITE_FLOAT:
- rX = sqlite3_value_double(pVal);
+ rX = sqlite3_column_double(pStmt, k);
memcpy(&uX, &rX, 8);
for(j=56; j>=0; j-=8) putc((uX>>j)&0xff, out);
break;
case SQLITE_TEXT:
- iX = sqlite3_value_bytes(pVal);
+ iX = sqlite3_column_bytes(pStmt, k);
putsVarint(out, (sqlite3_uint64)iX);
- fwrite(sqlite3_value_text(pVal),1,(size_t)iX,out);
+ fwrite(sqlite3_column_text(pStmt, k),1,(size_t)iX,out);
break;
case SQLITE_BLOB:
- iX = sqlite3_value_bytes(pVal);
+ iX = sqlite3_column_bytes(pStmt, k);
putsVarint(out, (sqlite3_uint64)iX);
- fwrite(sqlite3_value_blob(pVal),1,(size_t)iX,out);
+ fwrite(sqlite3_column_blob(pStmt, k),1,(size_t)iX,out);
break;
case SQLITE_NULL:
break;
@@ -1650,10 +1650,10 @@ static void changeset_one_table(const char *zTab, FILE *out){
case SQLITE_UPDATE: {
for(k=1, i=0; i<nCol; i++){
if( aiFlg[i] ){
- putValue(out, sqlite3_column_value(pStmt,k));
+ putValue(out, pStmt, k);
k++;
}else if( sqlite3_column_int(pStmt,k) ){
- putValue(out, sqlite3_column_value(pStmt,k+1));
+ putValue(out, pStmt, k+1);
k += 3;
}else{
putc(0, out);
@@ -1665,7 +1665,7 @@ static void changeset_one_table(const char *zTab, FILE *out){
putc(0, out);
k++;
}else if( sqlite3_column_int(pStmt,k) ){
- putValue(out, sqlite3_column_value(pStmt,k+2));
+ putValue(out, pStmt, k+2);
k += 3;
}else{
putc(0, out);
@@ -1677,10 +1677,10 @@ static void changeset_one_table(const char *zTab, FILE *out){
case SQLITE_INSERT: {
for(k=1, i=0; i<nCol; i++){
if( aiFlg[i] ){
- putValue(out, sqlite3_column_value(pStmt,k));
+ putValue(out, pStmt, k);
k++;
}else{
- putValue(out, sqlite3_column_value(pStmt,k+2));
+ putValue(out, pStmt, k+2);
k += 3;
}
}
@@ -1689,10 +1689,10 @@ static void changeset_one_table(const char *zTab, FILE *out){
case SQLITE_DELETE: {
for(k=1, i=0; i<nCol; i++){
if( aiFlg[i] ){
- putValue(out, sqlite3_column_value(pStmt,k));
+ putValue(out, pStmt, k);
k++;
}else{
- putValue(out, sqlite3_column_value(pStmt,k+1));
+ putValue(out, pStmt, k+1);
k += 3;
}
}
diff --git a/chromium/third_party/sqlite/src/tool/warnings.sh b/chromium/third_party/sqlite/src/tool/warnings.sh
index 69bb556789b..f8778fb74b1 100644
--- a/chromium/third_party/sqlite/src/tool/warnings.sh
+++ b/chromium/third_party/sqlite/src/tool/warnings.sh
@@ -16,10 +16,10 @@ fi
rm -f sqlite3.c
make sqlite3.c
-echo '********** No optimizations. Includes FTS4/5, RTREE, JSON1 ***'
+echo '********** No optimizations. Includes FTS4/5, GEOPOLY, JSON1 ***'
echo '********** ' Options: $WARNING_OPTS
gcc -c $WARNING_OPTS -std=c89 \
- -ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE \
+ -ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_GEOPOLY \
-DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_JSON1 \
sqlite3.c
if test x`uname` = 'xLinux'; then
@@ -52,9 +52,9 @@ echo '********** ' Options: $WARNING_OPTS
gcc -c $WARNING_OPTS -std=c89 \
-ansi -DSQLITE_ENABLE_STAT4 -DSQLITE_THREADSAFE=0 \
sqlite3.c
-echo '********** Optimized -O3. Includes FTS4/5, RTREE, JSON1 ******'
+echo '********** Optimized -O3. Includes FTS4/5, GEOPOLY, JSON1 ******'
echo '********** ' Options: $WARNING_OPTS
gcc -O3 -c $WARNING_OPTS -std=c89 \
- -ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE \
+ -ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_GEOPOLY \
-DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_JSON1 \
sqlite3.c