summaryrefslogtreecommitdiff
path: root/chromium/third_party/sqlite/src
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/sqlite/src')
-rw-r--r--chromium/third_party/sqlite/src/Makefile.in54
-rw-r--r--chromium/third_party/sqlite/src/Makefile.msc64
-rw-r--r--chromium/third_party/sqlite/src/VERSION2
-rw-r--r--chromium/third_party/sqlite/src/autoconf/Makefile.am2
-rw-r--r--chromium/third_party/sqlite/src/autoconf/Makefile.msc7
-rwxr-xr-xchromium/third_party/sqlite/src/configure64
-rw-r--r--chromium/third_party/sqlite/src/configure.ac12
-rw-r--r--chromium/third_party/sqlite/src/doc/lemon.html355
-rw-r--r--chromium/third_party/sqlite/src/ext/fts5/fts5_vocab.c162
-rw-r--r--chromium/third_party/sqlite/src/ext/lsm1/lsm_shared.c10
-rw-r--r--chromium/third_party/sqlite/src/ext/lsm1/lsm_vtab.c800
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/csv.c18
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/mmapwarm.c108
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/series.c5
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/unionvtab.c512
-rw-r--r--chromium/third_party/sqlite/src/ext/misc/vtablog.c509
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbu10.test2
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbufault.test2
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbufault3.test2
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbufts.test4
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/rbutemplimit.test129
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/sqlite3rbu.c85
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/sqlite3rbu.h44
-rw-r--r--chromium/third_party/sqlite/src/ext/rbu/test_rbu.c38
-rw-r--r--chromium/third_party/sqlite/src/ext/repair/README.md16
-rw-r--r--chromium/third_party/sqlite/src/ext/repair/checkfreelist.c299
-rw-r--r--chromium/third_party/sqlite/src/ext/rtree/rtree.c4
-rw-r--r--chromium/third_party/sqlite/src/ext/rtree/rtreeA.test4
-rw-r--r--chromium/third_party/sqlite/src/ext/rtree/rtreeconnect.test56
-rw-r--r--chromium/third_party/sqlite/src/ext/session/sqlite3session.h16
-rw-r--r--chromium/third_party/sqlite/src/main.mk54
-rw-r--r--chromium/third_party/sqlite/src/manifest339
-rw-r--r--chromium/third_party/sqlite/src/manifest.uuid2
-rw-r--r--chromium/third_party/sqlite/src/src/alter.c14
-rw-r--r--chromium/third_party/sqlite/src/src/attach.c9
-rw-r--r--chromium/third_party/sqlite/src/src/auth.c8
-rw-r--r--chromium/third_party/sqlite/src/src/btree.c467
-rw-r--r--chromium/third_party/sqlite/src/src/btree.h1
-rw-r--r--chromium/third_party/sqlite/src/src/btreeInt.h13
-rw-r--r--chromium/third_party/sqlite/src/src/build.c107
-rw-r--r--chromium/third_party/sqlite/src/src/callback.c6
-rw-r--r--chromium/third_party/sqlite/src/src/ctime.c3
-rw-r--r--chromium/third_party/sqlite/src/src/dbpage.c329
-rw-r--r--chromium/third_party/sqlite/src/src/delete.c6
-rw-r--r--chromium/third_party/sqlite/src/src/expr.c106
-rw-r--r--chromium/third_party/sqlite/src/src/func.c33
-rw-r--r--chromium/third_party/sqlite/src/src/global.c4
-rw-r--r--chromium/third_party/sqlite/src/src/insert.c23
-rw-r--r--chromium/third_party/sqlite/src/src/main.c65
-rw-r--r--chromium/third_party/sqlite/src/src/malloc.c156
-rw-r--r--chromium/third_party/sqlite/src/src/memjournal.c32
-rw-r--r--chromium/third_party/sqlite/src/src/os.c4
-rw-r--r--chromium/third_party/sqlite/src/src/os.h2
-rw-r--r--chromium/third_party/sqlite/src/src/os_unix.c211
-rw-r--r--chromium/third_party/sqlite/src/src/os_win.c90
-rw-r--r--chromium/third_party/sqlite/src/src/pager.c273
-rw-r--r--chromium/third_party/sqlite/src/src/pager.h1
-rw-r--r--chromium/third_party/sqlite/src/src/parse.y13
-rw-r--r--chromium/third_party/sqlite/src/src/pcache.c11
-rw-r--r--chromium/third_party/sqlite/src/src/pcache.h2
-rw-r--r--chromium/third_party/sqlite/src/src/pcache1.c62
-rw-r--r--chromium/third_party/sqlite/src/src/pragma.c153
-rw-r--r--chromium/third_party/sqlite/src/src/prepare.c80
-rw-r--r--chromium/third_party/sqlite/src/src/printf.c21
-rw-r--r--chromium/third_party/sqlite/src/src/resolve.c4
-rw-r--r--chromium/third_party/sqlite/src/src/select.c490
-rw-r--r--chromium/third_party/sqlite/src/src/shell.c8408
-rw-r--r--chromium/third_party/sqlite/src/src/shell.c.in78
-rw-r--r--chromium/third_party/sqlite/src/src/sqlite.h.in169
-rw-r--r--chromium/third_party/sqlite/src/src/sqlite3ext.h10
-rw-r--r--chromium/third_party/sqlite/src/src/sqliteInt.h126
-rw-r--r--chromium/third_party/sqlite/src/src/status.c34
-rw-r--r--chromium/third_party/sqlite/src/src/tclsqlite.c831
-rw-r--r--chromium/third_party/sqlite/src/src/test1.c74
-rw-r--r--chromium/third_party/sqlite/src/src/test6.c25
-rw-r--r--chromium/third_party/sqlite/src/src/test8.c21
-rw-r--r--chromium/third_party/sqlite/src/src/test_bestindex.c10
-rw-r--r--chromium/third_party/sqlite/src/src/test_config.c6
-rw-r--r--chromium/third_party/sqlite/src/src/test_devsym.c218
-rw-r--r--chromium/third_party/sqlite/src/src/test_func.c118
-rw-r--r--chromium/third_party/sqlite/src/src/test_malloc.c41
-rw-r--r--chromium/third_party/sqlite/src/src/test_md5.c450
-rw-r--r--chromium/third_party/sqlite/src/src/test_tclsh.c198
-rw-r--r--chromium/third_party/sqlite/src/src/test_tclvar.c90
-rw-r--r--chromium/third_party/sqlite/src/src/trigger.c2
-rw-r--r--chromium/third_party/sqlite/src/src/update.c23
-rw-r--r--chromium/third_party/sqlite/src/src/util.c54
-rw-r--r--chromium/third_party/sqlite/src/src/vacuum.c13
-rw-r--r--chromium/third_party/sqlite/src/src/vdbe.c221
-rw-r--r--chromium/third_party/sqlite/src/src/vdbeInt.h12
-rw-r--r--chromium/third_party/sqlite/src/src/vdbeapi.c52
-rw-r--r--chromium/third_party/sqlite/src/src/vdbeaux.c157
-rw-r--r--chromium/third_party/sqlite/src/src/vdbeblob.c48
-rw-r--r--chromium/third_party/sqlite/src/src/vdbemem.c69
-rw-r--r--chromium/third_party/sqlite/src/src/vdbesort.c23
-rw-r--r--chromium/third_party/sqlite/src/src/vdbetrace.c2
-rw-r--r--chromium/third_party/sqlite/src/src/vtab.c104
-rw-r--r--chromium/third_party/sqlite/src/src/wal.c22
-rw-r--r--chromium/third_party/sqlite/src/src/wal.h8
-rw-r--r--chromium/third_party/sqlite/src/src/walker.c26
-rw-r--r--chromium/third_party/sqlite/src/src/where.c168
-rw-r--r--chromium/third_party/sqlite/src/src/whereInt.h3
-rw-r--r--chromium/third_party/sqlite/src/src/wherecode.c10
-rw-r--r--chromium/third_party/sqlite/src/src/whereexpr.c214
-rw-r--r--chromium/third_party/sqlite/src/tool/addopcodes.tcl9
-rw-r--r--chromium/third_party/sqlite/src/tool/lemon.c25
-rw-r--r--chromium/third_party/sqlite/src/tool/lempar.c3
-rw-r--r--chromium/third_party/sqlite/src/tool/mkautoconfamal.sh2
-rwxr-xr-xchromium/third_party/sqlite/src/tool/mkccode.tcl93
-rw-r--r--chromium/third_party/sqlite/src/tool/mkopcodeh.tcl16
-rw-r--r--chromium/third_party/sqlite/src/tool/mkshellc.tcl15
-rw-r--r--chromium/third_party/sqlite/src/tool/mksourceid.c853
-rw-r--r--chromium/third_party/sqlite/src/tool/mksqlite3c.tcl41
-rw-r--r--chromium/third_party/sqlite/src/tool/mksqlite3h.tcl24
-rw-r--r--chromium/third_party/sqlite/src/tool/speed-check.sh14
-rw-r--r--chromium/third_party/sqlite/src/tool/split-sqlite3c.tcl2
-rw-r--r--chromium/third_party/sqlite/src/tool/sqlite3_analyzer.c.in27
-rw-r--r--chromium/third_party/sqlite/src/tool/tostr.tcl12
-rw-r--r--chromium/third_party/sqlite/src/tool/warnings-clang.sh6
119 files changed, 7836 insertions, 12023 deletions
diff --git a/chromium/third_party/sqlite/src/Makefile.in b/chromium/third_party/sqlite/src/Makefile.in
index 358e777d59a..a0f71d76a55 100644
--- a/chromium/third_party/sqlite/src/Makefile.in
+++ b/chromium/third_party/sqlite/src/Makefile.in
@@ -166,7 +166,8 @@ USE_AMALGAMATION = @USE_AMALGAMATION@
#
LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \
backup.lo bitvec.lo btmutex.lo btree.lo build.lo \
- callback.lo complete.lo ctime.lo date.lo dbstat.lo delete.lo \
+ callback.lo complete.lo ctime.lo \
+ date.lo dbpage.lo dbstat.lo delete.lo \
expr.lo fault.lo fkey.lo \
fts3.lo fts3_aux.lo fts3_expr.lo fts3_hash.lo fts3_icu.lo \
fts3_porter.lo fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo \
@@ -215,6 +216,7 @@ SRC = \
$(TOP)/src/complete.c \
$(TOP)/src/ctime.c \
$(TOP)/src/date.c \
+ $(TOP)/src/dbpage.c \
$(TOP)/src/dbstat.c \
$(TOP)/src/delete.c \
$(TOP)/src/expr.c \
@@ -265,7 +267,7 @@ SRC = \
$(TOP)/src/rowset.c \
$(TOP)/src/select.c \
$(TOP)/src/status.c \
- $(TOP)/src/shell.c \
+ $(TOP)/src/shell.c.in \
$(TOP)/src/sqlite.h.in \
$(TOP)/src/sqlite3ext.h \
$(TOP)/src/sqliteInt.h \
@@ -362,6 +364,7 @@ SRC += \
parse.c \
parse.h \
config.h \
+ shell.c \
sqlite3.h
# Source code to the test files.
@@ -393,6 +396,7 @@ TESTSRC = \
$(TOP)/src/test_intarray.c \
$(TOP)/src/test_journal.c \
$(TOP)/src/test_malloc.c \
+ $(TOP)/src/test_md5.c \
$(TOP)/src/test_multiplex.c \
$(TOP)/src/test_mutex.c \
$(TOP)/src/test_onefile.c \
@@ -404,6 +408,7 @@ TESTSRC = \
$(TOP)/src/test_server.c \
$(TOP)/src/test_superlock.c \
$(TOP)/src/test_syscall.c \
+ $(TOP)/src/test_tclsh.c \
$(TOP)/src/test_tclvar.c \
$(TOP)/src/test_thread.c \
$(TOP)/src/test_vfs.c \
@@ -428,6 +433,7 @@ TESTSRC += \
$(TOP)/ext/fts5/fts5_test_mi.c \
$(TOP)/ext/fts5/fts5_test_tok.c \
$(TOP)/ext/misc/ieee754.c \
+ $(TOP)/ext/misc/mmapwarm.c \
$(TOP)/ext/misc/nextchar.c \
$(TOP)/ext/misc/percentile.c \
$(TOP)/ext/misc/regexp.c \
@@ -448,6 +454,7 @@ TESTSRC2 = \
$(TOP)/src/build.c \
$(TOP)/src/ctime.c \
$(TOP)/src/date.c \
+ $(TOP)/src/dbpage.c \
$(TOP)/src/dbstat.c \
$(TOP)/src/expr.c \
$(TOP)/src/func.c \
@@ -568,6 +575,8 @@ SHELL_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4
SHELL_OPT += -DSQLITE_ENABLE_EXPLAIN_COMMENTS
SHELL_OPT += -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
SHELL_OPT += -DSQLITE_ENABLE_STMTVTAB
+SHELL_OPT += -DSQLITE_ENABLE_DBPAGE_VTAB
+SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ
FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000
@@ -596,9 +605,9 @@ libtclsqlite3.la: tclsqlite.lo libsqlite3.la
-version-info "8:6:8" \
-avoid-version
-sqlite3$(TEXE): $(TOP)/src/shell.c sqlite3.c
+sqlite3$(TEXE): shell.c sqlite3.c
$(LTLINK) $(READLINE_FLAGS) $(SHELL_OPT) -o $@ \
- $(TOP)/src/shell.c sqlite3.c \
+ shell.c sqlite3.c \
$(LIBREADLINE) $(TLIBS) -rpath "$(libdir)"
sqldiff$(TEXE): $(TOP)/tool/sqldiff.c sqlite3.lo sqlite3.h
@@ -693,6 +702,11 @@ lemon$(BEXE): $(TOP)/tool/lemon.c $(TOP)/tool/lempar.c
$(BCC) -o $@ $(TOP)/tool/lemon.c
cp $(TOP)/tool/lempar.c .
+# Rules to build the program that generates the source-id
+#
+mksourceid$(BEXE): $(TOP)/tool/mksourceid.c
+ $(BCC) -o $@ $(TOP)/tool/mksourceid.c
+
# Rules to build individual *.o files from generated *.c files. This
# applies to:
#
@@ -746,6 +760,9 @@ ctime.lo: $(TOP)/src/ctime.c $(HDR)
date.lo: $(TOP)/src/date.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/date.c
+dbpage.lo: $(TOP)/src/dbpage.c $(HDR)
+ $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/dbpage.c
+
dbstat.lo: $(TOP)/src/dbstat.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/dbstat.c
@@ -930,7 +947,7 @@ tclsqlite.lo: $(TOP)/src/tclsqlite.c $(HDR)
$(LTCOMPILE) -DUSE_TCL_STUBS=1 -c $(TOP)/src/tclsqlite.c
tclsqlite-shell.lo: $(TOP)/src/tclsqlite.c $(HDR)
- $(LTCOMPILE) -DTCLSH=1 -o $@ -c $(TOP)/src/tclsqlite.c
+ $(LTCOMPILE) -DTCLSH -o $@ -c $(TOP)/src/tclsqlite.c
tclsqlite-stubs.lo: $(TOP)/src/tclsqlite.c $(HDR)
$(LTCOMPILE) -DUSE_TCL_STUBS=1 -o $@ -c $(TOP)/src/tclsqlite.c
@@ -958,13 +975,24 @@ parse.c: $(TOP)/src/parse.y lemon$(BEXE) $(TOP)/tool/addopcodes.tcl
mv parse.h parse.h.temp
$(TCLSH_CMD) $(TOP)/tool/addopcodes.tcl parse.h.temp >parse.h
-sqlite3.h: $(TOP)/src/sqlite.h.in $(TOP)/manifest.uuid $(TOP)/VERSION
+sqlite3.h: $(TOP)/src/sqlite.h.in $(TOP)/manifest mksourceid$(BEXE) $(TOP)/VERSION
$(TCLSH_CMD) $(TOP)/tool/mksqlite3h.tcl $(TOP) >sqlite3.h
keywordhash.h: $(TOP)/tool/mkkeywordhash.c
$(BCC) -o mkkeywordhash$(BEXE) $(OPT_FEATURE_FLAGS) $(OPTS) $(TOP)/tool/mkkeywordhash.c
./mkkeywordhash$(BEXE) >keywordhash.h
+# Source files that go into making shell.c
+SHELL_SRC = \
+ $(TOP)/src/shell.c.in \
+ $(TOP)/ext/misc/shathree.c \
+ $(TOP)/ext/misc/fileio.c \
+ $(TOP)/ext/misc/completion.c
+
+shell.c: $(SHELL_SRC) $(TOP)/tool/mkshellc.tcl
+ $(TCLSH_CMD) $(TOP)/tool/mkshellc.tcl >shell.c
+
+
# Rules to build the extension objects.
@@ -1085,12 +1113,14 @@ sqlite3rbu.lo: $(TOP)/ext/rbu/sqlite3rbu.c $(HDR) $(EXTHDR)
# necessary because the test fixture requires non-API symbols which are
# hidden when the library is built via the amalgamation).
#
-TESTFIXTURE_FLAGS = -DTCLSH=1 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1
+TESTFIXTURE_FLAGS = -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1
+TESTFIXTURE_FLAGS += -DTCLSH_INIT_PROC=sqlite3TestInit
TESTFIXTURE_FLAGS += -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE
TESTFIXTURE_FLAGS += -DBUILD_sqlite
TESTFIXTURE_FLAGS += -DSQLITE_SERIES_CONSTRAINT_VERIFY=1
TESTFIXTURE_FLAGS += -DSQLITE_DEFAULT_PAGE_SIZE=1024
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_STMTVTAB
+TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_DBPAGE_VTAB
TESTFIXTURE_SRC0 = $(TESTSRC2) libsqlite3.la
TESTFIXTURE_SRC1 = sqlite3.c
@@ -1151,14 +1181,8 @@ valgrindtest: $(TESTPROGS) valgrindfuzz
smoketest: $(TESTPROGS) fuzzcheck$(TEXE)
./testfixture$(TEXE) $(TOP)/test/main.test $(TESTOPTS)
-sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl
- echo "#define TCLSH 2" > $@
- echo "#define SQLITE_ENABLE_DBSTAT_VTAB 1" >> $@
- cat sqlite3.c $(TOP)/src/tclsqlite.c >> $@
- echo "static const char *tclsh_main_loop(void){" >> $@
- echo "static const char *zMainloop = " >> $@
- $(TCLSH_CMD) $(TOP)/tool/tostr.tcl $(TOP)/tool/spaceanal.tcl >> $@
- echo "; return zMainloop; }" >> $@
+sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in
+ $(TCLSH_CMD) $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in >sqlite3_analyzer.c
sqlite3_analyzer$(TEXE): sqlite3_analyzer.c
$(LTLINK) sqlite3_analyzer.c -o $@ $(LIBTCL) $(TLIBS)
diff --git a/chromium/third_party/sqlite/src/Makefile.msc b/chromium/third_party/sqlite/src/Makefile.msc
index da94288c855..2804c25ab4c 100644
--- a/chromium/third_party/sqlite/src/Makefile.msc
+++ b/chromium/third_party/sqlite/src/Makefile.msc
@@ -1091,7 +1091,8 @@ LTLIBS = $(LTLIBS) $(LIBICU)
#
LIBOBJS0 = vdbe.lo parse.lo alter.lo analyze.lo attach.lo auth.lo \
backup.lo bitvec.lo btmutex.lo btree.lo build.lo \
- callback.lo complete.lo ctime.lo date.lo dbstat.lo delete.lo \
+ callback.lo complete.lo ctime.lo \
+ date.lo dbpage.lo dbstat.lo delete.lo \
expr.lo fault.lo fkey.lo \
fts3.lo fts3_aux.lo fts3_expr.lo fts3_hash.lo fts3_icu.lo \
fts3_porter.lo fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo \
@@ -1154,6 +1155,7 @@ SRC00 = \
$(TOP)\src\complete.c \
$(TOP)\src\ctime.c \
$(TOP)\src\date.c \
+ $(TOP)\src\dbpage.c \
$(TOP)\src\dbstat.c \
$(TOP)\src\delete.c \
$(TOP)\src\expr.c \
@@ -1220,11 +1222,6 @@ SRC01 = \
$(TOP)\src\wherecode.c \
$(TOP)\src\whereexpr.c
-# Shell source code files.
-#
-SRC02 = \
- $(TOP)\src\shell.c
-
# Core miscellaneous files.
#
SRC03 = \
@@ -1331,6 +1328,7 @@ SRC11 = \
keywordhash.h \
opcodes.h \
parse.h \
+ shell.c \
$(SQLITE3H)
# Generated Tcl header files
@@ -1345,7 +1343,7 @@ SRC12 =
# All source code files.
#
-SRC = $(SRC00) $(SRC01) $(SRC02) $(SRC03) $(SRC04) $(SRC05) $(SRC06) $(SRC07) $(SRC08) $(SRC09) $(SRC10) $(SRC11)
+SRC = $(SRC00) $(SRC01) $(SRC03) $(SRC04) $(SRC05) $(SRC06) $(SRC07) $(SRC08) $(SRC09) $(SRC10) $(SRC11)
# Source code to the test files.
#
@@ -1376,6 +1374,7 @@ TESTSRC = \
$(TOP)\src\test_intarray.c \
$(TOP)\src\test_journal.c \
$(TOP)\src\test_malloc.c \
+ $(TOP)\src\test_md5.c \
$(TOP)\src\test_multiplex.c \
$(TOP)\src\test_mutex.c \
$(TOP)\src\test_onefile.c \
@@ -1387,6 +1386,7 @@ TESTSRC = \
$(TOP)\src\test_server.c \
$(TOP)\src\test_superlock.c \
$(TOP)\src\test_syscall.c \
+ $(TOP)\src\test_tclsh.c \
$(TOP)\src\test_tclvar.c \
$(TOP)\src\test_thread.c \
$(TOP)\src\test_vfs.c \
@@ -1411,6 +1411,7 @@ TESTEXT = \
$(TOP)\ext\fts5\fts5_test_mi.c \
$(TOP)\ext\fts5\fts5_test_tok.c \
$(TOP)\ext\misc\ieee754.c \
+ $(TOP)\ext\misc\mmapwarm.c \
$(TOP)\ext\misc\nextchar.c \
$(TOP)\ext\misc\percentile.c \
$(TOP)\ext\misc\regexp.c \
@@ -1507,13 +1508,14 @@ FUZZDATA = \
# when the shell is not being dynamically linked.
#
!IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0
-SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_STMTVTAB
+SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_STMTVTAB
+SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_ENABLE_DBSTAT_VTAB
!ENDIF
# <<mark>>
# Extra compiler options for various test tools.
#
-MPTESTER_COMPILE_OPTS = -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS5
+MPTESTER_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5
FUZZERSHELL_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1
FUZZCHECK_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ -DSQLITE_MAX_MEMORY=50000000
FUZZCHECK_SRC = $(TOP)\test\fuzzcheck.c $(TOP)\test\ossfuzz.c
@@ -1568,8 +1570,8 @@ sqlite3.def: libsqlite3.lib
| sort >> sqlite3.def
# <</block2>>
-$(SQLITE3EXE): $(TOP)\src\shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H)
- $(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) $(TOP)\src\shell.c $(SHELL_CORE_SRC) \
+$(SQLITE3EXE): shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H)
+ $(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) shell.c $(SHELL_CORE_SRC) \
/link $(SQLITE3EXEPDB) $(LDFLAGS) $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
# <<mark>>
@@ -1628,7 +1630,6 @@ mptest: mptester.exe
-mkdir tsrc
for %i in ($(SRC00)) do copy /Y %i tsrc
for %i in ($(SRC01)) do copy /Y %i tsrc
- for %i in ($(SRC02)) do copy /Y %i tsrc
for %i in ($(SRC03)) do copy /Y %i tsrc
for %i in ($(SRC04)) do copy /Y %i tsrc
for %i in ($(SRC05)) do copy /Y %i tsrc
@@ -1670,6 +1671,12 @@ lemon.exe: $(TOP)\tool\lemon.c lempar.c
$(BCC) $(NO_WARN) -Daccess=_access \
-Fe$@ $(TOP)\tool\lemon.c /link $(LDFLAGS) $(NLTLINKOPTS) $(NLTLIBPATHS)
+# <<mark>>
+# Rules to build the source-id generator tool
+#
+mksourceid.exe: $(TOP)\tool\mksourceid.c
+ $(BCC) $(NO_WARN) -Fe$@ $(TOP)\tool\mksourceid.c /link $(LDFLAGS) $(NLTLINKOPTS) $(NLTLIBPATHS)
+
# Rules to build individual *.lo files from generated *.c files. This
# applies to:
#
@@ -1740,7 +1747,10 @@ ctime.lo: $(TOP)\src\ctime.c $(HDR)
date.lo: $(TOP)\src\date.c $(HDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\date.c
-dbstat.lo: $(TOP)\src\date.c $(HDR)
+dbpage.lo: $(TOP)\src\dbpage.c $(HDR)
+ $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\dbpage.c
+
+dbstat.lo: $(TOP)\src\dbstat.c $(HDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\dbstat.c
delete.lo: $(TOP)\src\delete.c $(HDR)
@@ -1924,7 +1934,7 @@ tclsqlite.lo: $(TOP)\src\tclsqlite.c $(HDR) $(SQLITE_TCL_DEP)
$(LTCOMPILE) $(NO_WARN) -DUSE_TCL_STUBS=1 -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c
tclsqlite-shell.lo: $(TOP)\src\tclsqlite.c $(HDR) $(SQLITE_TCL_DEP)
- $(LTCOMPILE) $(NO_WARN) -DTCLSH=1 -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c
+ $(LTCOMPILE) $(NO_WARN) -DTCLSH -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c
tclsqlite3.exe: tclsqlite-shell.lo $(SQLITE3C) $(SQLITE3H) $(LIBRESOBJS)
$(LTLINK) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite-shell.lo $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
@@ -1948,7 +1958,7 @@ parse.c: $(TOP)\src\parse.y lemon.exe $(TOP)\tool\addopcodes.tcl
move parse.h parse.h.temp
$(TCLSH_CMD) $(TOP)\tool\addopcodes.tcl parse.h.temp > parse.h
-$(SQLITE3H): $(TOP)\src\sqlite.h.in $(TOP)\manifest.uuid $(TOP)\VERSION
+$(SQLITE3H): $(TOP)\src\sqlite.h.in $(TOP)\manifest mksourceid.exe $(TOP)\VERSION
$(TCLSH_CMD) $(TOP)\tool\mksqlite3h.tcl $(TOP:\=/) > $(SQLITE3H) $(MKSQLITE3H_ARGS)
sqlite3ext.h: .target_source
@@ -1967,6 +1977,15 @@ mkkeywordhash.exe: $(TOP)\tool\mkkeywordhash.c
keywordhash.h: $(TOP)\tool\mkkeywordhash.c mkkeywordhash.exe
.\mkkeywordhash.exe > keywordhash.h
+# Source files that go into making shell.c
+SHELL_SRC = \
+ $(TOP)\src\shell.c.in \
+ $(TOP)\ext\misc\shathree.c \
+ $(TOP)\ext\misc\fileio.c \
+ $(TOP)\ext\misc\completion.c
+
+shell.c: $(SHELL_SRC) $(TOP)\tool\mkshellc.tcl
+ $(TCLSH_CMD) $(TOP)\tool\mkshellc.tcl > shell.c
# Rules to build the extension objects.
@@ -2086,12 +2105,13 @@ sqlite3rbu.lo: $(TOP)\ext\rbu\sqlite3rbu.c $(HDR) $(EXTHDR)
# necessary because the test fixture requires non-API symbols which are
# hidden when the library is built via the amalgamation).
#
-TESTFIXTURE_FLAGS = -DTCLSH=1 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1
+TESTFIXTURE_FLAGS = -DTCLSH_INIT_PROC=sqlite3TestInit -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERVER=1 -DSQLITE_PRIVATE=""
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_CORE $(NO_WARN)
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERIES_CONSTRAINT_VERIFY=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_DEFAULT_PAGE_SIZE=1024
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB
+TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) $(TEST_CCONV_OPTS)
TESTFIXTURE_SRC0 = $(TESTEXT) $(TESTSRC2)
@@ -2171,14 +2191,8 @@ smoketest: $(TESTPROGS)
@set PATH=$(LIBTCLPATH);$(PATH)
.\testfixture.exe $(TOP)\test\main.test $(TESTOPTS)
-sqlite3_analyzer.c: $(SQLITE3C) $(SQLITE3H) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl $(SQLITE_TCL_DEP)
- echo #define TCLSH 2 > $@
- echo #define SQLITE_ENABLE_DBSTAT_VTAB 1 >> $@
- copy $@ + $(SQLITE3C) + $(TOP)\src\tclsqlite.c $@
- echo static const char *tclsh_main_loop(void){ >> $@
- echo static const char *zMainloop = >> $@
- $(TCLSH_CMD) $(TOP)\tool\tostr.tcl $(TOP)\tool\spaceanal.tcl >> $@
- echo ; return zMainloop; } >> $@
+sqlite3_analyzer.c: $(SQLITE3C) $(SQLITE3H) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl $(TOP)\tool\mkccode.tcl $(TOP)\tool\sqlite3_analyzer.c.in $(SQLITE_TCL_DEP)
+ $(TCLSH_CMD) $(TOP)\tool\mkccode.tcl $(TOP)\tool\sqlite3_analyzer.c.in > $@
sqlite3_analyzer.exe: sqlite3_analyzer.c $(LIBRESOBJS)
$(LTLINK) $(NO_WARN) -DBUILD_sqlite -I$(TCLINCDIR) sqlite3_analyzer.c \
@@ -2260,7 +2274,7 @@ clean:
del /Q sqlite3.c sqlite3.h 2>NUL
del /Q opcodes.c opcodes.h 2>NUL
del /Q lemon.* lempar.c parse.* 2>NUL
- del /Q mkkeywordhash.* keywordhash.h 2>NUL
+ del /Q mksourceid.* mkkeywordhash.* keywordhash.h 2>NUL
del /Q notasharedlib.* 2>NUL
-rmdir /Q/S .deps 2>NUL
-rmdir /Q/S .libs 2>NUL
diff --git a/chromium/third_party/sqlite/src/VERSION b/chromium/third_party/sqlite/src/VERSION
index 076e9c774e0..6075c9a9ff9 100644
--- a/chromium/third_party/sqlite/src/VERSION
+++ b/chromium/third_party/sqlite/src/VERSION
@@ -1 +1 @@
-3.20.1
+3.21.0
diff --git a/chromium/third_party/sqlite/src/autoconf/Makefile.am b/chromium/third_party/sqlite/src/autoconf/Makefile.am
index e8211596d9b..8c046f822dd 100644
--- a/chromium/third_party/sqlite/src/autoconf/Makefile.am
+++ b/chromium/third_party/sqlite/src/autoconf/Makefile.am
@@ -10,7 +10,7 @@ sqlite3_SOURCES = shell.c sqlite3.h
EXTRA_sqlite3_SOURCES = sqlite3.c
sqlite3_LDADD = @EXTRA_SHELL_OBJ@ @READLINE_LIBS@
sqlite3_DEPENDENCIES = @EXTRA_SHELL_OBJ@
-sqlite3_CFLAGS = $(AM_CFLAGS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS
+sqlite3_CFLAGS = $(AM_CFLAGS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_ENABLE_STMTVTAB -DSQLITE_ENABLE_DBSTAT_VTAB
include_HEADERS = sqlite3.h sqlite3ext.h
diff --git a/chromium/third_party/sqlite/src/autoconf/Makefile.msc b/chromium/third_party/sqlite/src/autoconf/Makefile.msc
index f0f9a01ee00..e0f7ad8615f 100644
--- a/chromium/third_party/sqlite/src/autoconf/Makefile.msc
+++ b/chromium/third_party/sqlite/src/autoconf/Makefile.msc
@@ -927,7 +927,8 @@ LIBRESOBJS =
# when the shell is not being dynamically linked.
#
!IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0
-SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_STMTVTAB
+SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_STMTVTAB
+SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_ENABLE_DBSTAT_VTAB
!ENDIF
@@ -957,8 +958,8 @@ sqlite3.def: Replace.exe $(LIBOBJ)
| .\Replace.exe "^\s+/EXPORT:_?(sqlite3(?:session|changeset|changegroup)?_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \
| sort >> sqlite3.def
-$(SQLITE3EXE): $(TOP)\shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H)
- $(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) $(TOP)\shell.c $(SHELL_CORE_SRC) \
+$(SQLITE3EXE): shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H)
+ $(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) shell.c $(SHELL_CORE_SRC) \
/link $(SQLITE3EXEPDB) $(LDFLAGS) $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
diff --git a/chromium/third_party/sqlite/src/configure b/chromium/third_party/sqlite/src/configure
index c9b4073b79a..64b95e912c9 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.20.1.
+# Generated by GNU Autoconf 2.69 for sqlite 3.21.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.20.1'
-PACKAGE_STRING='sqlite 3.20.1'
+PACKAGE_VERSION='3.21.0'
+PACKAGE_STRING='sqlite 3.21.0'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -909,6 +909,7 @@ enable_fts3
enable_fts4
enable_fts5
enable_json1
+enable_update_limit
enable_rtree
enable_session
enable_gcov
@@ -1463,7 +1464,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.20.1 to adapt to many kinds of systems.
+\`configure' configures sqlite 3.21.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1528,7 +1529,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of sqlite 3.20.1:";;
+ short | recursive ) echo "Configuration of sqlite 3.21.0:";;
esac
cat <<\_ACEOF
@@ -1560,6 +1561,7 @@ Optional Features:
--enable-fts4 Enable the FTS4 extension
--enable-fts5 Enable the FTS5 extension
--enable-json1 Enable the JSON1 extension
+ --enable-update-limit Enable the UPDATE/DELETE LIMIT clause
--enable-rtree Enable the RTREE extension
--enable-session Enable the SESSION extension
--enable-gcov Enable coverage testing using gcov
@@ -1652,7 +1654,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-sqlite configure 3.20.1
+sqlite configure 3.21.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2071,7 +2073,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.20.1, which was
+It was created by sqlite $as_me 3.21.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -3929,13 +3931,13 @@ if ${lt_cv_nm_interface+:} false; then :
else
lt_cv_nm_interface="BSD nm"
echo "int some_variable = 0;" > conftest.$ac_ext
- (eval echo "\"\$as_me:3932: $ac_compile\"" >&5)
+ (eval echo "\"\$as_me:3934: $ac_compile\"" >&5)
(eval "$ac_compile" 2>conftest.err)
cat conftest.err >&5
- (eval echo "\"\$as_me:3935: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+ (eval echo "\"\$as_me:3937: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
cat conftest.err >&5
- (eval echo "\"\$as_me:3938: output\"" >&5)
+ (eval echo "\"\$as_me:3940: output\"" >&5)
cat conftest.out >&5
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
lt_cv_nm_interface="MS dumpbin"
@@ -5141,7 +5143,7 @@ ia64-*-hpux*)
;;
*-*-irix6*)
# Find out which ABI we are using.
- echo '#line 5144 "configure"' > conftest.$ac_ext
+ echo '#line 5146 "configure"' > conftest.$ac_ext
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -6666,11 +6668,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:6669: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:6671: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:6673: \$? = $ac_status" >&5
+ echo "$as_me:6675: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -7005,11 +7007,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7008: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7010: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:7012: \$? = $ac_status" >&5
+ echo "$as_me:7014: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -7110,11 +7112,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7113: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7115: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:7117: \$? = $ac_status" >&5
+ echo "$as_me:7119: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -7165,11 +7167,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7168: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7170: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:7172: \$? = $ac_status" >&5
+ echo "$as_me:7174: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -9545,7 +9547,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 9548 "configure"
+#line 9550 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -9641,7 +9643,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 9644 "configure"
+#line 9646 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -10302,7 +10304,7 @@ USE_AMALGAMATION=1
# if not, then we fall back to plain tclsh.
# TODO: try other versions before falling back?
#
-for ac_prog in tclsh8.6 tclsh8.5 tclsh
+for ac_prog in tclsh8.7 tclsh8.6 tclsh8.5 tclsh
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
@@ -11540,6 +11542,20 @@ if test "${enable_json1}" = "yes" ; then
fi
#########
+# See whether we should enable the LIMIT clause on UPDATE and DELETE
+# statements.
+# Check whether --enable-update-limit was given.
+if test "${enable_update_limit+set}" = set; then :
+ enableval=$enable_update_limit; enable_udlimit=yes
+else
+ enable_udlimit=no
+fi
+
+if test "${enable_udlimit}" = "yes" ; then
+ OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT"
+fi
+
+#########
# See whether we should enable RTREE
# Check whether --enable-rtree was given.
if test "${enable_rtree+set}" = set; then :
@@ -12151,7 +12167,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.20.1, which was
+This file was extended by sqlite $as_me 3.21.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -12217,7 +12233,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.20.1
+sqlite config.status 3.21.0
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/chromium/third_party/sqlite/src/configure.ac b/chromium/third_party/sqlite/src/configure.ac
index 39179cc8f8d..7adb3e700d9 100644
--- a/chromium/third_party/sqlite/src/configure.ac
+++ b/chromium/third_party/sqlite/src/configure.ac
@@ -120,7 +120,7 @@ USE_AMALGAMATION=1
# if not, then we fall back to plain tclsh.
# TODO: try other versions before falling back?
#
-AC_CHECK_PROGS(TCLSH_CMD, [tclsh8.6 tclsh8.5 tclsh], none)
+AC_CHECK_PROGS(TCLSH_CMD, [tclsh8.7 tclsh8.6 tclsh8.5 tclsh], none)
if test "$TCLSH_CMD" = "none"; then
# If we can't find a local tclsh, then building the amalgamation will fail.
# We act as though --disable-amalgamation has been used.
@@ -645,6 +645,16 @@ if test "${enable_json1}" = "yes" ; then
fi
#########
+# See whether we should enable the LIMIT clause on UPDATE and DELETE
+# statements.
+AC_ARG_ENABLE(update-limit, AC_HELP_STRING([--enable-update-limit],
+ [Enable the UPDATE/DELETE LIMIT clause]),
+ [enable_udlimit=yes],[enable_udlimit=no])
+if test "${enable_udlimit}" = "yes" ; then
+ OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT"
+fi
+
+#########
# See whether we should enable RTREE
AC_ARG_ENABLE(rtree, AC_HELP_STRING([--enable-rtree],
[Enable the RTREE extension]),
diff --git a/chromium/third_party/sqlite/src/doc/lemon.html b/chromium/third_party/sqlite/src/doc/lemon.html
index db8286200f1..eb6ff121242 100644
--- a/chromium/third_party/sqlite/src/doc/lemon.html
+++ b/chromium/third_party/sqlite/src/doc/lemon.html
@@ -2,12 +2,12 @@
<head>
<title>The Lemon Parser Generator</title>
</head>
-<body bgcolor=white>
-<h1 align=center>The Lemon Parser Generator</h1>
+<body bgcolor='white'>
+<h1 align='center'>The Lemon Parser Generator</h1>
<p>Lemon is an LALR(1) parser generator for C.
It does the same job as "bison" and "yacc".
-But lemon is not a bison or yacc clone. Lemon
+But Lemon is not a bison or yacc clone. Lemon
uses a different grammar syntax which is designed to
reduce the number of coding errors. Lemon also uses a
parsing engine that is faster than yacc and
@@ -16,7 +16,7 @@ bison and which is both reentrant and threadsafe.
has also been updated so that it too can generate a
reentrant and threadsafe parser.)
Lemon also implements features that can be used
-to eliminate resource leaks, making is suitable for use
+to eliminate resource leaks, making it suitable for use
in long-running programs such as graphical user interfaces
or embedded controllers.</p>
@@ -58,8 +58,8 @@ Lemon comes with a default parser template which works fine for most
applications. But the user is free to substitute a different parser
template if desired.</p>
-<p>Depending on command-line options, Lemon will generate between
-one and three files of outputs.
+<p>Depending on command-line options, Lemon will generate up to
+three output files.
<ul>
<li>C code to implement the parser.
<li>A header file defining an integer ID for each terminal symbol.
@@ -90,17 +90,20 @@ the states used by the parser automaton.</p>
You can obtain a list of the available command-line options together
with a brief explanation of what each does by typing
<pre>
- lemon -?
+ lemon "-?"
</pre>
As of this writing, the following command-line options are supported:
<ul>
<li><b>-b</b>
Show only the basis for each parser state in the report file.
<li><b>-c</b>
-Do not compress the generated action tables.
+Do not compress the generated action tables. The parser will be a
+little larger and slower, but it will detect syntax errors sooner.
<li><b>-D<i>name</i></b>
-Define C preprocessor macro <i>name</i>. This macro is useable by
-"%ifdef" lines in the grammar file.
+Define C preprocessor macro <i>name</i>. This macro is usable by
+"<tt><a href='#pifdef'>%ifdef</a></tt>" and
+"<tt><a href='#pifdef'>%ifndef</a></tt>" lines
+in the grammar file.
<li><b>-g</b>
Do not generate a parser. Instead write the input grammar to standard
output with all comments, actions, and other extraneous text removed.
@@ -165,7 +168,7 @@ once for each token:
</pre>
The first argument to the Parse() routine is the pointer returned by
ParseAlloc().
-The second argument is a small positive integer that tells the parse the
+The second argument is a small positive integer that tells the parser the
type of the next token in the data stream.
There is one token type for each terminal symbol in the grammar.
The gram.h file generated by Lemon contains #define statements that
@@ -173,7 +176,7 @@ map symbolic terminal symbol names into appropriate integer values.
A value of 0 for the second argument is a special flag to the
parser to indicate that the end of input has been reached.
The third argument is the value of the given token. By default,
-the type of the third argument is integer, but the grammar will
+the type of the third argument is "void*", but the grammar will
usually redefine this type to be some kind of structure.
Typically the second argument will be a broad category of tokens
such as "identifier" or "number" and the third argument will
@@ -181,7 +184,7 @@ be the name of the identifier or the value of the number.</p>
<p>The Parse() function may have either three or four arguments,
depending on the grammar. If the grammar specification file requests
-it (via the <a href='#extraarg'><tt>extra_argument</tt> directive</a>),
+it (via the <tt><a href='#extraarg'>%extra_argument</a></tt> directive),
the Parse() function will have a fourth parameter that can be
of any type chosen by the programmer. The parser doesn't do anything
with this argument except to pass it through to action routines.
@@ -191,20 +194,20 @@ to the action routines without having to use global variables.</p>
<p>A typical use of a Lemon parser might look something like the
following:
<pre>
- 01 ParseTree *ParseFile(const char *zFilename){
- 02 Tokenizer *pTokenizer;
- 03 void *pParser;
- 04 Token sToken;
- 05 int hTokenId;
- 06 ParserState sState;
- 07
- 08 pTokenizer = TokenizerCreate(zFilename);
- 09 pParser = ParseAlloc( malloc );
- 10 InitParserState(&sState);
- 11 while( GetNextToken(pTokenizer, &hTokenId, &sToken) ){
- 12 Parse(pParser, hTokenId, sToken, &sState);
+ 1 ParseTree *ParseFile(const char *zFilename){
+ 2 Tokenizer *pTokenizer;
+ 3 void *pParser;
+ 4 Token sToken;
+ 5 int hTokenId;
+ 6 ParserState sState;
+ 7
+ 8 pTokenizer = TokenizerCreate(zFilename);
+ 9 pParser = ParseAlloc( malloc );
+ 10 InitParserState(&amp;sState);
+ 11 while( GetNextToken(pTokenizer, &amp;hTokenId, &amp;sToken) ){
+ 12 Parse(pParser, hTokenId, sToken, &amp;sState);
13 }
- 14 Parse(pParser, 0, sToken, &sState);
+ 14 Parse(pParser, 0, sToken, &amp;sState);
15 ParseFree(pParser, free );
16 TokenizerFree(pTokenizer);
17 return sState.treeRoot;
@@ -220,7 +223,7 @@ on line 16. The GetNextToken() function on line 11 retrieves the
next token from the input file and puts its type in the
integer variable hTokenId. The sToken variable is assumed to be
some kind of structure that contains details about each token,
-such as its complete text, what line it occurs on, etc. </p>
+such as its complete text, what line it occurs on, etc.</p>
<p>This example also assumes the existence of structure of type
ParserState that holds state information about a particular parse.
@@ -237,7 +240,7 @@ tree.</p>
<pre>
ParseFile(){
pParser = ParseAlloc( malloc );
- while( GetNextToken(pTokenizer,&hTokenId, &sToken) ){
+ while( GetNextToken(pTokenizer,&amp;hTokenId, &amp;sToken) ){
Parse(pParser, hTokenId, sToken);
}
Parse(pParser, 0, sToken);
@@ -297,23 +300,23 @@ specifies additional information Lemon requires to do its job.
Most of the work in using Lemon is in writing an appropriate
grammar file.</p>
-<p>The grammar file for lemon is, for the most part, free format.
+<p>The grammar file for Lemon is, for the most part, free format.
It does not have sections or divisions like yacc or bison. Any
declaration can occur at any point in the file.
Lemon ignores whitespace (except where it is needed to separate
-tokens) and it honors the same commenting conventions as C and C++.</p>
+tokens), and it honors the same commenting conventions as C and C++.</p>
<h3>Terminals and Nonterminals</h3>
<p>A terminal symbol (token) is any string of alphanumeric
and/or underscore characters
-that begins with an upper case letter.
+that begins with an uppercase letter.
A terminal can contain lowercase letters after the first character,
-but the usual convention is to make terminals all upper case.
+but the usual convention is to make terminals all uppercase.
A nonterminal, on the other hand, is any string of alphanumeric
-and underscore characters than begins with a lower case letter.
-Again, the usual convention is to make nonterminals use all lower
-case letters.</p>
+and underscore characters than begins with a lowercase letter.
+Again, the usual convention is to make nonterminals use all lowercase
+letters.</p>
<p>In Lemon, terminal and nonterminal symbols do not need to
be declared or identified in a separate section of the grammar file.
@@ -339,7 +342,8 @@ The list of terminals and nonterminals on the right-hand side of the
rule can be empty.
Rules can occur in any order, except that the left-hand side of the
first rule is assumed to be the start symbol for the grammar (unless
-specified otherwise using the <tt>%start</tt> directive described below.)
+specified otherwise using the <tt><a href='#start_symbol'>%start_symbol</a></tt>
+directive described below.)
A typical sequence of grammar rules might look something like this:
<pre>
expr ::= expr PLUS expr.
@@ -382,7 +386,7 @@ names to each symbol in a grammar rule and then using those symbolic
names in the action.
In yacc or bison, one would write this:
<pre>
- expr -> expr PLUS expr { $$ = $1 + $3; };
+ expr -&gt; expr PLUS expr { $$ = $1 + $3; };
</pre>
But in Lemon, the same rule becomes the following:
<pre>
@@ -423,13 +427,13 @@ whichever rule comes first in the grammar file.</p>
<p>Just like in
yacc and bison, Lemon allows a measure of control
-over the resolution of paring conflicts using precedence rules.
+over the resolution of parsing conflicts using precedence rules.
A precedence value can be assigned to any terminal symbol
using the
-<a href='#pleft'>%left</a>,
-<a href='#pright'>%right</a> or
-<a href='#pnonassoc'>%nonassoc</a> directives. Terminal symbols
-mentioned in earlier directives have a lower precedence that
+<tt><a href='#pleft'>%left</a></tt>,
+<tt><a href='#pright'>%right</a></tt> or
+<tt><a href='#pnonassoc'>%nonassoc</a></tt> directives. Terminal symbols
+mentioned in earlier directives have a lower precedence than
terminal symbols mentioned in later directives. For example:</p>
<p><pre>
@@ -505,29 +509,29 @@ as follows:
<li> If the precedence of the token to be shifted is greater than
the precedence of the rule to reduce, then resolve in favor
of the shift. No parsing conflict is reported.
-<li> If the precedence of the token it be shifted is less than the
+<li> If the precedence of the token to be shifted is less than the
precedence of the rule to reduce, then resolve in favor of the
reduce action. No parsing conflict is reported.
<li> If the precedences are the same and the shift token is
right-associative, then resolve in favor of the shift.
No parsing conflict is reported.
-<li> If the precedences are the same the shift token is
+<li> If the precedences are the same and the shift token is
left-associative, then resolve in favor of the reduce.
No parsing conflict is reported.
-<li> Otherwise, resolve the conflict by doing the shift and
- report the parsing conflict.
+<li> Otherwise, resolve the conflict by doing the shift, and
+ report a parsing conflict.
</ul>
Reduce-reduce conflicts are resolved this way:
<ul>
<li> If either reduce rule
lacks precedence information, then resolve in favor of the
- rule that appears first in the grammar and report a parsing
+ rule that appears first in the grammar, and report a parsing
conflict.
-<li> If both rules have precedence and the precedence is different
+<li> If both rules have precedence and the precedence is different,
then resolve the dispute in favor of the rule with the highest
- precedence and do not report a conflict.
+ precedence, and do not report a conflict.
<li> Otherwise, resolve the conflict by reducing by the rule that
- appears first in the grammar and report a parsing conflict.
+ appears first in the grammar, and report a parsing conflict.
</ul>
<h3>Special Directives</h3>
@@ -536,40 +540,40 @@ Reduce-reduce conflicts are resolved this way:
directives. We've described all the grammar rules, so now we'll
talk about the special directives.</p>
-<p>Directives in lemon can occur in any order. You can put them before
-the grammar rules, or after the grammar rules, or in the mist of the
+<p>Directives in Lemon can occur in any order. You can put them before
+the grammar rules, or after the grammar rules, or in the midst of the
grammar rules. It doesn't matter. The relative order of
directives used to assign precedence to terminals is important, but
other than that, the order of directives in Lemon is arbitrary.</p>
<p>Lemon supports the following special directives:
<ul>
-<li><tt>%code</tt>
-<li><tt>%default_destructor</tt>
-<li><tt>%default_type</tt>
-<li><tt>%destructor</tt>
-<li><tt>%endif</tt>
-<li><tt>%extra_argument</tt>
-<li><tt>%fallback</tt>
-<li><tt>%ifdef</tt>
-<li><tt>%ifndef</tt>
-<li><tt>%include</tt>
-<li><tt>%left</tt>
-<li><tt>%name</tt>
-<li><tt>%nonassoc</tt>
-<li><tt>%parse_accept</tt>
-<li><tt>%parse_failure </tt>
-<li><tt>%right</tt>
-<li><tt>%stack_overflow</tt>
-<li><tt>%stack_size</tt>
-<li><tt>%start_symbol</tt>
-<li><tt>%syntax_error</tt>
-<li><tt>%token_class</tt>
-<li><tt>%token_destructor</tt>
-<li><tt>%token_prefix</tt>
-<li><tt>%token_type</tt>
-<li><tt>%type</tt>
-<li><tt>%wildcard</tt>
+<li><tt><a href='#pcode'>%code</a></tt>
+<li><tt><a href='#default_destructor'>%default_destructor</a></tt>
+<li><tt><a href='#default_type'>%default_type</a></tt>
+<li><tt><a href='#destructor'>%destructor</a></tt>
+<li><tt><a href='#pifdef'>%endif</a></tt>
+<li><tt><a href='#extraarg'>%extra_argument</a></tt>
+<li><tt><a href='#pfallback'>%fallback</a></tt>
+<li><tt><a href='#pifdef'>%ifdef</a></tt>
+<li><tt><a href='#pifdef'>%ifndef</a></tt>
+<li><tt><a href='#pinclude'>%include</a></tt>
+<li><tt><a href='#pleft'>%left</a></tt>
+<li><tt><a href='#pname'>%name</a></tt>
+<li><tt><a href='#pnonassoc'>%nonassoc</a></tt>
+<li><tt><a href='#parse_accept'>%parse_accept</a></tt>
+<li><tt><a href='#parse_failure'>%parse_failure</a></tt>
+<li><tt><a href='#pright'>%right</a></tt>
+<li><tt><a href='#stack_overflow'>%stack_overflow</a></tt>
+<li><tt><a href='#stack_size'>%stack_size</a></tt>
+<li><tt><a href='#start_symbol'>%start_symbol</a></tt>
+<li><tt><a href='#syntax_error'>%syntax_error</a></tt>
+<li><tt><a href='#token_class'>%token_class</a></tt>
+<li><tt><a href='#token_destructor'>%token_destructor</a></tt>
+<li><tt><a href='#token_prefix'>%token_prefix</a></tt>
+<li><tt><a href='#token_type'>%token_type</a></tt>
+<li><tt><a href='#ptype'>%type</a></tt>
+<li><tt><a href='#pwildcard'>%wildcard</a></tt>
</ul>
Each of these directives will be described separately in the
following sections:</p>
@@ -577,43 +581,42 @@ following sections:</p>
<a name='pcode'></a>
<h4>The <tt>%code</tt> directive</h4>
-<p>The %code directive is used to specify addition C code that
+<p>The <tt>%code</tt> directive is used to specify additional C code that
is added to the end of the main output file. This is similar to
-the <a href='#pinclude'>%include</a> directive except that %include
-is inserted at the beginning of the main output file.</p>
+the <tt><a href='#pinclude'>%include</a></tt> directive except that
+<tt>%include</tt> is inserted at the beginning of the main output file.</p>
-<p>%code is typically used to include some action routines or perhaps
+<p><tt>%code</tt> is typically used to include some action routines or perhaps
a tokenizer or even the "main()" function
as part of the output file.</p>
<a name='default_destructor'></a>
<h4>The <tt>%default_destructor</tt> directive</h4>
-<p>The %default_destructor directive specifies a destructor to
+<p>The <tt>%default_destructor</tt> directive specifies a destructor to
use for non-terminals that do not have their own destructor
-specified by a separate %destructor directive. See the documentation
-on the <a name='#destructor'>%destructor</a> directive below for
+specified by a separate <tt>%destructor</tt> directive. See the documentation
+on the <tt><a name='#destructor'>%destructor</a></tt> directive below for
additional information.</p>
-<p>In some grammers, many different non-terminal symbols have the
-same datatype and hence the same destructor. This directive is
-a convenience way to specify the same destructor for all those
+<p>In some grammars, many different non-terminal symbols have the
+same data type and hence the same destructor. This directive is
+a convenient way to specify the same destructor for all those
non-terminals using a single statement.</p>
<a name='default_type'></a>
<h4>The <tt>%default_type</tt> directive</h4>
-<p>The %default_type directive specifies the datatype of non-terminal
-symbols that do no have their own datatype defined using a separate
-<a href='#ptype'>%type</a> directive.
-</p>
+<p>The <tt>%default_type</tt> directive specifies the data type of non-terminal
+symbols that do not have their own data type defined using a separate
+<tt><a href='#ptype'>%type</a></tt> directive.</p>
<a name='destructor'></a>
<h4>The <tt>%destructor</tt> directive</h4>
-<p>The %destructor directive is used to specify a destructor for
+<p>The <tt>%destructor</tt> directive is used to specify a destructor for
a non-terminal symbol.
-(See also the <a href='#token_destructor'>%token_destructor</a>
+(See also the <tt><a href='#token_destructor'>%token_destructor</a></tt>
directive which is used to specify a destructor for terminal symbols.)</p>
<p>A non-terminal's destructor is called to dispose of the
@@ -635,7 +638,7 @@ or other resources held by that non-terminal.</p>
%destructor nt { free($$); }
nt(A) ::= ID NUM. { A = malloc( 100 ); }
</pre>
-This example is a bit contrived but it serves to illustrate how
+This example is a bit contrived, but it serves to illustrate how
destructors work. The example shows a non-terminal named
"nt" that holds values of type "void*". When the rule for
an "nt" reduces, it sets the value of the non-terminal to
@@ -651,17 +654,17 @@ stack, unless the non-terminal is used in a C-code action. If
the non-terminal is used by C-code, then it is assumed that the
C-code will take care of destroying it.
More commonly, the value is used to build some
-larger structure and we don't want to destroy it, which is why
+larger structure, and we don't want to destroy it, which is why
the destructor is not called in this circumstance.</p>
<p>Destructors help avoid memory leaks by automatically freeing
allocated objects when they go out of scope.
To do the same using yacc or bison is much more difficult.</p>
-<a name="extraarg"></a>
+<a name='extraarg'></a>
<h4>The <tt>%extra_argument</tt> directive</h4>
-The %extra_argument directive instructs Lemon to add a 4th parameter
+The <tt>%extra_argument</tt> directive instructs Lemon to add a 4th parameter
to the parameter list of the Parse() function it generates. Lemon
doesn't do anything itself with this extra argument, but it does
make the argument available to C-code action routines, destructors,
@@ -679,61 +682,64 @@ in the most recent call to Parse().</p>
<a name='pfallback'></a>
<h4>The <tt>%fallback</tt> directive</h4>
-<p>The %fallback directive specifies an alternative meaning for one
+<p>The <tt>%fallback</tt> directive specifies an alternative meaning for one
or more tokens. The alternative meaning is tried if the original token
-would have generated a syntax error.
+would have generated a syntax error.</p>
-<p>The %fallback directive was added to support robust parsing of SQL
-syntax in <a href="https://www.sqlite.org/">SQLite</a>.
+<p>The <tt>%fallback</tt> directive was added to support robust parsing of SQL
+syntax in <a href='https://www.sqlite.org/'>SQLite</a>.
The SQL language contains a large assortment of keywords, each of which
appears as a different token to the language parser. SQL contains so
-many keywords, that it can be difficult for programmers to keep up with
+many keywords that it can be difficult for programmers to keep up with
them all. Programmers will, therefore, sometimes mistakenly use an
-obscure language keyword for an identifier. The %fallback directive
+obscure language keyword for an identifier. The <tt>%fallback</tt> directive
provides a mechanism to tell the parser: "If you are unable to parse
-this keyword, try treating it as an identifier instead."
+this keyword, try treating it as an identifier instead."</p>
-<p>The syntax of %fallback is as follows:
+<p>The syntax of <tt>%fallback</tt> is as follows:
<blockquote>
-<tt>%fallback</tt> <i>ID</i> <i>TOKEN...</i> <b>.</b>
-</blockquote>
+<tt>%fallback</tt> <i>ID</i> <i>TOKEN...</i> <b>.</b>
+</blockquote></p>
-<p>In words, the %fallback directive is followed by a list of token names
-terminated by a period. The first token name is the fallback token - the
+<p>In words, the <tt>%fallback</tt> directive is followed by a list of token
+names terminated by a period.
+The first token name is the fallback token &mdash; the
token to which all the other tokens fall back to. The second and subsequent
arguments are tokens which fall back to the token identified by the first
-argument.
+argument.</p>
<a name='pifdef'></a>
-<h4>The <tt>%ifdef</tt>, <tt>%ifndef</tt>, and <tt>%endif</tt> directives.</h4>
+<h4>The <tt>%ifdef</tt>, <tt>%ifndef</tt>, and <tt>%endif</tt> directives</h4>
-<p>The %ifdef, %ifndef, and %endif directives are similar to
-#ifdef, #ifndef, and #endif in the C-preprocessor, just not as general.
+<p>The <tt>%ifdef</tt>, <tt>%ifndef</tt>, and <tt>%endif</tt> directives
+are similar to #ifdef, #ifndef, and #endif in the C-preprocessor,
+just not as general.
Each of these directives must begin at the left margin. No whitespace
-is allowed between the "%" and the directive name.
+is allowed between the "%" and the directive name.</p>
-<p>Grammar text in between "%ifdef MACRO" and the next nested "%endif" is
+<p>Grammar text in between "<tt>%ifdef MACRO</tt>" and the next nested
+"<tt>%endif</tt>" is
ignored unless the "-DMACRO" command-line option is used. Grammar text
-betwen "%ifndef MACRO" and the next nested "%endif" is included except when
-the "-DMACRO" command-line option is used.
+betwen "<tt>%ifndef MACRO</tt>" and the next nested "<tt>%endif</tt>" is
+included except when the "-DMACRO" command-line option is used.</p>
-<p>Note that the argument to %ifdef and %ifndef must be a single
-preprocessor symbol name, not a general expression. There is no "%else"
-directive.
+<p>Note that the argument to <tt>%ifdef</tt> and <tt>%ifndef</tt> must
+be a single preprocessor symbol name, not a general expression.
+There is no "<tt>%else</tt>" directive.</p>
<a name='pinclude'></a>
<h4>The <tt>%include</tt> directive</h4>
-<p>The %include directive specifies C code that is included at the
-top of the generated parser. You can include any text you want --
+<p>The <tt>%include</tt> directive specifies C code that is included at the
+top of the generated parser. You can include any text you want &mdash;
the Lemon parser generator copies it blindly. If you have multiple
-%include directives in your grammar file, their values are concatenated
-so that all %include code ultimately appears near the top of the
-generated parser, in the same order as it appeared in the grammer.</p>
+<tt>%include</tt> directives in your grammar file, their values are concatenated
+so that all <tt>%include</tt> code ultimately appears near the top of the
+generated parser, in the same order as it appeared in the grammar.</p>
-<p>The %include directive is very handy for getting some extra #include
+<p>The <tt>%include</tt> directive is very handy for getting some extra #include
preprocessor statements at the beginning of the generated parser.
For example:</p>
@@ -742,17 +748,19 @@ For example:</p>
</pre></p>
<p>This might be needed, for example, if some of the C actions in the
-grammar call functions that are prototyed in unistd.h.</p>
+grammar call functions that are prototyped in unistd.h.</p>
<a name='pleft'></a>
<h4>The <tt>%left</tt> directive</h4>
-The %left directive is used (along with the <a href='#pright'>%right</a> and
-<a href='#pnonassoc'>%nonassoc</a> directives) to declare precedences of
-terminal symbols. Every terminal symbol whose name appears after
-a %left directive but before the next period (".") is
+The <tt>%left</tt> directive is used (along with the
+<tt><a href='#pright'>%right</a></tt> and
+<tt><a href='#pnonassoc'>%nonassoc</a></tt> directives) to declare
+precedences of terminal symbols.
+Every terminal symbol whose name appears after
+a <tt>%left</tt> directive but before the next period (".") is
given the same left-associative precedence value. Subsequent
-%left directives have higher precedence. For example:</p>
+<tt>%left</tt> directives have higher precedence. For example:</p>
<p><pre>
%left AND.
@@ -763,20 +771,21 @@ given the same left-associative precedence value. Subsequent
%right EXP NOT.
</pre></p>
-<p>Note the period that terminates each %left, %right or %nonassoc
+<p>Note the period that terminates each <tt>%left</tt>,
+<tt>%right</tt> or <tt>%nonassoc</tt>
directive.</p>
<p>LALR(1) grammars can get into a situation where they require
a large amount of stack space if you make heavy use or right-associative
-operators. For this reason, it is recommended that you use %left
-rather than %right whenever possible.</p>
+operators. For this reason, it is recommended that you use <tt>%left</tt>
+rather than <tt>%right</tt> whenever possible.</p>
<a name='pname'></a>
<h4>The <tt>%name</tt> directive</h4>
<p>By default, the functions generated by Lemon all begin with the
five-character string "Parse". You can change this string to something
-different using the %name directive. For instance:</p>
+different using the <tt>%name</tt> directive. For instance:</p>
<p><pre>
%name Abcde
@@ -790,9 +799,8 @@ functions named
<li> AbcdeTrace(), and
<li> Abcde().
</ul>
-The %name directive allows you to generator two or more different
-parsers and link them all into the same executable.
-</p>
+The <tt>%name</tt> directive allows you to generate two or more different
+parsers and link them all into the same executable.</p>
<a name='pnonassoc'></a>
<h4>The <tt>%nonassoc</tt> directive</h4>
@@ -800,12 +808,13 @@ parsers and link them all into the same executable.
<p>This directive is used to assign non-associative precedence to
one or more terminal symbols. See the section on
<a href='#precrules'>precedence rules</a>
-or on the <a href='#pleft'>%left</a> directive for additional information.</p>
+or on the <tt><a href='#pleft'>%left</a></tt> directive
+for additional information.</p>
<a name='parse_accept'></a>
<h4>The <tt>%parse_accept</tt> directive</h4>
-<p>The %parse_accept directive specifies a block of C code that is
+<p>The <tt>%parse_accept</tt> directive specifies a block of C code that is
executed whenever the parser accepts its input string. To "accept"
an input string means that the parser was able to process all tokens
without error.</p>
@@ -821,7 +830,7 @@ without error.</p>
<a name='parse_failure'></a>
<h4>The <tt>%parse_failure</tt> directive</h4>
-<p>The %parse_failure directive specifies a block of C code that
+<p>The <tt>%parse_failure</tt> directive specifies a block of C code that
is executed whenever the parser fails complete. This code is not
executed until the parser has tried and failed to resolve an input
error using is usual error recovery strategy. The routine is
@@ -844,7 +853,7 @@ or on the <a href='#pleft'>%left</a> directive for additional information.</p>
<a name='stack_overflow'></a>
<h4>The <tt>%stack_overflow</tt> directive</h4>
-<p>The %stack_overflow directive specifies a block of C code that
+<p>The <tt>%stack_overflow</tt> directive specifies a block of C code that
is executed if the parser's internal stack ever overflows. Typically
this just prints an error message. After a stack overflow, the parser
will be unable to continue and must be reset.</p>
@@ -857,7 +866,7 @@ will be unable to continue and must be reset.</p>
<p>You can help prevent parser stack overflows by avoiding the use
of right recursion and right-precedence operators in your grammar.
-Use left recursion and and left-precedence operators instead, to
+Use left recursion and and left-precedence operators instead to
encourage rules to reduce sooner and keep the stack size down.
For example, do rules like this:
<pre>
@@ -868,7 +877,7 @@ Not like this:
<pre>
list ::= element list. // right-recursion. Bad!
list ::= .
-</pre>
+</pre></p>
<a name='stack_size'></a>
<h4>The <tt>%stack_size</tt> directive</h4>
@@ -876,7 +885,7 @@ Not like this:
<p>If stack overflow is a problem and you can't resolve the trouble
by using left-recursion, then you might want to increase the size
of the parser's stack using this directive. Put an positive integer
-after the %stack_size directive and Lemon will generate a parse
+after the <tt>%stack_size</tt> directive and Lemon will generate a parse
with a stack of the requested size. The default value is 100.</p>
<p><pre>
@@ -886,25 +895,40 @@ with a stack of the requested size. The default value is 100.</p>
<a name='start_symbol'></a>
<h4>The <tt>%start_symbol</tt> directive</h4>
-<p>By default, the start-symbol for the grammar that Lemon generates
+<p>By default, the start symbol for the grammar that Lemon generates
is the first non-terminal that appears in the grammar file. But you
-can choose a different start-symbol using the %start_symbol directive.</p>
+can choose a different start symbol using the
+<tt>%start_symbol</tt> directive.</p>
<p><pre>
%start_symbol prog
</pre></p>
+<a name='syntax_error'></a>
+<h4>The <tt>%syntax_error</tt> directive</h4>
+
+<p>See <a href='#error_processing'>Error Processing</a>.</p>
+
+<a name='token_class'></a>
+<h4>The <tt>%token_class</tt> directive</h4>
+
+<p>Undocumented. Appears to be related to the MULTITERMINAL concept.
+<a href='http://sqlite.org/src/fdiff?v1=796930d5fc2036c7&v2=624b24c5dc048e09&sbs=0'>Implementation</a>.</p>
+
<a name='token_destructor'></a>
<h4>The <tt>%token_destructor</tt> directive</h4>
-<p>The %destructor directive assigns a destructor to a non-terminal
-symbol. (See the description of the %destructor directive above.)
-This directive does the same thing for all terminal symbols.</p>
+<p>The <tt>%destructor</tt> directive assigns a destructor to a non-terminal
+symbol. (See the description of the
+<tt><a href='%destructor'>%destructor</a></tt> directive above.)
+The <tt>%token_destructor</tt> directive does the same thing
+for all terminal symbols.</p>
<p>Unlike non-terminal symbols which may each have a different data type
for their values, terminals all use the same data type (defined by
-the %token_type directive) and so they use a common destructor. Other
-than that, the token destructor works just like the non-terminal
+the <tt><a href='#token_type'>%token_type</a></tt> directive)
+and so they use a common destructor.
+Other than that, the token destructor works just like the non-terminal
destructors.</p>
<a name='token_prefix'></a>
@@ -913,8 +937,9 @@ destructors.</p>
<p>Lemon generates #defines that assign small integer constants
to each terminal symbol in the grammar. If desired, Lemon will
add a prefix specified by this directive
-to each of the #defines it generates.
-So if the default output of Lemon looked like this:
+to each of the #defines it generates.</p>
+
+<p>So if the default output of Lemon looked like this:
<pre>
#define AND 1
#define MINUS 2
@@ -931,7 +956,7 @@ to cause Lemon to produce these symbols instead:
#define TOKEN_MINUS 2
#define TOKEN_OR 3
#define TOKEN_PLUS 4
-</pre>
+</pre></p>
<a name='token_type'></a><a name='ptype'></a>
<h4>The <tt>%token_type</tt> and <tt>%type</tt> directives</h4>
@@ -952,7 +977,7 @@ token structure. Like this:</p>
is "void*".</p>
<p>Non-terminal symbols can each have their own data types. Typically
-the data type of a non-terminal is a pointer to the root of a parse-tree
+the data type of a non-terminal is a pointer to the root of a parse tree
structure that contains all information about that non-terminal.
For example:</p>
@@ -973,14 +998,15 @@ and able to pay that price, fine. You just need to know.</p>
<a name='pwildcard'></a>
<h4>The <tt>%wildcard</tt> directive</h4>
-<p>The %wildcard directive is followed by a single token name and a
+<p>The <tt>%wildcard</tt> directive is followed by a single token name and a
period. This directive specifies that the identified token should
-match any input token.
+match any input token.</p>
<p>When the generated parser has the choice of matching an input against
the wildcard token and some other token, the other token is always used.
-The wildcard token is only matched if there are no other alternatives.
+The wildcard token is only matched if there are no alternatives.</p>
+<a name='error_processing'></a>
<h3>Error Processing</h3>
<p>After extensive experimentation over several years, it has been
@@ -988,16 +1014,17 @@ discovered that the error recovery strategy used by yacc is about
as good as it gets. And so that is what Lemon uses.</p>
<p>When a Lemon-generated parser encounters a syntax error, it
-first invokes the code specified by the %syntax_error directive, if
+first invokes the code specified by the <tt>%syntax_error</tt> directive, if
any. It then enters its error recovery strategy. The error recovery
strategy is to begin popping the parsers stack until it enters a
state where it is permitted to shift a special non-terminal symbol
named "error". It then shifts this non-terminal and continues
-parsing. But the %syntax_error routine will not be called again
+parsing. The <tt>%syntax_error</tt> routine will not be called again
until at least three new tokens have been successfully shifted.</p>
<p>If the parser pops its stack until the stack is empty, and it still
-is unable to shift the error symbol, then the %parse_failed routine
+is unable to shift the error symbol, then the
+<tt><a href='#parse_failure'>%parse_failure</a></tt> routine
is invoked and the parser resets itself to its start state, ready
to begin parsing a new file. This is what will happen at the very
first syntax error, of course, if there are no instances of the
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 5d72c8065ad..7ac56589e26 100644
--- a/chromium/third_party/sqlite/src/ext/fts5/fts5_vocab.c
+++ b/chromium/third_party/sqlite/src/ext/fts5/fts5_vocab.c
@@ -29,6 +29,11 @@
** the number of fts5 rows that contain at least one instance of term
** $term. Field $cnt is set to the total number of instances of term
** $term in the database.
+**
+** instance:
+** CREATE TABLE vocab(term, doc, col, offset, PRIMARY KEY(<all-fields>));
+**
+** One row for each term instance in the database.
*/
@@ -44,7 +49,7 @@ struct Fts5VocabTable {
char *zFts5Db; /* Db containing fts5 table */
sqlite3 *db; /* Database handle */
Fts5Global *pGlobal; /* FTS5 global object for this database */
- int eType; /* FTS5_VOCAB_COL or ROW */
+ int eType; /* FTS5_VOCAB_COL, ROW or INSTANCE */
};
struct Fts5VocabCursor {
@@ -64,16 +69,22 @@ struct Fts5VocabCursor {
i64 *aCnt;
i64 *aDoc;
- /* Output values used by 'row' and 'col' tables */
+ /* Output values used by all tables. */
i64 rowid; /* This table's current rowid value */
Fts5Buffer term; /* Current value of 'term' column */
+
+ /* Output values Used by 'instance' tables only */
+ i64 iInstPos;
+ int iInstOff;
};
-#define FTS5_VOCAB_COL 0
-#define FTS5_VOCAB_ROW 1
+#define FTS5_VOCAB_COL 0
+#define FTS5_VOCAB_ROW 1
+#define FTS5_VOCAB_INSTANCE 2
#define FTS5_VOCAB_COL_SCHEMA "term, col, doc, cnt"
#define FTS5_VOCAB_ROW_SCHEMA "term, doc, cnt"
+#define FTS5_VOCAB_INST_SCHEMA "term, doc, col, offset"
/*
** Bits for the mask used as the idxNum value by xBestIndex/xFilter.
@@ -101,6 +112,9 @@ static int fts5VocabTableType(const char *zType, char **pzErr, int *peType){
if( sqlite3_stricmp(zCopy, "row")==0 ){
*peType = FTS5_VOCAB_ROW;
}else
+ if( sqlite3_stricmp(zCopy, "instance")==0 ){
+ *peType = FTS5_VOCAB_INSTANCE;
+ }else
{
*pzErr = sqlite3_mprintf("fts5vocab: unknown table type: %Q", zCopy);
rc = SQLITE_ERROR;
@@ -161,7 +175,8 @@ static int fts5VocabInitVtab(
){
const char *azSchema[] = {
"CREATE TABlE vocab(" FTS5_VOCAB_COL_SCHEMA ")",
- "CREATE TABlE vocab(" FTS5_VOCAB_ROW_SCHEMA ")"
+ "CREATE TABlE vocab(" FTS5_VOCAB_ROW_SCHEMA ")",
+ "CREATE TABlE vocab(" FTS5_VOCAB_INST_SCHEMA ")"
};
Fts5VocabTable *pRet = 0;
@@ -235,6 +250,15 @@ static int fts5VocabCreateMethod(
/*
** Implementation of the xBestIndex method.
+**
+** Only constraints of the form:
+**
+** term <= ?
+** term == ?
+** term >= ?
+**
+** are interpreted. Less-than and less-than-or-equal are treated
+** identically, as are greater-than and greater-than-or-equal.
*/
static int fts5VocabBestIndexMethod(
sqlite3_vtab *pUnused,
@@ -378,6 +402,54 @@ static int fts5VocabCloseMethod(sqlite3_vtab_cursor *pCursor){
return SQLITE_OK;
}
+static int fts5VocabInstanceNewTerm(Fts5VocabCursor *pCsr){
+ int rc = SQLITE_OK;
+
+ if( sqlite3Fts5IterEof(pCsr->pIter) ){
+ pCsr->bEof = 1;
+ }else{
+ const char *zTerm;
+ int nTerm;
+ zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
+ if( pCsr->nLeTerm>=0 ){
+ int nCmp = MIN(nTerm, pCsr->nLeTerm);
+ int bCmp = memcmp(pCsr->zLeTerm, zTerm, nCmp);
+ if( bCmp<0 || (bCmp==0 && pCsr->nLeTerm<nTerm) ){
+ pCsr->bEof = 1;
+ }
+ }
+
+ sqlite3Fts5BufferSet(&rc, &pCsr->term, nTerm, (const u8*)zTerm);
+ }
+ return rc;
+}
+
+static int fts5VocabInstanceNext(Fts5VocabCursor *pCsr){
+ int eDetail = pCsr->pConfig->eDetail;
+ int rc = SQLITE_OK;
+ Fts5IndexIter *pIter = pCsr->pIter;
+ i64 *pp = &pCsr->iInstPos;
+ int *po = &pCsr->iInstOff;
+
+ while( eDetail==FTS5_DETAIL_NONE
+ || sqlite3Fts5PoslistNext64(pIter->pData, pIter->nData, po, pp)
+ ){
+ pCsr->iInstPos = 0;
+ pCsr->iInstOff = 0;
+
+ rc = sqlite3Fts5IterNextScan(pCsr->pIter);
+ if( rc==SQLITE_OK ){
+ rc = fts5VocabInstanceNewTerm(pCsr);
+ if( eDetail==FTS5_DETAIL_NONE ) break;
+ }
+ if( rc ){
+ pCsr->bEof = 1;
+ break;
+ }
+ }
+
+ return rc;
+}
/*
** Advance the cursor to the next row in the table.
@@ -390,13 +462,17 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
pCsr->rowid++;
+ if( pTab->eType==FTS5_VOCAB_INSTANCE ){
+ return fts5VocabInstanceNext(pCsr);
+ }
+
if( pTab->eType==FTS5_VOCAB_COL ){
for(pCsr->iCol++; pCsr->iCol<nCol; pCsr->iCol++){
if( pCsr->aDoc[pCsr->iCol] ) break;
}
}
- if( pTab->eType==FTS5_VOCAB_ROW || pCsr->iCol>=nCol ){
+ if( pTab->eType!=FTS5_VOCAB_COL || pCsr->iCol>=nCol ){
if( sqlite3Fts5IterEof(pCsr->pIter) ){
pCsr->bEof = 1;
}else{
@@ -420,22 +496,26 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
assert( pTab->eType==FTS5_VOCAB_COL || pTab->eType==FTS5_VOCAB_ROW );
while( rc==SQLITE_OK ){
+ int eDetail = pCsr->pConfig->eDetail;
const u8 *pPos; int nPos; /* Position list */
i64 iPos = 0; /* 64-bit position read from poslist */
int iOff = 0; /* Current offset within position list */
pPos = pCsr->pIter->pData;
nPos = pCsr->pIter->nData;
- switch( pCsr->pConfig->eDetail ){
- case FTS5_DETAIL_FULL:
- pPos = pCsr->pIter->pData;
- nPos = pCsr->pIter->nData;
- if( pTab->eType==FTS5_VOCAB_ROW ){
+
+ switch( pTab->eType ){
+ case FTS5_VOCAB_ROW:
+ if( eDetail==FTS5_DETAIL_FULL ){
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
pCsr->aCnt[0]++;
}
- pCsr->aDoc[0]++;
- }else{
+ }
+ pCsr->aDoc[0]++;
+ break;
+
+ case FTS5_VOCAB_COL:
+ if( eDetail==FTS5_DETAIL_FULL ){
int iCol = -1;
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
int ii = FTS5_POS2COLUMN(iPos);
@@ -449,13 +529,7 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
iCol = ii;
}
}
- }
- break;
-
- case FTS5_DETAIL_COLUMNS:
- if( pTab->eType==FTS5_VOCAB_ROW ){
- pCsr->aDoc[0]++;
- }else{
+ }else if( eDetail==FTS5_DETAIL_COLUMNS ){
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff,&iPos) ){
assert_nc( iPos>=0 && iPos<nCol );
if( iPos>=nCol ){
@@ -464,18 +538,21 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
}
pCsr->aDoc[iPos]++;
}
+ }else{
+ assert( eDetail==FTS5_DETAIL_NONE );
+ pCsr->aDoc[0]++;
}
break;
default:
- assert( pCsr->pConfig->eDetail==FTS5_DETAIL_NONE );
- pCsr->aDoc[0]++;
+ assert( pTab->eType==FTS5_VOCAB_INSTANCE );
break;
}
if( rc==SQLITE_OK ){
rc = sqlite3Fts5IterNextScan(pCsr->pIter);
}
+ if( pTab->eType==FTS5_VOCAB_INSTANCE ) break;
if( rc==SQLITE_OK ){
zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
@@ -505,7 +582,9 @@ static int fts5VocabFilterMethod(
int nUnused, /* Number of elements in apVal */
sqlite3_value **apVal /* Arguments for the indexing scheme */
){
+ Fts5VocabTable *pTab = (Fts5VocabTable*)pCursor->pVtab;
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
+ int eType = pTab->eType;
int rc = SQLITE_OK;
int iVal = 0;
@@ -545,11 +624,16 @@ static int fts5VocabFilterMethod(
}
}
-
if( rc==SQLITE_OK ){
rc = sqlite3Fts5IndexQuery(pCsr->pIndex, zTerm, nTerm, f, 0, &pCsr->pIter);
}
- if( rc==SQLITE_OK ){
+ if( rc==SQLITE_OK && eType==FTS5_VOCAB_INSTANCE ){
+ rc = fts5VocabInstanceNewTerm(pCsr);
+ }
+ if( rc==SQLITE_OK
+ && !pCsr->bEof
+ && (eType!=FTS5_VOCAB_INSTANCE || pCsr->pConfig->eDetail!=FTS5_DETAIL_NONE)
+ ){
rc = fts5VocabNextMethod(pCursor);
}
@@ -591,13 +675,41 @@ static int fts5VocabColumnMethod(
}else{
iVal = pCsr->aCnt[pCsr->iCol];
}
- }else{
+ }else if( eType==FTS5_VOCAB_ROW ){
assert( iCol==1 || iCol==2 );
if( iCol==1 ){
iVal = pCsr->aDoc[0];
}else{
iVal = pCsr->aCnt[0];
}
+ }else{
+ assert( eType==FTS5_VOCAB_INSTANCE );
+ switch( iCol ){
+ case 1:
+ sqlite3_result_int64(pCtx, pCsr->pIter->iRowid);
+ break;
+ case 2: {
+ int ii = -1;
+ if( eDetail==FTS5_DETAIL_FULL ){
+ ii = FTS5_POS2COLUMN(pCsr->iInstPos);
+ }else if( eDetail==FTS5_DETAIL_COLUMNS ){
+ ii = (int)pCsr->iInstPos;
+ }
+ if( ii>=0 && ii<pCsr->pConfig->nCol ){
+ const char *z = pCsr->pConfig->azCol[ii];
+ sqlite3_result_text(pCtx, z, -1, SQLITE_STATIC);
+ }
+ break;
+ }
+ default: {
+ assert( iCol==3 );
+ if( eDetail==FTS5_DETAIL_FULL ){
+ int ii = FTS5_POS2OFFSET(pCsr->iInstPos);
+ sqlite3_result_int(pCtx, ii);
+ }
+ break;
+ }
+ }
}
if( iVal>0 ) sqlite3_result_int64(pCtx, iVal);
diff --git a/chromium/third_party/sqlite/src/ext/lsm1/lsm_shared.c b/chromium/third_party/sqlite/src/ext/lsm1/lsm_shared.c
index 95a866d370c..f8e2adb73dc 100644
--- a/chromium/third_party/sqlite/src/ext/lsm1/lsm_shared.c
+++ b/chromium/third_party/sqlite/src/ext/lsm1/lsm_shared.c
@@ -340,9 +340,6 @@ static int doDbConnect(lsm_db *pDb){
/* Obtain a pointer to the shared-memory header */
assert( pDb->pShmhdr==0 );
assert( pDb->bReadonly==0 );
- rc = lsmShmCacheChunks(pDb, 1);
- if( rc!=LSM_OK ) return rc;
- pDb->pShmhdr = (ShmHeader *)pDb->apShm[0];
/* Block for an exclusive lock on DMS1. This lock serializes all calls
** to doDbConnect() and doDbDisconnect() across all processes. */
@@ -353,10 +350,11 @@ static int doDbConnect(lsm_db *pDb){
nUs = nUs * 2;
if( nUs>nUsMax ) nUs = nUsMax;
}
- if( rc!=LSM_OK ){
- pDb->pShmhdr = 0;
- return rc;
+ if( rc==LSM_OK ){
+ rc = lsmShmCacheChunks(pDb, 1);
}
+ if( rc!=LSM_OK ) return rc;
+ pDb->pShmhdr = (ShmHeader *)pDb->apShm[0];
/* Try an exclusive lock on DMS2/DMS3. If successful, this is the first
** and only connection to the database. In this case initialize the
diff --git a/chromium/third_party/sqlite/src/ext/lsm1/lsm_vtab.c b/chromium/third_party/sqlite/src/ext/lsm1/lsm_vtab.c
index da6ef6f47f9..8a2cc968b48 100644
--- a/chromium/third_party/sqlite/src/ext/lsm1/lsm_vtab.c
+++ b/chromium/third_party/sqlite/src/ext/lsm1/lsm_vtab.c
@@ -10,8 +10,82 @@
**
*************************************************************************
**
-** This file implements a simple virtual table wrapper around the LSM
+** This file implements a virtual table for SQLite3 around the LSM
** storage engine from SQLite4.
+**
+** USAGE
+**
+** CREATE VIRTUAL TABLE demo USING lsm1(filename,key,keytype,value1,...);
+**
+** The filename parameter is the name of the LSM database file, which is
+** separate and distinct from the SQLite3 database file.
+**
+** The keytype must be one of: UINT, TEXT, BLOB. All keys must be of that
+** one type. "UINT" means unsigned integer. The values may be of any
+** SQLite datatype: BLOB, TEXT, INTEGER, FLOAT, or NULL.
+**
+** The virtual table contains read-only hidden columns:
+**
+** lsm1_key A BLOB which is the raw LSM key. If the "keytype"
+** is BLOB or TEXT then this column is exactly the
+** same as the key. For the UINT keytype, this column
+** will be a variable-length integer encoding of the key.
+**
+** lsm1_value A BLOB which is the raw LSM value. All of the value
+** columns are packed into this BLOB using the encoding
+** described below.
+**
+** Attempts to write values into the lsm1_key and lsm1_value columns are
+** silently ignored.
+**
+** EXAMPLE
+**
+** The virtual table declared this way:
+**
+** CREATE VIRTUAL TABLE demo2 USING lsm1('x.lsm',id,UINT,a,b,c,d);
+**
+** Results in a new virtual table named "demo2" that acts as if it has
+** the following schema:
+**
+** CREATE TABLE demo2(
+** id UINT PRIMARY KEY ON CONFLICT REPLACE,
+** a ANY,
+** b ANY,
+** c ANY,
+** d ANY,
+** lsm1_key BLOB HIDDEN,
+** lsm1_value BLOB HIDDEN
+** ) WITHOUT ROWID;
+**
+**
+**
+** INTERNALS
+**
+** The key encoding for BLOB and TEXT is just a copy of the blob or text.
+** UTF-8 is used for text. The key encoding for UINT is the variable-length
+** integer format at https://sqlite.org/src4/doc/trunk/www/varint.wiki.
+**
+** The values are encoded as a single blob (since that is what lsm stores as
+** its content). There is a "type integer" followed by "content" for each
+** value, alternating back and forth. The content might be empty.
+**
+** TYPE1 CONTENT1 TYPE2 CONTENT2 TYPE3 CONTENT3 ....
+**
+** Each "type integer" is encoded as a variable-length integer in the
+** format of the link above. Let the type integer be T. The actual
+** datatype is an integer 0-5 equal to T%6. Values 1 through 5 correspond
+** to SQLITE_INTEGER through SQLITE_NULL. The size of the content in bytes
+** is T/6. Type value 0 means that the value is an integer whose actual
+** values is T/6 and there is no content. The type-value-0 integer format
+** only works for integers in the range of 0 through 40.
+**
+** There is no content for NULL or type-0 integers. For BLOB and TEXT
+** values, the content is the blob data or the UTF-8 text data. For
+** non-negative integers X, the content is a variable-length integer X*2.
+** For negative integers Y, the content is varaible-length integer (1-Y)*2+1.
+** For FLOAT values, the content is the IEEE754 floating point value in
+** native byte-order. This means that FLOAT values will be corrupted when
+** database file is moved between big-endian and little-endian machines.
*/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
@@ -22,14 +96,19 @@ SQLITE_EXTENSION_INIT1
/* Forward declaration of subclasses of virtual table objects */
typedef struct lsm1_vtab lsm1_vtab;
typedef struct lsm1_cursor lsm1_cursor;
+typedef struct lsm1_vblob lsm1_vblob;
/* Primitive types */
typedef unsigned char u8;
+typedef unsigned int u32;
+typedef sqlite3_uint64 u64;
/* An open connection to an LSM table */
struct lsm1_vtab {
sqlite3_vtab base; /* Base class - must be first */
lsm_db *pDb; /* Open connection to the LSM table */
+ u8 keyType; /* SQLITE_BLOB, _TEXT, or _INTEGER */
+ u32 nVal; /* Number of value columns */
};
@@ -43,8 +122,82 @@ struct lsm1_cursor {
u8 isDesc; /* 0: scan forward. 1: scan reverse */
u8 atEof; /* True if the scan is complete */
u8 bUnique; /* True if no more than one row of output */
+ u8 *zData; /* Content of the current row */
+ u32 nData; /* Number of bytes in the current row */
+ u8 *aeType; /* Types for all column values */
+ u32 *aiOfst; /* Offsets to the various fields */
+ u32 *aiLen; /* Length of each field */
+ u8 *pKey2; /* Loop termination key, or NULL */
+ u32 nKey2; /* Length of the loop termination key */
};
+/* An extensible buffer object.
+**
+** Content can be appended. Space to hold new content is automatically
+** allocated.
+*/
+struct lsm1_vblob {
+ u8 *a; /* Space to hold content, from sqlite3_malloc64() */
+ u64 n; /* Bytes of space used */
+ u64 nAlloc; /* Bytes of space allocated */
+ u8 errNoMem; /* True if a memory allocation error has been seen */
+};
+
+#if defined(__GNUC__)
+# define LSM1_NOINLINE __attribute__((noinline))
+#elif defined(_MSC_VER) && _MSC_VER>=1310
+# define LSM1_NOINLINE __declspec(noinline)
+#else
+# define LSM1_NOINLINE
+#endif
+
+
+/* Increase the available space in the vblob object so that it can hold
+** at least N more bytes. Return the number of errors.
+*/
+static int lsm1VblobEnlarge(lsm1_vblob *p, u32 N){
+ if( p->n+N>p->nAlloc ){
+ if( p->errNoMem ) return 1;
+ p->nAlloc += N + (p->nAlloc ? p->nAlloc : N);
+ p->a = sqlite3_realloc64(p->a, p->nAlloc);
+ if( p->a==0 ){
+ p->n = 0;
+ p->nAlloc = 0;
+ p->errNoMem = 1;
+ return 1;
+ }
+ p->nAlloc = sqlite3_msize(p->a);
+ }
+ return 0;
+}
+
+/* Append N bytes to a vblob after first enlarging it */
+static LSM1_NOINLINE void lsm1VblobEnlargeAndAppend(
+ lsm1_vblob *p,
+ const u8 *pData,
+ u32 N
+){
+ if( p->n+N>p->nAlloc && lsm1VblobEnlarge(p, N) ) return;
+ memcpy(p->a+p->n, pData, N);
+ p->n += N;
+}
+
+/* Append N bytes to a vblob */
+static void lsm1VblobAppend(lsm1_vblob *p, const u8 *pData, u32 N){
+ sqlite3_int64 n = p->n;
+ if( n+N>p->nAlloc ){
+ lsm1VblobEnlargeAndAppend(p, pData, N);
+ }else{
+ p->n += N;
+ memcpy(p->a+n, pData, N);
+ }
+}
+
+/* append text to a vblob */
+static void lsm1VblobAppendText(lsm1_vblob *p, const char *z){
+ lsm1VblobAppend(p, (u8*)z, (u32)strlen(z));
+}
+
/* Dequote the string */
static void lsm1Dequote(char *z){
int j;
@@ -76,9 +229,28 @@ static int lsm1Connect(
lsm1_vtab *pNew;
int rc;
char *zFilename;
+ u8 keyType = 0;
+ int i;
+ lsm1_vblob sql;
+ static const char *azTypes[] = { "UINT", "TEXT", "BLOB" };
+ static const u8 aeTypes[] = { SQLITE_INTEGER, SQLITE_TEXT, SQLITE_BLOB };
+ static const char *azArgName[] = {"filename", "key", "key type", "value1" };
- if( argc!=4 || argv[3]==0 || argv[3][0]==0 ){
- *pzErr = sqlite3_mprintf("filename argument missing");
+ for(i=0; i<sizeof(azArgName)/sizeof(azArgName[0]); i++){
+ if( argc<i+4 || argv[i+3]==0 || argv[i+3][0]==0 ){
+ *pzErr = sqlite3_mprintf("%s (%r) argument missing",
+ azArgName[i], i+1);
+ return SQLITE_ERROR;
+ }
+ }
+ for(i=0; i<sizeof(azTypes)/sizeof(azTypes[0]); i++){
+ if( sqlite3_stricmp(azTypes[i],argv[5])==0 ){
+ keyType = aeTypes[i];
+ break;
+ }
+ }
+ if( keyType==0 ){
+ *pzErr = sqlite3_mprintf("key type should be INT, TEXT, or BLOB");
return SQLITE_ERROR;
}
*ppVtab = sqlite3_malloc( sizeof(*pNew) );
@@ -87,6 +259,7 @@ static int lsm1Connect(
return SQLITE_NOMEM;
}
memset(pNew, 0, sizeof(*pNew));
+ pNew->keyType = keyType;
rc = lsm_new(0, &pNew->pDb);
if( rc ){
*pzErr = sqlite3_mprintf("lsm_new failed with error code %d", rc);
@@ -103,22 +276,29 @@ static int lsm1Connect(
goto connect_failed;
}
-/* Column numbers */
-#define LSM1_COLUMN_KEY 0
-#define LSM1_COLUMN_BLOBKEY 1
-#define LSM1_COLUMN_VALUE 2
-#define LSM1_COLUMN_BLOBVALUE 3
-#define LSM1_COLUMN_COMMAND 4
-
- rc = sqlite3_declare_vtab(db,
- "CREATE TABLE x("
- " key," /* The primary key. Any non-NULL */
- " blobkey," /* Pure BLOB primary key */
- " value," /* The value associated with key. Any non-NULL */
- " blobvalue," /* Pure BLOB value */
- " command hidden" /* Insert here for control operations */
- ");"
- );
+ memset(&sql, 0, sizeof(sql));
+ lsm1VblobAppendText(&sql, "CREATE TABLE x(");
+ lsm1VblobAppendText(&sql, argv[4]);
+ lsm1VblobAppendText(&sql, " ");
+ lsm1VblobAppendText(&sql, argv[5]);
+ lsm1VblobAppendText(&sql, " PRIMARY KEY");
+ for(i=6; i<argc; i++){
+ lsm1VblobAppendText(&sql, ", ");
+ lsm1VblobAppendText(&sql, argv[i]);
+ pNew->nVal++;
+ }
+ lsm1VblobAppendText(&sql,
+ ", lsm1_command HIDDEN"
+ ", lsm1_key HIDDEN"
+ ", lsm1_value HIDDEN) WITHOUT ROWID");
+ lsm1VblobAppend(&sql, (u8*)"", 1);
+ if( sql.errNoMem ){
+ rc = SQLITE_NOMEM;
+ goto connect_failed;
+ }
+ rc = sqlite3_declare_vtab(db, (const char*)sql.a);
+ sqlite3_free(sql.a);
+
connect_failed:
if( rc!=SQLITE_OK ){
if( pNew ){
@@ -147,9 +327,13 @@ static int lsm1Open(sqlite3_vtab *pVtab, sqlite3_vtab_cursor **ppCursor){
lsm1_vtab *p = (lsm1_vtab*)pVtab;
lsm1_cursor *pCur;
int rc;
- pCur = sqlite3_malloc( sizeof(*pCur) );
+ pCur = sqlite3_malloc64( sizeof(*pCur)
+ + p->nVal*(sizeof(pCur->aiOfst)+sizeof(pCur->aiLen)+1) );
if( pCur==0 ) return SQLITE_NOMEM;
memset(pCur, 0, sizeof(*pCur));
+ pCur->aiOfst = (u32*)&pCur[1];
+ pCur->aiLen = &pCur->aiOfst[p->nVal];
+ pCur->aeType = (u8*)&pCur->aiLen[p->nVal];
*ppCursor = &pCur->base;
rc = lsm_csr_open(p->pDb, &pCur->pLsmCur);
if( rc==LSM_OK ){
@@ -167,6 +351,7 @@ static int lsm1Open(sqlite3_vtab *pVtab, sqlite3_vtab_cursor **ppCursor){
*/
static int lsm1Close(sqlite3_vtab_cursor *cur){
lsm1_cursor *pCur = (lsm1_cursor*)cur;
+ sqlite3_free(pCur->pKey2);
lsm_csr_close(pCur->pLsmCur);
sqlite3_free(pCur);
return SQLITE_OK;
@@ -190,6 +375,21 @@ static int lsm1Next(sqlite3_vtab_cursor *cur){
if( rc==LSM_OK && lsm_csr_valid(pCur->pLsmCur)==0 ){
pCur->atEof = 1;
}
+ if( pCur->pKey2 && pCur->atEof==0 ){
+ const u8 *pVal;
+ u32 nVal;
+ assert( pCur->isDesc==0 );
+ rc = lsm_csr_key(pCur->pLsmCur, (const void**)&pVal, (int*)&nVal);
+ if( rc==LSM_OK ){
+ u32 len = pCur->nKey2;
+ int c;
+ if( len>nVal ) len = nVal;
+ c = memcmp(pVal, pCur->pKey2, len);
+ if( c==0 ) c = nVal - pCur->nKey2;
+ if( c>0 ) pCur->atEof = 1;
+ }
+ }
+ pCur->zData = 0;
}
return rc==LSM_OK ? SQLITE_OK : SQLITE_ERROR;
}
@@ -295,6 +495,14 @@ static int lsm1PutVarint64(unsigned char *z, sqlite3_uint64 x){
return 9;
}
+/* Append non-negative integer x as a variable-length integer.
+*/
+static void lsm1VblobAppendVarint(lsm1_vblob *p, sqlite3_uint64 x){
+ sqlite3_int64 n = p->n;
+ if( n+9>p->nAlloc && lsm1VblobEnlarge(p, 9) ) return;
+ p->n += lsm1PutVarint64(p->a+p->n, x);
+}
+
/*
** Decode the varint in the first n bytes z[]. Write the integer value
** into *pResult and return the number of bytes in the varint.
@@ -349,69 +557,74 @@ static int lsm1GetVarint64(
return 9;
}
-/*
-** Generate a key encoding for pValue such that all keys compare in
-** lexicographical order. Return an SQLite error code or SQLITE_OK.
+/* Encoded a signed integer as a varint. Numbers close to zero uses fewer
+** bytes than numbers far away from zero. However, the result is not in
+** lexicographical order.
**
-** The key encoding is *pnKey bytes in length written into *ppKey.
-** Space to hold the key is taken from pSpace if sufficient, or else
-** from sqlite3_malloc(). The caller is responsible for freeing malloced
-** space.
+** Encoding: Non-negative integer X is encoding as an unsigned
+** varint X*2. Negative integer Y is encoding as an unsigned
+** varint (1-Y)*2 + 1.
*/
-static int lsm1EncodeKey(
- sqlite3_value *pValue, /* Value to be encoded */
- unsigned char **ppKey, /* Write the encoding here */
- int *pnKey, /* Write the size of the encoding here */
- unsigned char *pSpace, /* Use this space if it is large enough */
- int nSpace /* Size of pSpace[] */
+static int lsm1PutSignedVarint64(u8 *z, sqlite3_int64 v){
+ sqlite3_uint64 u;
+ if( v>=0 ){
+ u = (sqlite3_uint64)v;
+ return lsm1PutVarint64(z, u*2);
+ }else{
+ u = (sqlite3_uint64)(-1-v);
+ return lsm1PutVarint64(z, u*2+1);
+ }
+}
+
+/* Decoded a signed varint. */
+static int lsm1GetSignedVarint64(
+ const unsigned char *z,
+ int n,
+ sqlite3_int64 *pResult
){
- int eType = sqlite3_value_type(pValue);
- *ppKey = 0;
- *pnKey = 0;
- assert( nSpace>=32 );
- switch( eType ){
- default: {
- return SQLITE_ERROR; /* We cannot handle NULL keys */
- }
- case SQLITE_BLOB:
- case SQLITE_TEXT: {
- int nVal = sqlite3_value_bytes(pValue);
- const void *pVal;
- if( eType==SQLITE_BLOB ){
- eType = LSM1_TYPE_BLOB;
- pVal = sqlite3_value_blob(pValue);
- }else{
- eType = LSM1_TYPE_TEXT;
- pVal = (const void*)sqlite3_value_text(pValue);
- if( pVal==0 ) return SQLITE_NOMEM;
- }
- if( nVal+1>nSpace ){
- pSpace = sqlite3_malloc( nVal+1 );
- if( pSpace==0 ) return SQLITE_NOMEM;
- }
- pSpace[0] = (unsigned char)eType;
- memcpy(&pSpace[1], pVal, nVal);
- *ppKey = pSpace;
- *pnKey = nVal+1;
- break;
- }
- case SQLITE_INTEGER: {
- sqlite3_int64 iVal = sqlite3_value_int64(pValue);
- sqlite3_uint64 uVal;
- if( iVal<0 ){
- if( iVal==0xffffffffffffffffLL ) return SQLITE_ERROR;
- uVal = *(sqlite3_uint64*)&iVal;
- eType = LSM1_TYPE_NEGATIVE;
- }else{
- uVal = iVal;
- eType = LSM1_TYPE_POSITIVE;
- }
- pSpace[0] = (unsigned char)eType;
- *ppKey = pSpace;
- *pnKey = 1 + lsm1PutVarint64(&pSpace[1], uVal);
+ sqlite3_uint64 u = 0;
+ n = lsm1GetVarint64(z, n, &u);
+ if( u&1 ){
+ *pResult = -1 - (sqlite3_int64)(u>>1);
+ }else{
+ *pResult = (sqlite3_int64)(u>>1);
+ }
+ return n;
+}
+
+
+/*
+** Read the value part of the key-value pair and decode it into columns.
+*/
+static int lsm1DecodeValues(lsm1_cursor *pCur){
+ lsm1_vtab *pTab = (lsm1_vtab*)(pCur->base.pVtab);
+ int i, n;
+ int rc;
+ u8 eType;
+ sqlite3_uint64 v;
+
+ if( pCur->zData ) return 1;
+ rc = lsm_csr_value(pCur->pLsmCur, (const void**)&pCur->zData,
+ (int*)&pCur->nData);
+ if( rc ) return 0;
+ for(i=n=0; i<pTab->nVal; i++){
+ v = 0;
+ n += lsm1GetVarint64(pCur->zData+n, pCur->nData-n, &v);
+ pCur->aeType[i] = eType = (u8)(v%6);
+ if( eType==0 ){
+ pCur->aiOfst[i] = (u32)(v/6);
+ pCur->aiLen[i] = 0;
+ }else{
+ pCur->aiOfst[i] = n;
+ n += (pCur->aiLen[i] = (u32)(v/6));
}
+ if( n>pCur->nData ) break;
}
- return SQLITE_OK;
+ if( i<pTab->nVal ){
+ pCur->zData = 0;
+ return 0;
+ }
+ return 1;
}
/*
@@ -424,88 +637,104 @@ static int lsm1Column(
int i /* Which column to return */
){
lsm1_cursor *pCur = (lsm1_cursor*)cur;
- switch( i ){
- case LSM1_COLUMN_BLOBKEY: {
- const void *pVal;
- int nVal;
- if( lsm_csr_key(pCur->pLsmCur, &pVal, &nVal)==LSM_OK ){
+ lsm1_vtab *pTab = (lsm1_vtab*)(cur->pVtab);
+ if( i==0 ){
+ /* The key column */
+ const void *pVal;
+ int nVal;
+ if( lsm_csr_key(pCur->pLsmCur, &pVal, &nVal)==LSM_OK ){
+ if( pTab->keyType==SQLITE_BLOB ){
sqlite3_result_blob(ctx, pVal, nVal, SQLITE_TRANSIENT);
+ }else if( pTab->keyType==SQLITE_TEXT ){
+ sqlite3_result_text(ctx,(const char*)pVal, nVal, SQLITE_TRANSIENT);
+ }else{
+ const unsigned char *z = (const unsigned char*)pVal;
+ sqlite3_uint64 v1;
+ lsm1GetVarint64(z, nVal, &v1);
+ sqlite3_result_int64(ctx, (sqlite3_int64)v1);
}
- break;
}
- case LSM1_COLUMN_KEY: {
- const unsigned char *pVal;
+ }else if( i>pTab->nVal ){
+ if( i==pTab->nVal+2 ){ /* lsm1_key */
+ const void *pVal;
int nVal;
- if( lsm_csr_key(pCur->pLsmCur, (const void**)&pVal, &nVal)==LSM_OK
- && nVal>=1
- ){
- if( pVal[0]==LSM1_TYPE_BLOB ){
- sqlite3_result_blob(ctx, (const void*)&pVal[1],nVal-1,
- SQLITE_TRANSIENT);
- }else if( pVal[0]==LSM1_TYPE_TEXT ){
- sqlite3_result_text(ctx, (const char*)&pVal[1],nVal-1,
- SQLITE_TRANSIENT);
- }else if( nVal>=2 && nVal<=10 &&
- (pVal[0]==LSM1_TYPE_POSITIVE || pVal[0]==LSM1_TYPE_NEGATIVE)
- ){
- sqlite3_int64 iVal;
- lsm1GetVarint64(pVal+1, nVal-1, (sqlite3_uint64*)&iVal);
- sqlite3_result_int64(ctx, iVal);
- }
+ if( lsm_csr_key(pCur->pLsmCur, &pVal, &nVal)==LSM_OK ){
+ sqlite3_result_blob(ctx, pVal, nVal, SQLITE_TRANSIENT);
}
- break;
- }
- case LSM1_COLUMN_BLOBVALUE: {
+ }else if( i==pTab->nVal+3 ){ /* lsm1_value */
const void *pVal;
int nVal;
- if( lsm_csr_value(pCur->pLsmCur, (const void**)&pVal, &nVal)==LSM_OK ){
+ if( lsm_csr_value(pCur->pLsmCur, &pVal, &nVal)==LSM_OK ){
sqlite3_result_blob(ctx, pVal, nVal, SQLITE_TRANSIENT);
}
- break;
}
- case LSM1_COLUMN_VALUE: {
- const unsigned char *aVal;
- int nVal;
- if( lsm_csr_value(pCur->pLsmCur, (const void**)&aVal, &nVal)==LSM_OK
- && nVal>=1
- ){
- switch( aVal[0] ){
- case SQLITE_FLOAT:
- case SQLITE_INTEGER: {
- sqlite3_uint64 x = 0;
- int j;
- for(j=1; j<nVal; j++){
- x = (x<<8) | aVal[j];
- }
- if( aVal[0]==SQLITE_INTEGER ){
- sqlite3_result_int64(ctx, *(sqlite3_int64*)&x);
- }else{
- double r;
- assert( sizeof(r)==sizeof(x) );
- memcpy(&r, &x, sizeof(r));
- sqlite3_result_double(ctx, r);
- }
- break;
- }
- case SQLITE_TEXT: {
- sqlite3_result_text(ctx, (char*)&aVal[1], nVal-1, SQLITE_TRANSIENT);
- break;
- }
- case SQLITE_BLOB: {
- sqlite3_result_blob(ctx, &aVal[1], nVal-1, SQLITE_TRANSIENT);
- break;
- }
+ }else if( lsm1DecodeValues(pCur) ){
+ /* The i-th value column (where leftmost is 1) */
+ const u8 *zData;
+ u32 nData;
+ i--;
+ zData = pCur->zData + pCur->aiOfst[i];
+ nData = pCur->aiLen[i];
+ switch( pCur->aeType[i] ){
+ case 0: { /* in-line integer */
+ sqlite3_result_int(ctx, pCur->aiOfst[i]);
+ break;
+ }
+ case SQLITE_INTEGER: {
+ sqlite3_int64 v;
+ lsm1GetSignedVarint64(zData, nData, &v);
+ sqlite3_result_int64(ctx, v);
+ break;
+ }
+ case SQLITE_FLOAT: {
+ double v;
+ if( nData==sizeof(v) ){
+ memcpy(&v, zData, sizeof(v));
+ sqlite3_result_double(ctx, v);
}
+ break;
+ }
+ case SQLITE_TEXT: {
+ sqlite3_result_text(ctx, (const char*)zData, nData, SQLITE_TRANSIENT);
+ break;
+ }
+ case SQLITE_BLOB: {
+ sqlite3_result_blob(ctx, zData, nData, SQLITE_TRANSIENT);
+ break;
+ }
+ default: {
+ /* A NULL. Do nothing */
}
- break;
- }
- default: {
- break;
}
}
return SQLITE_OK;
}
+/* Parameter "pValue" contains an SQL value that is to be used as
+** a key in an LSM table. The type of the key is determined by
+** "keyType". Extract the raw bytes used for the key in LSM1.
+*/
+static void lsm1KeyFromValue(
+ int keyType, /* The key type */
+ sqlite3_value *pValue, /* The key value */
+ u8 *pBuf, /* Storage space for a generated key */
+ const u8 **ppKey, /* OUT: the bytes of the key */
+ int *pnKey /* OUT: size of the key */
+){
+ if( keyType==SQLITE_BLOB ){
+ *ppKey = (const u8*)sqlite3_value_blob(pValue);
+ *pnKey = sqlite3_value_bytes(pValue);
+ }else if( keyType==SQLITE_TEXT ){
+ *ppKey = (const u8*)sqlite3_value_text(pValue);
+ *pnKey = sqlite3_value_bytes(pValue);
+ }else{
+ sqlite3_int64 v = sqlite3_value_int64(pValue);
+ if( v<0 ) v = 0;
+ *pnKey = lsm1PutVarint64(pBuf, v);
+ *ppKey = pBuf;
+ }
+}
+
/* Move to the first row to return.
*/
static int lsm1Filter(
@@ -514,21 +743,74 @@ static int lsm1Filter(
int argc, sqlite3_value **argv
){
lsm1_cursor *pCur = (lsm1_cursor *)pVtabCursor;
+ lsm1_vtab *pTab = (lsm1_vtab*)(pCur->base.pVtab);
int rc = LSM_OK;
+ int seekType = -1;
+ const u8 *pVal = 0;
+ int nVal;
+ u8 keyType = pTab->keyType;
+ u8 aKey1[16];
+
pCur->atEof = 1;
- if( idxNum==1 ){
- assert( argc==1 );
- pCur->isDesc = 0;
- pCur->bUnique = 1;
- if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
- const void *pVal = sqlite3_value_blob(argv[0]);
- int nVal = sqlite3_value_bytes(argv[0]);
- rc = lsm_csr_seek(pCur->pLsmCur, pVal, nVal, LSM_SEEK_EQ);
+ sqlite3_free(pCur->pKey2);
+ pCur->pKey2 = 0;
+ if( idxNum<99 ){
+ lsm1KeyFromValue(keyType, argv[0], aKey1, &pVal, &nVal);
+ }
+ switch( idxNum ){
+ case 0: { /* key==argv[0] */
+ assert( argc==1 );
+ seekType = LSM_SEEK_EQ;
+ pCur->isDesc = 0;
+ pCur->bUnique = 1;
+ break;
}
+ case 1: { /* key>=argv[0] AND key<=argv[1] */
+ u8 aKey[12];
+ seekType = LSM_SEEK_GE;
+ pCur->isDesc = 0;
+ pCur->bUnique = 0;
+ if( keyType==SQLITE_INTEGER ){
+ sqlite3_int64 v = sqlite3_value_int64(argv[1]);
+ if( v<0 ) v = 0;
+ pCur->nKey2 = lsm1PutVarint64(aKey, (sqlite3_uint64)v);
+ pCur->pKey2 = sqlite3_malloc( pCur->nKey2 );
+ if( pCur->pKey2==0 ) return SQLITE_NOMEM;
+ memcpy(pCur->pKey2, aKey, pCur->nKey2);
+ }else{
+ pCur->nKey2 = sqlite3_value_bytes(argv[1]);
+ pCur->pKey2 = sqlite3_malloc( pCur->nKey2 );
+ if( pCur->pKey2==0 ) return SQLITE_NOMEM;
+ if( keyType==SQLITE_BLOB ){
+ memcpy(pCur->pKey2, sqlite3_value_blob(argv[1]), pCur->nKey2);
+ }else{
+ memcpy(pCur->pKey2, sqlite3_value_text(argv[1]), pCur->nKey2);
+ }
+ }
+ break;
+ }
+ case 2: { /* key>=argv[0] */
+ seekType = LSM_SEEK_GE;
+ pCur->isDesc = 0;
+ pCur->bUnique = 0;
+ break;
+ }
+ case 3: { /* key<=argv[0] */
+ seekType = LSM_SEEK_LE;
+ pCur->isDesc = 1;
+ pCur->bUnique = 0;
+ break;
+ }
+ default: { /* full table scan */
+ pCur->isDesc = 0;
+ pCur->bUnique = 0;
+ break;
+ }
+ }
+ if( pVal ){
+ rc = lsm_csr_seek(pCur->pLsmCur, pVal, nVal, seekType);
}else{
rc = lsm_csr_first(pCur->pLsmCur);
- pCur->isDesc = 0;
- pCur->bUnique = 0;
}
if( rc==LSM_OK && lsm_csr_valid(pCur->pLsmCur)!=0 ){
pCur->atEof = 0;
@@ -540,59 +822,87 @@ static int lsm1Filter(
** Only comparisons against the key are allowed. The idxNum defines
** which comparisons are available:
**
-** 0 Full table scan only
-** bit 1 key==?1 single argument for ?1
-** bit 2 key>?1
-** bit 3 key>=?1
-** bit 4 key<?N (N==1 if bits 2,3 clear, or 2 if bits2,3 set)
-** bit 5 key<=?N (N==1 if bits 2,3 clear, or 2 if bits2,3 set)
-** bit 6 Use blobkey instead of key
-**
-** To put it another way:
-**
-** 0 Full table scan.
-** 1 key==?1
-** 2 key>?1
-** 4 key>=?1
-** 8 key<?1
-** 10 key>?1 AND key<?2
-** 12 key>=?1 AND key<?2
-** 16 key<=?1
-** 18 key>?1 AND key<=?2
-** 20 key>=?1 AND key<=?2
-** 33..52 Use blobkey in place of key...
+** 0 key==?1
+** 1 key>=?1 AND key<=?2
+** 2 key>?1 or key>=?1
+** 3 key<?1 or key<=?1
+** 99 Full table scan only
*/
static int lsm1BestIndex(
sqlite3_vtab *tab,
sqlite3_index_info *pIdxInfo
){
int i; /* Loop over constraints */
- int idxNum = 0; /* The query plan bitmask */
+ int idxNum = 99; /* The query plan */
int nArg = 0; /* Number of arguments to xFilter */
- int eqIdx = -1; /* Index of the key== constraint, or -1 if none */
+ int argIdx = -1; /* Index of the key== constraint, or -1 if none */
+ int iIdx2 = -1; /* The index of the second key */
+ int omit1 = 0;
+ int omit2 = 0;
const struct sqlite3_index_constraint *pConstraint;
pConstraint = pIdxInfo->aConstraint;
for(i=0; i<pIdxInfo->nConstraint && idxNum<16; i++, pConstraint++){
if( pConstraint->usable==0 ) continue;
- if( pConstraint->iColumn!=LSM1_COLUMN_KEY ) continue;
- if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
+ if( pConstraint->iColumn!=0 ) continue;
switch( pConstraint->op ){
case SQLITE_INDEX_CONSTRAINT_EQ: {
- eqIdx = i;
- idxNum = 1;
+ if( idxNum>0 ){
+ argIdx = i;
+ iIdx2 = -1;
+ idxNum = 0;
+ omit1 = 1;
+ }
+ break;
+ }
+ case SQLITE_INDEX_CONSTRAINT_GE:
+ case SQLITE_INDEX_CONSTRAINT_GT: {
+ if( idxNum==99 ){
+ argIdx = i;
+ idxNum = 2;
+ omit1 = pConstraint->op==SQLITE_INDEX_CONSTRAINT_GE;
+ }else if( idxNum==3 ){
+ iIdx2 = idxNum;
+ omit2 = omit1;
+ argIdx = i;
+ idxNum = 1;
+ omit1 = pConstraint->op==SQLITE_INDEX_CONSTRAINT_GE;
+ }
+ break;
+ }
+ case SQLITE_INDEX_CONSTRAINT_LE:
+ case SQLITE_INDEX_CONSTRAINT_LT: {
+ if( idxNum==99 ){
+ argIdx = i;
+ idxNum = 3;
+ omit1 = pConstraint->op==SQLITE_INDEX_CONSTRAINT_LE;
+ }else if( idxNum==2 ){
+ iIdx2 = i;
+ idxNum = 1;
+ omit1 = pConstraint->op==SQLITE_INDEX_CONSTRAINT_LE;
+ }
break;
}
}
}
- if( eqIdx>=0 ){
- pIdxInfo->aConstraintUsage[eqIdx].argvIndex = ++nArg;
- pIdxInfo->aConstraintUsage[eqIdx].omit = 1;
+ if( argIdx>=0 ){
+ pIdxInfo->aConstraintUsage[argIdx].argvIndex = ++nArg;
+ pIdxInfo->aConstraintUsage[argIdx].omit = omit1;
}
- if( idxNum==1 ){
+ if( iIdx2>=0 ){
+ pIdxInfo->aConstraintUsage[iIdx2].argvIndex = ++nArg;
+ pIdxInfo->aConstraintUsage[iIdx2].omit = omit2;
+ }
+ if( idxNum==0 ){
pIdxInfo->estimatedCost = (double)1;
pIdxInfo->estimatedRows = 1;
pIdxInfo->orderByConsumed = 1;
+ }else if( idxNum==1 ){
+ pIdxInfo->estimatedCost = (double)100;
+ pIdxInfo->estimatedRows = 100;
+ }else if( idxNum<99 ){
+ pIdxInfo->estimatedCost = (double)5000;
+ pIdxInfo->estimatedRows = 5000;
}else{
/* Full table scan */
pIdxInfo->estimatedCost = (double)2147483647;
@@ -615,98 +925,84 @@ int lsm1Update(
sqlite_int64 *pRowid
){
lsm1_vtab *p = (lsm1_vtab*)pVTab;
- const void *pKey;
- void *pFree = 0;
- int nKey;
- int eType;
+ int nKey, nKey2;
+ int i;
int rc = LSM_OK;
- sqlite3_value *pValue;
- const unsigned char *pVal;
- unsigned char *pData;
- int nVal;
- unsigned char pSpace[100];
+ const u8 *pKey, *pKey2;
+ unsigned char aKey[16];
+ unsigned char pSpace[16];
+ lsm1_vblob val;
if( argc==1 ){
- pVTab->zErrMsg = sqlite3_mprintf("cannot DELETE");
- return SQLITE_ERROR;
+ /* DELETE the record whose key is argv[0] */
+ lsm1KeyFromValue(p->keyType, argv[0], aKey, &pKey, &nKey);
+ lsm_delete(p->pDb, pKey, nKey);
+ return SQLITE_OK;
}
+
if( sqlite3_value_type(argv[0])!=SQLITE_NULL ){
- pVTab->zErrMsg = sqlite3_mprintf("cannot UPDATE");
- return SQLITE_ERROR;
+ /* An UPDATE */
+ lsm1KeyFromValue(p->keyType, argv[0], aKey, &pKey, &nKey);
+ lsm1KeyFromValue(p->keyType, argv[1], pSpace, &pKey2, &nKey2);
+ if( nKey!=nKey2 || memcmp(pKey, pKey2, nKey)!=0 ){
+ /* The UPDATE changes the PRIMARY KEY value. DELETE the old key */
+ lsm_delete(p->pDb, pKey, nKey);
+ }
+ /* Fall through into the INSERT case to complete the UPDATE */
}
- /* "INSERT INTO tab(command) VALUES('....')" is used to implement
+ /* "INSERT INTO tab(lsm1_command) VALUES('....')" is used to implement
** special commands.
*/
- if( sqlite3_value_type(argv[2+LSM1_COLUMN_COMMAND])!=SQLITE_NULL ){
+ if( sqlite3_value_type(argv[3+p->nVal])!=SQLITE_NULL ){
return SQLITE_OK;
}
- if( sqlite3_value_type(argv[2+LSM1_COLUMN_BLOBKEY])==SQLITE_BLOB ){
- /* Use the blob key exactly as supplied */
- pKey = sqlite3_value_blob(argv[2+LSM1_COLUMN_BLOBKEY]);
- nKey = sqlite3_value_bytes(argv[2+LSM1_COLUMN_BLOBKEY]);
- }else{
- /* Use a key encoding that sorts in lexicographical order */
- rc = lsm1EncodeKey(argv[2+LSM1_COLUMN_KEY],
- (unsigned char**)&pKey,&nKey,
- pSpace,sizeof(pSpace));
- if( rc ) return rc;
- if( pKey!=(const void*)pSpace ) pFree = (void*)pKey;
- }
- if( sqlite3_value_type(argv[2+LSM1_COLUMN_BLOBVALUE])==SQLITE_BLOB ){
- pVal = sqlite3_value_blob(argv[2+LSM1_COLUMN_BLOBVALUE]);
- nVal = sqlite3_value_bytes(argv[2+LSM1_COLUMN_BLOBVALUE]);
- rc = lsm_insert(p->pDb, pKey, nKey, pVal, nVal);
- }else{
- pValue = argv[2+LSM1_COLUMN_VALUE];
- eType = sqlite3_value_type(pValue);
+ lsm1KeyFromValue(p->keyType, argv[2], aKey, &pKey, &nKey);
+ memset(&val, 0, sizeof(val));
+ for(i=0; i<p->nVal; i++){
+ sqlite3_value *pArg = argv[3+i];
+ u8 eType = sqlite3_value_type(pArg);
switch( eType ){
case SQLITE_NULL: {
- rc = lsm_delete(p->pDb, pKey, nKey);
+ lsm1VblobAppendVarint(&val, SQLITE_NULL);
break;
}
- case SQLITE_BLOB:
- case SQLITE_TEXT: {
- if( eType==SQLITE_TEXT ){
- pVal = sqlite3_value_text(pValue);
- }else{
- pVal = (unsigned char*)sqlite3_value_blob(pValue);
- }
- nVal = sqlite3_value_bytes(pValue);
- pData = sqlite3_malloc( nVal+1 );
- if( pData==0 ){
- rc = SQLITE_NOMEM;
+ case SQLITE_INTEGER: {
+ sqlite3_int64 v = sqlite3_value_int64(pArg);
+ if( v>=0 && v<=240/6 ){
+ lsm1VblobAppendVarint(&val, v*6);
}else{
- pData[0] = (unsigned char)eType;
- memcpy(&pData[1], pVal, nVal);
- rc = lsm_insert(p->pDb, pKey, nKey, pData, nVal+1);
- sqlite3_free(pData);
+ int n = lsm1PutSignedVarint64(pSpace, v);
+ lsm1VblobAppendVarint(&val, SQLITE_INTEGER + n*6);
+ lsm1VblobAppend(&val, pSpace, n);
}
break;
}
- case SQLITE_INTEGER:
case SQLITE_FLOAT: {
- sqlite3_uint64 x;
- unsigned char aVal[9];
- int i;
- if( eType==SQLITE_INTEGER ){
- *(sqlite3_int64*)&x = sqlite3_value_int64(pValue);
- }else{
- double r = sqlite3_value_double(pValue);
- assert( sizeof(r)==sizeof(x) );
- memcpy(&x, &r, sizeof(r));
- }
- for(i=8; x>0 && i>=1; i--){
- aVal[i] = x & 0xff;
- x >>= 8;
- }
- aVal[i] = (unsigned char)eType;
- rc = lsm_insert(p->pDb, pKey, nKey, &aVal[i], 9-i);
+ double r = sqlite3_value_double(pArg);
+ lsm1VblobAppendVarint(&val, SQLITE_FLOAT + 8*6);
+ lsm1VblobAppend(&val, (u8*)&r, sizeof(r));
+ break;
+ }
+ case SQLITE_BLOB: {
+ int n = sqlite3_value_bytes(pArg);
+ lsm1VblobAppendVarint(&val, n*6 + SQLITE_BLOB);
+ lsm1VblobAppend(&val, sqlite3_value_blob(pArg), n);
+ break;
+ }
+ case SQLITE_TEXT: {
+ int n = sqlite3_value_bytes(pArg);
+ lsm1VblobAppendVarint(&val, n*6 + SQLITE_TEXT);
+ lsm1VblobAppend(&val, sqlite3_value_text(pArg), n);
break;
}
}
}
- sqlite3_free(pFree);
+ if( val.errNoMem ){
+ return SQLITE_NOMEM;
+ }
+ rc = lsm_insert(p->pDb, pKey, nKey, val.a, val.n);
+ sqlite3_free(val.a);
return rc==LSM_OK ? SQLITE_OK : SQLITE_ERROR;
}
diff --git a/chromium/third_party/sqlite/src/ext/misc/csv.c b/chromium/third_party/sqlite/src/ext/misc/csv.c
index e66ba567145..83d6cb3fd0c 100644
--- a/chromium/third_party/sqlite/src/ext/misc/csv.c
+++ b/chromium/third_party/sqlite/src/ext/misc/csv.c
@@ -78,7 +78,7 @@ struct CsvReader {
int nAlloc; /* Space allocated for z[] */
int nLine; /* Current line number */
int bNotFirst; /* True if prior text has been seen */
- char cTerm; /* Character that terminated the most recent field */
+ int cTerm; /* Character that terminated the most recent field */
size_t iIn; /* Next unread character in the input buffer */
size_t nIn; /* Number of characters in the input buffer */
char *zIn; /* The input buffer */
@@ -166,7 +166,7 @@ static int csv_getc(CsvReader *p){
if( p->in!=0 ) return csv_getc_refill(p);
return EOF;
}
- return p->zIn[p->iIn++];
+ return ((unsigned char*)p->zIn)[p->iIn++];
}
/* Increase the size of p->z and append character c to the end.
@@ -680,16 +680,16 @@ static int csvtabNext(sqlite3_vtab_cursor *cur){
i++;
}
}while( pCur->rdr.cTerm==',' );
- while( i<pTab->nCol ){
- sqlite3_free(pCur->azVal[i]);
- pCur->azVal[i] = 0;
- pCur->aLen[i] = 0;
- i++;
- }
- if( z==0 || pCur->rdr.cTerm==EOF ){
+ if( z==0 || (pCur->rdr.cTerm==EOF && i<pTab->nCol) ){
pCur->iRowid = -1;
}else{
pCur->iRowid++;
+ while( i<pTab->nCol ){
+ sqlite3_free(pCur->azVal[i]);
+ pCur->azVal[i] = 0;
+ pCur->aLen[i] = 0;
+ i++;
+ }
}
return SQLITE_OK;
}
diff --git a/chromium/third_party/sqlite/src/ext/misc/mmapwarm.c b/chromium/third_party/sqlite/src/ext/misc/mmapwarm.c
new file mode 100644
index 00000000000..f4d1a01b54e
--- /dev/null
+++ b/chromium/third_party/sqlite/src/ext/misc/mmapwarm.c
@@ -0,0 +1,108 @@
+/*
+** 2017-09-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.
+**
+*************************************************************************
+**
+*/
+
+#include "sqlite3.h"
+
+
+/*
+** This function is used to touch each page of a mapping of a memory
+** mapped SQLite database. Assuming that the system has sufficient free
+** memory and supports sufficiently large mappings, this causes the OS
+** to cache the entire database in main memory, making subsequent
+** database accesses faster.
+**
+** If the second parameter to this function is not NULL, it is the name of
+** the specific database to operate on (i.e. "main" or the name of an
+** attached database).
+**
+** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
+** It is not considered an error if the file is not memory-mapped, or if
+** the mapping does not span the entire file. If an error does occur, a
+** transaction may be left open on the database file.
+**
+** It is illegal to call this function when the database handle has an
+** open transaction. SQLITE_MISUSE is returned in this case.
+*/
+int sqlite3_mmap_warm(sqlite3 *db, const char *zDb){
+ int rc = SQLITE_OK;
+ char *zSql = 0;
+ int pgsz = 0;
+ int nTotal = 0;
+
+ if( 0==sqlite3_get_autocommit(db) ) return SQLITE_MISUSE;
+
+ /* Open a read-only transaction on the file in question */
+ zSql = sqlite3_mprintf("BEGIN; SELECT * FROM %s%q%ssqlite_master",
+ (zDb ? "'" : ""), (zDb ? zDb : ""), (zDb ? "'." : "")
+ );
+ if( zSql==0 ) return SQLITE_NOMEM;
+ rc = sqlite3_exec(db, zSql, 0, 0, 0);
+ sqlite3_free(zSql);
+
+ /* Find the SQLite page size of the file */
+ if( rc==SQLITE_OK ){
+ zSql = sqlite3_mprintf("PRAGMA %s%q%spage_size",
+ (zDb ? "'" : ""), (zDb ? zDb : ""), (zDb ? "'." : "")
+ );
+ if( zSql==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ sqlite3_stmt *pPgsz = 0;
+ rc = sqlite3_prepare_v2(db, zSql, -1, &pPgsz, 0);
+ sqlite3_free(zSql);
+ if( rc==SQLITE_OK ){
+ if( sqlite3_step(pPgsz)==SQLITE_ROW ){
+ pgsz = sqlite3_column_int(pPgsz, 0);
+ }
+ rc = sqlite3_finalize(pPgsz);
+ }
+ if( rc==SQLITE_OK && pgsz==0 ){
+ rc = SQLITE_ERROR;
+ }
+ }
+ }
+
+ /* Touch each mmap'd page of the file */
+ if( rc==SQLITE_OK ){
+ int rc2;
+ sqlite3_file *pFd = 0;
+ rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_FILE_POINTER, &pFd);
+ if( rc==SQLITE_OK && pFd->pMethods->iVersion>=3 ){
+ sqlite3_int64 iPg = 1;
+ sqlite3_io_methods const *p = pFd->pMethods;
+ while( 1 ){
+ unsigned char *pMap;
+ rc = p->xFetch(pFd, pgsz*iPg, pgsz, (void**)&pMap);
+ if( rc!=SQLITE_OK || pMap==0 ) break;
+
+ nTotal += pMap[0];
+ nTotal += pMap[pgsz-1];
+
+ rc = p->xUnfetch(pFd, pgsz*iPg, (void*)pMap);
+ if( rc!=SQLITE_OK ) break;
+ iPg++;
+ }
+ sqlite3_log(SQLITE_OK,
+ "sqlite3_mmap_warm_cache: Warmed up %d pages of %s", iPg==1?0:iPg,
+ sqlite3_db_filename(db, zDb)
+ );
+ }
+
+ rc2 = sqlite3_exec(db, "END", 0, 0, 0);
+ if( rc==SQLITE_OK ) rc = rc2;
+ }
+
+ return rc;
+}
+
diff --git a/chromium/third_party/sqlite/src/ext/misc/series.c b/chromium/third_party/sqlite/src/ext/misc/series.c
index dc7dc0ef34a..d02a6908767 100644
--- a/chromium/third_party/sqlite/src/ext/misc/series.c
+++ b/chromium/third_party/sqlite/src/ext/misc/series.c
@@ -195,8 +195,9 @@ static int seriesColumn(
}
/*
-** Return the rowid for the current row. In this implementation, the
-** rowid is the same as the output value.
+** Return the rowid for the current row. In this implementation, the
+** first row returned is assigned rowid value 1, and each subsequent
+** row a value 1 more than that of the previous.
*/
static int seriesRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
series_cursor *pCur = (series_cursor*)cur;
diff --git a/chromium/third_party/sqlite/src/ext/misc/unionvtab.c b/chromium/third_party/sqlite/src/ext/misc/unionvtab.c
index 0ba783a49ba..b382bc5aa43 100644
--- a/chromium/third_party/sqlite/src/ext/misc/unionvtab.c
+++ b/chromium/third_party/sqlite/src/ext/misc/unionvtab.c
@@ -10,8 +10,8 @@
**
*************************************************************************
**
-** This file contains the implementation of the "unionvtab" virtual
-** table. This module provides read-only access to multiple tables,
+** This file contains the implementation of the "unionvtab" and "swarmvtab"
+** virtual tables. These modules provide read-only access to multiple tables,
** possibly in multiple database files, via a single database object.
** The source tables must have the following characteristics:
**
@@ -25,26 +25,48 @@
**
** * Each table must contain a distinct range of rowid values.
**
-** A "unionvtab" virtual table is created as follows:
+** The difference between the two virtual table modules is that for
+** "unionvtab", all source tables must be located in the main database or
+** in databases ATTACHed to the main database by the user. For "swarmvtab",
+** the tables may be located in any database file on disk. The "swarmvtab"
+** implementation takes care of opening and closing database files
+** automatically.
**
-** CREATE VIRTUAL TABLE <name> USING unionvtab(<sql statement>);
+** UNIONVTAB
**
-** The implementation evalutes <sql statement> whenever a unionvtab virtual
-** table is created or opened. It should return one row for each source
-** database table. The four columns required of each row are:
+** A "unionvtab" virtual table is created as follows:
**
-** 1. The name of the database containing the table ("main" or "temp" or
-** the name of an attached database). Or NULL to indicate that all
-** databases should be searched for the table in the usual fashion.
+** CREATE VIRTUAL TABLE <name> USING unionvtab(<sql-statement>);
**
-** 2. The name of the database table.
+** The implementation evalutes <sql statement> whenever a unionvtab virtual
+** table is created or opened. It should return one row for each source
+** database table. The four columns required of each row are:
**
-** 3. The smallest rowid in the range of rowids that may be stored in the
-** database table (an integer).
+** 1. The name of the database containing the table ("main" or "temp" or
+** the name of an attached database). Or NULL to indicate that all
+** databases should be searched for the table in the usual fashion.
**
-** 4. The largest rowid in the range of rowids that may be stored in the
-** database table (an integer).
+** 2. The name of the database table.
**
+** 3. The smallest rowid in the range of rowids that may be stored in the
+** database table (an integer).
+**
+** 4. The largest rowid in the range of rowids that may be stored in the
+** database table (an integer).
+**
+** SWARMVTAB
+**
+** A "swarmvtab" virtual table is created similarly to a unionvtab table:
+**
+** CREATE VIRTUAL TABLE <name>
+** USING swarmvtab(<sql-statement>, <callback>);
+**
+** The difference is that for a swarmvtab table, the first column returned
+** by the <sql statement> must return a path or URI that can be used to open
+** the database file containing the source table. The <callback> option
+** is optional. If included, it is the name of an application-defined
+** SQL function that is invoked with the URI of the file, if the file
+** does not already exist on disk.
*/
#include "sqlite3ext.h"
@@ -65,6 +87,30 @@ SQLITE_EXTENSION_INIT1
# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64)
#endif
+/*
+** The following is also copied from sqliteInt.h. To facilitate coverage
+** testing.
+*/
+#ifndef ALWAYS
+# if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
+# define ALWAYS(X) (1)
+# define NEVER(X) (0)
+# elif !defined(NDEBUG)
+# define ALWAYS(X) ((X)?1:(assert(0),0))
+# define NEVER(X) ((X)?(assert(0),1):0)
+# else
+# define ALWAYS(X) (X)
+# define NEVER(X) (X)
+# endif
+#endif
+
+/*
+** The swarmvtab module attempts to keep the number of open database files
+** at or below this limit. This may not be possible if there are too many
+** simultaneous queries.
+*/
+#define SWARMVTAB_MAX_OPEN 9
+
typedef struct UnionCsr UnionCsr;
typedef struct UnionTab UnionTab;
typedef struct UnionSrc UnionSrc;
@@ -79,6 +125,12 @@ struct UnionSrc {
char *zTab; /* Source table name */
sqlite3_int64 iMin; /* Minimum rowid */
sqlite3_int64 iMax; /* Maximum rowid */
+
+ /* Fields used by swarmvtab only */
+ char *zFile; /* Database file containing table zTab */
+ int nUser; /* Current number of users */
+ sqlite3 *db; /* Database handle */
+ UnionSrc *pNextClosable; /* Next in list of closable sources */
};
/*
@@ -87,9 +139,17 @@ struct UnionSrc {
struct UnionTab {
sqlite3_vtab base; /* Base class - must be first */
sqlite3 *db; /* Database handle */
+ int bSwarm; /* 1 for "swarmvtab", 0 for "unionvtab" */
int iPK; /* INTEGER PRIMARY KEY column, or -1 */
int nSrc; /* Number of elements in the aSrc[] array */
UnionSrc *aSrc; /* Array of source tables, sorted by rowid */
+
+ /* Used by swarmvtab only */
+ char *zSourceStr; /* Expected unionSourceToStr() value */
+ char *zNotFoundCallback; /* UDF to invoke if file not found on open */
+ UnionSrc *pClosable; /* First in list of closable sources */
+ int nOpen; /* Current number of open sources */
+ int nMaxOpen; /* Maximum number of open sources */
};
/*
@@ -98,9 +158,21 @@ struct UnionTab {
struct UnionCsr {
sqlite3_vtab_cursor base; /* Base class - must be first */
sqlite3_stmt *pStmt; /* SQL statement to run */
+
+ /* Used by swarmvtab only */
+ sqlite3_int64 iMaxRowid; /* Last rowid to visit */
+ int iTab; /* Index of table read by pStmt */
};
/*
+** Given UnionTab table pTab and UnionSrc object pSrc, return the database
+** handle that should be used to access the table identified by pSrc. This
+** is the main db handle for "unionvtab" tables, or the source-specific
+** handle for "swarmvtab".
+*/
+#define unionGetDb(pTab, pSrc) ((pTab)->bSwarm ? (pSrc)->db : (pTab)->db)
+
+/*
** If *pRc is other than SQLITE_OK when this function is called, it
** always returns NULL. Otherwise, it attempts to allocate and return
** a pointer to nByte bytes of zeroed memory. If the memory allocation
@@ -160,7 +232,7 @@ static void unionDequote(char *z){
int iIn = 1;
int iOut = 0;
if( q=='[' ) q = ']';
- while( z[iIn] ){
+ while( ALWAYS(z[iIn]) ){
if( z[iIn]==q ){
if( z[iIn+1]!=q ){
/* Character iIn was the close quote. */
@@ -202,6 +274,7 @@ static sqlite3_stmt *unionPrepare(
char **pzErr /* OUT: Error message */
){
sqlite3_stmt *pRet = 0;
+ assert( pzErr );
if( *pRc==SQLITE_OK ){
int rc = sqlite3_prepare_v2(db, zSql, -1, &pRet, 0);
if( rc!=SQLITE_OK ){
@@ -250,6 +323,7 @@ static sqlite3_stmt *unionPreparePrintf(
** In this case, *pzErr may be set to point to an error message
** buffer allocated by sqlite3_malloc().
*/
+#if 0
static void unionReset(int *pRc, sqlite3_stmt *pStmt, char **pzErr){
int rc = sqlite3_reset(pStmt);
if( *pRc==SQLITE_OK ){
@@ -259,15 +333,39 @@ static void unionReset(int *pRc, sqlite3_stmt *pStmt, char **pzErr){
}
}
}
+#endif
/*
** Call sqlite3_finalize() on SQL statement pStmt. If *pRc is set to
** SQLITE_OK when this function is called, then it is set to the
** value returned by sqlite3_finalize() before this function exits.
*/
-static void unionFinalize(int *pRc, sqlite3_stmt *pStmt){
+static void unionFinalize(int *pRc, sqlite3_stmt *pStmt, char **pzErr){
+ sqlite3 *db = sqlite3_db_handle(pStmt);
int rc = sqlite3_finalize(pStmt);
- if( *pRc==SQLITE_OK ) *pRc = rc;
+ if( *pRc==SQLITE_OK ){
+ *pRc = rc;
+ if( rc ){
+ *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
+ }
+ }
+}
+
+/*
+** This function is a no-op for unionvtab. For swarmvtab, it attempts to
+** close open database files until at most nMax are open. An SQLite error
+** code is returned if an error occurs, or SQLITE_OK otherwise.
+*/
+static void unionCloseSources(UnionTab *pTab, int nMax){
+ while( pTab->pClosable && pTab->nOpen>nMax ){
+ UnionSrc **pp;
+ for(pp=&pTab->pClosable; (*pp)->pNextClosable; pp=&(*pp)->pNextClosable);
+ assert( (*pp)->db );
+ sqlite3_close((*pp)->db);
+ (*pp)->db = 0;
+ *pp = 0;
+ pTab->nOpen--;
+ }
}
/*
@@ -278,9 +376,14 @@ static int unionDisconnect(sqlite3_vtab *pVtab){
UnionTab *pTab = (UnionTab*)pVtab;
int i;
for(i=0; i<pTab->nSrc; i++){
- sqlite3_free(pTab->aSrc[i].zDb);
- sqlite3_free(pTab->aSrc[i].zTab);
+ UnionSrc *pSrc = &pTab->aSrc[i];
+ sqlite3_free(pSrc->zDb);
+ sqlite3_free(pSrc->zTab);
+ sqlite3_free(pSrc->zFile);
+ sqlite3_close(pSrc->db);
}
+ sqlite3_free(pTab->zSourceStr);
+ sqlite3_free(pTab->zNotFoundCallback);
sqlite3_free(pTab->aSrc);
sqlite3_free(pTab);
}
@@ -288,6 +391,38 @@ static int unionDisconnect(sqlite3_vtab *pVtab){
}
/*
+** Check that the table identified by pSrc is a rowid table. If not,
+** return SQLITE_ERROR and set (*pzErr) to point to an English language
+** error message. If the table is a rowid table and no error occurs,
+** return SQLITE_OK and leave (*pzErr) unmodified.
+*/
+static int unionIsIntkeyTable(
+ sqlite3 *db, /* Database handle */
+ UnionSrc *pSrc, /* Source table to test */
+ char **pzErr /* OUT: Error message */
+){
+ int bPk = 0;
+ const char *zType = 0;
+ int rc;
+
+ sqlite3_table_column_metadata(
+ db, pSrc->zDb, pSrc->zTab, "_rowid_", &zType, 0, 0, &bPk, 0
+ );
+ rc = sqlite3_errcode(db);
+ if( rc==SQLITE_ERROR
+ || (rc==SQLITE_OK && (!bPk || sqlite3_stricmp("integer", zType)))
+ ){
+ rc = SQLITE_ERROR;
+ *pzErr = sqlite3_mprintf("no such rowid table: %s%s%s",
+ (pSrc->zDb ? pSrc->zDb : ""),
+ (pSrc->zDb ? "." : ""),
+ pSrc->zTab
+ );
+ }
+ return rc;
+}
+
+/*
** This function is a no-op if *pRc is other than SQLITE_OK when it is
** called. In this case it returns NULL.
**
@@ -306,41 +441,27 @@ static int unionDisconnect(sqlite3_vtab *pVtab){
*/
static char *unionSourceToStr(
int *pRc, /* IN/OUT: Error code */
- sqlite3 *db, /* Database handle */
+ UnionTab *pTab, /* Virtual table object */
UnionSrc *pSrc, /* Source table to test */
- sqlite3_stmt *pStmt,
char **pzErr /* OUT: Error message */
){
char *zRet = 0;
if( *pRc==SQLITE_OK ){
- int bPk = 0;
- const char *zType = 0;
- int rc;
-
- sqlite3_table_column_metadata(
- db, pSrc->zDb, pSrc->zTab, "_rowid_", &zType, 0, 0, &bPk, 0
+ sqlite3 *db = unionGetDb(pTab, pSrc);
+ int rc = unionIsIntkeyTable(db, pSrc, pzErr);
+ sqlite3_stmt *pStmt = unionPrepare(&rc, db,
+ "SELECT group_concat(quote(name) || '.' || quote(type)) "
+ "FROM pragma_table_info(?, ?)", pzErr
);
- rc = sqlite3_errcode(db);
- if( rc==SQLITE_ERROR
- || (rc==SQLITE_OK && (!bPk || sqlite3_stricmp("integer", zType)))
- ){
- rc = SQLITE_ERROR;
- *pzErr = sqlite3_mprintf("no such rowid table: %s%s%s",
- (pSrc->zDb ? pSrc->zDb : ""),
- (pSrc->zDb ? "." : ""),
- pSrc->zTab
- );
- }
-
if( rc==SQLITE_OK ){
sqlite3_bind_text(pStmt, 1, pSrc->zTab, -1, SQLITE_STATIC);
sqlite3_bind_text(pStmt, 2, pSrc->zDb, -1, SQLITE_STATIC);
if( SQLITE_ROW==sqlite3_step(pStmt) ){
- zRet = unionStrdup(&rc, (const char*)sqlite3_column_text(pStmt, 0));
+ const char *z = (const char*)sqlite3_column_text(pStmt, 0);
+ zRet = unionStrdup(&rc, z);
}
- unionReset(&rc, pStmt, pzErr);
+ unionFinalize(&rc, pStmt, pzErr);
}
-
*pRc = rc;
}
@@ -356,34 +477,152 @@ static char *unionSourceToStr(
** other error occurs, SQLITE_OK is returned.
*/
static int unionSourceCheck(UnionTab *pTab, char **pzErr){
- const char *zSql =
- "SELECT group_concat(quote(name) || '.' || quote(type)) "
- "FROM pragma_table_info(?, ?)";
int rc = SQLITE_OK;
+ char *z0 = 0;
+ int i;
- if( pTab->nSrc==0 ){
- *pzErr = sqlite3_mprintf("no source tables configured");
- rc = SQLITE_ERROR;
- }else{
- sqlite3_stmt *pStmt = 0;
- char *z0 = 0;
- int i;
+ assert( *pzErr==0 );
+ z0 = unionSourceToStr(&rc, pTab, &pTab->aSrc[0], pzErr);
+ for(i=1; i<pTab->nSrc; i++){
+ char *z = unionSourceToStr(&rc, pTab, &pTab->aSrc[i], pzErr);
+ if( rc==SQLITE_OK && sqlite3_stricmp(z, z0) ){
+ *pzErr = sqlite3_mprintf("source table schema mismatch");
+ rc = SQLITE_ERROR;
+ }
+ sqlite3_free(z);
+ }
+ sqlite3_free(z0);
- pStmt = unionPrepare(&rc, pTab->db, zSql, pzErr);
- if( rc==SQLITE_OK ){
- z0 = unionSourceToStr(&rc, pTab->db, &pTab->aSrc[0], pStmt, pzErr);
+ return rc;
+}
+
+
+/*
+** Try to open the swarmvtab database. If initially unable, invoke the
+** not-found callback UDF and then try again.
+*/
+static int unionOpenDatabaseInner(UnionTab *pTab, UnionSrc *pSrc, char **pzErr){
+ int rc = SQLITE_OK;
+ static const int openFlags =
+ SQLITE_OPEN_READONLY | SQLITE_OPEN_URI;
+ rc = sqlite3_open_v2(pSrc->zFile, &pSrc->db, openFlags, 0);
+ if( rc==SQLITE_OK ) return rc;
+ if( pTab->zNotFoundCallback ){
+ char *zSql = sqlite3_mprintf("SELECT \"%w\"(%Q);",
+ pTab->zNotFoundCallback, pSrc->zFile);
+ sqlite3_close(pSrc->db);
+ pSrc->db = 0;
+ if( zSql==0 ){
+ *pzErr = sqlite3_mprintf("out of memory");
+ return SQLITE_NOMEM;
}
- for(i=1; i<pTab->nSrc; i++){
- char *z = unionSourceToStr(&rc, pTab->db, &pTab->aSrc[i], pStmt, pzErr);
- if( rc==SQLITE_OK && sqlite3_stricmp(z, z0) ){
- *pzErr = sqlite3_mprintf("source table schema mismatch");
- rc = SQLITE_ERROR;
+ rc = sqlite3_exec(pTab->db, zSql, 0, 0, pzErr);
+ sqlite3_free(zSql);
+ if( rc ) return rc;
+ rc = sqlite3_open_v2(pSrc->zFile, &pSrc->db, openFlags, 0);
+ }
+ if( rc!=SQLITE_OK ){
+ *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(pSrc->db));
+ }
+ return rc;
+}
+
+/*
+** This function may only be called for swarmvtab tables. The results of
+** calling it on a unionvtab table are undefined.
+**
+** For a swarmvtab table, this function ensures that source database iSrc
+** is open. If the database is opened successfully and the schema is as
+** expected, or if it is already open when this function is called, SQLITE_OK
+** is returned.
+**
+** Alternatively If an error occurs while opening the databases, or if the
+** database schema is unsuitable, an SQLite error code is returned and (*pzErr)
+** may be set to point to an English language error message. In this case it is
+** the responsibility of the caller to eventually free the error message buffer
+** using sqlite3_free().
+*/
+static int unionOpenDatabase(UnionTab *pTab, int iSrc, char **pzErr){
+ int rc = SQLITE_OK;
+ UnionSrc *pSrc = &pTab->aSrc[iSrc];
+
+ assert( pTab->bSwarm && iSrc<pTab->nSrc );
+ if( pSrc->db==0 ){
+ unionCloseSources(pTab, pTab->nMaxOpen-1);
+ rc = unionOpenDatabaseInner(pTab, pSrc, pzErr);
+ if( rc==SQLITE_OK ){
+ char *z = unionSourceToStr(&rc, pTab, pSrc, pzErr);
+ if( rc==SQLITE_OK ){
+ if( pTab->zSourceStr==0 ){
+ pTab->zSourceStr = z;
+ }else{
+ if( sqlite3_stricmp(z, pTab->zSourceStr) ){
+ *pzErr = sqlite3_mprintf("source table schema mismatch");
+ rc = SQLITE_ERROR;
+ }
+ sqlite3_free(z);
+ }
}
- sqlite3_free(z);
}
- unionFinalize(&rc, pStmt);
- sqlite3_free(z0);
+ if( rc==SQLITE_OK ){
+ pSrc->pNextClosable = pTab->pClosable;
+ pTab->pClosable = pSrc;
+ pTab->nOpen++;
+ }else{
+ sqlite3_close(pSrc->db);
+ pSrc->db = 0;
+ }
+ }
+
+ return rc;
+}
+
+
+/*
+** This function is a no-op for unionvtab tables. For swarmvtab, increment
+** the reference count for source table iTab. If the reference count was
+** zero before it was incremented, also remove the source from the closable
+** list.
+*/
+static void unionIncrRefcount(UnionTab *pTab, int iTab){
+ if( pTab->bSwarm ){
+ UnionSrc *pSrc = &pTab->aSrc[iTab];
+ assert( pSrc->nUser>=0 && pSrc->db );
+ if( pSrc->nUser==0 ){
+ UnionSrc **pp;
+ for(pp=&pTab->pClosable; *pp!=pSrc; pp=&(*pp)->pNextClosable);
+ *pp = pSrc->pNextClosable;
+ pSrc->pNextClosable = 0;
+ }
+ pSrc->nUser++;
+ }
+}
+
+/*
+** Finalize the SQL statement pCsr->pStmt and return the result.
+**
+** If this is a swarmvtab table (not unionvtab) and pCsr->pStmt was not
+** NULL when this function was called, also decrement the reference
+** count on the associated source table. If this means the source tables
+** refcount is now zero, add it to the closable list.
+*/
+static int unionFinalizeCsrStmt(UnionCsr *pCsr){
+ int rc = SQLITE_OK;
+ if( pCsr->pStmt ){
+ UnionTab *pTab = (UnionTab*)pCsr->base.pVtab;
+ UnionSrc *pSrc = &pTab->aSrc[pCsr->iTab];
+ rc = sqlite3_finalize(pCsr->pStmt);
+ pCsr->pStmt = 0;
+ if( pTab->bSwarm ){
+ pSrc->nUser--;
+ assert( pSrc->nUser>=0 );
+ if( pSrc->nUser==0 ){
+ pSrc->pNextClosable = pTab->pClosable;
+ pTab->pClosable = pSrc;
+ }
+ unionCloseSources(pTab, pTab->nMaxOpen);
+ }
}
return rc;
}
@@ -393,10 +632,11 @@ static int unionSourceCheck(UnionTab *pTab, char **pzErr){
**
** The argv[] array contains the following:
**
-** argv[0] -> module name ("unionvtab")
+** argv[0] -> module name ("unionvtab" or "swarmvtab")
** argv[1] -> database name
** argv[2] -> table name
** argv[3] -> SQL statement
+** argv[4] -> not-found callback UDF name
*/
static int unionConnect(
sqlite3 *db,
@@ -407,14 +647,15 @@ static int unionConnect(
){
UnionTab *pTab = 0;
int rc = SQLITE_OK;
+ int bSwarm = (pAux==0 ? 0 : 1);
+ const char *zVtab = (bSwarm ? "swarmvtab" : "unionvtab");
- (void)pAux; /* Suppress harmless 'unused parameter' warning */
if( sqlite3_stricmp("temp", argv[1]) ){
/* unionvtab tables may only be created in the temp schema */
- *pzErr = sqlite3_mprintf("unionvtab tables must be created in TEMP schema");
+ *pzErr = sqlite3_mprintf("%s tables must be created in TEMP schema", zVtab);
rc = SQLITE_ERROR;
- }else if( argc!=4 ){
- *pzErr = sqlite3_mprintf("wrong number of arguments for unionvtab");
+ }else if( argc!=4 && argc!=5 ){
+ *pzErr = sqlite3_mprintf("wrong number of arguments for %s", zVtab);
rc = SQLITE_ERROR;
}else{
int nAlloc = 0; /* Allocated size of pTab->aSrc[] */
@@ -464,30 +705,60 @@ static int unionConnect(
rc = SQLITE_ERROR;
}
- pSrc = &pTab->aSrc[pTab->nSrc++];
- pSrc->zDb = unionStrdup(&rc, zDb);
- pSrc->zTab = unionStrdup(&rc, zTab);
- pSrc->iMin = iMin;
- pSrc->iMax = iMax;
+ if( rc==SQLITE_OK ){
+ pSrc = &pTab->aSrc[pTab->nSrc++];
+ pSrc->zTab = unionStrdup(&rc, zTab);
+ pSrc->iMin = iMin;
+ pSrc->iMax = iMax;
+ if( bSwarm ){
+ pSrc->zFile = unionStrdup(&rc, zDb);
+ }else{
+ pSrc->zDb = unionStrdup(&rc, zDb);
+ }
+ }
}
- unionFinalize(&rc, pStmt);
+ unionFinalize(&rc, pStmt, pzErr);
pStmt = 0;
- /* Verify that all source tables exist and have compatible schemas. */
+ /* Capture the not-found callback UDF name */
+ if( rc==SQLITE_OK && argc>=5 ){
+ pTab->zNotFoundCallback = unionStrdup(&rc, argv[4]);
+ unionDequote(pTab->zNotFoundCallback);
+ }
+
+ /* It is an error if the SELECT statement returned zero rows. If only
+ ** because there is no way to determine the schema of the virtual
+ ** table in this case. */
+ if( rc==SQLITE_OK && pTab->nSrc==0 ){
+ *pzErr = sqlite3_mprintf("no source tables configured");
+ rc = SQLITE_ERROR;
+ }
+
+ /* For unionvtab, verify that all source tables exist and have
+ ** compatible schemas. For swarmvtab, attach the first database and
+ ** check that the first table is a rowid table only. */
if( rc==SQLITE_OK ){
pTab->db = db;
- rc = unionSourceCheck(pTab, pzErr);
+ pTab->bSwarm = bSwarm;
+ pTab->nMaxOpen = SWARMVTAB_MAX_OPEN;
+ if( bSwarm ){
+ rc = unionOpenDatabase(pTab, 0, pzErr);
+ }else{
+ rc = unionSourceCheck(pTab, pzErr);
+ }
}
/* Compose a CREATE TABLE statement and pass it to declare_vtab() */
if( rc==SQLITE_OK ){
- pStmt = unionPreparePrintf(&rc, pzErr, db, "SELECT "
+ UnionSrc *pSrc = &pTab->aSrc[0];
+ sqlite3 *tdb = unionGetDb(pTab, pSrc);
+ pStmt = unionPreparePrintf(&rc, pzErr, tdb, "SELECT "
"'CREATE TABLE xyz('"
" || group_concat(quote(name) || ' ' || type, ', ')"
" || ')',"
"max((cid+1) * (type='INTEGER' COLLATE nocase AND pk=1))-1 "
"FROM pragma_table_info(%Q, ?)",
- pTab->aSrc[0].zTab, pTab->aSrc[0].zDb
+ pSrc->zTab, pSrc->zDb
);
}
if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
@@ -496,7 +767,7 @@ static int unionConnect(
pTab->iPK = sqlite3_column_int(pStmt, 1);
}
- unionFinalize(&rc, pStmt);
+ unionFinalize(&rc, pStmt, pzErr);
}
if( rc!=SQLITE_OK ){
@@ -508,7 +779,6 @@ static int unionConnect(
return rc;
}
-
/*
** xOpen
*/
@@ -526,25 +796,56 @@ static int unionOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
*/
static int unionClose(sqlite3_vtab_cursor *cur){
UnionCsr *pCsr = (UnionCsr*)cur;
- sqlite3_finalize(pCsr->pStmt);
+ unionFinalizeCsrStmt(pCsr);
sqlite3_free(pCsr);
return SQLITE_OK;
}
+/*
+** This function does the work of the xNext() method. Except that, if it
+** returns SQLITE_ROW, it should be called again within the same xNext()
+** method call. See unionNext() for details.
+*/
+static int doUnionNext(UnionCsr *pCsr){
+ int rc = SQLITE_OK;
+ assert( pCsr->pStmt );
+ if( sqlite3_step(pCsr->pStmt)!=SQLITE_ROW ){
+ UnionTab *pTab = (UnionTab*)pCsr->base.pVtab;
+ rc = unionFinalizeCsrStmt(pCsr);
+ if( rc==SQLITE_OK && pTab->bSwarm ){
+ pCsr->iTab++;
+ if( pCsr->iTab<pTab->nSrc ){
+ UnionSrc *pSrc = &pTab->aSrc[pCsr->iTab];
+ if( pCsr->iMaxRowid>=pSrc->iMin ){
+ /* It is necessary to scan the next table. */
+ rc = unionOpenDatabase(pTab, pCsr->iTab, &pTab->base.zErrMsg);
+ pCsr->pStmt = unionPreparePrintf(&rc, &pTab->base.zErrMsg, pSrc->db,
+ "SELECT rowid, * FROM %Q %s %lld",
+ pSrc->zTab,
+ (pSrc->iMax>pCsr->iMaxRowid ? "WHERE _rowid_ <=" : "-- "),
+ pCsr->iMaxRowid
+ );
+ if( rc==SQLITE_OK ){
+ assert( pCsr->pStmt );
+ unionIncrRefcount(pTab, pCsr->iTab);
+ rc = SQLITE_ROW;
+ }
+ }
+ }
+ }
+ }
+
+ return rc;
+}
/*
** xNext
*/
static int unionNext(sqlite3_vtab_cursor *cur){
- UnionCsr *pCsr = (UnionCsr*)cur;
int rc;
- assert( pCsr->pStmt );
- if( sqlite3_step(pCsr->pStmt)!=SQLITE_ROW ){
- rc = sqlite3_finalize(pCsr->pStmt);
- pCsr->pStmt = 0;
- }else{
- rc = SQLITE_OK;
- }
+ do {
+ rc = doUnionNext((UnionCsr*)cur);
+ }while( rc==SQLITE_ROW );
return rc;
}
@@ -637,8 +938,7 @@ static int unionFilter(
}
}
- sqlite3_finalize(pCsr->pStmt);
- pCsr->pStmt = 0;
+ unionFinalizeCsrStmt(pCsr);
if( bZero ){
return SQLITE_OK;
}
@@ -674,12 +974,25 @@ static int unionFilter(
zSql = sqlite3_mprintf("%z %s rowid<=%lld", zSql, zWhere, iMax);
}
}
- }
+ if( pTab->bSwarm ){
+ pCsr->iTab = i;
+ pCsr->iMaxRowid = iMax;
+ rc = unionOpenDatabase(pTab, i, &pTab->base.zErrMsg);
+ break;
+ }
+ }
- if( zSql==0 ) return rc;
- pCsr->pStmt = unionPrepare(&rc, pTab->db, zSql, &pTab->base.zErrMsg);
- sqlite3_free(zSql);
+ if( zSql==0 ){
+ return rc;
+ }else{
+ sqlite3 *db = unionGetDb(pTab, &pTab->aSrc[pCsr->iTab]);
+ pCsr->pStmt = unionPrepare(&rc, db, zSql, &pTab->base.zErrMsg);
+ if( pCsr->pStmt ){
+ unionIncrRefcount(pTab, pCsr->iTab);
+ }
+ sqlite3_free(zSql);
+ }
if( rc!=SQLITE_OK ) return rc;
return unionNext(pVtabCursor);
}
@@ -791,8 +1104,13 @@ static int createUnionVtab(sqlite3 *db){
0, /* xRelease */
0 /* xRollbackTo */
};
+ int rc;
- return sqlite3_create_module(db, "unionvtab", &unionModule, 0);
+ rc = sqlite3_create_module(db, "unionvtab", &unionModule, 0);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3_create_module(db, "swarmvtab", &unionModule, (void*)db);
+ }
+ return rc;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
diff --git a/chromium/third_party/sqlite/src/ext/misc/vtablog.c b/chromium/third_party/sqlite/src/ext/misc/vtablog.c
new file mode 100644
index 00000000000..e183906165f
--- /dev/null
+++ b/chromium/third_party/sqlite/src/ext/misc/vtablog.c
@@ -0,0 +1,509 @@
+/*
+** 2017-08-10
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file implements a virtual table that prints diagnostic information
+** on stdout when its key interfaces are called. This is intended for
+** interactive analysis and debugging of virtual table interfaces.
+**
+** Usage example:
+**
+** .load ./vtablog
+** CREATE VIRTUAL TABLE temp.log USING vtablog(
+** schema='CREATE TABLE x(a,b,c)',
+** rows=25
+** );
+** SELECT * FROM log;
+*/
+#include "sqlite3ext.h"
+SQLITE_EXTENSION_INIT1
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+
+
+/* vtablog_vtab is a subclass of sqlite3_vtab which will
+** serve as the underlying representation of a vtablog virtual table
+*/
+typedef struct vtablog_vtab vtablog_vtab;
+struct vtablog_vtab {
+ sqlite3_vtab base; /* Base class - must be first */
+ int nRow; /* Number of rows in the table */
+ int iInst; /* Instance number for this vtablog table */
+ int nCursor; /* Number of cursors created */
+};
+
+/* vtablog_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 vtablog_cursor vtablog_cursor;
+struct vtablog_cursor {
+ sqlite3_vtab_cursor base; /* Base class - must be first */
+ int iCursor; /* Cursor number */
+ sqlite3_int64 iRowid; /* The rowid */
+};
+
+/* Skip leading whitespace. Return a pointer to the first non-whitespace
+** character, or to the zero terminator if the string has only whitespace */
+static const char *vtablog_skip_whitespace(const char *z){
+ while( isspace((unsigned char)z[0]) ) z++;
+ return z;
+}
+
+/* Remove trailing whitespace from the end of string z[] */
+static void vtablog_trim_whitespace(char *z){
+ size_t n = strlen(z);
+ while( n>0 && isspace((unsigned char)z[n]) ) n--;
+ z[n] = 0;
+}
+
+/* Dequote the string */
+static void vtablog_dequote(char *z){
+ int j;
+ char cQuote = z[0];
+ size_t i, n;
+
+ if( cQuote!='\'' && cQuote!='"' ) return;
+ n = strlen(z);
+ if( n<2 || z[n-1]!=z[0] ) return;
+ for(i=1, j=0; i<n-1; i++){
+ if( z[i]==cQuote && z[i+1]==cQuote ) i++;
+ z[j++] = z[i];
+ }
+ z[j] = 0;
+}
+
+/* Check to see if the string is of the form: "TAG = VALUE" with optional
+** whitespace before and around tokens. If it is, return a pointer to the
+** first character of VALUE. If it is not, return NULL.
+*/
+static const char *vtablog_parameter(const char *zTag, int nTag, const char *z){
+ z = vtablog_skip_whitespace(z);
+ if( strncmp(zTag, z, nTag)!=0 ) return 0;
+ z = vtablog_skip_whitespace(z+nTag);
+ if( z[0]!='=' ) return 0;
+ return vtablog_skip_whitespace(z+1);
+}
+
+/* Decode a parameter that requires a dequoted string.
+**
+** Return non-zero on an error.
+*/
+static int vtablog_string_parameter(
+ char **pzErr, /* Leave the error message here, if there is one */
+ const char *zParam, /* Parameter we are checking for */
+ const char *zArg, /* Raw text of the virtual table argment */
+ char **pzVal /* Write the dequoted string value here */
+){
+ const char *zValue;
+ zValue = vtablog_parameter(zParam,(int)strlen(zParam),zArg);
+ if( zValue==0 ) return 0;
+ if( *pzVal ){
+ *pzErr = sqlite3_mprintf("more than one '%s' parameter", zParam);
+ return 1;
+ }
+ *pzVal = sqlite3_mprintf("%s", zValue);
+ if( *pzVal==0 ){
+ *pzErr = sqlite3_mprintf("out of memory");
+ return 1;
+ }
+ vtablog_trim_whitespace(*pzVal);
+ vtablog_dequote(*pzVal);
+ return 0;
+}
+
+#if 0 /* not used - yet */
+/* Return 0 if the argument is false and 1 if it is true. Return -1 if
+** we cannot really tell.
+*/
+static int vtablog_boolean(const char *z){
+ if( sqlite3_stricmp("yes",z)==0
+ || sqlite3_stricmp("on",z)==0
+ || sqlite3_stricmp("true",z)==0
+ || (z[0]=='1' && z[1]==0)
+ ){
+ return 1;
+ }
+ if( sqlite3_stricmp("no",z)==0
+ || sqlite3_stricmp("off",z)==0
+ || sqlite3_stricmp("false",z)==0
+ || (z[0]=='0' && z[1]==0)
+ ){
+ return 0;
+ }
+ return -1;
+}
+#endif
+
+/*
+** The vtablogConnect() method is invoked to create a new
+** vtablog_vtab that describes the vtablog virtual table.
+**
+** Think of this routine as the constructor for vtablog_vtab objects.
+**
+** All this routine needs to do is:
+**
+** (1) Allocate the vtablog_vtab object and initialize all fields.
+**
+** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
+** result set of queries against vtablog will look like.
+*/
+static int vtablogConnectCreate(
+ sqlite3 *db,
+ void *pAux,
+ int argc, const char *const*argv,
+ sqlite3_vtab **ppVtab,
+ char **pzErr,
+ int isCreate
+){
+ static int nInst = 0;
+ vtablog_vtab *pNew;
+ int i;
+ int rc;
+ int iInst = ++nInst;
+ char *zSchema = 0;
+ char *zNRow = 0;
+
+ printf("vtablog%s(tab=%d):\n", isCreate ? "Create" : "Connect", iInst);
+ printf(" argc=%d\n", argc);
+ for(i=0; i<argc; i++){
+ printf(" argv[%d] = ", i);
+ if( argv[i] ){
+ printf("[%s]\n", argv[i]);
+ }else{
+ printf("NULL\n");
+ }
+ }
+
+ for(i=3; i<argc; i++){
+ const char *z = argv[i];
+ if( vtablog_string_parameter(pzErr, "schema", z, &zSchema) ){
+ return SQLITE_ERROR;
+ }
+ if( vtablog_string_parameter(pzErr, "rows", z, &zNRow) ){
+ return SQLITE_ERROR;
+ }
+ }
+
+ if( zSchema==0 ){
+ *pzErr = sqlite3_mprintf("no schema defined");
+ return SQLITE_ERROR;
+ }
+ rc = sqlite3_declare_vtab(db, zSchema);
+ 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->nRow = 10;
+ if( zNRow ) pNew->nRow = atoi(zNRow);
+ pNew->iInst = iInst;
+ }
+ return rc;
+}
+static int vtablogCreate(
+ sqlite3 *db,
+ void *pAux,
+ int argc, const char *const*argv,
+ sqlite3_vtab **ppVtab,
+ char **pzErr
+){
+ return vtablogConnectCreate(db,pAux,argc,argv,ppVtab,pzErr,1);
+}
+static int vtablogConnect(
+ sqlite3 *db,
+ void *pAux,
+ int argc, const char *const*argv,
+ sqlite3_vtab **ppVtab,
+ char **pzErr
+){
+ return vtablogConnectCreate(db,pAux,argc,argv,ppVtab,pzErr,0);
+}
+
+
+/*
+** This method is the destructor for vtablog_cursor objects.
+*/
+static int vtablogDisconnect(sqlite3_vtab *pVtab){
+ vtablog_vtab *pTab = (vtablog_vtab*)pVtab;
+ printf("vtablogDisconnect(%d)\n", pTab->iInst);
+ sqlite3_free(pVtab);
+ return SQLITE_OK;
+}
+
+/*
+** This method is the destructor for vtablog_cursor objects.
+*/
+static int vtablogDestroy(sqlite3_vtab *pVtab){
+ vtablog_vtab *pTab = (vtablog_vtab*)pVtab;
+ printf("vtablogDestroy(%d)\n", pTab->iInst);
+ sqlite3_free(pVtab);
+ return SQLITE_OK;
+}
+
+/*
+** Constructor for a new vtablog_cursor object.
+*/
+static int vtablogOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
+ vtablog_vtab *pTab = (vtablog_vtab*)p;
+ vtablog_cursor *pCur;
+ printf("vtablogOpen(tab=%d, cursor=%d)\n", pTab->iInst, ++pTab->nCursor);
+ pCur = sqlite3_malloc( sizeof(*pCur) );
+ if( pCur==0 ) return SQLITE_NOMEM;
+ memset(pCur, 0, sizeof(*pCur));
+ pCur->iCursor = pTab->nCursor;
+ *ppCursor = &pCur->base;
+ return SQLITE_OK;
+}
+
+/*
+** Destructor for a vtablog_cursor.
+*/
+static int vtablogClose(sqlite3_vtab_cursor *cur){
+ vtablog_cursor *pCur = (vtablog_cursor*)cur;
+ vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab;
+ printf("vtablogClose(tab=%d, cursor=%d)\n", pTab->iInst, pCur->iCursor);
+ sqlite3_free(cur);
+ return SQLITE_OK;
+}
+
+
+/*
+** Advance a vtablog_cursor to its next row of output.
+*/
+static int vtablogNext(sqlite3_vtab_cursor *cur){
+ vtablog_cursor *pCur = (vtablog_cursor*)cur;
+ vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab;
+ printf("vtablogNext(tab=%d, cursor=%d) rowid %d -> %d\n",
+ pTab->iInst, pCur->iCursor, (int)pCur->iRowid, (int)pCur->iRowid+1);
+ pCur->iRowid++;
+ return SQLITE_OK;
+}
+
+/*
+** Return values of columns for the row at which the vtablog_cursor
+** is currently pointing.
+*/
+static int vtablogColumn(
+ sqlite3_vtab_cursor *cur, /* The cursor */
+ sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
+ int i /* Which column to return */
+){
+ vtablog_cursor *pCur = (vtablog_cursor*)cur;
+ vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab;
+ char zVal[50];
+
+ if( i<26 ){
+ sqlite3_snprintf(sizeof(zVal),zVal,"%c%d",
+ "abcdefghijklmnopqrstuvwyz"[i], pCur->iRowid);
+ }else{
+ sqlite3_snprintf(sizeof(zVal),zVal,"{%d}%d", i, pCur->iRowid);
+ }
+ printf("vtablogColumn(tab=%d, cursor=%d, i=%d): [%s]\n",
+ pTab->iInst, pCur->iCursor, i, zVal);
+ sqlite3_result_text(ctx, zVal, -1, SQLITE_TRANSIENT);
+ return SQLITE_OK;
+}
+
+/*
+** Return the rowid for the current row. In this implementation, the
+** rowid is the same as the output value.
+*/
+static int vtablogRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
+ vtablog_cursor *pCur = (vtablog_cursor*)cur;
+ vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab;
+ printf("vtablogRowid(tab=%d, cursor=%d): %d\n",
+ pTab->iInst, pCur->iCursor, (int)pCur->iRowid);
+ *pRowid = pCur->iRowid;
+ return SQLITE_OK;
+}
+
+/*
+** Return TRUE if the cursor has been moved off of the last
+** row of output.
+*/
+static int vtablogEof(sqlite3_vtab_cursor *cur){
+ vtablog_cursor *pCur = (vtablog_cursor*)cur;
+ vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab;
+ int rc = pCur->iRowid >= pTab->nRow;
+ printf("vtablogEof(tab=%d, cursor=%d): %d\n",
+ pTab->iInst, pCur->iCursor, rc);
+ return rc;
+}
+
+/*
+** Output an sqlite3_value object's value as an SQL literal.
+*/
+static void vtablogQuote(sqlite3_value *p){
+ char z[50];
+ switch( sqlite3_value_type(p) ){
+ case SQLITE_NULL: {
+ printf("NULL");
+ break;
+ }
+ case SQLITE_INTEGER: {
+ sqlite3_snprintf(50,z,"%lld", sqlite3_value_int64(p));
+ printf("%s", z);
+ break;
+ }
+ case SQLITE_FLOAT: {
+ sqlite3_snprintf(50,z,"%!.20g", sqlite3_value_double(p));
+ printf("%s", z);
+ break;
+ }
+ case SQLITE_BLOB: {
+ int n = sqlite3_value_bytes(p);
+ const unsigned char *z = (const unsigned char*)sqlite3_value_blob(p);
+ int i;
+ printf("x'");
+ for(i=0; i<n; i++) printf("%02x", z[i]);
+ printf("'");
+ break;
+ }
+ case SQLITE_TEXT: {
+ const char *z = (const char*)sqlite3_value_text(p);
+ int i;
+ char c;
+ for(i=0; (c = z[i])!=0 && c!='\''; i++){}
+ if( c==0 ){
+ printf("'%s'",z);
+ }else{
+ printf("'");
+ while( *z ){
+ for(i=0; (c = z[i])!=0 && c!='\''; i++){}
+ if( c=='\'' ) i++;
+ if( i ){
+ printf("%.*s", i, z);
+ z += i;
+ }
+ if( c=='\'' ){
+ printf("'");
+ continue;
+ }
+ if( c==0 ){
+ break;
+ }
+ z++;
+ }
+ printf("'");
+ }
+ break;
+ }
+ }
+}
+
+
+/*
+** This method is called to "rewind" the vtablog_cursor object back
+** to the first row of output. This method is always called at least
+** once prior to any call to vtablogColumn() or vtablogRowid() or
+** vtablogEof().
+*/
+static int vtablogFilter(
+ sqlite3_vtab_cursor *cur,
+ int idxNum, const char *idxStr,
+ int argc, sqlite3_value **argv
+){
+ vtablog_cursor *pCur = (vtablog_cursor *)cur;
+ vtablog_vtab *pTab = (vtablog_vtab*)cur->pVtab;
+ printf("vtablogFilter(tab=%d, cursor=%d):\n", pTab->iInst, pCur->iCursor);
+ pCur->iRowid = 0;
+ return SQLITE_OK;
+}
+
+/*
+** SQLite will invoke this method one or more times while planning a query
+** that uses the vtablog virtual table. This routine needs to create
+** a query plan for each invocation and compute an estimated cost for that
+** plan.
+*/
+static int vtablogBestIndex(
+ sqlite3_vtab *tab,
+ sqlite3_index_info *pIdxInfo
+){
+ vtablog_vtab *pTab = (vtablog_vtab*)tab;
+ printf("vtablogBestIndex(tab=%d):\n", pTab->iInst);
+ pIdxInfo->estimatedCost = (double)500;
+ pIdxInfo->estimatedRows = 500;
+ return SQLITE_OK;
+}
+
+/*
+** SQLite invokes this method to INSERT, UPDATE, or DELETE content from
+** the table.
+**
+** This implementation does not actually make any changes to the table
+** content. It merely logs the fact that the method was invoked
+*/
+static int vtablogUpdate(
+ sqlite3_vtab *tab,
+ int argc,
+ sqlite3_value **argv,
+ sqlite_int64 *pRowid
+){
+ vtablog_vtab *pTab = (vtablog_vtab*)tab;
+ int i;
+ printf("vtablogUpdate(tab=%d):\n", pTab->iInst);
+ printf(" argc=%d\n", argc);
+ for(i=0; i<argc; i++){
+ printf(" argv[%d]=", i);
+ vtablogQuote(argv[i]);
+ printf("\n");
+ }
+ return SQLITE_OK;
+}
+
+/*
+** This following structure defines all the methods for the
+** vtablog virtual table.
+*/
+static sqlite3_module vtablogModule = {
+ 0, /* iVersion */
+ vtablogCreate, /* xCreate */
+ vtablogConnect, /* xConnect */
+ vtablogBestIndex, /* xBestIndex */
+ vtablogDisconnect, /* xDisconnect */
+ vtablogDestroy, /* xDestroy */
+ vtablogOpen, /* xOpen - open a cursor */
+ vtablogClose, /* xClose - close a cursor */
+ vtablogFilter, /* xFilter - configure scan constraints */
+ vtablogNext, /* xNext - advance a cursor */
+ vtablogEof, /* xEof - check for end of scan */
+ vtablogColumn, /* xColumn - read data */
+ vtablogRowid, /* xRowid - read data */
+ vtablogUpdate, /* xUpdate */
+ 0, /* xBegin */
+ 0, /* xSync */
+ 0, /* xCommit */
+ 0, /* xRollback */
+ 0, /* xFindMethod */
+ 0, /* xRename */
+ 0, /* xSavepoint */
+ 0, /* xRelease */
+ 0, /* xRollbackTo */
+};
+
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int sqlite3_vtablog_init(
+ sqlite3 *db,
+ char **pzErrMsg,
+ const sqlite3_api_routines *pApi
+){
+ int rc;
+ SQLITE_EXTENSION_INIT2(pApi);
+ rc = sqlite3_create_module(db, "vtablog", &vtablogModule, 0);
+ return rc;
+}
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbu10.test b/chromium/third_party/sqlite/src/ext/rbu/rbu10.test
index 852fe27c760..98d60760b01 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbu10.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbu10.test
@@ -114,7 +114,7 @@ ifcapable fts3 {
INSERT INTO data_xt VALUES('a', 'b', 1, 0);
}
} msg] $msg
- } {1 {SQLITE_ERROR - SQL logic error or missing database}}
+ } {1 {SQLITE_ERROR - SQL logic error}}
}
#--------------------------------------------------------------------
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbufault.test b/chromium/third_party/sqlite/src/ext/rbu/rbufault.test
index c00f5010767..c7fb0577c6d 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbufault.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbufault.test
@@ -125,7 +125,7 @@ foreach {tn2 setup sql expect} {
{1 SQLITE_IOERR_WRITE}
{1 SQLITE_IOERR_READ}
{1 SQLITE_IOERR_FSYNC}
- {1 {SQLITE_ERROR - SQL logic error or missing database}}
+ {1 {SQLITE_ERROR - SQL logic error}}
{1 {SQLITE_ERROR - unable to open database: rbu.db}}
{1 {SQLITE_IOERR - unable to open database: rbu.db}}
}
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbufault3.test b/chromium/third_party/sqlite/src/ext/rbu/rbufault3.test
index 58e045143a5..3e8f8cc22eb 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbufault3.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbufault3.test
@@ -31,7 +31,7 @@ foreach {fault errlist} {
{1 SQLITE_IOERR_READ}
{1 {SQLITE_IOERR - unable to open database: test.db2}}
{1 {SQLITE_ERROR - unable to open database: test.db2}}
- {1 {SQLITE_ERROR - SQL logic error or missing database}}
+ {1 {SQLITE_ERROR - SQL logic error}}
}
cantopen* {
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbufts.test b/chromium/third_party/sqlite/src/ext/rbu/rbufts.test
index d067de1ecec..dd4148209f4 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/rbufts.test
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbufts.test
@@ -119,14 +119,14 @@ do_test 3.2 {
CREATE TABLE data_ft(x, rbu_rowid, rbu_control);
INSERT INTO data_ft VALUES(NULL, 2, 1);
} } msg] $msg]
-} {1 {SQLITE_ERROR - SQL logic error or missing database]}}
+} {1 {SQLITE_ERROR - SQL logic error]}}
do_test 3.3 {
list [catch { apply_rbu_update test.db {
CREATE TABLE data_ft(x, rbu_rowid, rbu_control);
INSERT INTO data_ft VALUES('7 8 9', 1, 'x');
} } msg] $msg]
-} {1 {SQLITE_ERROR - SQL logic error or missing database]}}
+} {1 {SQLITE_ERROR - SQL logic error]}}
diff --git a/chromium/third_party/sqlite/src/ext/rbu/rbutemplimit.test b/chromium/third_party/sqlite/src/ext/rbu/rbutemplimit.test
new file mode 100644
index 00000000000..066c61ecd2a
--- /dev/null
+++ b/chromium/third_party/sqlite/src/ext/rbu/rbutemplimit.test
@@ -0,0 +1,129 @@
+# 2014 August 30
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+
+source [file join [file dirname [info script]] rbu_common.tcl]
+set ::testprefix rbutemplimit
+
+db close
+sqlite3_shutdown
+sqlite3_config_uri 1
+
+proc setup_databases {} {
+ forcedelete test.db2
+ forcedelete test.db
+ sqlite3 db test.db
+ execsql {
+ -- Create target database schema.
+ --
+ CREATE TABLE t1(a INTEGER PRIMARY KEY, b BLOB(100), c BLOB(100));
+ CREATE TABLE t2(a INTEGER PRIMARY KEY, b BLOB(100), c BLOB(100));
+ CREATE INDEX i1b ON t1(b);
+ CREATE INDEX i1c ON t1(c);
+ CREATE INDEX i2b ON t2(b);
+ CREATE INDEX i2c ON t2(c);
+
+ -- Create a large RBU database.
+ --
+ ATTACH 'test.db2' AS rbu;
+ CREATE TABLE rbu.data_t1(a, b, c, rbu_control);
+ WITH s(i) AS (
+ VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<10000
+ )
+ INSERT INTO data_t1 SELECT i, randomblob(100), randomblob(100), 0 FROM s;
+ CREATE TABLE rbu.data_t2(a, b, c, rbu_control);
+ WITH s(i) AS (
+ VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<15000
+ )
+ INSERT INTO data_t2 SELECT i, randomblob(100), randomblob(100), 0 FROM s;
+ }
+ db close
+}
+
+proc run_rbu_cachesize {target rbu cachesize temp_limit} {
+ sqlite3rbu rbu $target $rbu
+ rbu temp_size_limit $temp_limit
+ sqlite3_exec_nr [rbu db 1] "PRAGMA cache_size = $cachesize"
+ while 1 {
+ set rc [rbu step]
+ set ::A([rbu temp_size]) 1
+ if {$rc!="SQLITE_OK"} break
+ }
+ list [catch {rbu close} msg] $msg
+}
+
+proc step_rbu_cachesize {target rbu stepsize cachesize temp_limit} {
+ set res ""
+ while 1 {
+ sqlite3rbu rbu $target $rbu
+ rbu temp_size_limit $temp_limit
+ sqlite3_exec_nr [rbu db 1] "PRAGMA cache_size = $cachesize"
+ for {set i 0} {$i < $stepsize} {incr i} {
+ set rc [rbu step]
+ set ::A([rbu temp_size]) 1
+ if {$rc!="SQLITE_OK"} break
+ }
+ set res [list [catch {rbu close} msg] $msg]
+ if {$res != "0 SQLITE_OK"} break
+ }
+ set res
+}
+
+do_test 1.1.0 { setup_databases } {}
+
+do_test 1.1.1 {
+ unset -nocomplain ::A
+ run_rbu_cachesize test.db test.db2 10 0
+} {0 SQLITE_DONE}
+
+do_test 1.1.2 { llength [array names ::A] } 3
+
+do_test 1.1.3 {
+ foreach {a0 a1 a2} [lsort -integer [array names ::A]] {}
+ list [expr $a0==0] \
+ [expr $a1>1048576] [expr $a1<1200000] \
+ [expr $a2>1500000] [expr $a2<1700000]
+} {1 1 1 1 1}
+
+do_test 1.2.1 {
+ setup_databases
+ run_rbu_cachesize test.db test.db2 10 1000000
+} {1 SQLITE_FULL}
+do_test 1.2.2 { info commands rbu } {}
+
+do_test 1.3.1 {
+ setup_databases
+ run_rbu_cachesize test.db test.db2 10 1300000
+} {1 SQLITE_FULL}
+do_test 1.3.2 { info commands rbu } {}
+
+do_test 1.4.1 {
+ setup_databases
+ run_rbu_cachesize test.db test.db2 10 1800000
+} {0 SQLITE_DONE}
+do_test 1.4.2 { info commands rbu } {}
+
+do_test 1.5.1 {
+ setup_databases
+ unset -nocomplain ::A
+ step_rbu_cachesize test.db test.db2 1000 10 2400000
+} {0 SQLITE_DONE}
+do_test 1.5.2 { info commands rbu } {}
+
+do_test 1.6.1 {
+ setup_databases
+ unset -nocomplain ::A
+ step_rbu_cachesize test.db test.db2 1000 10 1400000
+} {1 SQLITE_FULL}
+do_test 1.6.2 { info commands rbu } {}
+
+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 ccba0f121ab..361d3355611 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/sqlite3rbu.c
+++ b/chromium/third_party/sqlite/src/ext/rbu/sqlite3rbu.c
@@ -96,6 +96,13 @@
/* Maximum number of prepared UPDATE statements held by this module */
#define SQLITE_RBU_UPDATE_CACHESIZE 16
+/* Delta checksums disabled by default. Compile with -DRBU_ENABLE_DELTA_CKSUM
+** to enable checksum verification.
+*/
+#ifndef RBU_ENABLE_DELTA_CKSUM
+# define RBU_ENABLE_DELTA_CKSUM 0
+#endif
+
/*
** Swap two objects of type TYPE.
*/
@@ -371,6 +378,8 @@ struct sqlite3rbu {
int pgsz;
u8 *aBuf;
i64 iWalCksum;
+ i64 szTemp; /* Current size of all temp files in use */
+ i64 szTempLimit; /* Total size limit for temp files */
/* Used in RBU vacuum mode only */
int nRbu; /* Number of RBU VFS in the stack */
@@ -379,23 +388,33 @@ struct sqlite3rbu {
/*
** An rbu VFS is implemented using an instance of this structure.
+**
+** Variable pRbu is only non-NULL for automatically created RBU VFS objects.
+** It is NULL for RBU VFS objects created explicitly using
+** sqlite3rbu_create_vfs(). It is used to track the total amount of temp
+** space used by the RBU handle.
*/
struct rbu_vfs {
sqlite3_vfs base; /* rbu VFS shim methods */
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 */
};
/*
** Each file opened by an rbu VFS is represented by an instance of
** the following structure.
+**
+** If this is a temporary file (pRbu!=0 && flags&DELETE_ON_CLOSE), variable
+** "sz" is set to the current size of the database file.
*/
struct rbu_file {
sqlite3_file base; /* sqlite3_file methods */
sqlite3_file *pReal; /* Underlying file handle */
rbu_vfs *pRbuVfs; /* Pointer to the rbu_vfs object */
sqlite3rbu *pRbu; /* Pointer to rbu object (rbu target only) */
+ i64 sz; /* Size of file in bytes (temp only) */
int openFlags; /* Flags this file was opened with */
u32 iCookie; /* Cookie value for main db files */
@@ -458,6 +477,7 @@ static unsigned int rbuDeltaGetInt(const char **pz, int *pLen){
return v;
}
+#if RBU_ENABLE_DELTA_CKSUM
/*
** Compute a 32-bit checksum on the N-byte buffer. Return the result.
*/
@@ -492,6 +512,7 @@ static unsigned int rbuDeltaChecksum(const char *zIn, size_t N){
}
return sum3;
}
+#endif
/*
** Apply a delta.
@@ -522,7 +543,7 @@ static int rbuDeltaApply(
){
unsigned int limit;
unsigned int total = 0;
-#ifndef FOSSIL_OMIT_DELTA_CKSUM_TEST
+#if RBU_ENABLE_DELTA_CKSUM
char *zOrigOut = zOut;
#endif
@@ -577,7 +598,7 @@ static int rbuDeltaApply(
case ';': {
zDelta++; lenDelta--;
zOut[0] = 0;
-#ifndef FOSSIL_OMIT_DELTA_CKSUM_TEST
+#if RBU_ENABLE_DELTA_CKSUM
if( cnt!=rbuDeltaChecksum(zOrigOut, total) ){
/* ERROR: bad checksum */
return -1;
@@ -3409,6 +3430,7 @@ static void rbuCreateVfs(sqlite3rbu *p){
sqlite3_vfs *pVfs = sqlite3_vfs_find(zRnd);
assert( pVfs );
p->zVfsName = pVfs->zName;
+ ((rbu_vfs*)pVfs)->pRbu = p;
}
}
@@ -3781,6 +3803,7 @@ int sqlite3rbu_close(sqlite3rbu *p, char **pzErrmsg){
/* Close the open database handle and VFS object. */
sqlite3_close(p->dbRbu);
sqlite3_close(p->dbMain);
+ assert( p->szTemp==0 );
rbuDeleteVfs(p);
sqlite3_free(p->aBuf);
sqlite3_free(p->aFrame);
@@ -3968,6 +3991,7 @@ int sqlite3rbu_savestate(sqlite3rbu *p){
*/
static void rbuUnlockShm(rbu_file *p){
+ assert( p->openFlags & SQLITE_OPEN_MAIN_DB );
if( p->pRbu ){
int (*xShmLock)(sqlite3_file*,int,int,int) = p->pReal->pMethods->xShmLock;
int i;
@@ -3981,6 +4005,18 @@ static void rbuUnlockShm(rbu_file *p){
}
/*
+*/
+static int rbuUpdateTempSize(rbu_file *pFd, sqlite3_int64 nNew){
+ sqlite3rbu *pRbu = pFd->pRbu;
+ i64 nDiff = nNew - pFd->sz;
+ pRbu->szTemp += nDiff;
+ pFd->sz = nNew;
+ assert( pRbu->szTemp>=0 );
+ if( pRbu->szTempLimit && pRbu->szTemp>pRbu->szTempLimit ) return SQLITE_FULL;
+ return SQLITE_OK;
+}
+
+/*
** Close an rbu file.
*/
static int rbuVfsClose(sqlite3_file *pFile){
@@ -4005,6 +4041,9 @@ static int rbuVfsClose(sqlite3_file *pFile){
rbuUnlockShm(p);
p->pReal->pMethods->xShmUnmap(p->pReal, 0);
}
+ else if( (p->openFlags & SQLITE_OPEN_DELETEONCLOSE) && p->pRbu ){
+ rbuUpdateTempSize(p, 0);
+ }
/* Close the underlying file handle */
rc = p->pReal->pMethods->xClose(p->pReal);
@@ -4122,11 +4161,19 @@ static int rbuVfsWrite(
assert( p->openFlags & SQLITE_OPEN_MAIN_DB );
rc = rbuCaptureDbWrite(p->pRbu, iOfst);
}else{
- if( pRbu && pRbu->eStage==RBU_STAGE_OAL
- && (p->openFlags & SQLITE_OPEN_WAL)
- && iOfst>=pRbu->iOalSz
- ){
- pRbu->iOalSz = iAmt + iOfst;
+ if( pRbu ){
+ if( pRbu->eStage==RBU_STAGE_OAL
+ && (p->openFlags & SQLITE_OPEN_WAL)
+ && iOfst>=pRbu->iOalSz
+ ){
+ pRbu->iOalSz = iAmt + iOfst;
+ }else if( p->openFlags & SQLITE_OPEN_DELETEONCLOSE ){
+ i64 szNew = iAmt+iOfst;
+ if( szNew>p->sz ){
+ rc = rbuUpdateTempSize(p, szNew);
+ if( rc!=SQLITE_OK ) return rc;
+ }
+ }
}
rc = p->pReal->pMethods->xWrite(p->pReal, zBuf, iAmt, iOfst);
if( rc==SQLITE_OK && iOfst==0 && (p->openFlags & SQLITE_OPEN_MAIN_DB) ){
@@ -4145,6 +4192,10 @@ static int rbuVfsWrite(
*/
static int rbuVfsTruncate(sqlite3_file *pFile, sqlite_int64 size){
rbu_file *p = (rbu_file*)pFile;
+ if( (p->openFlags & SQLITE_OPEN_DELETEONCLOSE) && p->pRbu ){
+ int rc = rbuUpdateTempSize(p, size);
+ if( rc!=SQLITE_OK ) return rc;
+ }
return p->pReal->pMethods->xTruncate(p->pReal, size);
}
@@ -4534,6 +4585,8 @@ static int rbuVfsOpen(
pDb->pWalFd = pFd;
}
}
+ }else{
+ pFd->pRbu = pRbuVfs->pRbu;
}
if( oflags & SQLITE_OPEN_MAIN_DB
@@ -4610,7 +4663,9 @@ static int rbuVfsAccess(
if( *pResOut ){
rc = SQLITE_CANTOPEN;
}else{
- *pResOut = 1;
+ sqlite3_int64 sz = 0;
+ rc = rbuVfsFileSize(&pDb->base, &sz);
+ *pResOut = (sz>0);
}
}
}
@@ -4799,6 +4854,20 @@ int sqlite3rbu_create_vfs(const char *zName, const char *zParent){
return rc;
}
+/*
+** Configure the aggregate temp file size limit for this RBU handle.
+*/
+sqlite3_int64 sqlite3rbu_temp_size_limit(sqlite3rbu *pRbu, sqlite3_int64 n){
+ if( n>=0 ){
+ pRbu->szTempLimit = n;
+ }
+ return pRbu->szTempLimit;
+}
+
+sqlite3_int64 sqlite3rbu_temp_size(sqlite3rbu *pRbu){
+ return pRbu->szTemp;
+}
+
/**************************************************************************/
diff --git a/chromium/third_party/sqlite/src/ext/rbu/sqlite3rbu.h b/chromium/third_party/sqlite/src/ext/rbu/sqlite3rbu.h
index 29c1028d690..07b8685e243 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/sqlite3rbu.h
+++ b/chromium/third_party/sqlite/src/ext/rbu/sqlite3rbu.h
@@ -308,7 +308,7 @@ typedef struct sqlite3rbu sqlite3rbu;
** not work out of the box with zipvfs. Refer to the comment describing
** the zipvfs_create_vfs() API below for details on using RBU with zipvfs.
*/
-sqlite3rbu *sqlite3rbu_open(
+SQLITE_API sqlite3rbu *sqlite3rbu_open(
const char *zTarget,
const char *zRbu,
const char *zState
@@ -347,12 +347,34 @@ sqlite3rbu *sqlite3rbu_open(
** a description of the complications associated with using RBU with
** zipvfs databases.
*/
-sqlite3rbu *sqlite3rbu_vacuum(
+SQLITE_API sqlite3rbu *sqlite3rbu_vacuum(
const char *zTarget,
const char *zState
);
/*
+** Configure a limit for the amount of temp space that may be used by
+** the RBU handle passed as the first argument. The new limit is specified
+** in bytes by the second parameter. If it is positive, the limit is updated.
+** If the second parameter to this function is passed zero, then the limit
+** is removed entirely. If the second parameter is negative, the limit is
+** not modified (this is useful for querying the current limit).
+**
+** In all cases the returned value is the current limit in bytes (zero
+** indicates unlimited).
+**
+** If the temp space limit is exceeded during operation, an SQLITE_FULL
+** error is returned.
+*/
+SQLITE_API sqlite3_int64 sqlite3rbu_temp_size_limit(sqlite3rbu*, sqlite3_int64);
+
+/*
+** Return the current amount of temp file space, in bytes, currently used by
+** the RBU handle passed as the only argument.
+*/
+SQLITE_API sqlite3_int64 sqlite3rbu_temp_size(sqlite3rbu*);
+
+/*
** Internally, each RBU connection uses a separate SQLite database
** connection to access the target and rbu update databases. This
** API allows the application direct access to these database handles.
@@ -383,7 +405,7 @@ sqlite3rbu *sqlite3rbu_vacuum(
** Database handles returned by this function remain valid until the next
** call to any sqlite3rbu_xxx() function other than sqlite3rbu_db().
*/
-sqlite3 *sqlite3rbu_db(sqlite3rbu*, int bRbu);
+SQLITE_API sqlite3 *sqlite3rbu_db(sqlite3rbu*, int bRbu);
/*
** Do some work towards applying the RBU update to the target db.
@@ -397,7 +419,7 @@ sqlite3 *sqlite3rbu_db(sqlite3rbu*, int bRbu);
** SQLITE_OK, all subsequent calls on the same RBU handle are no-ops
** that immediately return the same value.
*/
-int sqlite3rbu_step(sqlite3rbu *pRbu);
+SQLITE_API int sqlite3rbu_step(sqlite3rbu *pRbu);
/*
** Force RBU to save its state to disk.
@@ -409,7 +431,7 @@ int sqlite3rbu_step(sqlite3rbu *pRbu);
**
** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
*/
-int sqlite3rbu_savestate(sqlite3rbu *pRbu);
+SQLITE_API int sqlite3rbu_savestate(sqlite3rbu *pRbu);
/*
** Close an RBU handle.
@@ -429,14 +451,14 @@ int sqlite3rbu_savestate(sqlite3rbu *pRbu);
** update has been partially applied, or SQLITE_DONE if it has been
** completely applied.
*/
-int sqlite3rbu_close(sqlite3rbu *pRbu, char **pzErrmsg);
+SQLITE_API int sqlite3rbu_close(sqlite3rbu *pRbu, char **pzErrmsg);
/*
** Return the total number of key-value operations (inserts, deletes or
** updates) that have been performed on the target database since the
** current RBU update was started.
*/
-sqlite3_int64 sqlite3rbu_progress(sqlite3rbu *pRbu);
+SQLITE_API sqlite3_int64 sqlite3rbu_progress(sqlite3rbu *pRbu);
/*
** Obtain permyriadage (permyriadage is to 10000 as percentage is to 100)
@@ -478,7 +500,7 @@ sqlite3_int64 sqlite3rbu_progress(sqlite3rbu *pRbu);
** table exists but is not correctly populated, the value of the *pnOne
** output variable during stage 1 is undefined.
*/
-void sqlite3rbu_bp_progress(sqlite3rbu *pRbu, int *pnOne, int *pnTwo);
+SQLITE_API void sqlite3rbu_bp_progress(sqlite3rbu *pRbu, int *pnOne, int*pnTwo);
/*
** Obtain an indication as to the current stage of an RBU update or vacuum.
@@ -516,7 +538,7 @@ void sqlite3rbu_bp_progress(sqlite3rbu *pRbu, int *pnOne, int *pnTwo);
#define SQLITE_RBU_STATE_DONE 4
#define SQLITE_RBU_STATE_ERROR 5
-int sqlite3rbu_state(sqlite3rbu *pRbu);
+SQLITE_API int sqlite3rbu_state(sqlite3rbu *pRbu);
/*
** Create an RBU VFS named zName that accesses the underlying file-system
@@ -560,7 +582,7 @@ int sqlite3rbu_state(sqlite3rbu *pRbu);
** file-system via "rbu" all the time, even if it only uses RBU functionality
** occasionally.
*/
-int sqlite3rbu_create_vfs(const char *zName, const char *zParent);
+SQLITE_API int sqlite3rbu_create_vfs(const char *zName, const char *zParent);
/*
** Deregister and destroy an RBU vfs created by an earlier call to
@@ -570,7 +592,7 @@ int sqlite3rbu_create_vfs(const char *zName, const char *zParent);
** before all database handles that use it have been closed, the results
** are undefined.
*/
-void sqlite3rbu_destroy_vfs(const char *zName);
+SQLITE_API void sqlite3rbu_destroy_vfs(const char *zName);
#ifdef __cplusplus
} /* end of the 'extern "C"' block */
diff --git a/chromium/third_party/sqlite/src/ext/rbu/test_rbu.c b/chromium/third_party/sqlite/src/ext/rbu/test_rbu.c
index 9c61535445d..0973fba8efc 100644
--- a/chromium/third_party/sqlite/src/ext/rbu/test_rbu.c
+++ b/chromium/third_party/sqlite/src/ext/rbu/test_rbu.c
@@ -69,16 +69,18 @@ static int SQLITE_TCLAPI test_sqlite3rbu_cmd(
int nArg;
const char *zUsage;
} aCmd[] = {
- {"step", 2, ""}, /* 0 */
- {"close", 2, ""}, /* 1 */
- {"create_rbu_delta", 2, ""}, /* 2 */
- {"savestate", 2, ""}, /* 3 */
- {"dbMain_eval", 3, "SQL"}, /* 4 */
- {"bp_progress", 2, ""}, /* 5 */
- {"db", 3, "RBU"}, /* 6 */
- {"state", 2, ""}, /* 7 */
- {"progress", 2, ""}, /* 8 */
- {"close_no_error", 2, ""}, /* 9 */
+ {"step", 2, ""}, /* 0 */
+ {"close", 2, ""}, /* 1 */
+ {"create_rbu_delta", 2, ""}, /* 2 */
+ {"savestate", 2, ""}, /* 3 */
+ {"dbMain_eval", 3, "SQL"}, /* 4 */
+ {"bp_progress", 2, ""}, /* 5 */
+ {"db", 3, "RBU"}, /* 6 */
+ {"state", 2, ""}, /* 7 */
+ {"progress", 2, ""}, /* 8 */
+ {"close_no_error", 2, ""}, /* 9 */
+ {"temp_size_limit", 3, "LIMIT"}, /* 10 */
+ {"temp_size", 2, ""}, /* 11 */
{0,0,0}
};
int iCmd;
@@ -194,6 +196,22 @@ static int SQLITE_TCLAPI test_sqlite3rbu_cmd(
break;
}
+ case 10: /* temp_size_limit */ {
+ sqlite3_int64 nLimit;
+ if( Tcl_GetWideIntFromObj(interp, objv[2], &nLimit) ){
+ ret = TCL_ERROR;
+ }else{
+ nLimit = sqlite3rbu_temp_size_limit(pRbu, nLimit);
+ Tcl_SetObjResult(interp, Tcl_NewWideIntObj(nLimit));
+ }
+ break;
+ }
+ case 11: /* temp_size */ {
+ sqlite3_int64 sz = sqlite3rbu_temp_size(pRbu);
+ Tcl_SetObjResult(interp, Tcl_NewWideIntObj(sz));
+ break;
+ }
+
default: /* seems unlikely */
assert( !"cannot happen" );
break;
diff --git a/chromium/third_party/sqlite/src/ext/repair/README.md b/chromium/third_party/sqlite/src/ext/repair/README.md
new file mode 100644
index 00000000000..643058144ce
--- /dev/null
+++ b/chromium/third_party/sqlite/src/ext/repair/README.md
@@ -0,0 +1,16 @@
+This folder contains extensions and utility programs intended to analyze
+live database files, detect problems, and possibly fix them.
+
+As SQLite is being used on larger and larger databases, database sizes
+are growing into the terabyte range. At that size, hardware malfunctions
+and/or cosmic rays will occasionally corrupt a database file. Detecting
+problems and fixing errors a terabyte-sized databases can take hours or days,
+and it is undesirable to take applications that depend on the databases
+off-line for such a long time.
+The utilities in the folder are intended to provide mechanisms for
+detecting and fixing problems in large databases while those databases
+are in active use.
+
+The utilities and extensions in this folder are experimental and under
+active development at the time of this writing (2017-10-12). If and when
+they stabilize, this README will be updated to reflect that fact.
diff --git a/chromium/third_party/sqlite/src/ext/repair/checkfreelist.c b/chromium/third_party/sqlite/src/ext/repair/checkfreelist.c
new file mode 100644
index 00000000000..16865e65d62
--- /dev/null
+++ b/chromium/third_party/sqlite/src/ext/repair/checkfreelist.c
@@ -0,0 +1,299 @@
+/*
+** 2017 October 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 module exports a single C function:
+**
+** int sqlite3_check_freelist(sqlite3 *db, const char *zDb);
+**
+** This function checks the free-list in database zDb (one of "main",
+** "temp", etc.) and reports any errors by invoking the sqlite3_log()
+** function. It returns SQLITE_OK if successful, or an SQLite error
+** code otherwise. It is not an error if the free-list is corrupted but
+** no IO or OOM errors occur.
+**
+** If this file is compiled and loaded as an SQLite loadable extension,
+** it adds an SQL function "checkfreelist" to the database handle, to
+** be invoked as follows:
+**
+** SELECT checkfreelist(<database-name>);
+**
+** This function performs the same checks as sqlite3_check_freelist(),
+** except that it returns all error messages as a single text value,
+** separated by newline characters. If the freelist is not corrupted
+** in any way, an empty string is returned.
+**
+** To compile this module for use as an SQLite loadable extension:
+**
+** gcc -Os -fPIC -shared checkfreelist.c -o checkfreelist.so
+*/
+
+#include "sqlite3ext.h"
+SQLITE_EXTENSION_INIT1
+
+#ifndef SQLITE_AMALGAMATION
+# include <string.h>
+# include <stdio.h>
+# include <stdlib.h>
+# include <assert.h>
+# define ALWAYS(X) 1
+# define NEVER(X) 0
+ typedef unsigned char u8;
+ typedef unsigned short u16;
+ typedef unsigned int u32;
+#define get4byte(x) ( \
+ ((u32)((x)[0])<<24) + \
+ ((u32)((x)[1])<<16) + \
+ ((u32)((x)[2])<<8) + \
+ ((u32)((x)[3])) \
+)
+#endif
+
+/*
+** Execute a single PRAGMA statement and return the integer value returned
+** via output parameter (*pnOut).
+**
+** The SQL statement passed as the third argument should be a printf-style
+** format string containing a single "%s" which will be replace by the
+** value passed as the second argument. e.g.
+**
+** sqlGetInteger(db, "main", "PRAGMA %s.page_count", pnOut)
+**
+** executes "PRAGMA main.page_count" and stores the results in (*pnOut).
+*/
+static int sqlGetInteger(
+ sqlite3 *db, /* Database handle */
+ const char *zDb, /* Database name ("main", "temp" etc.) */
+ const char *zFmt, /* SQL statement format */
+ u32 *pnOut /* OUT: Integer value */
+){
+ int rc, rc2;
+ char *zSql;
+ sqlite3_stmt *pStmt = 0;
+ int bOk = 0;
+
+ zSql = sqlite3_mprintf(zFmt, zDb);
+ if( zSql==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
+ sqlite3_free(zSql);
+ }
+
+ if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
+ *pnOut = (u32)sqlite3_column_int(pStmt, 0);
+ bOk = 1;
+ }
+
+ rc2 = sqlite3_finalize(pStmt);
+ if( rc==SQLITE_OK ) rc = rc2;
+ if( rc==SQLITE_OK && bOk==0 ) rc = SQLITE_ERROR;
+ return rc;
+}
+
+/*
+** Argument zFmt must be a printf-style format string and must be
+** followed by its required arguments. If argument pzOut is NULL,
+** then the results of printf()ing the format string are passed to
+** sqlite3_log(). Otherwise, they are appended to the string
+** at (*pzOut).
+*/
+static int checkFreelistError(char **pzOut, const char *zFmt, ...){
+ int rc = SQLITE_OK;
+ char *zErr = 0;
+ va_list ap;
+
+ va_start(ap, zFmt);
+ zErr = sqlite3_vmprintf(zFmt, ap);
+ if( zErr==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ if( pzOut ){
+ *pzOut = sqlite3_mprintf("%s%z%s", *pzOut?"\n":"", *pzOut, zErr);
+ if( *pzOut==0 ) rc = SQLITE_NOMEM;
+ }else{
+ sqlite3_log(SQLITE_ERROR, "checkfreelist: %s", zErr);
+ }
+ sqlite3_free(zErr);
+ }
+ va_end(ap);
+ return rc;
+}
+
+static int checkFreelist(
+ sqlite3 *db,
+ const char *zDb,
+ char **pzOut
+){
+ /* This query returns one row for each page on the free list. Each row has
+ ** two columns - the page number and page content. */
+ const char *zTrunk =
+ "WITH freelist_trunk(i, d, n) AS ("
+ "SELECT 1, NULL, sqlite_readint32(data, 32) "
+ "FROM sqlite_dbpage(:1) WHERE pgno=1 "
+ "UNION ALL "
+ "SELECT n, data, sqlite_readint32(data) "
+ "FROM freelist_trunk, sqlite_dbpage(:1) WHERE pgno=n "
+ ")"
+ "SELECT i, d FROM freelist_trunk WHERE i!=1;";
+
+ int rc, rc2; /* Return code */
+ sqlite3_stmt *pTrunk = 0; /* Compilation of zTrunk */
+ u32 nPage = 0; /* Number of pages in db */
+ u32 nExpected = 0; /* Expected number of free pages */
+ u32 nFree = 0; /* Number of pages on free list */
+
+ if( zDb==0 ) zDb = "main";
+
+ if( (rc = sqlGetInteger(db, zDb, "PRAGMA %s.page_count", &nPage))
+ || (rc = sqlGetInteger(db, zDb, "PRAGMA %s.freelist_count", &nExpected))
+ ){
+ return rc;
+ }
+
+ rc = sqlite3_prepare_v2(db, zTrunk, -1, &pTrunk, 0);
+ if( rc!=SQLITE_OK ) return rc;
+ sqlite3_bind_text(pTrunk, 1, zDb, -1, SQLITE_STATIC);
+ while( rc==SQLITE_OK && sqlite3_step(pTrunk)==SQLITE_ROW ){
+ u32 i;
+ u32 iTrunk = (u32)sqlite3_column_int(pTrunk, 0);
+ const u8 *aData = (const u8*)sqlite3_column_blob(pTrunk, 1);
+ int nData = sqlite3_column_bytes(pTrunk, 1);
+ u32 iNext = get4byte(&aData[0]);
+ u32 nLeaf = get4byte(&aData[4]);
+
+ if( nLeaf>((nData/4)-2-6) ){
+ rc = checkFreelistError(pzOut,
+ "leaf count out of range (%d) on trunk page %d",
+ (int)nLeaf, (int)iTrunk
+ );
+ nLeaf = (nData/4) - 2 - 6;
+ }
+
+ nFree += 1+nLeaf;
+ if( iNext>nPage ){
+ rc = checkFreelistError(pzOut,
+ "trunk page %d is out of range", (int)iNext
+ );
+ }
+
+ for(i=0; rc==SQLITE_OK && i<nLeaf; i++){
+ u32 iLeaf = get4byte(&aData[8 + 4*i]);
+ if( iLeaf==0 || iLeaf>nPage ){
+ rc = checkFreelistError(pzOut,
+ "leaf page %d is out of range (child %d of trunk page %d)",
+ (int)iLeaf, (int)i, (int)iTrunk
+ );
+ }
+ }
+ }
+
+ if( rc==SQLITE_OK && nFree!=nExpected ){
+ rc = checkFreelistError(pzOut,
+ "free-list count mismatch: actual=%d header=%d",
+ (int)nFree, (int)nExpected
+ );
+ }
+
+ rc2 = sqlite3_finalize(pTrunk);
+ if( rc==SQLITE_OK ) rc = rc2;
+ return rc;
+}
+
+int sqlite3_check_freelist(sqlite3 *db, const char *zDb){
+ return checkFreelist(db, zDb, 0);
+}
+
+static void checkfreelist_function(
+ sqlite3_context *pCtx,
+ int nArg,
+ sqlite3_value **apArg
+){
+ const char *zDb;
+ int rc;
+ char *zOut = 0;
+ sqlite3 *db = sqlite3_context_db_handle(pCtx);
+
+ assert( nArg==1 );
+ zDb = (const char*)sqlite3_value_text(apArg[0]);
+ rc = checkFreelist(db, zDb, &zOut);
+ if( rc==SQLITE_OK ){
+ sqlite3_result_text(pCtx, zOut?zOut:"ok", -1, SQLITE_TRANSIENT);
+ }else{
+ sqlite3_result_error_code(pCtx, rc);
+ }
+
+ sqlite3_free(zOut);
+}
+
+/*
+** An SQL function invoked as follows:
+**
+** sqlite_readint32(BLOB) -- Decode 32-bit integer from start of blob
+*/
+static void readint_function(
+ sqlite3_context *pCtx,
+ int nArg,
+ sqlite3_value **apArg
+){
+ const u8 *zBlob;
+ int nBlob;
+ int iOff = 0;
+ u32 iRet = 0;
+
+ if( nArg!=1 && nArg!=2 ){
+ sqlite3_result_error(
+ pCtx, "wrong number of arguments to function sqlite_readint32()", -1
+ );
+ return;
+ }
+ if( nArg==2 ){
+ iOff = sqlite3_value_int(apArg[1]);
+ }
+
+ zBlob = sqlite3_value_blob(apArg[0]);
+ nBlob = sqlite3_value_bytes(apArg[0]);
+
+ if( nBlob>=(iOff+4) ){
+ iRet = get4byte(&zBlob[iOff]);
+ }
+
+ sqlite3_result_int64(pCtx, (sqlite3_int64)iRet);
+}
+
+/*
+** Register the SQL functions.
+*/
+static int cflRegister(sqlite3 *db){
+ int rc = sqlite3_create_function(
+ db, "sqlite_readint32", -1, SQLITE_UTF8, 0, readint_function, 0, 0
+ );
+ if( rc!=SQLITE_OK ) return rc;
+ rc = sqlite3_create_function(
+ db, "checkfreelist", 1, SQLITE_UTF8, 0, checkfreelist_function, 0, 0
+ );
+ return rc;
+}
+
+/*
+** Extension load function.
+*/
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int sqlite3_checkfreelist_init(
+ sqlite3 *db,
+ char **pzErrMsg,
+ const sqlite3_api_routines *pApi
+){
+ SQLITE_EXTENSION_INIT2(pApi);
+ return cflRegister(db);
+}
diff --git a/chromium/third_party/sqlite/src/ext/rtree/rtree.c b/chromium/third_party/sqlite/src/ext/rtree/rtree.c
index 38440516401..f7cfe82006b 100644
--- a/chromium/third_party/sqlite/src/ext/rtree/rtree.c
+++ b/chromium/third_party/sqlite/src/ext/rtree/rtree.c
@@ -2853,7 +2853,7 @@ static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){
int rc; /* Return code */
RtreeNode *pLeaf = 0; /* Leaf node containing record iDelete */
int iCell; /* Index of iDelete cell in pLeaf */
- RtreeNode *pRoot; /* Root node of rtree structure */
+ RtreeNode *pRoot = 0; /* Root node of rtree structure */
/* Obtain a reference to the root node to initialize Rtree.iDepth */
@@ -3414,7 +3414,7 @@ static int getNodeSize(
if( rc!=SQLITE_OK ){
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
}else if( pRtree->iNodeSize<(512-64) ){
- rc = SQLITE_CORRUPT;
+ rc = SQLITE_CORRUPT_VTAB;
*pzErr = sqlite3_mprintf("undersize RTree blobs in \"%q_node\"",
pRtree->zName);
}
diff --git a/chromium/third_party/sqlite/src/ext/rtree/rtreeA.test b/chromium/third_party/sqlite/src/ext/rtree/rtreeA.test
index 6dc96092887..9318463afdf 100644
--- a/chromium/third_party/sqlite/src/ext/rtree/rtreeA.test
+++ b/chromium/third_party/sqlite/src/ext/rtree/rtreeA.test
@@ -228,6 +228,10 @@ do_execsql_test rtreeA-7.100 {
do_catchsql_test rtreeA-7.110 {
SELECT * FROM t1 WHERE x1>0 AND x1<100 AND x2>0 AND x2<100;
} {1 {undersize RTree blobs in "t1_node"}}
+do_test rtreeA-7.120 {
+ sqlite3_extended_errcode db
+} {SQLITE_CORRUPT_VTAB}
+
finish_test
diff --git a/chromium/third_party/sqlite/src/ext/rtree/rtreeconnect.test b/chromium/third_party/sqlite/src/ext/rtree/rtreeconnect.test
new file mode 100644
index 00000000000..133efbd8383
--- /dev/null
+++ b/chromium/third_party/sqlite/src/ext/rtree/rtreeconnect.test
@@ -0,0 +1,56 @@
+# 2017 August 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.
+#
+#***********************************************************************
+#
+# The focus of this file is testing the r-tree extension. Specifically,
+# the impact of an SQLITE_SCHEMA error within the rtree module xConnect
+# callback.
+#
+
+
+if {![info exists testdir]} {
+ set testdir [file join [file dirname [info script]] .. .. test]
+}
+source $testdir/tester.tcl
+set testprefix rtreeconnect
+
+ifcapable !rtree {
+ finish_test
+ return
+}
+
+do_execsql_test 1.0 {
+ CREATE VIRTUAL TABLE r1 USING rtree(id, x1, x2, y1, y2);
+ CREATE TABLE t1(id, x1, x2, y1, y2);
+ CREATE TABLE log(l);
+
+ CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
+ INSERT INTO r1 VALUES(new.id, new.x1, new.x2, new.y1, new.y2);
+ INSERT INTO log VALUES('r1: ' || new.id);
+ END;
+}
+
+db close
+sqlite3 db test.db
+sqlite3 db2 test.db
+
+do_test 1.1 {
+ db eval { INSERT INTO log VALUES('startup'); }
+ db2 eval { CREATE TABLE newtable(x,y); }
+} {}
+
+do_execsql_test 1.2 {
+ INSERT INTO t1 VALUES(1, 2, 3, 4, 5);
+}
+
+db2 close
+db close
+
+finish_test
diff --git a/chromium/third_party/sqlite/src/ext/session/sqlite3session.h b/chromium/third_party/sqlite/src/ext/session/sqlite3session.h
index 0bb362e2401..b3df6d7b887 100644
--- a/chromium/third_party/sqlite/src/ext/session/sqlite3session.h
+++ b/chromium/third_party/sqlite/src/ext/session/sqlite3session.h
@@ -375,8 +375,8 @@ int sqlite3session_diff(
*/
int sqlite3session_patchset(
sqlite3_session *pSession, /* Session object */
- int *pnPatchset, /* OUT: Size of buffer at *ppChangeset */
- void **ppPatchset /* OUT: Buffer containing changeset */
+ int *pnPatchset, /* OUT: Size of buffer at *ppPatchset */
+ void **ppPatchset /* OUT: Buffer containing patchset */
);
/*
@@ -1143,12 +1143,12 @@ int sqlite3changeset_apply(
**
** <table border=1 style="margin-left:8ex;margin-right:8ex">
** <tr><th>Streaming function<th>Non-streaming equivalent</th>
-** <tr><td>sqlite3changeset_apply_str<td>[sqlite3changeset_apply]
-** <tr><td>sqlite3changeset_concat_str<td>[sqlite3changeset_concat]
-** <tr><td>sqlite3changeset_invert_str<td>[sqlite3changeset_invert]
-** <tr><td>sqlite3changeset_start_str<td>[sqlite3changeset_start]
-** <tr><td>sqlite3session_changeset_str<td>[sqlite3session_changeset]
-** <tr><td>sqlite3session_patchset_str<td>[sqlite3session_patchset]
+** <tr><td>sqlite3changeset_apply_strm<td>[sqlite3changeset_apply]
+** <tr><td>sqlite3changeset_concat_strm<td>[sqlite3changeset_concat]
+** <tr><td>sqlite3changeset_invert_strm<td>[sqlite3changeset_invert]
+** <tr><td>sqlite3changeset_start_strm<td>[sqlite3changeset_start]
+** <tr><td>sqlite3session_changeset_strm<td>[sqlite3session_changeset]
+** <tr><td>sqlite3session_patchset_strm<td>[sqlite3session_patchset]
** </table>
**
** Non-streaming functions that accept changesets (or patchsets) as input
diff --git a/chromium/third_party/sqlite/src/main.mk b/chromium/third_party/sqlite/src/main.mk
index 908cf510c5b..5c34a8d9b53 100644
--- a/chromium/third_party/sqlite/src/main.mk
+++ b/chromium/third_party/sqlite/src/main.mk
@@ -55,7 +55,8 @@ THREADLIB += $(LIBS)
LIBOBJ+= vdbe.o parse.o \
alter.o analyze.o attach.o auth.o \
backup.o bitvec.o btmutex.o btree.o build.o \
- callback.o complete.o ctime.o date.o dbstat.o delete.o expr.o \
+ callback.o complete.o ctime.o \
+ date.o dbpage.o dbstat.o delete.o expr.o \
fault.o fkey.o \
fts3.o fts3_aux.o fts3_expr.o fts3_hash.o fts3_icu.o fts3_porter.o \
fts3_snippet.o fts3_tokenizer.o fts3_tokenizer1.o \
@@ -98,6 +99,7 @@ SRC = \
$(TOP)/src/complete.c \
$(TOP)/src/ctime.c \
$(TOP)/src/date.c \
+ $(TOP)/src/dbpage.c \
$(TOP)/src/dbstat.c \
$(TOP)/src/delete.c \
$(TOP)/src/expr.c \
@@ -148,7 +150,7 @@ SRC = \
$(TOP)/src/rowset.c \
$(TOP)/src/select.c \
$(TOP)/src/status.c \
- $(TOP)/src/shell.c \
+ $(TOP)/src/shell.c.in \
$(TOP)/src/sqlite.h.in \
$(TOP)/src/sqlite3ext.h \
$(TOP)/src/sqliteInt.h \
@@ -272,6 +274,7 @@ SRC += \
opcodes.h \
parse.c \
parse.h \
+ shell.c \
sqlite3.h
@@ -307,6 +310,7 @@ TESTSRC = \
$(TOP)/src/test_intarray.c \
$(TOP)/src/test_journal.c \
$(TOP)/src/test_malloc.c \
+ $(TOP)/src/test_md5.c \
$(TOP)/src/test_multiplex.c \
$(TOP)/src/test_mutex.c \
$(TOP)/src/test_onefile.c \
@@ -319,6 +323,7 @@ TESTSRC = \
$(TOP)/src/test_sqllog.c \
$(TOP)/src/test_superlock.c \
$(TOP)/src/test_syscall.c \
+ $(TOP)/src/test_tclsh.c \
$(TOP)/src/test_tclvar.c \
$(TOP)/src/test_thread.c \
$(TOP)/src/test_vfs.c \
@@ -336,6 +341,7 @@ TESTSRC += \
$(TOP)/ext/misc/fileio.c \
$(TOP)/ext/misc/fuzzer.c \
$(TOP)/ext/misc/ieee754.c \
+ $(TOP)/ext/misc/mmapwarm.c \
$(TOP)/ext/misc/nextchar.c \
$(TOP)/ext/misc/percentile.c \
$(TOP)/ext/misc/regexp.c \
@@ -360,6 +366,7 @@ TESTSRC2 = \
$(TOP)/src/btree.c \
$(TOP)/src/build.c \
$(TOP)/src/date.c \
+ $(TOP)/src/dbpage.c \
$(TOP)/src/dbstat.c \
$(TOP)/src/expr.c \
$(TOP)/src/func.c \
@@ -483,6 +490,8 @@ SHELL_OPT += -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS5
SHELL_OPT += -DSQLITE_ENABLE_EXPLAIN_COMMENTS
SHELL_OPT += -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
SHELL_OPT += -DSQLITE_ENABLE_STMTVTAB
+SHELL_OPT += -DSQLITE_ENABLE_DBPAGE_VTAB
+SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5
FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000
@@ -499,9 +508,9 @@ libsqlite3.a: $(LIBOBJ)
$(AR) libsqlite3.a $(LIBOBJ)
$(RANLIB) libsqlite3.a
-sqlite3$(EXE): $(TOP)/src/shell.c libsqlite3.a sqlite3.h
+sqlite3$(EXE): shell.c libsqlite3.a sqlite3.h
$(TCCX) $(READLINE_FLAGS) -o sqlite3$(EXE) $(SHELL_OPT) \
- $(TOP)/src/shell.c $(SHELL_ICU) 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 \
@@ -610,6 +619,11 @@ lemon: $(TOP)/tool/lemon.c $(TOP)/tool/lempar.c
$(BCC) -o lemon $(TOP)/tool/lemon.c
cp $(TOP)/tool/lempar.c .
+# A tool to generate the source-id
+#
+mksourceid: $(TOP)/tool/mksourceid.c
+ $(BCC) -o mksourceid $(TOP)/tool/mksourceid.c
+
# Rules to build individual *.o files from generated *.c files. This
# applies to:
#
@@ -649,13 +663,23 @@ parse.c: $(TOP)/src/parse.y lemon $(TOP)/tool/addopcodes.tcl
mv parse.h parse.h.temp
tclsh $(TOP)/tool/addopcodes.tcl parse.h.temp >parse.h
-sqlite3.h: $(TOP)/src/sqlite.h.in $(TOP)/manifest.uuid $(TOP)/VERSION $(TOP)/ext/rtree/sqlite3rtree.h
+sqlite3.h: $(TOP)/src/sqlite.h.in $(TOP)/manifest mksourceid $(TOP)/VERSION $(TOP)/ext/rtree/sqlite3rtree.h
tclsh $(TOP)/tool/mksqlite3h.tcl $(TOP) >sqlite3.h
keywordhash.h: $(TOP)/tool/mkkeywordhash.c
$(BCC) -o mkkeywordhash $(OPTS) $(TOP)/tool/mkkeywordhash.c
./mkkeywordhash >keywordhash.h
+# Source files that go into making shell.c
+SHELL_SRC = \
+ $(TOP)/src/shell.c.in \
+ $(TOP)/ext/misc/shathree.c \
+ $(TOP)/ext/misc/fileio.c \
+ $(TOP)/ext/misc/completion.c
+
+shell.c: $(SHELL_SRC) $(TOP)/tool/mkshellc.tcl
+ tclsh $(TOP)/tool/mkshellc.tcl >shell.c
+
# Rules to build the extension objects.
@@ -757,17 +781,11 @@ sqlite3rbu.o: $(TOP)/ext/rbu/sqlite3rbu.c $(HDR) $(EXTHDR)
# Rules for building test programs and for running tests
#
tclsqlite3: $(TOP)/src/tclsqlite.c libsqlite3.a
- $(TCCX) $(TCL_FLAGS) -DTCLSH=1 -o tclsqlite3 \
+ $(TCCX) $(TCL_FLAGS) -DTCLSH -o tclsqlite3 \
$(TOP)/src/tclsqlite.c libsqlite3.a $(LIBTCL) $(THREADLIB)
-sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl
- echo "#define TCLSH 2" > $@
- echo "#define SQLITE_ENABLE_DBSTAT_VTAB 1" >> $@
- cat sqlite3.c $(TOP)/src/tclsqlite.c >> $@
- echo "static const char *tclsh_main_loop(void){" >> $@
- echo "static const char *zMainloop = " >> $@
- tclsh $(TOP)/tool/tostr.tcl $(TOP)/tool/spaceanal.tcl >> $@
- echo "; return zMainloop; }" >> $@
+sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl $(TOP)/tool/sqlite3_analyzer.c.in $(TOP)/tool/mkccode.tcl
+ tclsh $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in >sqlite3_analyzer.c
sqlite3_analyzer$(EXE): sqlite3_analyzer.c
$(TCCX) $(TCL_FLAGS) sqlite3_analyzer.c -o $@ $(LIBTCL) $(TLIBS) $(THREADLIB)
@@ -783,22 +801,24 @@ TESTFIXTURE_FLAGS += -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE
TESTFIXTURE_FLAGS += -DSQLITE_SERIES_CONSTRAINT_VERIFY=1
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) -DTCLSH=1 $(TESTFIXTURE_FLAGS) \
+ $(TCCX) $(TCL_FLAGS) $(TESTFIXTURE_FLAGS) \
$(TESTSRC) $(TESTSRC2) $(TOP)/src/tclsqlite.c \
-o testfixture$(EXE) $(LIBTCL) libsqlite3.a $(THREADLIB)
amalgamation-testfixture$(EXE): sqlite3.c $(TESTSRC) $(TOP)/src/tclsqlite.c \
$(TOP)/ext/session/test_session.c
- $(TCCX) $(TCL_FLAGS) -DTCLSH=1 $(TESTFIXTURE_FLAGS) \
+ $(TCCX) $(TCL_FLAGS) $(TESTFIXTURE_FLAGS) \
$(TESTSRC) $(TOP)/src/tclsqlite.c sqlite3.c \
$(TOP)/ext/session/test_session.c \
-o testfixture$(EXE) $(LIBTCL) $(THREADLIB)
fts3-testfixture$(EXE): sqlite3.c fts3amal.c $(TESTSRC) $(TOP)/src/tclsqlite.c
- $(TCCX) $(TCL_FLAGS) -DTCLSH=1 $(TESTFIXTURE_FLAGS) \
+ $(TCCX) $(TCL_FLAGS) $(TESTFIXTURE_FLAGS) \
-DSQLITE_ENABLE_FTS3=1 \
$(TESTSRC) $(TOP)/src/tclsqlite.c sqlite3.c fts3amal.c \
-o testfixture$(EXE) $(LIBTCL) $(THREADLIB)
diff --git a/chromium/third_party/sqlite/src/manifest b/chromium/third_party/sqlite/src/manifest
index 7f1ee7d4152..66502bfeeb2 100644
--- a/chromium/third_party/sqlite/src/manifest
+++ b/chromium/third_party/sqlite/src/manifest
@@ -1,17 +1,17 @@
-C Version\s3.20.1
-D 2017-08-24T16:21:36.477
-F Makefile.in d9873c9925917cca9990ee24be17eb9613a668012c85a343aef7e5536ae266e8
+C Version\s3.21.0
+D 2017-10-24T18:55:49.833
+F Makefile.in e016061b23e60ac9ec27c65cb577292b6bde0307ca55abd874ab3487b3b1beb2
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
-F Makefile.msc 02b469e9dcd5b7ee63fc1fb05babc174260ee4cfa4e0ef2e48c3c6801567a016
+F Makefile.msc 37740aba9c4bb359c627eadccf1cfd7be4f5f847078723777ea7763969e533b1
F README.md f5c87359573c4d255425e588a56554b50fdcc2afba4e017a2e02a43701456afd
-F VERSION 2fd9e47664e2bdb2b12a5fcced76c6768d35cd2730c4d8d5948638d6e1697176
+F VERSION f81232df28e2d3ff049feefad5fbd5489cc33697f6bd2ecf61af7f0dde3b83d0
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
-F autoconf/Makefile.am 1a47d071e3d5435f8f7ebff7eb6703848bbd65d4
-F autoconf/Makefile.msc b77aec100e4fb4739748a2461b5aa82c179fcde35bc0e08ce52ae7322d218701
+F autoconf/Makefile.am 66c0befa511f0d95ba229e180067cf0357a9ebf8b3201b06d683c5ba6220fb39
+F autoconf/Makefile.msc 645b8a9774281515dc4a8de65d8a914f7b418ba8bd1c48b53ccbf43d3b339715
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1
F autoconf/configure.ac 2893b823ecc86cea13739f6c8109a41392254d1db08235c5615e0af5722c8578
@@ -30,10 +30,10 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
-F configure 2158ca3525085497feff8aa56386ee451bb0ebe49ef5d5fde3ac00e255fbc808 x
-F configure.ac 13f45f02e6c51dd0e347315b5401c3f047712b7f79b7f35619115c23755afcff
+F configure e9dbb65b61c36bb9622225de254b768d4816749ff4cb4d71307bb067095aceec x
+F configure.ac 369ebae6c04d9d2de5064e21d300f2f42f2fbf13235cabff9d1a54f2b2c4d05d
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
-F doc/lemon.html 1f8b8d4c9f5cfe40e679fee279cc9eb2da8e6eb74ad406028538d7864cc4b6cb
+F doc/lemon.html 278113807f49d12d04179a93fab92b5b917a08771152ca7949d34e928efa3941
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
F doc/vfs-shm.txt e101f27ea02a8387ce46a05be2b1a902a021d37a
F ext/README.md fd5f78013b0a2bc6f0067afb19e6ad040e89a10179b4f6f03eee58fac5f169bd
@@ -114,7 +114,7 @@ F ext/fts5/fts5_test_tok.c ffd657dd67e7fcdb31bf63fb60b6d867299a581d0f46e97086aba
F ext/fts5/fts5_tokenize.c 2ce7b44183538ec46b7907726262ee43ffdd39a8
F ext/fts5/fts5_unicode2.c b450b209b157d598f7b9df9f837afb75a14c24bf
F ext/fts5/fts5_varint.c a5aceacda04dafcbae725413d7a16818ecd65738
-F ext/fts5/fts5_vocab.c e44fefa7f0c1db252998af071daf06a7147e17e7
+F ext/fts5/fts5_vocab.c 1cd79854cb21543e66507b25b0578bc1b20aa6a1349b7feceb8e8fed0e7a77a6
F ext/fts5/fts5parse.y a070b538e08ae9e2177d15c337ed2a3464408f0f886e746307098f746efd94ca
F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
F ext/fts5/test/fts5_common.tcl b01c584144b5064f30e6c648145a2dd6bc440841
@@ -140,6 +140,7 @@ 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/fts5content.test 688d5ac7af194ebc67495daea76a69e3cd5480122c2320e72d41241b423b4116
F ext/fts5/test/fts5corrupt.test 8957f0f7e57e0f8a102c5b6e1a7326d6a1966b28e1d99c5883822af1e6038e9e
F ext/fts5/test/fts5corrupt2.test 6deaf9f9606b3c957529db9881622bb3a7829b19bb3cdf8f276f074d684ede56
@@ -201,13 +202,14 @@ F ext/fts5/test/fts5unindexed.test 9021af86a0fb9fc616f7a69a996db0116e7936d0db638
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/tool/fts5speed.tcl b0056f91a55b2d1a3684ec05729de92b042e2f85
F ext/fts5/tool/fts5txt2db.tcl 526a9979c963f1c54fd50976a05a502e533a4c59
F ext/fts5/tool/loadfts5.tcl 95b03429ee6b138645703c6ca192c3ac96eaf093
F ext/fts5/tool/mkfts5c.tcl d1c2a9ab8e0ec690a52316f33dd9b1d379942f45
F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c
F ext/icu/README.txt d9fbbad0c2f647c3fdf715fc9fd64af53aedfc43
-F ext/icu/icu.c 84900472a088a3a172c6c079f58a1d3a1952c332
+F ext/icu/icu.c 635775226d07c743c770888a9dd5175afc6e67d3e28a4032b7fedc3bcaa92e65
F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37
F ext/lsm1/Makefile 2951812df1c1cbc9e023af7e070876f479b3d75ce3898b3b9d00f83fecf13608
F ext/lsm1/Makefile.msc f8c878b467232226de288da320e1ac71c131f5ec91e08b21f502303347260013
@@ -243,16 +245,16 @@ F ext/lsm1/lsm_log.c a8bf334532109bba05b09a504ee45fc393828b0d034ca61ab45e3940709
F ext/lsm1/lsm_main.c 15e73ccdafdd44ddeefc29e332079d88ba8f00c12c797b3c2b63d3171b5afce8
F ext/lsm1/lsm_mem.c 4c51ea9fa285ee6e35301b33491642d071740a0a
F ext/lsm1/lsm_mutex.c 378edf0a2b142b4f7640ee982df06d50b98788ea
-F ext/lsm1/lsm_shared.c 5bc37768e558492f60d7196735ddd54843cd239bd66c1af6eb205a6348ca5e46
+F ext/lsm1/lsm_shared.c 1a76b7a5e89a003c24d58f1fb295c4203b48ef6acba9a194ac6003ade09fcd47
F ext/lsm1/lsm_sorted.c a04518dfbfff0171fafb152a46e9fe9f45e1edbf3570e4533dd58ddb6567f0c9
F ext/lsm1/lsm_str.c 65e361b488c87b10bf3e5c0070b14ffc602cf84f094880bece77bbf6678bca82
F ext/lsm1/lsm_tree.c 682679d7ef2b8b6f2fe77aeb532c8d29695bca671c220b0abac77069de5fb9fb
F ext/lsm1/lsm_unix.c 57361bcf5b1a1a028f5d66571ee490e9064d2cfb145a2cc9e5ddade467bb551b
F ext/lsm1/lsm_varint.c 43f954af668a66c7928b81597c14d6ad4be9fedbc276bbd80f52fa28a02fdb62
-F ext/lsm1/lsm_vtab.c d5af32abe32601b3f2618b9488225db9ca06af803ddee1aaaf1653e08e9d112b
+F ext/lsm1/lsm_vtab.c 529255dc704289001b225d97e57e0cfa14b29c3f281c7349cfa8fdb655de79ae
F ext/lsm1/lsm_win32.c 0a4acbd7e8d136dd3a5753f0a9e7a9802263a9d96cef3278cf120bcaa724db7c
F ext/lsm1/test/lsm1_common.tcl 5ed4bab07c93be2e4f300ebe46007ecf4b3e20bc5fbe1dedaf04a8774a6d8d82
-F ext/lsm1/test/lsm1_simple.test 3bb38951450cd1f12a6c294949334d6fbb109a3da38c48eaf0877a37c43a0fab
+F ext/lsm1/test/lsm1_simple.test ca949efefa102f4644231dcd9291d8cda7699a4ce1006b26e0e3fcb72233f422
F ext/misc/README.md 8e008c8d2b02e09096b31dfba033253ac27c6c06a18aa5826e299fa7601d90b2
F ext/misc/amatch.c 6db4607cb17c54b853a2d7c7c36046d004853f65b9b733e6f019d543d5dfae87
F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb
@@ -260,7 +262,7 @@ F ext/misc/carray.c ed96c218ea940b85c9a274c4d9c59fe9491c299147a38a8bba537687bd6c
F ext/misc/closure.c 0d2a038df8fbae7f19de42e7c7d71f2e4dc88704
F ext/misc/completion.c 52c3f01523e3e387eb321b4739a89d1fe47cbe6025aa1f2d8d3685e9e365df0f
F ext/misc/compress.c 122faa92d25033d6c3f07c39231de074ab3d2e83
-F ext/misc/csv.c d91c0388445b08f6e373dd0e8fc024d4551b1fcaf64e876a1c3f4fac8a63adc2
+F ext/misc/csv.c 1a009b93650732e22334edc92459c4630b9fa703397cbb3c8ca279921a36ca11
F ext/misc/dbdump.c 3509fa6b8932d04e932d6b6b827b6a82ca362781b8e8f3c77336f416793e215e
F ext/misc/eval.c f971962e92ebb8b0a4e6b62949463ee454d88fa2
F ext/misc/fileio.c b1aa06c0f1dac277695d4529e5e976c65ab5678dcbb53a0304deaa8adc44b332
@@ -268,27 +270,29 @@ F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25
F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c
F ext/misc/json1.c dbe086615b9546c156bf32b9378fc09383b58bd17513b866cfd24c1e15281984
F ext/misc/memvfs.c e5225bc22e79dde6b28380f3a068ddf600683a33
+F ext/misc/mmapwarm.c 70b618f2d0bde43fae288ad0b7498a629f2b6f61b50a27e06fae3cd23c83af29
F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
F ext/misc/percentile.c 92699c8cd7d517ff610e6037e56506f8904dae2e
F ext/misc/regexp.c a68d25c659bd2d893cd1215667bbf75ecb9dc7d4
F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a
F ext/misc/scrub.c 1c5bfb8b0cd18b602fcb55755e84abf0023ac2fb
-F ext/misc/series.c b0f5f346aca9b7ff7caaf0da2efb4ad462441abd4dcd92a460cb573b3ea2370b
+F ext/misc/series.c f3c0dba5c5c749ce1782b53076108f87cf0b71041eb6023f727a9c50681da564
F ext/misc/sha1.c 0b9e9b855354910d3ca467bf39099d570e73db56
F ext/misc/shathree.c fa185d7aee0ad0aca5e091b4a2db7baff11796170e5793b5de99e511a13af448
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
F ext/misc/spellfix.c a4723b6aff748a417b5091b68a46443265c40f0d
F ext/misc/stmt.c 6f16443abb3551e3f5813bb13ba19a30e7032830015b0f92fe0c0453045c0a11
F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
-F ext/misc/unionvtab.c 56fd163d2b6d2f4df0078be482fc9a874658ce51cce33f180c08834193449c78
+F ext/misc/unionvtab.c 1e0ebc5078e1a916db191bcd88f87e94ea7ba4aa563ee30ff706261cb4b39461
F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95
F ext/misc/vfsstat.c bf10ef0bc51e1ad6756629e1edb142f7a8db1178
+F ext/misc/vtablog.c 31d0d8f4406795679dcd3a67917c213d3a2a5fb3ea5de35f6e773491ed7e13c9
F ext/misc/vtshim.c 1976e6dd68dd0d64508c91a6dfab8e75f8aaf6cd
F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212
F ext/rbu/rbu.c ea7d1b7eb44c123a2a619332e19fe5313500705c4a58aaa1887905c0d83ffc2e
F ext/rbu/rbu1.test 43836fac8c7179a358eaf38a8a1ef3d6e6285842
-F ext/rbu/rbu10.test 046b0980041d30700464a800bbf6733ed2df515d
+F ext/rbu/rbu10.test 1846519a438697f45e9dcb246908af81b551c29e1078d0304fae83f1fed7e9ee
F ext/rbu/rbu11.test 9bc68c2d3dbeb1720153626e3bd0466dcc017702
F ext/rbu/rbu12.test bde22ed0004dd5d1888c72a84ae407e574aeae16
F ext/rbu/rbu13.test 462ff799c4afedc3ef8a47ff818c0ffbf14ae4f2
@@ -307,21 +311,24 @@ F ext/rbu/rbucrash.test 61470d977a06a0abc2ec35b05d82a1d7d87d10f4ffabad14c1c231ed
F ext/rbu/rbucrash2.test b2ecbdd7bb72c88bd217c65bd00dafa07f7f2d4d
F ext/rbu/rbudiff.test 3e605cf624d00d04d0fb1316a3acec4fbe3b3ac5
F ext/rbu/rbudor.test 99b05cc0df613e962c2c8085cfb05686a09cf315
-F ext/rbu/rbufault.test cc0be8d5d392d98b0c2d6a51be377ea989250a89
+F ext/rbu/rbufault.test 2654aef20f8ee7de37c9c1997a44f2773dc7bf24887adea39fb19314ef32cb90
F ext/rbu/rbufault2.test 9a7f19edd6ea35c4c9f807d8a3db0a03a5670c06
-F ext/rbu/rbufault3.test 54a399888ac4af44c68f9f58afbed23149428bca
+F ext/rbu/rbufault3.test 0913c1aeaee266d9c36c33179341a5a504aad7d423d1979cfec43c8346a29899
F ext/rbu/rbufault4.test 34e70701cbec51571ffbd9fbf9d4e0f2ec495ca7
-F ext/rbu/rbufts.test 828cd689da825f0a7b7c53ffc1f6f7fdb6fa5bda
+F ext/rbu/rbufts.test a2bbd202c9321fba15fb4a62a90add7d70e07bd8404e1e598135adbfff8a0508
F ext/rbu/rbuprogress.test 1849d4e0e50616edf5ce75ce7db86622e656b5cf
F ext/rbu/rburesume.test 8acb77f4a422ff55acfcfc9cc15a5cb210b1de83
F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48
+F ext/rbu/rbutemplimit.test cd553a9288d515d0b5f87d277e76fd18c4aa740b761e7880fab11ce986ea18d1
F ext/rbu/rbuvacuum.test ff357e9b556ca7ad4673da0ff7f244def919ff858e0f9f350d3e30fdd83a62a8
F ext/rbu/rbuvacuum2.test 2074ab14fe66e1c7e7210c62562650dcd215bbaa
-F ext/rbu/sqlite3rbu.c d1438580a451eebda3bfd42ef69b677512f00125285e0e4e789b6131a45f6dd8
-F ext/rbu/sqlite3rbu.h fc25e1fcd99b5c6d32b1b5b1c73122632e873ac89bd0be9bf646db362b7ce02c
-F ext/rbu/test_rbu.c ec18cfc69a104309df23c359e3c80306c9a6bdd1d2c53c8b70ae158e9832dcd6
+F ext/rbu/sqlite3rbu.c 64bd08c1011456f90564ed167abce3a9c2af421a924b21eb57231e078da04feb
+F ext/rbu/sqlite3rbu.h b42bcd4d8357268c6c39ab2a60b29c091e89328fa8cc49c8fac5ab8d007e79b2
+F ext/rbu/test_rbu.c 7073979b9cc80912bb03599ac8d85ab5d3bf03cfacd3463f2dcdd7822997533a
+F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
+F ext/repair/checkfreelist.c 0abb84b4545016d57ba1a2aa8884c72c73ed838968909858c03bc1f38fb6b054
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
-F ext/rtree/rtree.c 4f1804b80ae06ddf7ff69192aacdceee283646dc6a328acb951f116147445212
+F ext/rtree/rtree.c f2fd34db37ea053798f8e66b44a473449b21301d2b92505ee576823789e909fb
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
F ext/rtree/rtree1.test 4fdd60ae034e43f2fefc26492032d02e742e8b14d468b7c51d95a1e2fa47cf00
F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba
@@ -332,7 +339,7 @@ F ext/rtree/rtree6.test 773a90db2dce6a8353dd0d5b64bca69b29761196
F ext/rtree/rtree7.test 1fa710b9e6bf997a0c1a537b81be7bb6fded1971
F ext/rtree/rtree8.test 076d9d5b783b61b7a23a5ab45fc899551dfffd821974f36ee599ff29f4de7a61
F ext/rtree/rtree9.test 8bfa84dfaba1c897468a2448c28db0a00ad12d464225b5993c7814e907f3776f
-F ext/rtree/rtreeA.test e25d76c1701f8591e7a0b6de8224d5dbc1418c562654c7240e6f33f37b1e36f7
+F ext/rtree/rtreeA.test c09ad3f76c08feac00770685ff50ca12966dc0c641bf19a982b26a80643b46d1
F ext/rtree/rtreeB.test c85f9ce78766c4e68b8b89fbf2979ee9cfa82b4e
F ext/rtree/rtreeC.test c0a9c67f2efa98b6fae12acb8a28348d231a481d
F ext/rtree/rtreeD.test fe46aa7f012e137bd58294409b16c0d43976c3bb92c8f710481e577c4a1100dc
@@ -341,6 +348,7 @@ F ext/rtree/rtreeF.test 66deb9fd1611c7ca2e374adba63debdc2dbb12b4
F ext/rtree/rtreeG.test 3b185719630795f38594f64cd7d1de86a33f91f1
F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195
F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea
+F ext/rtree/rtreeconnect.test 225ad3fcb483d36cbee423a25052a6bbae762c9576ae9268332360c68c170d3d
F ext/rtree/sqlite3rtree.h 9c5777af3d2921c7b4ae4954e8e5697502289d28
F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
@@ -368,7 +376,7 @@ F ext/session/sessionfault.test da273f2712b6411e85e71465a1733b8501dbf6f7
F ext/session/sessionfault2.test 04aa0bc9aa70ea43d8de82c4f648db4de1e990b0
F ext/session/sessionwor.test 2f3744236dc8b170a695b7d8ddc8c743c7e79fdc
F ext/session/sqlite3session.c cc127222a9ea6f4eaa31281aa9da924f5244f6099be0ee526c950684fb3513a6
-F ext/session/sqlite3session.h d4db650adfcc7a4360e9f12a09c2d117b1db6b53
+F ext/session/sqlite3session.h cb4d860101ba6d3ac810f18684539b766d24d668fa2436cdde90d711af9464fb
F ext/session/test_session.c eb0bd6c1ea791c1d66ee4ef94c16500dad936386
F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
@@ -376,7 +384,7 @@ F ext/userauth/userauth.c 3410be31283abba70255d71fd24734e017a4497f
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
-F main.mk 5b7d72ab03dd70aa1401f934d31e85aefd6fc542eb58094d7a95d6921390b2d0
+F main.mk a39528d993afc1f0c0aebde2e3623ab4171d3bba484eea1e5241615c706c9ce8
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -388,43 +396,44 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
-F src/alter.c 850ede4e607f12fa25ea4f3cb6ece2b2e29d1aa50e3f786ce49d615788849552
+F src/alter.c cf7a8af45cb0ace672f47a1b29ab24092a9e8cd8d945a9974e3b5d925f548594
F src/analyze.c 0d0ccf7520a201d8747ea2f02c92c26e26f801bc161f714f27b9f7630dde0421
-F src/attach.c 3bd555e28382603e80d430dfebb2270f86e1e375b4c4be3e1ab1aec3a0c44943
-F src/auth.c 79f96c6f33bf0e5da8d1c282cee5ebb1852bb8a6ccca3e485d7c459b035d9c3c
+F src/attach.c 07b706e336fd3cedbd855e1f8266d10e82fecae07daf86717b5760cd7784c584
+F src/auth.c 6277d63837357549fe14e723490d6dc1a38768d71c795c5eb5c0f8a99f918f73
F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
F src/btmutex.c 0e9ce2d56159b89b9bc8e197e023ee11e39ff8ca
-F src/btree.c f55ea8f456d103328d61076be40fa39acbfea05eaa4eccfed275532a63c867c4
-F src/btree.h 3edc5329bc59534d2d15b4f069a9f54b779a7e51289e98fa481ae3c0e526a5ca
-F src/btreeInt.h 97700795edf8a43245720414798b7b29d8e465aef46bf301ffacd431910c0da1
-F src/build.c c3837ad57cea1351cd824a646836d2bb678f264ae160d691b632d495c8be2f5b
-F src/callback.c 8e14b60d1ed1c87c02cb5f121ecda99224f2aea6524a77ee6f72c9b5c7110f84
+F src/btree.c 75229a5a47985997f861b428552acd14fe42b657f755cba5e0b1a007bd77b2ea
+F src/btree.h 32ef5d3f25dc70ef1ee9cecf84a023c21378f06a57cd701d2e866e141b150f09
+F src/btreeInt.h 55b702efce17e5d1941865464227d3802cfc9c7c832fac81d4c94dced47a71fc
+F src/build.c e24b61144f9c9b15c4aa05954514190361061da721e56dcd1af6e0e945ee5909
+F src/callback.c 28a8ede982fde4129b828350f78f2c01fe7d12c74d1a0a05d7108ab36f308688
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
-F src/ctime.c 928954802b1397d9fb1378c7eb702c94b4735bbab1d5793e21b6a77734f56a1b
+F src/ctime.c ff1be3eed7bdd75aaca61ca8dc848f7c9f850ef2fb9cb56f2734e922a098f9c0
F src/date.c 48f743d88bbe88f848532d333cca84f26e52a4f217e86f86be7fc1b919c33d74
+F src/dbpage.c c625a0bd605d4cea9a3258b8db49a5474a04976e95a9fe380cdaf74e8eb6736d
F src/dbstat.c 7a4ba8518b6369ef3600c49cf9c918ad979acba610b2aebef1b656d649b96720
-F src/delete.c 939bd15e6b54b82b951e1c0ffc2ff2b4ab579196780a1f6d394e47bd6f799b6c
-F src/expr.c fdb2fc465cabbf372fecad1fc2b291758bec74150b4db0fb945332e09df28a0e
+F src/delete.c 21a5f1812fdb599e9f7afb9f650bdabab60a3afd51d7e94e539c982f647b0023
+F src/expr.c 755caeafc43e3cd31e1d810795712641f6e19f7e7e9575faece4c77381fd8304
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 5ff2c895fe087756d8085dc1a9bc229b5670e2a65c3929dd87c71e43649af333
-F src/func.c e2854b19386b93ad6b498a3f3b7d6baa98ec14cfe84530fb12fce4414263d871
-F src/global.c 8a6ab6b4d91effb96ffa81b39f0d70c862abca157f8aaa194600a4a8b7923344
+F src/func.c b4d259af627e3cd9510cf08db37f0bcc88b1887c735169c74490c3739d5cf5c6
+F src/global.c ac3094f1dc59fbeb919aef7cc0cc827a8459d1fb1adb7972ef75bd9e0c10b75b
F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a
F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4
F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
-F src/insert.c 487d2c1cd8d549f8d9492377ecc4d2f507b1bd5185e96c54389f6b607dce854c
+F src/insert.c 1f33ef4ca0553b60fff03aa171370f8709a3e945acfcc68ccafc92752d872f40
F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e
F src/loadext.c 20865b183bb8a3723d59cf1efffc3c50217eb452c1021d077b908c94da26b0b2
-F src/main.c 3a9da9e3974d8a32ef6ca15b75503d540af22d284beb75bc7f0d93254ca3f8f7
-F src/malloc.c e20bb2b48abec52d3faf01cce12e8b4f95973755fafec98d45162dfdab111978
+F src/main.c 54637b9e7f91de6d281e577cd1a997762a4613f51a0509790027ca9865185d7c
+F src/malloc.c a02c9e69bc76bee0f639416b947a946412890b606301454727feadcb313536d6
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a
F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944
-F src/memjournal.c 95752936c11dc6995672d1dd783cd633eea0cc95
+F src/memjournal.c 6f3d36a0a8f72f48f6c3c722f04301ac64f2515435fa42924293e46fc7994661
F src/msvc.h 4942752b6a253116baaa8de75256c51a459a5e81
F src/mutex.c 8e45800ee78e0cd1f1f3fe8e398853307f4a085c
F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85
@@ -432,65 +441,65 @@ F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4
F src/mutex_unix.c 27bb6cc49485ee46711a6580ab7b3f1402211d23
F src/mutex_w32.c a898fa969823b100c0f5fdc57e54c9a1e419ab4d
F src/notify.c 9711a7575036f0d3040ba61bc6e217f13a9888e7
-F src/os.c add02933b1dce7a39a005b00a2f5364b763e9a24
-F src/os.h 8e976e59eb4ca1c0fca6d35ee803e38951cb0343
+F src/os.c 22d31db3ca5a96a408fbf1ceeaaebcaf64c87024d2ff9fe1cf2ddbec3e75c104
+F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
-F src/os_unix.c 30e2c43e4955db990e5b5a81e901f8aa74cc8820
-F src/os_win.c 2a6c73eef01c51a048cc4ddccd57f981afbec18a
+F src/os_unix.c 3984fc069df59e26f000e30609611cecdb4e93293e6ee52313a473a7e874af1b
+F src/os_win.c 6892c3ff23b7886577e47f13d827ca220c0831bae3ce00eea8c258352692f8c6
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
-F src/pager.c 14f6982c470c05b8e85575c69e9c1712010602e20400f8670d8699e21283e0e4
-F src/pager.h f2a99646c5533ffe11afa43e9e0bea74054e4efa
-F src/parse.y e384cb73f99e1b074085c974b37f4d830e885359e4b60837e30f7d67c16ba65b
-F src/pcache.c 62835bed959e2914edd26afadfecce29ece0e870
-F src/pcache.h 521bb9610d38ef17a3cc9b5ddafd4546c2ea67fa3d0e464823d73c2a28d50e11
-F src/pcache1.c 1195a21fe28e223e024f900b2011e80df53793f0356a24caace4188b098540dc
-F src/pragma.c cd6aeda3587be6c5c08f9b2d45eae6068666a03c9d077c8c43cdb85fb0aa70f2
+F src/pager.c 07cf850241667874fcce9d7d924c814305e499b26c804322e2261247b5921903
+F src/pager.h 581698f2177e8bd4008fe4760898ce20b6133d1df22139b9101b5155f900df7a
+F src/parse.y 52ef3cecd0934e9da4a45b585883a03243ad615d338ad94f44501a05891dcdfa
+F src/pcache.c 4bada070456980c3c1f16d58ec2e64e389ad77b935e3d77e0c96e7bbd397289c
+F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170
+F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880
+F src/pragma.c d04725ac25387d9638919e197fb009f378e13af7bf899516979e54b3164e3602
F src/pragma.h bb83728944b42f6d409c77f5838a8edbdb0fe83046c5496ffc9602b40340a324
-F src/prepare.c dd250f904739b1dc449c131ac527c35e3424d94082dd111321bd83f80c6bb0fe
-F src/printf.c 8757834f1b54dae512fb25eb1acc8e94a0d15dd2290b58f2563f65973265adb2
+F src/prepare.c 9a141a1b02dca53beaa9771699d390aafcac01f5d1f1c0ae6e23ded8dcdb709a
+F src/printf.c 40aee47ae9be4bd3dbdc8968bd07fddc027be8edec8daddf24d3391d36698a1c
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
-F src/resolve.c 4324a94573b1e29286f8121e4881db59eaedc014afeb274c8d3e07ed282e0e20
+F src/resolve.c 5a461643f294ec510ca615b67256fc3861e4c8eff5f29e5940491e70553b1955
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
-F src/select.c 31b35ddf55f1021f7148a01306984b057c11ebb6e3463d94677225e0a1e301a3
-F src/shell.c bd6a37cbe8bf64ef6a6a74fdc50f067d3148149b4ce2b4d03154663e66ded55f
-F src/shell.c.in b5725acacba95ccefa57b6d068f710e29ba8239c3aa704628a1902a1f729c175
-F src/sqlite.h.in a7e29d5977916cded93ff6cf0d56ada657e13e91adbc2039e5cf02e41122a45f
+F src/select.c e6a068d9ea54417d625578086d3d482284af8d5a449bb3593d40c257080806a8
+F src/shell.c.in f13262c8778f0cd76bf8d9c01bbf5ef66842e6b14e1705cd60d86ab32a6ce69f
+F src/sqlite.h.in ab4f8a29d1580dfaeb6891fa1b83cff8229ba0daa56994707ceaca71495d9ab7
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
-F src/sqlite3ext.h 0f9f72b86a3792314f5db7a1dfbc2c82376bcd8d0919ceb80637bca126ec3c68
-F src/sqliteInt.h bd6be75bc43d38ada272ef0b3472bc44ef0cc15536bea22c349ca1a2812a19ce
+F src/sqlite3ext.h c02d628cca67f3889c689d82d25c3eb45e2c155db08e4c6089b5840d64687d34
+F src/sqliteInt.h 6f93fd6fde862410ac26b930f70752c38ad99ea78c3fc28356bac78049c53bd9
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
-F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1
+F src/status.c 9737ed017279a9e0c5da748701c3c7bf1e8ae0dae459aad20dd64fcff97a7e35
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
-F src/tclsqlite.c 2c29b0b76e91edfd1b43bf135c32c8674710089197327682b6b7e6af88062c3d
-F src/test1.c cfb78b728b37ae3a2b14fe1b3a6c766e0da41370eda112594e698c94011b622e
+F src/tclsqlite.c 1833388c01e3b77f4c712185ee7250b9423ee0981ce6ae7e401e47db0319a696
+F src/test1.c 8ef15f7a357f85dfc41c6c748ce9c947b4f676e01bb5ae6a45bee4923dff8b51
F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
F src/test3.c b8434949dfb8aff8dfa082c8b592109e77844c2135ed3c492113839b6956255b
F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6
F src/test5.c 328aae2c010c57a9829d255dc099d6899311672d
-F src/test6.c 004ad42f121f693b8cbe060d1a330678abc61620
+F src/test6.c e8d839fbc552ce044bec8234561a2d5b8819b48e29548ad0ba400471697946a8
F src/test7.c 5612e9aecf934d6df7bba6ce861fdf5ba5456010
-F src/test8.c 4f4904721167b32f7a4fa8c7b32a07a673d6cc86
+F src/test8.c 3f7d0cc4e12e06832ba3db4455cb16867ccadafa602eb6ff5fcf097bffce56ed
F src/test9.c 12e5ba554d2d1cbe0158f6ab3f7ffcd7a86ee4e5
F src/test_async.c 195ab49da082053fdb0f949c114b806a49ca770a
F src/test_autoext.c 915d245e736652a219a907909bb6710f0d587871
F src/test_backup.c bf5da90c9926df0a4b941f2d92825a01bbe090a0
-F src/test_bestindex.c d23f80d334c59662af69191854c76b8d3d0c8c96
+F src/test_bestindex.c 78809f11026f18a93fcfd798d9479cba37e1201c830260bf1edc674b2fa9b857
F src/test_blob.c ae4a0620b478548afb67963095a7417cd06a4ec0a56adb453542203bfdcb31ce
F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274
-F src/test_config.c abf6fc1fe9d041b699578c42e3db81f8831c4f5b804f1927958102ee8f2b773e
+F src/test_config.c 3000f00b9b47b149d842059904c3fcab5f3871fb6aee7d7cc5756f0c64779ae3
F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f
F src/test_demovfs.c a0c3bdd45ed044115c2c9f7779e56eafff18741e
-F src/test_devsym.c 4e58dec2602d8e139ca08659f62a62450587cb58
+F src/test_devsym.c 1960abbb234b97e9b920f07e99503fc04b443f62bbc3c6ff2c2cea2133e3b8a2
F src/test_fs.c 35a2f7dd8a915900873386331386d9ba1ae1b5026d74fd20c2807bc76221f291
-F src/test_func.c a4fdab3363b436c1b12660e9362ce3f3782b7b5e
+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_journal.c 619f2aa10e0d7a5f87c0f06825bc61dfce1c6b9c7f3ad990fb13de6c3b8874a3
F src/test_loadext.c 337056bae59f80b9eb00ba82088b39d0f4fe6dfd
-F src/test_malloc.c c05f6c40bd6c8bfe5f1718212f81fd5687f91766
+F src/test_malloc.c 4f06a805de86be5216a127b3777ca2d5a1ff99d1a9238374ce136a47411be36c
+F src/test_md5.c 7268e1e8c399d4a5e181b64ac20e1e6f3bc4dd9fc87abac02db145a3d951fa8c
F src/test_multiplex.c e054459f7633f3ff8ce1245da724f9a8be189e4e
F src/test_multiplex.h 5436d03f2d0501d04f3ed50a75819e190495b635
F src/test_mutex.c 7f4337ba23ee6b1d2ec81c189653608cb069926a
@@ -505,7 +514,8 @@ F src/test_server.c a2615049954cbb9cfb4a62e18e2f0616e4dc38fe
F src/test_sqllog.c 11e6ce7575f489155c604ac4b439f2ac1d3d5aef
F src/test_superlock.c 4839644b9201da822f181c5bc406c0b2385f672e
F src/test_syscall.c 1073306ba2e9bfc886771871a13d3de281ed3939
-F src/test_tclvar.c df9fe1213c2634687a9ca0b0bec0d2119d359ae3
+F src/test_tclsh.c 74fcfb7f3b0ff1f871e62263dd84ffba46a8e9d477439115e0fb2035e4bf69e1
+F src/test_tclvar.c 33ff42149494a39c5fbb0df3d25d6fafb2f668888e41c0688d07273dcb268dfc
F src/test_thread.c 911d15fb14e19c0c542bdc8aabf981c2f10a4858
F src/test_vfs.c f0186261a24de2671d080bcd8050732f0cb64f6e
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
@@ -515,29 +525,29 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c 1003d6d90c6783206c711f0a9397656fa5b055209f4d092caa43bb3bf5215db5
F src/treeview.c 2ee4a5dada213d5ab08a742af5c876cee6f1aaae65f10a61923f3fb63846afef
-F src/trigger.c d1cae560bfacc8bfb3a072d73658245c1714c0389097da69b4cb23877a082d7e
-F src/update.c c443935c652af9365e033f756550b5032d02e1b06eb2cb890ed7511ae0c051dc
+F src/trigger.c 48e0f7ed6749ce4d50a695e09e20ce9cf84ecabf2691852c965a51e0b620eccc
+F src/update.c 5404be9e840717323a69209190cdbc9d0d34adaedaaf1d1a1069babf2c4171c0
F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
-F src/util.c fc081ec6f63448dcd80d3dfad35baecfa104823254a815b081a4d9fe76e1db23
-F src/vacuum.c 874c0f2f15ab2908748297d587d22d485ea96d55aaec91d4775dddb2e24d2ecf
-F src/vdbe.c 1e541ec7ff409bbabcc6b4f154957296fff5827c16c2ab0056348acae75685bf
+F src/util.c 5168013cfd937a695d23cce8c67cb07a3dda242d4cb812530ba1148b88e0f159
+F src/vacuum.c 90839322fd5f00df9617eb21b68beda9b6e2a2937576b0d65985e4aeb1c53739
+F src/vdbe.c 3393b508d9ad084ffce232a7c53e375ef5ac99b50b685c5131fcdfce97a9d534
F src/vdbe.h d50cadf12bcf9fb99117ef392ce1ea283aa429270481426b6e8b0280c101fd97
-F src/vdbeInt.h ff2b7db0968d20e6184aee256d2e535d565f5a172e3588a78adb166a41fc4911
-F src/vdbeapi.c d362429ebb02df609a71a24abb295406b47252a3caa231d0bd0d715033b5d362
-F src/vdbeaux.c 3fe68bad02b33b09e08bdc0ad90d6b92b3d571f7864c3d047abca1bde050751c
-F src/vdbeblob.c 359891617358deefc85bef7bcf787fa6b77facb9
-F src/vdbemem.c 9ca2854976f35db40341977e688a08204c96427505f5b90215dc7970f6ea42c4
-F src/vdbesort.c f512c68d0bf7e0105316a5594c4329358c8ee9cae3b25138df041d97516c0372
-F src/vdbetrace.c 41963d5376f0349842b5fc4aaaaacd7d9cdc0834
-F src/vtab.c 35b9bdc2b41de32a417141d12097bcc4e29a77ed7cdb8f836d1d2305d946b61b
+F src/vdbeInt.h 1fe00770144c12c4913128f35262d11527ef3284561baaab59b947a41c08d0d9
+F src/vdbeapi.c 9c670ca0dcc1cd86373aa353b747b26fe531ca5cd4331690c611d1f03842e2a1
+F src/vdbeaux.c c423065d50cee24bc8cba57764f5e9869a1bb920c50907f5dd363ebd7c5aef82
+F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191
+F src/vdbemem.c 5c1533bf756918b4e46b2ed2bb82c29c7c651e1e37bbd0a0d8731a68787598ff
+F src/vdbesort.c 731a09e5cb9e96b70c394c1b7cf3860fbe84acca7682e178615eb941a3a0ef2f
+F src/vdbetrace.c 48e11ebe040c6b41d146abed2602e3d00d621d7ebe4eb29b0a0f1617fd3c2f6c
+F src/vtab.c 0e4885495172e1bdf54b12cce23b395ac74ef5729031f15e1bc1e3e6b360ed1a
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
-F src/wal.c 40c543f0a2195d1b0dc88ef12142bea690009344
-F src/wal.h 06b2a0b599cc0f53ea97f497cf8c6b758c999f71
-F src/walker.c a7ca64ce08a83a20d32186fbe06bca9234e348cfcf07959ee322fdc3e8a6173a
-F src/where.c cbe8ddffbcec7ce86f7a800fe8fd10aee412c76c87e0dd3732a1682e68d74cd9
-F src/whereInt.h 93bb90b77d39901eda31b44d8e90da1351193ccfe96876f89b58a93a33b84c3d
-F src/wherecode.c c0c4c31573486cd14bb2cbfc63e41eda591609e5190416261999f211bf97abc1
-F src/whereexpr.c bf983d2d33e325cd63a36c40b8de289fd3d7b4d9f2db9052fb8f59f7161a34a0
+F src/wal.c 839db09792fead5052bb35e533fa485e134913d547d05b5f42e537b73e63f07a
+F src/wal.h 8de5d2d3de0956d6f6cb48c83a4012d5f227b8fe940f3a349a4b7e85ebcb492a
+F src/walker.c 3ccfa8637f95355bff61144e01a615b8ef26f79c312880848da73f03367da1e6
+F src/where.c d8c6d690c4b11f30211de073011fe19352364a6303ae053f45cb66f9576ba8a9
+F src/whereInt.h 82c04c5075308abbac59180c8bad5ecb45b07453981f60a53f3c7dee21e1e971
+F src/wherecode.c e8c2ece5843ea56e6c90277d421f2d628f3f7b7c976642369cc519f008e1d2b1
+F src/whereexpr.c afcac9cccfc0fdaccbdda94034a398947b6dc47dbf821c1b496261722832a6a4
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
@@ -558,7 +568,7 @@ F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4
F test/analyze6.test f1c552ce39cca4ec922a7e4e0e5d0203d6b3281f
F test/analyze7.test bb1409afc9e8629e414387ef048b8e0e3e0bdc4f
F test/analyze8.test c05a461d0a6b05991106467d0c47480f2e709c82
-F test/analyze9.test b817b8e798315fc65b820a5463f73ad5f48ed8dd
+F test/analyze9.test dac0bdc7eab965b9ad639ca83564d98717aaf13ce5a776f23d9a3680238cecd8
F test/analyzeA.test 3335697f6700c7052295cfd0067fc5b2aacddf9a
F test/analyzeB.test a4c1c3048f6d9e090eb76e83eecb18bcf6d31a70
F test/analyzeC.test 555a6cc388b9818b6eda6df816f01ce0a75d3a93
@@ -572,8 +582,9 @@ F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7
F test/async4.test 1787e3952128aa10238bf39945126de7ca23685a
F test/async5.test 383ab533fdb9f7ad228cc99ee66e1acb34cc0dc0
F test/atof1.test ff0b0156fd705b67c506e1f2bfe9e26102bea9bd
+F test/atomic.test 065a453dde33c77ff586d91ccaa6ed419829d492dbb1a5694b8a09f3f9d7d061
F test/attach.test f4b8918ba2f3e88e6883b8452340545f10a1388af808343c37fc5c577be8281c
-F test/attach2.test 0ec5defa340363de6cd50fd595046465e9aaba2d
+F test/attach2.test 256bd240da1835fb8408dd59fb7ef71f8358c7a756c46662434d11d07ba3a0ce
F test/attach3.test c59d92791070c59272e00183b7353eeb94915976
F test/attach4.test 53bf502f17647c6d6c5add46dda6bac8b6f4665c
F test/attachmalloc.test 3a4bfca9545bfe906a8d2e622de10fbac5b711b0
@@ -604,9 +615,11 @@ F test/bestindex1.test 0cf1bd2d7b97d3a3a8c10736125274f64765c4ee
F test/bestindex2.test 4a06b8922ab2fd09434870da8d1cdf525aaf7060
F test/bestindex3.test 578b6a52dab819e63f28e3640e04b32c85aed320
F test/bestindex4.test 4cb5ff7dbaebadb87d366f51969271778423b455
+F test/bestindex5.test 412b42f8036b28d8b2f3534d89389ad946a4b1a65a12263f51936f7424296f1b
F test/between.test 34d375fb5ce1ae283ffe82b6b233e9f38e84fc6c
F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59
F test/bigfile2.test 1b489a3a39ae90c7f027b79110d6b4e1dbc71bfc
+F test/bigmmap.test abe819e6e1ac1db0c3bfe364ff58889d96e7896b2bbc8bdf1afc77cdeb7d7a9b
F test/bigrow.test f0aeb7573dcb8caaafea76454be3ade29b7fc747
F test/bigsort.test 8299fa9298f4f1e02fc7d2712e8b77d6cd60e5a2
F test/bind.test 1e136709b306f7ed3192d349c2930d89df6ab621654ad6f1a72381d3fe76f483
@@ -624,7 +637,7 @@ F test/boundary4.test 89e02fa66397b8a325d5eb102b5806f961f8ec4b
F test/btree01.test e08b3613540145b353f20c81cb18ead54ff12e0f
F test/btree02.test fe69453d474d8154d19b904157ff1db4812fed99
F test/btreefault.test c2bcb542685eea44621275cfedbd8a13f65201e3
-F test/busy.test 76b4887f8b9160ba903c1ac22e8ff406ad6ae2f0
+F test/busy.test 510dc6daaad18bcbbc085bcc6217d6dc418def5e73f72ce1475eea0cb7834727
F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de
F test/cacheflush.test af25bb1509df04c1da10e38d8f322d66eceedf61
F test/cachespill.test 895997f84a25b323b166aecb69baab2d6380ea98f9e0bcc688c4493c535cfab9
@@ -637,6 +650,7 @@ F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe
F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3
F test/cffault.test 9d6b20606afe712374952eec4f8fd74b1a8097ef
F test/check.test 33a698e8c63613449d85d624a38ef669bf20331daabebe3891c9405dd6df463a
+F test/checkfreelist.test 100283a3e6b8a3018c7fab7cfdaf03d1d6540fc66453114e248cf82b25784d3b
F test/close.test 799ea4599d2f5704b0a30f477d17c2c760d8523fa5d0c8be4a7df2a8cad787d8
F test/closure01.test b1703ba40639cfc9b295cf478d70739415eec6a4
F test/coalesce.test cee0dccb9fbd2d494b77234bccf9dc6c6786eb91
@@ -652,7 +666,7 @@ F test/collate9.test 3adcc799229545940df2f25308dd1ad65869145a
F test/collateA.test b8218ab90d1fa5c59dcf156efabb1b2599c580d6
F test/collateB.test 1e68906951b846570f29f20102ed91d29e634854ee47454d725f2151ecac0b95
F test/colmeta.test 2c765ea61ee37bc43bbe6d6047f89004e6508eb1
-F test/colname.test b111edd2a84f558567320904bb94c779d7eec47254265b5f0a3d1f3e52cc28e0
+F test/colname.test c47639d26cbeba6977457e5ef2c2c55c5b6c889478dd7eb0ed858ba894e7fa93
F test/conflict.test 029faa2d81a0d1cafb5f88614beb663d972c01db
F test/conflict2.test bb0b94cf7196c64a3cbd815c66d3ee98c2fecd9c
F test/conflict3.test a83db76a6c3503b2fa057c7bfb08c318d8a422202d8bc5b86226e078e5b49ff9
@@ -668,7 +682,7 @@ F test/corrupt8.test 2399dfe40d2c0c63af86706e30f3e6302a8d0516
F test/corrupt9.test 730a3db08d4ab9aa43392ea30d9c2b4879cbff85
F test/corruptA.test 112f4b2ae0b95ebf3ea63718642fb969a93acea557ace3a307234d19c245989b
F test/corruptB.test 73a8d6c0b9833697ecf16b63e3c5c05c945b5dec
-F test/corruptC.test 46ec43bd90a02fd7b37ad8a7a949c55aa5717f89
+F test/corruptC.test 138ecb02188ed1a719b533d4a139568204039f72f00e07a8d30d920bd83122db
F test/corruptD.test b3c205fac7952b1de645ce44bb02335cd9e3e040
F test/corruptE.test 82ccf4f8f543fdbedd4aa42c709cb077f7374c62
F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4
@@ -676,7 +690,7 @@ F test/corruptG.test adf79b669cbfd19e28c8191a610d083ae53a6d51
F test/corruptH.test 79801d97ec5c2f9f3c87739aa1ec2eb786f96454
F test/corruptI.test 075fe1d75aa1d84e2949be56b6264376c41502e4
F test/corruptJ.test 4d5ccc4bf959464229a836d60142831ef76a5aa4
-F test/corruptK.test 814a59ec699d8546b4e29005fba3d16e933ef2fe
+F test/corruptK.test 91550557849244a9904f4e090052e3f2c1c3f1106840d58b00ffaa3a8c2d3fc0
F test/cost.test 1eedbfd868f806f3fa08ff072b04cf270dcf61c8
F test/count.test cb2e0f934c6eb33670044520748d2ecccd46259c
F test/coveridxscan.test b629e896b14df2f000a99b8d170d80589c46562c
@@ -692,13 +706,14 @@ F test/crashM.test d95f59046fa749b0d0822edf18a717788c8f318d
F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
F test/createtab.test b5de160630b209c4b8925bdcbbaf48cc90b67fe8
F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c
-F test/csv01.test e0ba3caaa57e4c667a0b45977689fb8082f14348
+F test/csv01.test 526fc6aefd052badd5a0283f86b4b395c3df76bfe98d96c801f494f5e2c7836c
F test/ctime.test 78749e6c9a5f0010d67985be80788f841e3cd2da18114e2ed6010399a7d807f3
F test/cursorhint.test 7bc346788390475e77a345da2b92270d04d35856
F test/cursorhint2.test 8457e93d97f665f23f97cdbc8477d16e3480331b
F test/date.test 9b73bbeb1b82d9c1f44dec5cf563bf7da58d2373
F test/date2.test 74c234bece1b016e94dd4ef9c8cc7a199a8806c0e2291cab7ba64bace6350b10
F test/dbfuzz.c 73047c920d6210e5912c87cdffd9a1c281d4252e
+F test/dbpage.test 10b9e91d07b0892444fff4578706648e955b5fb260218298f838da74f0d9d211
F test/dbstatus.test 73149851b3aff14fc6db478e58f9083a66422cf5
F test/dbstatus2.test e93ab03bfae6d62d4d935f20de928c19ca0ed0ab
F test/default.test 0cb49b1c315a0d81c81d775e407f66906a2a604d
@@ -723,7 +738,7 @@ F test/e_createtable.test d4c6059d44dcd4b636de9aae322766062b471844
F test/e_delete.test ab39084f26ae1f033c940b70ebdbbd523dc4962e
F test/e_droptrigger.test 3cd080807622c13e5bbb61fc9a57bd7754da2412
F test/e_dropview.test 21ce09c361227ddbc9819a5608ee2700c276bdd5
-F test/e_expr.test 146deba180273d19e3bf9f6b45f4e50094c64c7ec4756ea72f79dda25818eb17
+F test/e_expr.test ca8896601ade1e27c6559614c7f32c63d44636fdfa720436a160f09b8bf66c89
F test/e_fkey.test dcdc6ad26b1d4f07636208de4c1c22aae7c0597a685a6c10fe6da91f3191dd96
F test/e_fts3.test 8cf40550bb088a6aa187c818c00fabe26ef82900a4cd5c66b427ccafe28bedaa
F test/e_insert.test f02f7f17852b2163732c6611d193f84fc67bc641fb4882c77a464076e5eba80e
@@ -733,7 +748,7 @@ F test/e_select.test 16651bb681e83a1a2875ff4a595ed2b4b4dee375
F test/e_select2.test aceb80ab927d46fba5ce7586ebabf23e2bb0604f
F test/e_totalchanges.test b12ee5809d3e63aeb83238dd501a7bca7fd72c10
F test/e_update.test f46c2554d915c9197548681e8d8c33a267e84528
-F test/e_uri.test 25385396082b67fd02ae0038b95a3b3575fe0519
+F test/e_uri.test 47eeb2960e74613f0f8722b2f13aef08fde69daa16e5380ac93df84dac8b1f72
F test/e_vacuum.test 1b8b4772d05374aa1b8958669138bbb4213ee26a
F test/e_wal.test ae9a593207a77d711443ee69ffe081fda9243625
F test/e_walauto.test 248af31e73c98df23476a22bdb815524c9dc3ba8
@@ -744,7 +759,7 @@ F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
F test/enc2.test 83437a79ba1545a55fb549309175c683fb334473
F test/enc3.test 6807f7a7740a00361ca8d0ccd66bc60c8dc5f2b6
F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020
-F test/eqp.test 3f9ba0b2594837c7beaa3ba824e2137cfe857308f020ec5a0c7a62b444e837b0
+F test/eqp.test 3fe051af50921284189d1970eb653f9fcf5117d2
F test/errmsg.test eae9f091eb39ce7e20305de45d8e5d115b68fa856fba4ea6757b6ca3705ff7f9
F test/eval.test a64c9105d6ff163df7cf09d6ac29cdad5922078c
F test/exclusive.test 9a57bd66e39144b888ca75c309914fcdefb4e3f9
@@ -754,7 +769,7 @@ F test/exists.test 79a75323c78f02bbe9c251ea502a092f9ef63dac
F test/expr.test 66a2c9ac34f74f036faa4092f5402c7d3162fc93
F test/extension01.test 00d13cec817f331a687a243e0e5a2d87b0e358c9
F test/extraquick.test cb254400bd42bfb777ff675356aabf3287978f79
-F test/fallocate.test 3e979af17dfa7e5e9dda5eba1a696c04fa9d47f7
+F test/fallocate.test 87b5e43c872b7e69cd80b7b8813eb102b571a75d45dda24e38b65537bcc85733
F test/filectrl.test 6e871c2d35dead1d9a88e176e8d2ca094fec6bb3
F test/filefmt.test f393e80c4b8d493b7a7f8f3809a8425bbf4292af1f5140f01cb1427798a2bbd4
F test/fkey1.test ba64806ff9a04eecab2679caad377ae99a5e94e4
@@ -827,7 +842,7 @@ F test/fts3aux2.test 7ae2b2c13aefdf4169279a27a5f51780ce57f6ba
F test/fts3b.test c15c4a9d04e210d0be67e54ce6a87b927168fbf9c1e3faec8c1a732c366fd491
F test/fts3c.test fc723a9cf10b397fdfc2b32e73c53c8b1ec02958
F test/fts3comp1.test a0f5b16a2df44dd0b15751787130af2183167c0c
-F test/fts3conf.test 60317efd562080e198b5bdc9fcd222ce32cf01d7
+F test/fts3conf.test c84bbaec81281c1788aa545ac6e78a6bd6cde2bdbbce2da261690e3659f5a76b
F test/fts3corrupt.test 2710b77983cc7789295ddbffea52c1d3b7506dbb
F test/fts3corrupt2.test 6d96efae2f8a6af3eeaf283aba437e6d0e5447ba
F test/fts3corrupt3.test 56e0ee83e90b57f5f3644cb7d1b36a067b7b8b19cdf0dedce45e5e13cf752f65
@@ -855,6 +870,7 @@ F test/fts3offsets.test b85fd382abdc78ebce721d8117bd552dfb75094c
F test/fts3prefix.test fa794eaab0bdae466494947b0b153d7844478ab2
F test/fts3prefix2.test e1f0a822ca661dced7f12ce392e14eaf65609dce
F test/fts3query.test f33eb71a1fe1084ea585eeb7ee76b390729f5170
+F test/fts3rank.test e4d2e16a28c98cae95001a75e2b4b05b19b051ffd6aaab15491c5e0595127b9b
F test/fts3rnd.test 1320d8826a845e38a96e769562bf83d7a92a15d0
F test/fts3shared.test 57e26a801f21027b7530da77db54286a6fe4997e
F test/fts3snippet.test 01a4231816e03a0660ae53ba2404fe69012fe0db
@@ -902,7 +918,7 @@ F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14
F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
F test/gcfault.test dd28c228a38976d6336a3fc42d7e5f1ad060cb8c
F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
-F test/having.test b3d6b17cc9601b6b373b2d0f08c075ccf30e2d307249c3c8a236e3c36907b1a5
+F test/having.test e4098a4b8962f9596035c3b87a8928a10648acc509f1bb8d6f96413bbf79a1b3
F test/hexlit.test 4a6a5f46e3c65c4bf1fa06f5dd5a9507a5627751
F test/hidden.test 23c1393a79e846d68fd902d72c85d5e5dcf98711
F test/hook.test dbc0b87756e1e20e7497b56889c9e9cd2f8cc2b5
@@ -936,8 +952,8 @@ F test/index7.test 7feababe16f2091b229c22aff2bcc1d4d6b9d2bb
F test/index8.test bc2e3db70e8e62459aaa1bd7e4a9b39664f8f9d7
F test/index9.test 0aa3e509dddf81f93380396e40e9bb386904c1054924ba8fa9bcdfe85a8e7721
F test/indexedby.test 9c4cd331224e57f79fbf411ae245e6272d415985
-F test/indexexpr1.test f348668daf7f533f1e5578dd4f31e4b9a3875da1ee2a60a8d2d50b938a7699c9
-F test/indexexpr2.test 3ddd7f23bc381b9f2b7a15f2d083b1a4078e7733dce8295602ecfa3c74a34cf9
+F test/indexexpr1.test 84100e880154a4b645db9f4fc7642756d9a2b6011b68f73c8efda4d244816de9
+F test/indexexpr2.test 13247bac49143196556eb3f65e97ef301bd3e993f4511558b5db322ddc370ea6
F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
F test/insert.test 38742b5e9601c8f8d76e9b7555f7270288c2d371
@@ -975,10 +991,10 @@ F test/json102.test eeb54efa221e50b74a2d6fb9259963b48d7414dca3ce2fdfdeed45cb2848
F test/json103.test c5f6b85e69de05f6b3195f9f9d5ce9cd179099a0
F test/json104.test 877d5845f6303899b7889ea5dd1bea99076e3100574d5c536082245c5805dcaa
F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
-F test/kvtest.c d2b8cfc91047ebf6cac4f3a04f19c3a864e4ecfd683bbb65c395df450b8dc79c
+F test/kvtest.c fcb38ffe3db028a3138b4818fc098359c80dc51a0d1278a91c99c554cc1abb92
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
-F test/like.test 3d26ae14d7042a0e96f7b0b9e9ad2c8ca6ed122772439c6b1c691fe167e15a37
+F test/like.test 11cfd7d4ef8625389df9efc46735ff0b0b41d5e62047ef0f3bc24c380d28a7a6
F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da
F test/like3.test 3608a2042b6f922f900fbfd5d3ce4e7eca57f7c4
F test/limit.test 0c99a27a87b14c646a9d583c7c89fd06c352663e
@@ -993,7 +1009,7 @@ F test/lock5.test c6c5e0ebcb21c61a572870cc86c0cb9f14cede38
F test/lock6.test ad5b387a3a8096afd3c68a55b9535056431b0cf5
F test/lock7.test 49f1eaff1cdc491cc5dee3669f3c671d9f172431
F test/lock_common.tcl 7ffb45accf6ee91c736df9bafe0806a44358f035
-F test/lookaside.test 90052e87282de256d613fcf8c9cbb845e4001d2f
+F test/lookaside.test b17c99ae3aef96a8c9fa6f6be33cc75b93d657cb791d3827302b6835b71941f7
F test/main.test bb75e406c9b64931f3dc7e7f04626633365bb22f
F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9
F test/malloc.test 21c213365f2cca95ab2d7dc078dc8525f96065f8
@@ -1023,13 +1039,13 @@ F test/manydb.test 28385ae2087967aa05c38624cec7d96ec74feb3e
F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f
F test/memdb.test c1f2a343ad14398d5d6debda6ea33e80d0dafcc7
F test/memleak.test 10b9c6c57e19fc68c32941495e9ba1c50123f6e2
-F test/memsubsys1.test 6d268d0ae90f8d61a2356a1838665654d83de518
+F test/memsubsys1.test 9e7555a22173b8f1c96c281ce289b338fcba2abe8b157f8798ca195bbf1d347e
F test/memsubsys2.test 3e4a8d0c05fd3e5fa92017c64666730a520c7e08
F test/minmax.test 6751e87b409fe11b02e70a306d846fa544e25a41
F test/minmax2.test b44bae787fc7b227597b01b0ca5575c7cb54d3bc
F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354
F test/minmax4.test 936941484ebdceb8adec7c86b6cd9b6e5e897c1f
-F test/misc1.test 6430dabfb4b4fa480633590118964201f94d3ccc
+F test/misc1.test 76737c259537586355f45e2a1e121b6e91b5476c4604ad5c53d1abfcb3acf786
F test/misc2.test 00d7de54eda90e237fc9a38b9e5ccc769ebf6d4d
F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d
F test/misc4.test 0d8be3466adf123a7791a66ba2bc8e8d229e87f3
@@ -1038,18 +1054,20 @@ F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
F test/misc7.test edd0b63e2ee29a256900b0514f6fff27e19e9bb2
F test/misc8.test ba03aaa08f02d62fbb8d3b2f5595c1b33aa9bbc5
F test/misuse.test 9e7f78402005e833af71dcab32d048003869eca5abcaccc985d4f8dc1d86bcc7
+F test/mjournal.test 68b749956f9a179e7e633a3958b48a5a905d28d30c7ec88f3f26dc6f220129db
F test/mmap1.test d2cfc1635171c434dcff0ece2f1c8e0a658807ce
F test/mmap2.test 9d6dd9ddb4ad2379f29cc78f38ce1e63ed418022
F test/mmap3.test b3c297e78e6a8520aafcc1a8f140535594c9086e
F test/mmap4.test 2e2b4e32555b58da15176e6fe750f17c9dcf7f93
F test/mmapfault.test d4c9eff9cd8c2dc14bc43e71e042f175b0a26fe3
+F test/mmapwarm.test 2272005969cd17a910077bd5082f70bc1fefad9a875afec7fc9af483898ecaf3
F test/multiplex.test dc0d67b66f84b484a83cb8bbdf3f0a7f49562ccd
F test/multiplex2.test 580ca5817c7edbe4cc68fa150609c9473393003a
F test/multiplex3.test d228f59eac91839a977eac19f21d053f03e4d101
F test/multiplex4.test e8ae4c4bd70606a5727743241f13b5701990abe4
F test/mutex1.test ea2cc74d97f077b9e74c84cbd024f14d79a8126f
F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
-F test/nan.test dacc57f80859c06a433d30839336fe227d2038b3
+F test/nan.test 437d40e6d0778b050d7750726c0cbd2c9936b81962926e8f8c48ca698f00f4d1
F test/nockpt.test 9a436a7213ba5ef7a32304998d386d3ea3f76c9d
F test/nolock.test f196cf8b8fbea4e2ca345140a2b3f3b0da45c76e
F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf
@@ -1071,7 +1089,7 @@ F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da
F test/orderby8.test 23ef1a5d72bd3adcc2f65561c654295d1b8047bd
F test/orderby9.test 87fb9548debcc2cd141c5299002dd94672fa76a3
F test/oserror.test b32dc34f2363ef18532e3a0a7358e3e7e321974f
-F test/ossfuzz.c f5abed3177f719df3c3109901fcdd26b9fb7f581c8da50fc26f3a81ddfb2c2ae
+F test/ossfuzz.c 7f5cc87a0280a5854c1bfa7d5c4d07d34731f08ec34dc9c916aa35ed292b1468
F test/ossshell.c 296ab63067841bd1b1e97b46a0b2af48ee7f69d50d1a723008bee12dd7122622
F test/ovfl.test 199c482696defceacee8c8e0e0ef36da62726b2f
F test/pager1.test 8149b2a8986fee667ab6a8171ab310be19e77ae215bebad0e90c857b0df1935c
@@ -1087,11 +1105,12 @@ F test/parser1.test 391b9bf9a229547a129c61ac345ed1a6f5eb1854
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
-F test/permutations.test 5e2e5439642898e0947ced066ad09b82bd817ddfb83dc71291b4c957efc84b62
-F test/pragma.test f274259d6393b6681eb433beb8dd39a26ec06a4431052a4880b43b84912a3f58
+F test/permutations.test 490e3333b9b1aefb7ebc6e9ab2ae0e382b7dd8713ccc4a2786b0f75467c2ab6b
+F test/pragma.test 7c8cfc328a1717a95663cf8edb06c52ddfeaf97bb0aee69ae7457132e8d39e7d
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
F test/pragma3.test 14c12bc5352b1e100e0b6b44f371053a81ccf8ed
-F test/pragma4.test 6e85b6eab8e61ffc9c7db59d842276674e8e3264
+F test/pragma4.test 3046501bee2f652dc2a4f9c87781e2741361d6864439c8381aba6c3b774b335c
+F test/pragma5.test fd517f42ee847e126afbbbd9fd0fb9e5a4a61a962496a350adb8a22583fbdc37
F test/pragmafault.test 275edaf3161771d37de60e5c2b412627ac94cef11739236bec12ed1258b240f8
F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc
F test/printf2.test 9e6db85f81c63f2367c34a9d7db384088bd374ad
@@ -1111,9 +1130,9 @@ F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
F test/regexp2.test 40e894223b3d6672655481493f1be12012f2b33c
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
-F test/releasetest.tcl 7bb585433ce7fb2a2c255ae4b5e24f1bc27fe177ec1120f886cc4852f48f5ee9 x
+F test/releasetest.tcl 0b0b3d926e36822ff63b405d683544ce1014303b029f2678bbcf40c162b5f246 x
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
-F test/rollback.test 458fe73eb3ffdfdf9f6ba3e9b7350a6220414dea
+F test/rollback.test f580934279800d480a19176c6b44909df31ce7ad45267ea475a541daa522f3d3
F test/rollback2.test 8435d6ff0f13f51d2a4181c232e706005fa90fc5
F test/rollbackfault.test 0e646aeab8840c399cfbfa43daab46fd609cf04a
F test/rowallock.test 3f88ec6819489d0b2341c7a7528ae17c053ab7cc
@@ -1131,22 +1150,23 @@ F test/rowvalue9.test d8dd2c6ecac432dadaa79e41dc2434f007be1b6b
F test/rowvaluefault.test 7cd9ccc6c2fbdd881672984087aad0491bb75504
F test/rtree.test 0c8d9dd458d6824e59683c19ab2ffa9ef946f798
F test/run-wordcount.sh 891e89c4c2d16e629cd45951d4ed899ad12afc09
-F test/savepoint.test c671fdbd34cd3bfe1518a777526ada595180cf8d
+F test/savepoint.test 1f8a6b1aea9a0d05837adc463d4bf47bd9d0f1c842f1c2a9caccd639baf34bf9
F test/savepoint2.test 9b8543940572a2f01a18298c3135ad0c9f4f67d7
F test/savepoint4.test c8f8159ade6d2acd9128be61e1230f1c1edc6cc0
F test/savepoint5.test 0735db177e0ebbaedc39812c8d065075d563c4fd
F test/savepoint6.test f41279c5e137139fa5c21485773332c7adb98cd7
F test/savepoint7.test cde525ea3075283eb950cdcdefe23ead4f700daa
F test/savepointfault.test f044eac64b59f09746c7020ee261734de82bf9b2
-F test/scanstatus.test 5253c219e331318a437f436268e0e82345700285
+F test/scanstatus.test 1ba0e2ee25dcd1d55ec770803b19832cffaecbf0b15d376807759ebeed3669b0
F test/schema.test 8f7999be894260f151adf15c2c7540f1c6d6a481
F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5
F test/schema3.test 1bc1008e1f8cb5654b248c55f27249366eb7ed38
F test/schema4.test 3b26c9fa916abb6dadf894137adcf41b7796f7b9
F test/schema5.test 29699b4421f183c8f0e88bd28ce7d75d13ea653e
+F test/schema6.test e4bd1f23d368695eb9e7b51ef6e02ca0642ea2ab4a52579959826b5e7dce1f9b
F test/securedel.test 5f997cb6bd38727b81e0985f53ec386c99db6441b2b9e6357240649d29017239
F test/securedel2.test 2d54c28e46eb1fd6902089958b20b1b056c6f1c5
-F test/select1.test be62204d2bd9a5a8a149e9974cfddce893d8f686
+F test/select1.test 460a5824df01575b18f7fa4bd8e40d09de20c542e90c1543e164bc7d3b0a0bb7
F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56
F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054
F test/select4.test 5389d9895968d1196c457d59b3ee6515d771d328
@@ -1193,7 +1213,7 @@ F test/skipscan3.test ec5bab3f81c7038b43450e7b3062e04a198bdbb5
F test/skipscan5.test 67817a4b6857c47e0e33ba3e506da6f23ef68de2
F test/skipscan6.test 5866039d03a56f5bd0b3d172a012074a1d90a15b
F test/snapshot.test 85735bd997a4f6d710140c28fd860519a299649f
-F test/snapshot2.test 867652ed4a13282dce218723535fad1c7b44c3c4
+F test/snapshot2.test 925e42427e923262db63c9d7155183f889e3e99feaedec4075f659e51608344f
F test/snapshot_fault.test 52c5e97ebd218846a8ae2da4d147d3e77d71f963
F test/soak.test 0b5b6375c9f4110c828070b826b3b4b0bb65cd5f
F test/softheap1.test 843cd84db9891b2d01b9ab64cef3e9020f98d087
@@ -1211,7 +1231,7 @@ F test/speed3.test 694affeb9100526007436334cf7d08f3d74b85ef
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
-F test/speedtest1.c 7b1ab42b097b484c18d99e1d1c71a6a0c9c87a7a
+F test/speedtest1.c e44c5fccddcfe916c3bf7fe2f87dcc4b4fd66a0d923eb83515f311212670f267
F test/spellfix.test f9c1f431e2c096c8775fec032952320c0e4700db
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
@@ -1229,10 +1249,13 @@ F test/subselect.test 0966aa8e720224dbd6a5e769a3ec2a723e332303
F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a
F test/subtype1.test 7fe09496352f97053af1437150751be2d0a0cae8
F test/superlock.test ec94f0556b6488d97f71c79f9061ae08d9ab8f12
+F test/swarmvtab.test c2279311b44de032f86a8295a9b06818d864856f9428b4c99eee91a0d419cf25
+F test/swarmvtab2.test 9a3a68a1e58d00f4ed6c68d12d52f2df971b9e22a80a41f6f8c1409abba8e5b4
+F test/swarmvtabfault.test 00aec54665909490f5c383f3cae3b5d18bd97c12490b429ff8752a3027acfa42
F test/symlink.test c9ebe7330d228249e447038276bfc8a7b22f4849
F test/sync.test 2f84bdbc2b2df1fcb0220575b4b9f8cea94b7529
F test/sync2.test 6be8ed007fa063b147773c1982b5bdba97a32badc536bdc6077eff5cf8710ece
-F test/syscall.test 7a60601770172a8014a4d222d5f3d95a5d2b5c47fbb0374e2698e89c99e37256
+F test/syscall.test a39d9a36f852ae6e4800f861bc2f2e83f68bbc2112d9399931ecfadeabd2d69d
F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04
F test/tabfunc01.test c47171c36b3d411df2bd49719dcaa5d034f8d277477fd41d253940723b969a51
F test/table.test b708f3e5fa2542fa51dfab21fc07b36ea445cb2f
@@ -1246,7 +1269,7 @@ F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
F test/temptable2.test cd396beb41117a5302fff61767c35fa4270a0d5e
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
-F test/tester.tcl 581f0185434daf7026ccede4c07e8d1479186ec5
+F test/tester.tcl 9948bd856ce8a1c127f2f7900365387a42a917ce0dc87185bdd128fa5b11aff2
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@ -1434,7 +1457,7 @@ F test/types.test bf816ce73c7dfcfe26b700c19f97ef4050d194ff
F test/types2.test 1aeb81976841a91eef292723649b5c4fe3bc3cac
F test/types3.test 99e009491a54f4dc02c06bdbc0c5eea56ae3e25a
F test/unionvtab.test 595fb601de00188ca5e7c6dbe266c17a0faf234cf434ce85eccec1a929ef9baf
-F test/unionvtabfault.test 18f4f878e550ae3c5efa195b1420c78607c0f9810f7a71a49ab6379dfe501f32
+F test/unionvtabfault.test 26b6854d5aef9005cd630513025690bff1b7378ae9c97b81e2a3cbe84eee0f58
F test/unique.test 93f8b2ef5ea51b9495f8d6493429b1fd0f465264
F test/unique2.test 3674e9f2a3f1fbbfd4772ac74b7a97090d0f77d2
F test/unixexcl.test d936ba2b06794018e136418addd59a2354eeae97
@@ -1455,7 +1478,7 @@ F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
F test/view.test 765802c7a66d37fabd5ac8e2f2dbe572b43eb9ab
F test/vtab1.test 8f91b9538d1404c3932293a588c4344218a0c94792d4289bb55e41020e7b3fff
-F test/vtab2.test f8cd1bb9aba7143eba97812d9617880a36d247ad
+F test/vtab2.test 14d4ab26cee13ba6cf5c5601b158e4f57552d3b055cdd9406cf7f711e9c84082
F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e
F test/vtab4.test 8e73ed268f3d596bc3590f45fc948fb40f28e9c3
F test/vtab5.test 889f444970393c73f1e077e2bdc5d845e157a391
@@ -1467,15 +1490,16 @@ F test/vtabA.test 1317f06a03597eee29f40a49b6c21e1aaba4285f
F test/vtabB.test 04df5dc531b9f44d9ca65b9c1b79f12b5922a796
F test/vtabC.test 4528f459a13136f982e75614d120aef165f17292
F test/vtabD.test 05b3f1d77117271671089e48719524b676842e96
-F test/vtabE.test d5024aa42754962f6bb0afd261681686488e7afe
+F test/vtabE.test 2a143fe75a11275781d1fd1988d86b66a3f69cb98f4add62e3da8fd0f637b45f
F test/vtabF.test 1918844c7c902f6a16c8dacf1ec8f84886d6e78b
-F test/vtabH.test 26d54e8b5407f797638b787a55f9c88323850a58dd142de02d06b9a1159bd283
+F test/vtabH.test 3cf9aa1c1c4381b3b3ac33f933376f06fbb99d2294a83c79b7562d3ed87be450
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_shared.test 5253bff2355a9a3f014c15337da7e177ab0ef8ad
F test/wal.test 613efec03e517e1775d86b993a54877d2e29a477
-F test/wal2.test 56b0bc95b8693a0be294f8d210c49025dd094bd7
+F test/wal2.test 6ac39b94a284ebac6efb6be93b0cdfe73ee6083f129555e3144d8a615e9900ef
F test/wal3.test 2a93004bc0fb2b5c29888964024695bade278ab2
F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c
F test/wal5.test 9c11da7aeccd83a46d79a556ad11a18d3cb15aa9
@@ -1513,12 +1537,12 @@ F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b
F test/where7.test f520bcec2c3d12dc4615623b06b2aec7c2d67e94
F test/where8.test 98eedca0d375fb400b8377269c4b4686582dfb45
F test/where9.test 729c3ba9b47e8f9f1aab96bae7dad2a524f1d1a2
-F test/whereA.test 4d253178d135ec46d1671e440cd8f2b916aa6e6b
+F test/whereA.test 6c6a420ca7d313242f9b1bd471dc80e4d0f8323700ba9c78df0bb843d4daa3b4
F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5
F test/whereC.test cae295158703cb3fc23bf1a108a9ab730efff0f6
F test/whereD.test 711d4df58d6d4fb9b3f5ce040b818564198be002
F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f
-F test/whereF.test 97a86ecdfa4c21684fdff501dbd2cb7397689be8676d0dbad1f5a0892c6b56a3
+F test/whereF.test d44b58338fe5ddd7286023e9bedb255aa264a6c4d2168b49591b167371c675c7
F test/whereG.test dde4c52a97385a55be6a7cd46be8373f0cf35501
F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2
F test/whereI.test eab5b226bbc344ac70d7dc09b963a064860ae6d7
@@ -1527,7 +1551,7 @@ F test/whereK.test f8e3cf26a8513ecc7f514f54df9f0572c046c42b
F test/wherefault.test 1374c3aa198388925246475f84ad4cd5f9528864
F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31
F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
-F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c
+F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2aeee74
F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
@@ -1541,13 +1565,14 @@ F test/without_rowid3.test 2724c787a51a5dce09d078453a758117b4b728f1
F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a
F test/without_rowid5.test 89b1c587bd92a0590e440da33e7666bf4891572a
F test/without_rowid6.test 1f99644e6508447fb050f73697350c7ceca3392e
-F test/wordcount.c 06efb84b7c48a4973c2c24ea06c93d00bce24389
+F test/wordcount.c cb589cec469a1d90add05b1f8cee75c7210338d87a5afd65260ed5c0f4bbf8ac
+F test/writecrash.test f1da7f7adfe8d7f09ea79b42e5ca6dcc41102f27f8e334ad71539501ddd910cc
F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa
F test/zerodamage.test e59a56443d6298ecf7435f618f0b27654f0c849e
F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5
F tool/GetTclKit.bat 8995df40c4209808b31f24de0b58f90930239a234f7591e3675d45bfbb990c5d
F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91
-F tool/addopcodes.tcl edbd53806bf20e25af2373ad0c091be4385081c1aa1813b916bf093f94ed8380
+F tool/addopcodes.tcl 7181c041d495e3f26acc36d15c86923ed722285f9015f017f41a3efdb9a0dab4
F tool/build-all-msvc.bat c12328d06c45fec8baada5949e3d5af54bf8c887 x
F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367
F tool/cg_anno.tcl f95b0006c52cf7f0496b506343415b6ee3cdcdd3 x
@@ -1561,25 +1586,27 @@ F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f
-F tool/lemon.c 5a04dff28578a67415cea5bf981b893c50cebfdd4388fb21254d1892525edfd8
-F tool/lempar.c 10579a61dc2290182725e7abdefe311dd8b521a8f7f0aabbfc571e9012a09eaf
+F tool/lemon.c e6056373044d55296d21f81467dba7632bbb81dc49af072b3f0e76338771497e
+F tool/lempar.c 105d0d9cbe5a25d24d4769241ffbfc63ac7c09e6ccee0dc43dcc8a4c4ae4e426
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca
F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439
-F tool/mkautoconfamal.sh e855df211ecbcc7131dee817110ff386cfb112f7
+F tool/mkautoconfamal.sh 422fc365358a2e92876ffc62971a0ff28ed472fc8bcf9de0df921c736fdeca5e
+F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x
F tool/mkctimec.tcl dd183b73ae1c28249669741c250525f0407e579a70482371668fd5f130d9feb3
F tool/mkkeywordhash.c 2e852ac0dfdc5af18886dc1ce7e9676d11714ae3df0a282dc7d90b3a0fe2033c
F tool/mkmsvcmin.tcl cbd93f1cfa3a0a9ae56fc958510aa3fc3ac65e29cb111716199e3d0e66eefaa4
F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
-F tool/mkopcodeh.tcl bb04ab6e5e2000c91e0c69a597e7e36e002320d123e2e1944cb2819181b72ee9
+F tool/mkopcodeh.tcl 4ee2a30ccbd900dc4d5cdb61bdab87cd2166cd2affcc78c9cc0b8d22a65b2eee
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
F tool/mkpragmatab.tcl 2144bc8550a6471a029db262a132d2df4b9e0db61b90398bf64f5b7b3f8d92cd
-F tool/mkshellc.tcl 69c38ecd7b74b2b0799a35ce20e1e3998e504d8c99c100ca4b98ae9d8f6279bc
+F tool/mkshellc.tcl 574307265b49d813301fba91ccd74e6a26d33f65f74b6891c320a0ffbee07895
+F tool/mksourceid.c d458f9004c837bee87a6382228ac20d3eae3c49ea3b0a5aace936f8b60748d3b
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
F tool/mksqlite3c-noext.tcl fef88397668ae83166735c41af99d79f56afaabb
-F tool/mksqlite3c.tcl f6214285bec900d28441366ca31af327aade18bbc424b0480497966ec05bc43c
-F tool/mksqlite3h.tcl 51bd5e7e840a920388a5966c9f2ccc618f434c57bd68c1bab4085b2553e1e237
+F tool/mksqlite3c.tcl 1fb69d39166f52d802a70ec37d99bca51d011c8ab30be27bc495be493196ae41
+F tool/mksqlite3h.tcl f92f994d9709aeb9e2b6e6f9fc8b069d2f55202c8e23f453edc44390a25982dc
F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b
F tool/mkvsix.tcl b9e0777a213c23156b6542842c238479e496ebf5
F tool/offsets.c fe4262fdfa378e8f5499a42136d17bf3b98f6091
@@ -1597,23 +1624,23 @@ F tool/showstat4.c 0682ebea7abf4d3657f53c4a243f2e7eab48eab344ed36a94bb75dcd19a5c
F tool/showwal.c ad9d768f96ca6199ad3a8c9562d679680bd032dd01204ea3e5ea6fb931d81847
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
F tool/spaceanal.tcl f40dc82b4d5e39d040a02a3ec38268e324068815e4292a15ffa30ee93208bbfd
-F tool/speed-check.sh fd24151fd66465f01886c3f75faf8fa46d19f068c69d16514ca73887adcdafe4
+F tool/speed-check.sh a97ae367e9172a706101901e7caef48f1a14fc8a49053b25e79f6a67296b3412
F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355
F tool/speedtest16.c ecb6542862151c3e6509bbc00509b234562ae81e
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd
-F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c
+F tool/split-sqlite3c.tcl 3efcd4240b738f6bb2b5af0aea7e1e0ef9bc1c61654f645076cec883030b710c
F tool/sqldiff.c 30879bbc8de686df4624e86adce2d8981f500904c1cfb55b5d1eea2ffd9341eb
+F tool/sqlite3_analyzer.c.in 771d15fb9c67645fd8ef932a438f98959da4b7c7da3cb87ae1850b27c969edf3
F tool/srcck1.c 371de5363b70154012955544f86fdee8f6e5326f
F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43
F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d
F tool/symbols.sh c5a617b8c61a0926747a56c65f5671ef8ac0e148
-F tool/tostr.tcl 96022f35ada2194f6f8ccf6fd95809e90ed277c4
F tool/varint.c 5d94cb5003db9dbbcbcc5df08d66f16071aee003
F tool/vdbe-compress.tcl 5926c71f9c12d2ab73ef35c29376e756eb68361c
F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f
-F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
+F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
F tool/warnings.sh 8a4acea31e0f9c562949a2d767329533c0930d699ea19c6704c0ca0aa9154068
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
F vsixtest/App.xaml b76d3b48860e7454775c47ea38ffea9c4abe3e85
@@ -1637,11 +1664,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 70338c7cb128855bb134dddebf04fbcf4c0c36b3127a53b9e24cd9f7fd235905
-R f28d3a18ae99c0abfb9dbb754ba936b5
+P 41ef34a1f0650c50cacb203665cd9d57db53a49c979bf0d5a78937517f763a2c
+R ba55e91a353da744095752f95418b3a4
T +bgcolor * #d0c0ff
T +sym-release *
-T +sym-version-3.20.1 *
+T +sym-version-3.21.0 *
U drh
-Z 060abdbd0746413c79f6ad9e0e76e1d3
+Z c165baaf48a254c276ef91f282f216a1
# 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 cbd32dcf878..8a167684ab2 100644
--- a/chromium/third_party/sqlite/src/manifest.uuid
+++ b/chromium/third_party/sqlite/src/manifest.uuid
@@ -1 +1 @@
-8d3a7ea6c5690d6b7c3767558f4f01b511c55463e3f9e64506801fe9b74dce34
+1a584e499906b5c87ec7d43d4abce641fdf017c42125b083109bc77c4de48827
diff --git a/chromium/third_party/sqlite/src/src/alter.c b/chromium/third_party/sqlite/src/src/alter.c
index 69397e1f35b..93ac16d57d9 100644
--- a/chromium/third_party/sqlite/src/src/alter.c
+++ b/chromium/third_party/sqlite/src/src/alter.c
@@ -403,9 +403,9 @@ void sqlite3AlterRenameTable(
char *zWhere = 0; /* Where clause to locate temp triggers */
#endif
VTable *pVTab = 0; /* Non-zero if this is a v-tab with an xRename() */
- int savedDbFlags; /* Saved value of db->flags */
+ u32 savedDbFlags; /* Saved value of db->mDbFlags */
- savedDbFlags = db->flags;
+ savedDbFlags = db->mDbFlags;
if( NEVER(db->mallocFailed) ) goto exit_rename_table;
assert( pSrc->nSrc==1 );
assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
@@ -414,7 +414,7 @@ void sqlite3AlterRenameTable(
if( !pTab ) goto exit_rename_table;
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
zDb = db->aDb[iDb].zDbSName;
- db->flags |= SQLITE_PreferBuiltin;
+ db->mDbFlags |= DBFLAG_PreferBuiltin;
/* Get a NULL terminated version of the new table name. */
zName = sqlite3NameFromToken(db, pName);
@@ -579,7 +579,7 @@ void sqlite3AlterRenameTable(
exit_rename_table:
sqlite3SrcListDelete(db, pSrc);
sqlite3DbFree(db, zName);
- db->flags = savedDbFlags;
+ db->mDbFlags = savedDbFlags;
}
/*
@@ -680,11 +680,11 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
zCol = sqlite3DbStrNDup(db, (char*)pColDef->z, pColDef->n);
if( zCol ){
char *zEnd = &zCol[pColDef->n-1];
- int savedDbFlags = db->flags;
+ u32 savedDbFlags = db->mDbFlags;
while( zEnd>zCol && (*zEnd==';' || sqlite3Isspace(*zEnd)) ){
*zEnd-- = '\0';
}
- db->flags |= SQLITE_PreferBuiltin;
+ db->mDbFlags |= DBFLAG_PreferBuiltin;
sqlite3NestedParse(pParse,
"UPDATE \"%w\".%s SET "
"sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d) "
@@ -693,7 +693,7 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
zTab
);
sqlite3DbFree(db, zCol);
- db->flags = savedDbFlags;
+ db->mDbFlags = savedDbFlags;
}
/* Make sure the schema version is at least 3. But do not upgrade
diff --git a/chromium/third_party/sqlite/src/src/attach.c b/chromium/third_party/sqlite/src/src/attach.c
index 2e8f8c1cf02..fbbd37b77ec 100644
--- a/chromium/third_party/sqlite/src/src/attach.c
+++ b/chromium/third_party/sqlite/src/src/attach.c
@@ -93,10 +93,6 @@ static void attachFunc(
);
goto attach_error;
}
- if( !db->autoCommit ){
- zErrDyn = sqlite3MPrintf(db, "cannot ATTACH database within transaction");
- goto attach_error;
- }
for(i=0; i<db->nDb; i++){
char *z = db->aDb[i].zDbSName;
assert( z && zName );
@@ -288,11 +284,6 @@ static void detachFunc(
sqlite3_snprintf(sizeof(zErr),zErr, "cannot detach database %s", zName);
goto detach_error;
}
- if( !db->autoCommit ){
- sqlite3_snprintf(sizeof(zErr), zErr,
- "cannot DETACH database within transaction");
- goto detach_error;
- }
if( sqlite3BtreeIsInReadTrans(pDb->pBt) || sqlite3BtreeIsInBackup(pDb->pBt) ){
sqlite3_snprintf(sizeof(zErr),zErr, "database %s is locked", zName);
goto detach_error;
diff --git a/chromium/third_party/sqlite/src/src/auth.c b/chromium/third_party/sqlite/src/src/auth.c
index 4255440fc3d..d85352f192b 100644
--- a/chromium/third_party/sqlite/src/src/auth.c
+++ b/chromium/third_party/sqlite/src/src/auth.c
@@ -118,11 +118,9 @@ int sqlite3AuthReadCol(
#endif
);
if( rc==SQLITE_DENY ){
- if( db->nDb>2 || iDb!=0 ){
- sqlite3ErrorMsg(pParse, "access to %s.%s.%s is prohibited",zDb,zTab,zCol);
- }else{
- sqlite3ErrorMsg(pParse, "access to %s.%s is prohibited", zTab, zCol);
- }
+ char *z = sqlite3_mprintf("%s.%s", zTab, zCol);
+ if( db->nDb>2 || iDb!=0 ) z = sqlite3_mprintf("%s.%z", zDb, z);
+ sqlite3ErrorMsg(pParse, "access to %z is prohibited", z);
pParse->rc = SQLITE_AUTH;
}else if( rc!=SQLITE_IGNORE && rc!=SQLITE_OK ){
sqliteAuthBadReturnCode(pParse);
diff --git a/chromium/third_party/sqlite/src/src/btree.c b/chromium/third_party/sqlite/src/src/btree.c
index 26c2d762e2e..e349eac4b01 100644
--- a/chromium/third_party/sqlite/src/src/btree.c
+++ b/chromium/third_party/sqlite/src/src/btree.c
@@ -439,7 +439,9 @@ static void downgradeAllSharedCacheTableLocks(Btree *p){
#endif /* SQLITE_OMIT_SHARED_CACHE */
-static void releasePage(MemPage *pPage); /* Forward reference */
+static void releasePage(MemPage *pPage); /* Forward reference */
+static void releasePageOne(MemPage *pPage); /* Forward reference */
+static void releasePageNotNull(MemPage *pPage); /* Forward reference */
/*
***** This routine is used inside of assert() only ****
@@ -598,11 +600,13 @@ static void btreeClearHasContent(BtShared *pBt){
*/
static void btreeReleaseAllCursorPages(BtCursor *pCur){
int i;
- for(i=0; i<=pCur->iPage; i++){
- releasePage(pCur->apPage[i]);
- pCur->apPage[i] = 0;
+ if( pCur->iPage>=0 ){
+ for(i=0; i<pCur->iPage; i++){
+ releasePageNotNull(pCur->apPage[i]);
+ }
+ releasePageNotNull(pCur->pPage);
+ pCur->iPage = -1;
}
- pCur->iPage = -1;
}
/*
@@ -731,7 +735,7 @@ static int SQLITE_NOINLINE saveCursorsOnList(
return rc;
}
}else{
- testcase( p->iPage>0 );
+ testcase( p->iPage>=0 );
btreeReleaseAllCursorPages(p);
}
}
@@ -771,7 +775,7 @@ static int btreeMoveto(
if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT;
sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey);
if( pIdxKey->nField==0 ){
- rc = SQLITE_CORRUPT_PGNO(pCur->apPage[pCur->iPage]->pgno);
+ rc = SQLITE_CORRUPT_BKPT;
goto moveto_done;
}
}else{
@@ -836,6 +840,17 @@ int sqlite3BtreeCursorHasMoved(BtCursor *pCur){
}
/*
+** Return a pointer to a fake BtCursor object that will always answer
+** false to the sqlite3BtreeCursorHasMoved() routine above. The fake
+** cursor returned must not be used with any other Btree interface.
+*/
+BtCursor *sqlite3BtreeFakeValidCursor(void){
+ static u8 fakeCursor = CURSOR_VALID;
+ assert( offsetof(BtCursor, eState)==0 );
+ return (BtCursor*)&fakeCursor;
+}
+
+/*
** This routine restores a cursor back to its original position after it
** has been moved by some outside activity (such as a btree rebalance or
** a row having been deleted out from under the cursor).
@@ -1384,8 +1399,11 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
int sz2 = 0;
int sz = get2byte(&data[iFree+2]);
int top = get2byte(&data[hdr+5]);
+ if( top>=iFree ){
+ return SQLITE_CORRUPT_PGNO(pPage->pgno);
+ }
if( iFree2 ){
- if( iFree+sz>iFree2 ) return SQLITE_CORRUPT_PGNO(pPage->pgno);
+ assert( iFree+sz<=iFree2 ); /* Verified by pageFindSlot() */
sz2 = get2byte(&data[iFree2+2]);
assert( iFree+sz+sz2+iFree2-(iFree+sz) <= usableSize );
memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz));
@@ -1474,16 +1492,10 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
int pc = get2byte(&aData[iAddr]);
int x;
int usableSize = pPg->pBt->usableSize;
+ int size; /* Size of the free slot */
assert( pc>0 );
- do{
- int size; /* Size of the free slot */
- /* EVIDENCE-OF: R-06866-39125 Freeblocks are always connected in order of
- ** increasing offset. */
- if( pc>usableSize-4 || pc<iAddr+4 ){
- *pRc = SQLITE_CORRUPT_PGNO(pPg->pgno);
- return 0;
- }
+ while( pc<=usableSize-4 ){
/* EVIDENCE-OF: R-22710-53328 The third and fourth bytes of each
** freeblock form a big-endian integer which is the size of the freeblock
** in bytes, including the 4-byte header. */
@@ -1491,7 +1503,7 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
if( (x = size - nByte)>=0 ){
testcase( x==4 );
testcase( x==3 );
- if( pc < pPg->cellOffset+2*pPg->nCell || size+pc > usableSize ){
+ if( size+pc > usableSize ){
*pRc = SQLITE_CORRUPT_PGNO(pPg->pgno);
return 0;
}else if( x<4 ){
@@ -1512,7 +1524,11 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
}
iAddr = pc;
pc = get2byte(&aData[pc]);
- }while( pc );
+ if( pc<iAddr+size ) break;
+ }
+ if( pc ){
+ *pRc = SQLITE_CORRUPT_PGNO(pPg->pgno);
+ }
return 0;
}
@@ -1626,7 +1642,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
u8 hdr; /* Page header size. 0 or 100 */
u8 nFrag = 0; /* Reduction in fragmentation */
u16 iOrigSize = iSize; /* Original value of iSize */
- u32 iLast = pPage->pBt->usableSize-4; /* Largest possible freeblock offset */
+ u16 x; /* Offset to cell content area */
u32 iEnd = iStart + iSize; /* First byte past the iStart buffer */
unsigned char *data = pPage->aData; /* Page content */
@@ -1636,13 +1652,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
assert( CORRUPT_DB || iEnd <= pPage->pBt->usableSize );
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
assert( iSize>=4 ); /* Minimum cell size is 4 */
- assert( iStart<=iLast );
-
- /* Overwrite deleted information with zeros when the secure_delete
- ** option is enabled */
- if( pPage->pBt->btsFlags & BTS_FAST_SECURE ){
- memset(&data[iStart], 0, iSize);
- }
+ assert( iStart<=pPage->pBt->usableSize-4 );
/* The list of freeblocks must be in ascending order. Find the
** spot on the list where iStart should be inserted.
@@ -1659,7 +1669,9 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
}
iPtr = iFreeBlk;
}
- if( iFreeBlk>iLast ) return SQLITE_CORRUPT_PGNO(pPage->pgno);
+ if( iFreeBlk>pPage->pBt->usableSize-4 ){
+ return SQLITE_CORRUPT_PGNO(pPage->pgno);
+ }
assert( iFreeBlk>iPtr || iFreeBlk==0 );
/* At this point:
@@ -1695,19 +1707,25 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_PGNO(pPage->pgno);
data[hdr+7] -= nFrag;
}
- if( iStart==get2byte(&data[hdr+5]) ){
+ x = get2byte(&data[hdr+5]);
+ if( iStart<=x ){
/* The new freeblock is at the beginning of the cell content area,
** so just extend the cell content area rather than create another
** freelist entry */
- if( iPtr!=hdr+1 ) return SQLITE_CORRUPT_PGNO(pPage->pgno);
+ if( iStart<x || iPtr!=hdr+1 ) return SQLITE_CORRUPT_PGNO(pPage->pgno);
put2byte(&data[hdr+1], iFreeBlk);
put2byte(&data[hdr+5], iEnd);
}else{
/* Insert the new freeblock into the freelist */
put2byte(&data[iPtr], iStart);
- put2byte(&data[iStart], iFreeBlk);
- put2byte(&data[iStart+2], iSize);
}
+ if( pPage->pBt->btsFlags & BTS_FAST_SECURE ){
+ /* Overwrite deleted information with zeros when the secure_delete
+ ** option is enabled */
+ memset(&data[iStart], 0, iSize);
+ }
+ put2byte(&data[iStart], iFreeBlk);
+ put2byte(&data[iStart+2], iSize);
pPage->nFree += iOrigSize;
return SQLITE_OK;
}
@@ -2022,7 +2040,7 @@ static Pgno btreePagecount(BtShared *pBt){
}
u32 sqlite3BtreeLastPage(Btree *p){
assert( sqlite3BtreeHoldsMutex(p) );
- assert( ((p->pBt->nPage)&0x8000000)==0 );
+ assert( ((p->pBt->nPage)&0x80000000)==0 );
return btreePagecount(p->pBt);
}
@@ -2049,7 +2067,7 @@ static int getAndInitPage(
int rc;
DbPage *pDbPage;
assert( sqlite3_mutex_held(pBt->mutex) );
- assert( pCur==0 || ppPage==&pCur->apPage[pCur->iPage] );
+ assert( pCur==0 || ppPage==&pCur->pPage );
assert( pCur==0 || bReadOnly==pCur->curPagerFlags );
assert( pCur==0 || pCur->iPage>0 );
@@ -2083,7 +2101,10 @@ static int getAndInitPage(
return SQLITE_OK;
getAndInitPage_error:
- if( pCur ) pCur->iPage--;
+ if( pCur ){
+ pCur->iPage--;
+ pCur->pPage = pCur->apPage[pCur->iPage];
+ }
testcase( pgno==0 );
assert( pgno!=0 || rc==SQLITE_CORRUPT );
return rc;
@@ -2092,6 +2113,8 @@ getAndInitPage_error:
/*
** Release a MemPage. This should be called once for each prior
** call to btreeGetPage.
+**
+** Page1 is a special case and must be released using releasePageOne().
*/
static void releasePageNotNull(MemPage *pPage){
assert( pPage->aData );
@@ -2105,6 +2128,16 @@ static void releasePageNotNull(MemPage *pPage){
static void releasePage(MemPage *pPage){
if( pPage ) releasePageNotNull(pPage);
}
+static void releasePageOne(MemPage *pPage){
+ assert( pPage!=0 );
+ assert( pPage->aData );
+ assert( pPage->pBt );
+ assert( pPage->pDbPage!=0 );
+ assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage );
+ assert( sqlite3PagerGetData(pPage->pDbPage)==pPage->aData );
+ assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+ sqlite3PagerUnrefPageOne(pPage->pDbPage);
+}
/*
** Get an unused page.
@@ -2889,7 +2922,8 @@ int sqlite3BtreeGetAutoVacuum(Btree *p){
** set to the value passed to this function as the second parameter,
** set it so.
*/
-#if SQLITE_DEFAULT_SYNCHRONOUS!=SQLITE_DEFAULT_WAL_SYNCHRONOUS
+#if SQLITE_DEFAULT_SYNCHRONOUS!=SQLITE_DEFAULT_WAL_SYNCHRONOUS \
+ && !defined(SQLITE_OMIT_WAL)
static void setDefaultSyncFlag(BtShared *pBt, u8 safety_level){
sqlite3 *db;
Db *pDb;
@@ -3023,7 +3057,7 @@ static int lockBtree(BtShared *pBt){
}else{
setDefaultSyncFlag(pBt, SQLITE_DEFAULT_WAL_SYNCHRONOUS+1);
if( isOpen==0 ){
- releasePage(pPage1);
+ releasePageOne(pPage1);
return SQLITE_OK;
}
}
@@ -3070,7 +3104,7 @@ static int lockBtree(BtShared *pBt){
** zero and return SQLITE_OK. The caller will call this function
** again with the correct page-size.
*/
- releasePage(pPage1);
+ releasePageOne(pPage1);
pBt->usableSize = usableSize;
pBt->pageSize = pageSize;
freeTempSpace(pBt);
@@ -3124,7 +3158,7 @@ static int lockBtree(BtShared *pBt){
return SQLITE_OK;
page1_init_failed:
- releasePage(pPage1);
+ releasePageOne(pPage1);
pBt->pPage1 = 0;
return rc;
}
@@ -3169,7 +3203,7 @@ static void unlockBtreeIfUnused(BtShared *pBt){
assert( pPage1->aData );
assert( sqlite3PagerRefcount(pBt->pPager)==1 );
pBt->pPage1 = 0;
- releasePageNotNull(pPage1);
+ releasePageOne(pPage1);
}
}
@@ -4035,7 +4069,6 @@ int sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode, int writeOnly){
if( pBtree ){
sqlite3BtreeEnter(pBtree);
for(p=pBtree->pBt->pCursor; p; p=p->pNext){
- int i;
if( writeOnly && (p->curFlags & BTCF_WriteFlag)==0 ){
if( p->eState==CURSOR_VALID || p->eState==CURSOR_SKIPNEXT ){
rc = saveCursorPosition(p);
@@ -4049,10 +4082,7 @@ int sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode, int writeOnly){
p->eState = CURSOR_FAULT;
p->skipNext = errCode;
}
- for(i=0; i<=p->iPage; i++){
- releasePage(p->apPage[i]);
- p->apPage[i] = 0;
- }
+ btreeReleaseAllCursorPages(p);
}
sqlite3BtreeLeave(pBtree);
}
@@ -4109,7 +4139,7 @@ int sqlite3BtreeRollback(Btree *p, int tripCode, int writeOnly){
if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage);
testcase( pBt->nPage!=nPage );
pBt->nPage = nPage;
- releasePage(pPage1);
+ releasePageOne(pPage1);
}
assert( countValidCursors(pBt, 1)==0 );
pBt->inTransaction = TRANS_READ;
@@ -4351,10 +4381,8 @@ void sqlite3BtreeCursorZero(BtCursor *p){
int sqlite3BtreeCloseCursor(BtCursor *pCur){
Btree *pBtree = pCur->pBtree;
if( pBtree ){
- int i;
BtShared *pBt = pCur->pBt;
sqlite3BtreeEnter(pBtree);
- sqlite3BtreeClearCursor(pCur);
assert( pBt->pCursor!=0 );
if( pBt->pCursor==pCur ){
pBt->pCursor = pCur->pNext;
@@ -4368,12 +4396,10 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){
pPrev = pPrev->pNext;
}while( ALWAYS(pPrev) );
}
- for(i=0; i<=pCur->iPage; i++){
- releasePage(pCur->apPage[i]);
- }
+ btreeReleaseAllCursorPages(pCur);
unlockBtreeIfUnused(pBt);
sqlite3_free(pCur->aOverflow);
- /* sqlite3_free(pCur); */
+ sqlite3_free(pCur->pKey);
sqlite3BtreeLeave(pBtree);
}
return SQLITE_OK;
@@ -4390,9 +4416,8 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){
#ifndef NDEBUG
static void assertCellInfo(BtCursor *pCur){
CellInfo info;
- int iPage = pCur->iPage;
memset(&info, 0, sizeof(info));
- btreeParseCell(pCur->apPage[iPage], pCur->ix, &info);
+ btreeParseCell(pCur->pPage, pCur->ix, &info);
assert( CORRUPT_DB || memcmp(&info, &pCur->info, sizeof(info))==0 );
}
#else
@@ -4400,9 +4425,8 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){
#endif
static SQLITE_NOINLINE void getCellInfo(BtCursor *pCur){
if( pCur->info.nSize==0 ){
- int iPage = pCur->iPage;
pCur->curFlags |= BTCF_ValidNKey;
- btreeParseCell(pCur->apPage[iPage],pCur->ix,&pCur->info);
+ btreeParseCell(pCur->pPage,pCur->ix,&pCur->info);
}else{
assertCellInfo(pCur);
}
@@ -4600,7 +4624,7 @@ static int accessPayload(
unsigned char *aPayload;
int rc = SQLITE_OK;
int iIdx = 0;
- MemPage *pPage = pCur->apPage[pCur->iPage]; /* Btree page of current entry */
+ MemPage *pPage = pCur->pPage; /* Btree page of current entry */
BtShared *pBt = pCur->pBt; /* Btree this cursor belongs to */
#ifdef SQLITE_DIRECT_OVERFLOW_READ
unsigned char * const pBufStart = pBuf; /* Start of original out buffer */
@@ -4796,8 +4820,8 @@ static int accessPayload(
int sqlite3BtreePayload(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
assert( cursorHoldsMutex(pCur) );
assert( pCur->eState==CURSOR_VALID );
- assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] );
- assert( pCur->ix<pCur->apPage[pCur->iPage]->nCell );
+ assert( pCur->iPage>=0 && pCur->pPage );
+ assert( pCur->ix<pCur->pPage->nCell );
return accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0);
}
@@ -4854,18 +4878,23 @@ static const void *fetchPayload(
BtCursor *pCur, /* Cursor pointing to entry to read from */
u32 *pAmt /* Write the number of available bytes here */
){
- u32 amt;
- assert( pCur!=0 && pCur->iPage>=0 && pCur->apPage[pCur->iPage]);
+ int amt;
+ assert( pCur!=0 && pCur->iPage>=0 && pCur->pPage);
assert( pCur->eState==CURSOR_VALID );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
assert( cursorOwnsBtShared(pCur) );
- assert( pCur->ix<pCur->apPage[pCur->iPage]->nCell );
+ assert( pCur->ix<pCur->pPage->nCell );
assert( pCur->info.nSize>0 );
- assert( pCur->info.pPayload>pCur->apPage[pCur->iPage]->aData || CORRUPT_DB );
- assert( pCur->info.pPayload<pCur->apPage[pCur->iPage]->aDataEnd ||CORRUPT_DB);
- amt = (int)(pCur->apPage[pCur->iPage]->aDataEnd - pCur->info.pPayload);
- if( pCur->info.nLocal<amt ) amt = pCur->info.nLocal;
- *pAmt = amt;
+ assert( pCur->info.pPayload>pCur->pPage->aData || CORRUPT_DB );
+ assert( pCur->info.pPayload<pCur->pPage->aDataEnd ||CORRUPT_DB);
+ amt = pCur->info.nLocal;
+ if( amt>(int)(pCur->pPage->aDataEnd - pCur->info.pPayload) ){
+ /* There is too little space on the page for the expected amount
+ ** of local content. Database must be corrupt. */
+ assert( CORRUPT_DB );
+ amt = MAX(0, (int)(pCur->pPage->aDataEnd - pCur->info.pPayload));
+ }
+ *pAmt = (u32)amt;
return (void*)pCur->info.pPayload;
}
@@ -4910,10 +4939,11 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){
}
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
- pCur->aiIdx[pCur->iPage++] = pCur->ix;
+ pCur->aiIdx[pCur->iPage] = pCur->ix;
+ pCur->apPage[pCur->iPage] = pCur->pPage;
pCur->ix = 0;
- return getAndInitPage(pBt, newPgno, &pCur->apPage[pCur->iPage],
- pCur, pCur->curPagerFlags);
+ pCur->iPage++;
+ return getAndInitPage(pBt, newPgno, &pCur->pPage, pCur, pCur->curPagerFlags);
}
#ifdef SQLITE_DEBUG
@@ -4947,20 +4977,23 @@ static void assertParentIndex(MemPage *pParent, int iIdx, Pgno iChild){
** the largest cell index.
*/
static void moveToParent(BtCursor *pCur){
+ MemPage *pLeaf;
assert( cursorOwnsBtShared(pCur) );
assert( pCur->eState==CURSOR_VALID );
assert( pCur->iPage>0 );
- assert( pCur->apPage[pCur->iPage] );
+ assert( pCur->pPage );
assertParentIndex(
pCur->apPage[pCur->iPage-1],
pCur->aiIdx[pCur->iPage-1],
- pCur->apPage[pCur->iPage]->pgno
+ pCur->pPage->pgno
);
testcase( pCur->aiIdx[pCur->iPage-1] > pCur->apPage[pCur->iPage-1]->nCell );
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
pCur->ix = pCur->aiIdx[pCur->iPage-1];
- releasePageNotNull(pCur->apPage[pCur->iPage--]);
+ pLeaf = pCur->pPage;
+ pCur->pPage = pCur->apPage[--pCur->iPage];
+ releasePageNotNull(pLeaf);
}
/*
@@ -4972,9 +5005,9 @@ static void moveToParent(BtCursor *pCur){
** single child page. This can only happen with the table rooted at page 1.
**
** If the b-tree structure is empty, the cursor state is set to
-** CURSOR_INVALID. Otherwise, the cursor is set to point to the first
-** cell located on the root (or virtual root) page and the cursor state
-** is set to CURSOR_VALID.
+** CURSOR_INVALID and this routine returns SQLITE_EMPTY. Otherwise,
+** the cursor is set to point to the first cell located on the root
+** (or virtual root) page and the cursor state is set to CURSOR_VALID.
**
** If this function returns successfully, it may be assumed that the
** page-header flags indicate that the [virtual] root-page is the expected
@@ -4992,37 +5025,40 @@ static int moveToRoot(BtCursor *pCur){
assert( CURSOR_INVALID < CURSOR_REQUIRESEEK );
assert( CURSOR_VALID < CURSOR_REQUIRESEEK );
assert( CURSOR_FAULT > CURSOR_REQUIRESEEK );
- if( pCur->eState>=CURSOR_REQUIRESEEK ){
- if( pCur->eState==CURSOR_FAULT ){
- assert( pCur->skipNext!=SQLITE_OK );
- return pCur->skipNext;
- }
- sqlite3BtreeClearCursor(pCur);
- }
+ assert( pCur->eState < CURSOR_REQUIRESEEK || pCur->iPage<0 );
+ assert( pCur->pgnoRoot>0 || pCur->iPage<0 );
if( pCur->iPage>=0 ){
if( pCur->iPage ){
- do{
- assert( pCur->apPage[pCur->iPage]!=0 );
- releasePageNotNull(pCur->apPage[pCur->iPage--]);
- }while( pCur->iPage);
+ releasePageNotNull(pCur->pPage);
+ while( --pCur->iPage ){
+ releasePageNotNull(pCur->apPage[pCur->iPage]);
+ }
+ pCur->pPage = pCur->apPage[0];
goto skip_init;
}
}else if( pCur->pgnoRoot==0 ){
pCur->eState = CURSOR_INVALID;
- return SQLITE_OK;
+ return SQLITE_EMPTY;
}else{
assert( pCur->iPage==(-1) );
- rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->apPage[0],
+ if( pCur->eState>=CURSOR_REQUIRESEEK ){
+ if( pCur->eState==CURSOR_FAULT ){
+ assert( pCur->skipNext!=SQLITE_OK );
+ return pCur->skipNext;
+ }
+ sqlite3BtreeClearCursor(pCur);
+ }
+ rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->pPage,
0, pCur->curPagerFlags);
if( rc!=SQLITE_OK ){
pCur->eState = CURSOR_INVALID;
- return rc;
+ return rc;
}
pCur->iPage = 0;
- pCur->curIntKey = pCur->apPage[0]->intKey;
+ pCur->curIntKey = pCur->pPage->intKey;
}
- pRoot = pCur->apPage[0];
+ pRoot = pCur->pPage;
assert( pRoot->pgno==pCur->pgnoRoot );
/* If pCur->pKeyInfo is not NULL, then the caller that opened this cursor
@@ -5037,7 +5073,7 @@ static int moveToRoot(BtCursor *pCur){
** (or the freelist). */
assert( pRoot->intKey==1 || pRoot->intKey==0 );
if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){
- return SQLITE_CORRUPT_PGNO(pCur->apPage[pCur->iPage]->pgno);
+ return SQLITE_CORRUPT_PGNO(pCur->pPage->pgno);
}
skip_init:
@@ -5045,7 +5081,7 @@ skip_init:
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl);
- pRoot = pCur->apPage[0];
+ pRoot = pCur->pPage;
if( pRoot->nCell>0 ){
pCur->eState = CURSOR_VALID;
}else if( !pRoot->leaf ){
@@ -5056,6 +5092,7 @@ skip_init:
rc = moveToChild(pCur, subpage);
}else{
pCur->eState = CURSOR_INVALID;
+ rc = SQLITE_EMPTY;
}
return rc;
}
@@ -5074,7 +5111,7 @@ static int moveToLeftmost(BtCursor *pCur){
assert( cursorOwnsBtShared(pCur) );
assert( pCur->eState==CURSOR_VALID );
- while( rc==SQLITE_OK && !(pPage = pCur->apPage[pCur->iPage])->leaf ){
+ while( rc==SQLITE_OK && !(pPage = pCur->pPage)->leaf ){
assert( pCur->ix<pPage->nCell );
pgno = get4byte(findCell(pPage, pCur->ix));
rc = moveToChild(pCur, pgno);
@@ -5099,7 +5136,7 @@ static int moveToRightmost(BtCursor *pCur){
assert( cursorOwnsBtShared(pCur) );
assert( pCur->eState==CURSOR_VALID );
- while( !(pPage = pCur->apPage[pCur->iPage])->leaf ){
+ while( !(pPage = pCur->pPage)->leaf ){
pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
pCur->ix = pPage->nCell;
rc = moveToChild(pCur, pgno);
@@ -5122,14 +5159,13 @@ int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
rc = moveToRoot(pCur);
if( rc==SQLITE_OK ){
- if( pCur->eState==CURSOR_INVALID ){
- assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
- *pRes = 1;
- }else{
- assert( pCur->apPage[pCur->iPage]->nCell>0 );
- *pRes = 0;
- rc = moveToLeftmost(pCur);
- }
+ assert( pCur->pPage->nCell>0 );
+ *pRes = 0;
+ rc = moveToLeftmost(pCur);
+ }else if( rc==SQLITE_EMPTY ){
+ assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 );
+ *pRes = 1;
+ rc = SQLITE_OK;
}
return rc;
}
@@ -5153,28 +5189,26 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
for(ii=0; ii<pCur->iPage; ii++){
assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell );
}
- assert( pCur->ix==pCur->apPage[pCur->iPage]->nCell-1 );
- assert( pCur->apPage[pCur->iPage]->leaf );
+ assert( pCur->ix==pCur->pPage->nCell-1 );
+ assert( pCur->pPage->leaf );
#endif
return SQLITE_OK;
}
rc = moveToRoot(pCur);
if( rc==SQLITE_OK ){
- if( CURSOR_INVALID==pCur->eState ){
- assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
- *pRes = 1;
+ assert( pCur->eState==CURSOR_VALID );
+ *pRes = 0;
+ rc = moveToRightmost(pCur);
+ if( rc==SQLITE_OK ){
+ pCur->curFlags |= BTCF_AtLast;
}else{
- assert( pCur->eState==CURSOR_VALID );
- *pRes = 0;
- rc = moveToRightmost(pCur);
- if( rc==SQLITE_OK ){
- pCur->curFlags |= BTCF_AtLast;
- }else{
- pCur->curFlags &= ~BTCF_AtLast;
- }
-
+ pCur->curFlags &= ~BTCF_AtLast;
}
+ }else if( rc==SQLITE_EMPTY ){
+ assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 );
+ *pRes = 1;
+ rc = SQLITE_OK;
}
return rc;
}
@@ -5273,22 +5307,23 @@ int sqlite3BtreeMovetoUnpacked(
rc = moveToRoot(pCur);
if( rc ){
+ if( rc==SQLITE_EMPTY ){
+ assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 );
+ *pRes = -1;
+ return SQLITE_OK;
+ }
return rc;
}
- assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage] );
- assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->isInit );
- assert( pCur->eState==CURSOR_INVALID || pCur->apPage[pCur->iPage]->nCell>0 );
- if( pCur->eState==CURSOR_INVALID ){
- *pRes = -1;
- assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
- return SQLITE_OK;
- }
- assert( pCur->apPage[0]->intKey==pCur->curIntKey );
+ assert( pCur->pPage );
+ assert( pCur->pPage->isInit );
+ assert( pCur->eState==CURSOR_VALID );
+ assert( pCur->pPage->nCell > 0 );
+ assert( pCur->iPage==0 || pCur->apPage[0]->intKey==pCur->curIntKey );
assert( pCur->curIntKey || pIdxKey );
for(;;){
int lwr, upr, idx, c;
Pgno chldPg;
- MemPage *pPage = pCur->apPage[pCur->iPage];
+ MemPage *pPage = pCur->pPage;
u8 *pCell; /* Pointer to current cell in pPage */
/* pPage->nCell must be greater than zero. If this is the root-page
@@ -5416,7 +5451,7 @@ int sqlite3BtreeMovetoUnpacked(
*pRes = 0;
rc = SQLITE_OK;
pCur->ix = (u16)idx;
- if( pIdxKey->errCode ) rc = SQLITE_CORRUPT;
+ if( pIdxKey->errCode ) rc = SQLITE_CORRUPT_BKPT;
goto moveto_finish;
}
if( lwr>upr ) break;
@@ -5427,7 +5462,7 @@ int sqlite3BtreeMovetoUnpacked(
assert( lwr==upr+1 || (pPage->intKey && !pPage->leaf) );
assert( pPage->isInit );
if( pPage->leaf ){
- assert( pCur->ix<pCur->apPage[pCur->iPage]->nCell );
+ assert( pCur->ix<pCur->pPage->nCell );
pCur->ix = (u16)idx;
*pRes = c;
rc = SQLITE_OK;
@@ -5481,9 +5516,10 @@ i64 sqlite3BtreeRowCountEst(BtCursor *pCur){
** opcode, and it that case the cursor will always be valid and
** will always point to a leaf node. */
if( NEVER(pCur->eState!=CURSOR_VALID) ) return -1;
- if( NEVER(pCur->apPage[pCur->iPage]->leaf==0) ) return -1;
+ if( NEVER(pCur->pPage->leaf==0) ) return -1;
- for(n=1, i=0; i<=pCur->iPage; i++){
+ n = pCur->pPage->nCell;
+ for(i=0; i<pCur->iPage; i++){
n *= pCur->apPage[i]->nCell;
}
return n;
@@ -5536,7 +5572,7 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur){
}
}
- pPage = pCur->apPage[pCur->iPage];
+ pPage = pCur->pPage;
idx = ++pCur->ix;
assert( pPage->isInit );
@@ -5559,7 +5595,7 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur){
return SQLITE_DONE;
}
moveToParent(pCur);
- pPage = pCur->apPage[pCur->iPage];
+ pPage = pCur->pPage;
}while( pCur->ix>=pPage->nCell );
if( pPage->intKey ){
return sqlite3BtreeNext(pCur, 0);
@@ -5582,7 +5618,7 @@ int sqlite3BtreeNext(BtCursor *pCur, int flags){
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
if( pCur->eState!=CURSOR_VALID ) return btreeNext(pCur);
- pPage = pCur->apPage[pCur->iPage];
+ pPage = pCur->pPage;
if( (++pCur->ix)>=pPage->nCell ){
pCur->ix--;
return btreeNext(pCur);
@@ -5641,7 +5677,7 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur){
}
}
- pPage = pCur->apPage[pCur->iPage];
+ pPage = pCur->pPage;
assert( pPage->isInit );
if( !pPage->leaf ){
int idx = pCur->ix;
@@ -5660,7 +5696,7 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur){
assert( (pCur->curFlags & (BTCF_ValidOvfl))==0 );
pCur->ix--;
- pPage = pCur->apPage[pCur->iPage];
+ pPage = pCur->pPage;
if( pPage->intKey && !pPage->leaf ){
rc = sqlite3BtreePrevious(pCur, 0);
}else{
@@ -5678,7 +5714,7 @@ int sqlite3BtreePrevious(BtCursor *pCur, int flags){
pCur->info.nSize = 0;
if( pCur->eState!=CURSOR_VALID
|| pCur->ix==0
- || pCur->apPage[pCur->iPage]->leaf==0
+ || pCur->pPage->leaf==0
){
return btreePrevious(pCur);
}
@@ -6174,7 +6210,7 @@ static int clearCell(
unsigned char *pCell, /* First byte of the Cell */
CellInfo *pInfo /* Size information about the cell */
){
- BtShared *pBt = pPage->pBt;
+ BtShared *pBt;
Pgno ovflPgno;
int rc;
int nOvfl;
@@ -6190,6 +6226,7 @@ static int clearCell(
return SQLITE_CORRUPT_PGNO(pPage->pgno);
}
ovflPgno = get4byte(pCell + pInfo->nSize - 4);
+ pBt = pPage->pBt;
assert( pBt->usableSize > 4 );
ovflPageSize = pBt->usableSize - 4;
nOvfl = (pInfo->nPayload - pInfo->nLocal + ovflPageSize - 1)/ovflPageSize;
@@ -6257,21 +6294,20 @@ static int fillInCell(
){
int nPayload;
const u8 *pSrc;
- int nSrc, n, rc;
+ int nSrc, n, rc, mn;
int spaceLeft;
- MemPage *pOvfl = 0;
- MemPage *pToRelease = 0;
+ MemPage *pToRelease;
unsigned char *pPrior;
unsigned char *pPayload;
- BtShared *pBt = pPage->pBt;
- Pgno pgnoOvfl = 0;
+ BtShared *pBt;
+ Pgno pgnoOvfl;
int nHeader;
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
/* pPage is not necessarily writeable since pCell might be auxiliary
** buffer space that is separate from the pPage buffer area */
- assert( pCell<pPage->aData || pCell>=&pPage->aData[pBt->pageSize]
+ assert( pCell<pPage->aData || pCell>=&pPage->aData[pPage->pBt->pageSize]
|| sqlite3PagerIswriteable(pPage->pDbPage) );
/* Fill in the header. */
@@ -6291,25 +6327,36 @@ static int fillInCell(
}
/* Fill in the payload */
+ pPayload = &pCell[nHeader];
if( nPayload<=pPage->maxLocal ){
+ /* This is the common case where everything fits on the btree page
+ ** and no overflow pages are required. */
n = nHeader + nPayload;
testcase( n==3 );
testcase( n==4 );
if( n<4 ) n = 4;
*pnSize = n;
- spaceLeft = nPayload;
- pPrior = pCell;
- }else{
- int mn = pPage->minLocal;
- n = mn + (nPayload - mn) % (pPage->pBt->usableSize - 4);
- testcase( n==pPage->maxLocal );
- testcase( n==pPage->maxLocal+1 );
- if( n > pPage->maxLocal ) n = mn;
- spaceLeft = n;
- *pnSize = n + nHeader + 4;
- pPrior = &pCell[nHeader+n];
+ assert( nSrc<=nPayload );
+ testcase( nSrc<nPayload );
+ memcpy(pPayload, pSrc, nSrc);
+ memset(pPayload+nSrc, 0, nPayload-nSrc);
+ return SQLITE_OK;
}
- pPayload = &pCell[nHeader];
+
+ /* If we reach this point, it means that some of the content will need
+ ** to spill onto overflow pages.
+ */
+ mn = pPage->minLocal;
+ n = mn + (nPayload - mn) % (pPage->pBt->usableSize - 4);
+ testcase( n==pPage->maxLocal );
+ testcase( n==pPage->maxLocal+1 );
+ if( n > pPage->maxLocal ) n = mn;
+ spaceLeft = n;
+ *pnSize = n + nHeader + 4;
+ pPrior = &pCell[nHeader+n];
+ pToRelease = 0;
+ pgnoOvfl = 0;
+ pBt = pPage->pBt;
/* At this point variables should be set as follows:
**
@@ -6335,8 +6382,35 @@ static int fillInCell(
#endif
/* Write the payload into the local Cell and any extra into overflow pages */
- while( nPayload>0 ){
+ while( 1 ){
+ n = nPayload;
+ if( n>spaceLeft ) n = spaceLeft;
+
+ /* If pToRelease is not zero than pPayload points into the data area
+ ** of pToRelease. Make sure pToRelease is still writeable. */
+ assert( pToRelease==0 || sqlite3PagerIswriteable(pToRelease->pDbPage) );
+
+ /* If pPayload is part of the data area of pPage, then make sure pPage
+ ** is still writeable */
+ assert( pPayload<pPage->aData || pPayload>=&pPage->aData[pBt->pageSize]
+ || sqlite3PagerIswriteable(pPage->pDbPage) );
+
+ if( nSrc>=n ){
+ memcpy(pPayload, pSrc, n);
+ }else if( nSrc>0 ){
+ n = nSrc;
+ memcpy(pPayload, pSrc, n);
+ }else{
+ memset(pPayload, 0, n);
+ }
+ nPayload -= n;
+ if( nPayload<=0 ) break;
+ pPayload += n;
+ pSrc += n;
+ nSrc -= n;
+ spaceLeft -= n;
if( spaceLeft==0 ){
+ MemPage *pOvfl = 0;
#ifndef SQLITE_OMIT_AUTOVACUUM
Pgno pgnoPtrmap = pgnoOvfl; /* Overflow page pointer-map entry page */
if( pBt->autoVacuum ){
@@ -6389,30 +6463,6 @@ static int fillInCell(
pPayload = &pOvfl->aData[4];
spaceLeft = pBt->usableSize - 4;
}
- n = nPayload;
- if( n>spaceLeft ) n = spaceLeft;
-
- /* If pToRelease is not zero than pPayload points into the data area
- ** of pToRelease. Make sure pToRelease is still writeable. */
- assert( pToRelease==0 || sqlite3PagerIswriteable(pToRelease->pDbPage) );
-
- /* If pPayload is part of the data area of pPage, then make sure pPage
- ** is still writeable */
- assert( pPayload<pPage->aData || pPayload>=&pPage->aData[pBt->pageSize]
- || sqlite3PagerIswriteable(pPage->pDbPage) );
-
- if( nSrc>0 ){
- if( n>nSrc ) n = nSrc;
- assert( pSrc );
- memcpy(pPayload, pSrc, n);
- }else{
- memset(pPayload, 0, n);
- }
- nPayload -= n;
- pPayload += n;
- pSrc += n;
- nSrc -= n;
- spaceLeft -= n;
}
releasePage(pToRelease);
return SQLITE_OK;
@@ -6444,7 +6494,7 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
hdr = pPage->hdrOffset;
testcase( pc==get2byte(&data[hdr+5]) );
testcase( pc+sz==pPage->pBt->usableSize );
- if( pc < (u32)get2byte(&data[hdr+5]) || pc+sz > pPage->pBt->usableSize ){
+ if( pc+sz > pPage->pBt->usableSize ){
*pRC = SQLITE_CORRUPT_BKPT;
return;
}
@@ -7311,10 +7361,8 @@ static int balance_nonroot(
+ nMaxCells*sizeof(u16) /* b.szCell */
+ pBt->pageSize; /* aSpace1 */
- /* EVIDENCE-OF: R-28375-38319 SQLite will never request a scratch buffer
- ** that is more than 6 times the database page size. */
assert( szScratch<=6*(int)pBt->pageSize );
- b.apCell = sqlite3ScratchMalloc( szScratch );
+ b.apCell = sqlite3StackAllocRaw(0, szScratch );
if( b.apCell==0 ){
rc = SQLITE_NOMEM_BKPT;
goto balance_cleanup;
@@ -7892,7 +7940,7 @@ static int balance_nonroot(
** Cleanup before returning.
*/
balance_cleanup:
- sqlite3ScratchFree(b.apCell);
+ sqlite3StackFree(0, b.apCell);
for(i=0; i<nOld; i++){
releasePage(apOld[i]);
}
@@ -7991,7 +8039,7 @@ static int balance(BtCursor *pCur){
do {
int iPage = pCur->iPage;
- MemPage *pPage = pCur->apPage[iPage];
+ MemPage *pPage = pCur->pPage;
if( iPage==0 ){
if( pPage->nOverflow ){
@@ -8007,7 +8055,9 @@ static int balance(BtCursor *pCur){
pCur->iPage = 1;
pCur->ix = 0;
pCur->aiIdx[0] = 0;
- assert( pCur->apPage[1]->nOverflow );
+ pCur->apPage[0] = pPage;
+ pCur->pPage = pCur->apPage[1];
+ assert( pCur->pPage->nOverflow );
}
}else{
break;
@@ -8087,6 +8137,7 @@ static int balance(BtCursor *pCur){
releasePage(pPage);
pCur->iPage--;
assert( pCur->iPage>=0 );
+ pCur->pPage = pCur->apPage[pCur->iPage];
}
}while( rc==SQLITE_OK );
@@ -8218,7 +8269,7 @@ int sqlite3BtreeInsert(
}
assert( pCur->eState==CURSOR_VALID || (pCur->eState==CURSOR_INVALID && loc) );
- pPage = pCur->apPage[pCur->iPage];
+ pPage = pCur->pPage;
assert( pPage->intKey || pX->nKey>=0 );
assert( pPage->leaf || !pPage->intKey );
@@ -8305,10 +8356,10 @@ int sqlite3BtreeInsert(
** fails. Internal data structure corruption will result otherwise.
** Also, set the cursor state to invalid. This stops saveCursorPosition()
** from trying to save the current position of the cursor. */
- pCur->apPage[pCur->iPage]->nOverflow = 0;
+ pCur->pPage->nOverflow = 0;
pCur->eState = CURSOR_INVALID;
if( (flags & BTREE_SAVEPOSITION) && rc==SQLITE_OK ){
- rc = moveToRoot(pCur);
+ btreeReleaseAllCursorPages(pCur);
if( pCur->pKeyInfo ){
assert( pCur->pKey==0 );
pCur->pKey = sqlite3Malloc( pX->nKey );
@@ -8322,7 +8373,7 @@ int sqlite3BtreeInsert(
pCur->nKey = pX->nKey;
}
}
- assert( pCur->apPage[pCur->iPage]->nOverflow==0 );
+ assert( pCur->iPage<0 || pCur->pPage->nOverflow==0 );
end_insert:
return rc;
@@ -8363,13 +8414,13 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
assert( pCur->curFlags & BTCF_WriteFlag );
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
assert( !hasReadConflicts(p, pCur->pgnoRoot) );
- assert( pCur->ix<pCur->apPage[pCur->iPage]->nCell );
+ assert( pCur->ix<pCur->pPage->nCell );
assert( pCur->eState==CURSOR_VALID );
assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 );
iCellDepth = pCur->iPage;
iCellIdx = pCur->ix;
- pPage = pCur->apPage[iCellDepth];
+ pPage = pCur->pPage;
pCell = findCell(pPage, iCellIdx);
/* If the bPreserve flag is set to true, then the cursor position must
@@ -8435,11 +8486,16 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
** node. The cell from the leaf node needs to be moved to the internal
** node to replace the deleted cell. */
if( !pPage->leaf ){
- MemPage *pLeaf = pCur->apPage[pCur->iPage];
+ MemPage *pLeaf = pCur->pPage;
int nCell;
- Pgno n = pCur->apPage[iCellDepth+1]->pgno;
+ Pgno n;
unsigned char *pTmp;
+ if( iCellDepth<pCur->iPage-1 ){
+ n = pCur->apPage[iCellDepth+1]->pgno;
+ }else{
+ n = pCur->pPage->pgno;
+ }
pCell = findCell(pLeaf, pLeaf->nCell-1);
if( pCell<&pLeaf->aData[4] ) return SQLITE_CORRUPT_BKPT;
nCell = pLeaf->xCellSize(pLeaf, pCell);
@@ -8471,16 +8527,19 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
** well. */
rc = balance(pCur);
if( rc==SQLITE_OK && pCur->iPage>iCellDepth ){
+ releasePageNotNull(pCur->pPage);
+ pCur->iPage--;
while( pCur->iPage>iCellDepth ){
releasePage(pCur->apPage[pCur->iPage--]);
}
+ pCur->pPage = pCur->apPage[pCur->iPage];
rc = balance(pCur);
}
if( rc==SQLITE_OK ){
if( bSkipnext ){
assert( bPreserve && (pCur->iPage==iCellDepth || CORRUPT_DB) );
- assert( pPage==pCur->apPage[pCur->iPage] || CORRUPT_DB );
+ assert( pPage==pCur->pPage || CORRUPT_DB );
assert( (pPage->nCell>0 || CORRUPT_DB) && iCellIdx<=pPage->nCell );
pCur->eState = CURSOR_SKIPNEXT;
if( iCellIdx>=pPage->nCell ){
@@ -8492,8 +8551,10 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
}else{
rc = moveToRoot(pCur);
if( bPreserve ){
+ btreeReleaseAllCursorPages(pCur);
pCur->eState = CURSOR_REQUIRESEEK;
}
+ if( rc==SQLITE_EMPTY ) rc = SQLITE_OK;
}
}
return rc;
@@ -8958,11 +9019,11 @@ int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
i64 nEntry = 0; /* Value to return in *pnEntry */
int rc; /* Return code */
- if( pCur->pgnoRoot==0 ){
+ rc = moveToRoot(pCur);
+ if( rc==SQLITE_EMPTY ){
*pnEntry = 0;
return SQLITE_OK;
}
- rc = moveToRoot(pCur);
/* Unless an error occurs, the following loop runs one iteration for each
** page in the B-Tree structure (not including overflow pages).
@@ -8975,7 +9036,7 @@ int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
** this page contains countable entries. Increment the entry counter
** accordingly.
*/
- pPage = pCur->apPage[pCur->iPage];
+ pPage = pCur->pPage;
if( pPage->leaf || !pPage->intKey ){
nEntry += pPage->nCell;
}
@@ -8998,10 +9059,10 @@ int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
return moveToRoot(pCur);
}
moveToParent(pCur);
- }while ( pCur->ix>=pCur->apPage[pCur->iPage]->nCell );
+ }while ( pCur->ix>=pCur->pPage->nCell );
pCur->ix++;
- pPage = pCur->apPage[pCur->iPage];
+ pPage = pCur->pPage;
}
/* Descend to the child node of the cell that the cursor currently
@@ -9842,7 +9903,7 @@ int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){
&& pCsr->pBt->inTransaction==TRANS_WRITE );
assert( hasSharedCacheTableLock(pCsr->pBtree, pCsr->pgnoRoot, 0, 2) );
assert( !hasReadConflicts(pCsr->pBtree, pCsr->pgnoRoot) );
- assert( pCsr->apPage[pCsr->iPage]->intKey );
+ assert( pCsr->pPage->intKey );
return accessPayload(pCsr, offset, amt, (unsigned char *)z, 1);
}
diff --git a/chromium/third_party/sqlite/src/src/btree.h b/chromium/third_party/sqlite/src/src/btree.h
index 7ba2cab407d..3a0b008abad 100644
--- a/chromium/third_party/sqlite/src/src/btree.h
+++ b/chromium/third_party/sqlite/src/src/btree.h
@@ -232,6 +232,7 @@ int sqlite3BtreeCursor(
struct KeyInfo*, /* First argument to compare function */
BtCursor *pCursor /* Space to write cursor structure */
);
+BtCursor *sqlite3BtreeFakeValidCursor(void);
int sqlite3BtreeCursorSize(void);
void sqlite3BtreeCursorZero(BtCursor*);
void sqlite3BtreeCursorHintFlags(BtCursor*, unsigned);
diff --git a/chromium/third_party/sqlite/src/src/btreeInt.h b/chromium/third_party/sqlite/src/src/btreeInt.h
index 139a0abb7bf..0694b31a78c 100644
--- a/chromium/third_party/sqlite/src/src/btreeInt.h
+++ b/chromium/third_party/sqlite/src/src/btreeInt.h
@@ -500,6 +500,11 @@ struct CellInfo {
** eState==FAULT: Cursor fault with skipNext as error code.
*/
struct BtCursor {
+ u8 eState; /* One of the CURSOR_XXX constants (see below) */
+ u8 curFlags; /* zero or more BTCF_* flags defined below */
+ u8 curPagerFlags; /* Flags to send to sqlite3PagerGet() */
+ u8 hints; /* As configured by CursorSetHints() */
+ int nOvflAlloc; /* Allocated size of aOverflow[] array */
Btree *pBtree; /* The Btree to which this cursor belongs */
BtShared *pBt; /* The BtShared this cursor points to */
BtCursor *pNext; /* Forms a linked list of all cursors */
@@ -508,13 +513,8 @@ struct BtCursor {
i64 nKey; /* Size of pKey, or last integer key */
void *pKey; /* Saved key that was cursor last known position */
Pgno pgnoRoot; /* The root page of this tree */
- int nOvflAlloc; /* Allocated size of aOverflow[] array */
int skipNext; /* Prev() is noop if negative. Next() is noop if positive.
** Error code if eState==CURSOR_FAULT */
- u8 curFlags; /* zero or more BTCF_* flags defined below */
- u8 curPagerFlags; /* Flags to send to sqlite3PagerGet() */
- u8 eState; /* One of the CURSOR_XXX constants (see below) */
- u8 hints; /* As configured by CursorSetHints() */
/* All fields above are zeroed when the cursor is allocated. See
** sqlite3BtreeCursorZero(). Fields that follow must be manually
** initialized. */
@@ -523,7 +523,8 @@ struct BtCursor {
u16 ix; /* Current index for apPage[iPage] */
u16 aiIdx[BTCURSOR_MAX_DEPTH-1]; /* Current index in apPage[i] */
struct KeyInfo *pKeyInfo; /* Arg passed to comparison function */
- MemPage *apPage[BTCURSOR_MAX_DEPTH]; /* Pages from root to current page */
+ MemPage *pPage; /* Current page */
+ MemPage *apPage[BTCURSOR_MAX_DEPTH-1]; /* Stack of parents of current page */
};
/*
diff --git a/chromium/third_party/sqlite/src/src/build.c b/chromium/third_party/sqlite/src/src/build.c
index 60200946911..15a9fda405c 100644
--- a/chromium/third_party/sqlite/src/src/build.c
+++ b/chromium/third_party/sqlite/src/src/build.c
@@ -479,7 +479,7 @@ void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char *zIdxName){
}
freeIndex(db, pIndex);
}
- db->flags |= SQLITE_InternChanges;
+ db->mDbFlags |= DBFLAG_SchemaChange;
}
/*
@@ -514,28 +514,26 @@ void sqlite3CollapseDatabaseArray(sqlite3 *db){
/*
** Reset the schema for the database at index iDb. Also reset the
-** TEMP schema.
+** TEMP schema. The reset is deferred if db->nSchemaLock is not zero.
+** Deferred resets may be run by calling with iDb<0.
*/
void sqlite3ResetOneSchema(sqlite3 *db, int iDb){
- Db *pDb;
+ int i;
assert( iDb<db->nDb );
- /* Case 1: Reset the single schema identified by iDb */
- pDb = &db->aDb[iDb];
- assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
- assert( pDb->pSchema!=0 );
- sqlite3SchemaClear(pDb->pSchema);
+ if( iDb>=0 ){
+ assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
+ DbSetProperty(db, iDb, DB_ResetWanted);
+ DbSetProperty(db, 1, DB_ResetWanted);
+ }
- /* If any database other than TEMP is reset, then also reset TEMP
- ** since TEMP might be holding triggers that reference tables in the
- ** other database.
- */
- if( iDb!=1 ){
- pDb = &db->aDb[1];
- assert( pDb->pSchema!=0 );
- sqlite3SchemaClear(pDb->pSchema);
+ if( db->nSchemaLock==0 ){
+ for(i=0; i<db->nDb; i++){
+ if( DbHasProperty(db, i, DB_ResetWanted) ){
+ sqlite3SchemaClear(db->aDb[i].pSchema);
+ }
+ }
}
- return;
}
/*
@@ -545,13 +543,14 @@ 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);
}
}
- db->flags &= ~SQLITE_InternChanges;
+ db->mDbFlags &= ~DBFLAG_SchemaChange;
sqlite3VtabUnlockList(db);
sqlite3BtreeLeaveAll(db);
sqlite3CollapseDatabaseArray(db);
@@ -561,7 +560,7 @@ void sqlite3ResetAllSchemasOfConnection(sqlite3 *db){
** This routine is called when a commit occurs.
*/
void sqlite3CommitInternalChanges(sqlite3 *db){
- db->flags &= ~SQLITE_InternChanges;
+ db->mDbFlags &= ~DBFLAG_SchemaChange;
}
/*
@@ -599,13 +598,16 @@ void sqlite3DeleteColumnNames(sqlite3 *db, Table *pTable){
*/
static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){
Index *pIndex, *pNext;
- TESTONLY( int nLookaside; ) /* Used to verify lookaside not used for schema */
+#ifdef SQLITE_DEBUG
/* Record the number of outstanding lookaside allocations in schema Tables
** prior to doing any free() operations. Since schema Tables do not use
** lookaside, this number should not change. */
- TESTONLY( nLookaside = (db && (pTable->tabFlags & TF_Ephemeral)==0) ?
- db->lookaside.nOut : 0 );
+ int nLookaside = 0;
+ if( db && (pTable->tabFlags & TF_Ephemeral)==0 ){
+ nLookaside = sqlite3LookasideUsed(db, 0);
+ }
+#endif
/* Delete all indices associated with this table. */
for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){
@@ -639,7 +641,7 @@ static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){
sqlite3DbFree(db, pTable);
/* Verify that no lookaside memory was used by schema tables */
- assert( nLookaside==0 || nLookaside==db->lookaside.nOut );
+ assert( nLookaside==0 || nLookaside==sqlite3LookasideUsed(db,0) );
}
void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
/* Do not delete the table until the reference count reaches zero. */
@@ -665,7 +667,7 @@ void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){
pDb = &db->aDb[iDb];
p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName, 0);
sqlite3DeleteTable(db, p);
- db->flags |= SQLITE_InternChanges;
+ db->mDbFlags |= DBFLAG_SchemaChange;
}
/*
@@ -778,7 +780,8 @@ int sqlite3TwoPartName(
return -1;
}
}else{
- assert( db->init.iDb==0 || db->init.busy || (db->flags & SQLITE_Vacuum)!=0);
+ assert( db->init.iDb==0 || db->init.busy
+ || (db->mDbFlags & DBFLAG_Vacuum)!=0);
iDb = db->init.iDb;
*pUnqual = pName1;
}
@@ -1010,7 +1013,8 @@ void sqlite3StartTable(
}else
#endif
{
- pParse->addrCrTab = sqlite3VdbeAddOp2(v, OP_CreateTable, iDb, reg2);
+ pParse->addrCrTab =
+ sqlite3VdbeAddOp3(v, OP_CreateBtree, iDb, reg2, BTREE_INTKEY);
}
sqlite3OpenMasterTable(pParse, iDb);
sqlite3VdbeAddOp2(v, OP_NewRowid, 0, reg1);
@@ -1059,12 +1063,10 @@ void sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){
Column *pCol;
sqlite3 *db = pParse->db;
if( (p = pParse->pNewTable)==0 ) return;
-#if SQLITE_MAX_COLUMN
if( p->nCol+1>db->aLimit[SQLITE_LIMIT_COLUMN] ){
sqlite3ErrorMsg(pParse, "too many columns on %s", p->zName);
return;
}
-#endif
z = sqlite3DbMallocRaw(db, pName->n + pType->n + 2);
if( z==0 ) return;
memcpy(z, pName->z, pName->n);
@@ -1670,9 +1672,8 @@ static int hasColumn(const i16 *aiCol, int nCol, int x){
** Changes include:
**
** (1) Set all columns of the PRIMARY KEY schema object to be NOT NULL.
-** (2) Convert the OP_CreateTable into an OP_CreateIndex. There is
-** no rowid btree for a WITHOUT ROWID. Instead, the canonical
-** data storage is a covering index btree.
+** (2) Convert P3 parameter of the OP_CreateBtree from BTREE_INTKEY
+** into BTREE_BLOBKEY.
** (3) Bypass the creation of the sqlite_master table entry
** for the PRIMARY KEY as the primary key index is now
** identified by the sqlite_master table entry of the table itself.
@@ -1680,7 +1681,7 @@ static int hasColumn(const i16 *aiCol, int nCol, int x){
** schema to the rootpage from the main table.
** (5) Add all table columns to the PRIMARY KEY Index object
** so that the PRIMARY KEY is a covering index. The surplus
-** columns are part of KeyInfo.nXField and are not used for
+** columns are part of KeyInfo.nAllField and are not used for
** sorting or lookup or uniqueness checks.
** (6) Replace the rowid tail on all automatically generated UNIQUE
** indices with the PRIMARY KEY columns.
@@ -1709,13 +1710,12 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
** virtual tables */
if( IN_DECLARE_VTAB ) return;
- /* Convert the OP_CreateTable opcode that would normally create the
- ** root-page for the table into an OP_CreateIndex opcode. The index
- ** created will become the PRIMARY KEY index.
+ /* Convert the P3 operand of the OP_CreateBtree opcode from BTREE_INTKEY
+ ** into BTREE_BLOBKEY.
*/
if( pParse->addrCrTab ){
assert( v );
- sqlite3VdbeChangeOpcode(v, pParse->addrCrTab, OP_CreateIndex);
+ sqlite3VdbeChangeP3(v, pParse->addrCrTab, BTREE_BLOBKEY);
}
/* Locate the PRIMARY KEY index. Or, if this table was originally
@@ -2055,7 +2055,7 @@ void sqlite3EndTable(
return;
}
pParse->pNewTable = 0;
- db->flags |= SQLITE_InternChanges;
+ db->mDbFlags |= DBFLAG_SchemaChange;
#ifndef SQLITE_OMIT_ALTERTABLE
if( !p->pSelect ){
@@ -2154,6 +2154,9 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
int nErr = 0; /* Number of errors encountered */
int n; /* Temporarily holds the number of cursors assigned */
sqlite3 *db = pParse->db; /* Database connection for malloc errors */
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ int rc;
+#endif
#ifndef SQLITE_OMIT_AUTHORIZATION
sqlite3_xauth xAuth; /* Saved xAuth pointer */
#endif
@@ -2161,8 +2164,11 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
assert( pTable );
#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( sqlite3VtabCallConnect(pParse, pTable) ){
- return SQLITE_ERROR;
+ db->nSchemaLock++;
+ rc = sqlite3VtabCallConnect(pParse, pTable);
+ db->nSchemaLock--;
+ if( rc ){
+ return 1;
}
if( IsVirtual(pTable) ) return 0;
#endif
@@ -2358,14 +2364,6 @@ static void destroyRootPage(Parse *pParse, int iTable, int iDb){
** is also added (this can happen with an auto-vacuum database).
*/
static void destroyTable(Parse *pParse, Table *pTab){
-#ifdef SQLITE_OMIT_AUTOVACUUM
- Index *pIdx;
- int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
- destroyRootPage(pParse, pTab->tnum, iDb);
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- destroyRootPage(pParse, pIdx->tnum, iDb);
- }
-#else
/* If the database may be auto-vacuum capable (if SQLITE_OMIT_AUTOVACUUM
** is not defined), then it is important to call OP_Destroy on the
** table and index root-pages in order, starting with the numerically
@@ -2408,7 +2406,6 @@ static void destroyTable(Parse *pParse, Table *pTab){
iDestroyed = iLargest;
}
}
-#endif
}
/*
@@ -2835,7 +2832,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
addr2 = sqlite3VdbeCurrentAddr(v);
}
sqlite3VdbeAddOp3(v, OP_SorterData, iSorter, regRecord, iIdx);
- sqlite3VdbeAddOp3(v, OP_Last, iIdx, 0, -1);
+ sqlite3VdbeAddOp1(v, OP_SeekEnd, iIdx);
sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdx, regRecord);
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
sqlite3ReleaseTempReg(pParse, regRecord);
@@ -3324,7 +3321,7 @@ void sqlite3CreateIndex(
sqlite3OomFault(db);
goto exit_create_index;
}
- db->flags |= SQLITE_InternChanges;
+ db->mDbFlags |= DBFLAG_SchemaChange;
if( pTblName!=0 ){
pIndex->tnum = db->init.newTnum;
}
@@ -3360,7 +3357,7 @@ void sqlite3CreateIndex(
** that case the convertToWithoutRowidTable() routine will replace
** the Noop with a Goto to jump over the VDBE code generated below. */
pIndex->tnum = sqlite3VdbeAddOp0(v, OP_Noop);
- sqlite3VdbeAddOp2(v, OP_CreateIndex, iDb, iMem);
+ sqlite3VdbeAddOp3(v, OP_CreateBtree, iDb, iMem, BTREE_BLOBKEY);
/* Gather the complete text of the CREATE INDEX statement into
** the zStmt variable
@@ -3882,8 +3879,10 @@ SrcList *sqlite3SrcListAppendFromTerm(
*/
void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pIndexedBy){
assert( pIndexedBy!=0 );
- if( p && ALWAYS(p->nSrc>0) ){
- struct SrcList_item *pItem = &p->a[p->nSrc-1];
+ if( p && pIndexedBy->n>0 ){
+ struct SrcList_item *pItem;
+ assert( p->nSrc>0 );
+ pItem = &p->a[p->nSrc-1];
assert( pItem->fg.notIndexed==0 );
assert( pItem->fg.isIndexedBy==0 );
assert( pItem->fg.isTabFunc==0 );
@@ -3893,7 +3892,7 @@ void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pIndexedBy){
pItem->fg.notIndexed = 1;
}else{
pItem->u1.zIndexedBy = sqlite3NameFromToken(pParse->db, pIndexedBy);
- pItem->fg.isIndexedBy = (pItem->u1.zIndexedBy!=0);
+ pItem->fg.isIndexedBy = 1;
}
}
}
diff --git a/chromium/third_party/sqlite/src/src/callback.c b/chromium/third_party/sqlite/src/src/callback.c
index eb2e31bf3f3..38ba172ccdf 100644
--- a/chromium/third_party/sqlite/src/src/callback.c
+++ b/chromium/third_party/sqlite/src/src/callback.c
@@ -374,7 +374,7 @@ FuncDef *sqlite3FindFunction(
/* If no match is found, search the built-in functions.
**
- ** If the SQLITE_PreferBuiltin flag is set, then search the built-in
+ ** If the DBFLAG_PreferBuiltin flag is set, then search the built-in
** functions even if a prior app-defined function was found. And give
** priority to built-in functions.
**
@@ -384,7 +384,7 @@ FuncDef *sqlite3FindFunction(
** new function. But the FuncDefs for built-in functions are read-only.
** So we must not search for built-ins when creating a new function.
*/
- if( !createFlag && (pBest==0 || (db->flags & SQLITE_PreferBuiltin)!=0) ){
+ if( !createFlag && (pBest==0 || (db->mDbFlags & DBFLAG_PreferBuiltin)!=0) ){
bestScore = 0;
h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % SQLITE_FUNC_HASH_SZ;
p = functionSearch(h, zName);
@@ -457,8 +457,8 @@ void sqlite3SchemaClear(void *p){
pSchema->pSeqTab = 0;
if( pSchema->schemaFlags & DB_SchemaLoaded ){
pSchema->iGeneration++;
- pSchema->schemaFlags &= ~DB_SchemaLoaded;
}
+ pSchema->schemaFlags &= ~(DB_SchemaLoaded|DB_ResetWanted);
}
/*
diff --git a/chromium/third_party/sqlite/src/src/ctime.c b/chromium/third_party/sqlite/src/src/ctime.c
index 059bb8426fa..94309244bd3 100644
--- a/chromium/third_party/sqlite/src/src/ctime.c
+++ b/chromium/third_party/sqlite/src/src/ctime.c
@@ -184,6 +184,9 @@ static const char * const sqlite3azCompileOpt[] = {
#if SQLITE_ENABLE_ATOMIC_WRITE
"ENABLE_ATOMIC_WRITE",
#endif
+#if SQLITE_ENABLE_BATCH_ATOMIC_WRITE
+ "ENABLE_BATCH_ATOMIC_WRITE",
+#endif
#if SQLITE_ENABLE_CEROD
"ENABLE_CEROD",
#endif
diff --git a/chromium/third_party/sqlite/src/src/dbpage.c b/chromium/third_party/sqlite/src/src/dbpage.c
new file mode 100644
index 00000000000..9cd112a45f0
--- /dev/null
+++ b/chromium/third_party/sqlite/src/src/dbpage.c
@@ -0,0 +1,329 @@
+/*
+** 2017-10-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 contains an implementation of the "sqlite_dbpage" virtual table.
+**
+** The sqlite_dbpage virtual table is used to read or write whole raw
+** pages of the database file. The pager interface is used so that
+** uncommitted changes and changes recorded in the WAL file are correctly
+** retrieved.
+**
+** Usage example:
+**
+** SELECT data FROM sqlite_dbpage('aux1') WHERE pgno=123;
+**
+** This is an eponymous virtual table so it does not need to be created before
+** use. The optional argument to the sqlite_dbpage() table name is the
+** schema for the database file that is to be read. The default schema is
+** "main".
+**
+** The data field of sqlite_dbpage table can be updated. The new
+** value must be a BLOB which is the correct page size, otherwise the
+** update fails. Rows may not be deleted or inserted.
+*/
+
+#include "sqliteInt.h" /* Requires access to internal data structures */
+#if (defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)) \
+ && !defined(SQLITE_OMIT_VIRTUALTABLE)
+
+typedef struct DbpageTable DbpageTable;
+typedef struct DbpageCursor DbpageCursor;
+
+struct DbpageCursor {
+ sqlite3_vtab_cursor base; /* Base class. Must be first */
+ int pgno; /* Current page number */
+ int mxPgno; /* Last page to visit on this scan */
+};
+
+struct DbpageTable {
+ sqlite3_vtab base; /* Base class. Must be first */
+ sqlite3 *db; /* The database */
+ Pager *pPager; /* Pager being read/written */
+ int iDb; /* Index of database to analyze */
+ int szPage; /* Size of each page in bytes */
+ int nPage; /* Number of pages in the file */
+};
+
+/*
+** Connect to or create a dbpagevfs virtual table.
+*/
+static int dbpageConnect(
+ sqlite3 *db,
+ void *pAux,
+ int argc, const char *const*argv,
+ sqlite3_vtab **ppVtab,
+ char **pzErr
+){
+ DbpageTable *pTab = 0;
+ int rc = SQLITE_OK;
+ int iDb;
+
+ if( argc>=4 ){
+ Token nm;
+ sqlite3TokenInit(&nm, (char*)argv[3]);
+ iDb = sqlite3FindDb(db, &nm);
+ if( iDb<0 ){
+ *pzErr = sqlite3_mprintf("no such schema: %s", argv[3]);
+ return SQLITE_ERROR;
+ }
+ }else{
+ iDb = 0;
+ }
+ rc = sqlite3_declare_vtab(db,
+ "CREATE TABLE x(pgno INTEGER PRIMARY KEY, data BLOB, schema HIDDEN)");
+ if( rc==SQLITE_OK ){
+ pTab = (DbpageTable *)sqlite3_malloc64(sizeof(DbpageTable));
+ if( pTab==0 ) rc = SQLITE_NOMEM_BKPT;
+ }
+
+ assert( rc==SQLITE_OK || pTab==0 );
+ if( rc==SQLITE_OK ){
+ Btree *pBt = db->aDb[iDb].pBt;
+ memset(pTab, 0, sizeof(DbpageTable));
+ pTab->db = db;
+ pTab->iDb = iDb;
+ pTab->pPager = pBt ? sqlite3BtreePager(pBt) : 0;
+ }
+
+ *ppVtab = (sqlite3_vtab*)pTab;
+ return rc;
+}
+
+/*
+** Disconnect from or destroy a dbpagevfs virtual table.
+*/
+static int dbpageDisconnect(sqlite3_vtab *pVtab){
+ sqlite3_free(pVtab);
+ return SQLITE_OK;
+}
+
+/*
+** idxNum:
+**
+** 0 full table scan
+** 1 pgno=?1
+*/
+static int dbpageBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
+ int i;
+ pIdxInfo->estimatedCost = 1.0e6; /* Initial cost estimate */
+ for(i=0; i<pIdxInfo->nConstraint; i++){
+ struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i];
+ if( p->usable && p->iColumn<=0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ ){
+ pIdxInfo->estimatedRows = 1;
+ pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_UNIQUE;
+ pIdxInfo->estimatedCost = 1.0;
+ pIdxInfo->idxNum = 1;
+ pIdxInfo->aConstraintUsage[i].argvIndex = 1;
+ pIdxInfo->aConstraintUsage[i].omit = 1;
+ break;
+ }
+ }
+ if( pIdxInfo->nOrderBy>=1
+ && pIdxInfo->aOrderBy[0].iColumn<=0
+ && pIdxInfo->aOrderBy[0].desc==0
+ ){
+ pIdxInfo->orderByConsumed = 1;
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Open a new dbpagevfs cursor.
+*/
+static int dbpageOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
+ DbpageCursor *pCsr;
+
+ pCsr = (DbpageCursor *)sqlite3_malloc64(sizeof(DbpageCursor));
+ if( pCsr==0 ){
+ return SQLITE_NOMEM_BKPT;
+ }else{
+ memset(pCsr, 0, sizeof(DbpageCursor));
+ pCsr->base.pVtab = pVTab;
+ pCsr->pgno = -1;
+ }
+
+ *ppCursor = (sqlite3_vtab_cursor *)pCsr;
+ return SQLITE_OK;
+}
+
+/*
+** Close a dbpagevfs cursor.
+*/
+static int dbpageClose(sqlite3_vtab_cursor *pCursor){
+ DbpageCursor *pCsr = (DbpageCursor *)pCursor;
+ sqlite3_free(pCsr);
+ return SQLITE_OK;
+}
+
+/*
+** Move a dbpagevfs cursor to the next entry in the file.
+*/
+static int dbpageNext(sqlite3_vtab_cursor *pCursor){
+ int rc = SQLITE_OK;
+ DbpageCursor *pCsr = (DbpageCursor *)pCursor;
+ pCsr->pgno++;
+ return rc;
+}
+
+static int dbpageEof(sqlite3_vtab_cursor *pCursor){
+ DbpageCursor *pCsr = (DbpageCursor *)pCursor;
+ return pCsr->pgno > pCsr->mxPgno;
+}
+
+static int dbpageFilter(
+ sqlite3_vtab_cursor *pCursor,
+ int idxNum, const char *idxStr,
+ int argc, sqlite3_value **argv
+){
+ DbpageCursor *pCsr = (DbpageCursor *)pCursor;
+ DbpageTable *pTab = (DbpageTable *)pCursor->pVtab;
+ int rc = SQLITE_OK;
+ Btree *pBt = pTab->db->aDb[pTab->iDb].pBt;
+
+ pTab->szPage = sqlite3BtreeGetPageSize(pBt);
+ pTab->nPage = sqlite3BtreeLastPage(pBt);
+ if( idxNum==1 ){
+ pCsr->pgno = sqlite3_value_int(argv[0]);
+ if( pCsr->pgno<1 || pCsr->pgno>pTab->nPage ){
+ pCsr->pgno = 1;
+ pCsr->mxPgno = 0;
+ }else{
+ pCsr->mxPgno = pCsr->pgno;
+ }
+ }else{
+ pCsr->pgno = 1;
+ pCsr->mxPgno = pTab->nPage;
+ }
+ return rc;
+}
+
+static int dbpageColumn(
+ sqlite3_vtab_cursor *pCursor,
+ sqlite3_context *ctx,
+ int i
+){
+ DbpageCursor *pCsr = (DbpageCursor *)pCursor;
+ DbpageTable *pTab = (DbpageTable *)pCursor->pVtab;
+ int rc = SQLITE_OK;
+ switch( i ){
+ case 0: { /* pgno */
+ sqlite3_result_int(ctx, pCsr->pgno);
+ break;
+ }
+ case 1: { /* data */
+ DbPage *pDbPage = 0;
+ rc = sqlite3PagerGet(pTab->pPager, pCsr->pgno, (DbPage**)&pDbPage, 0);
+ if( rc==SQLITE_OK ){
+ sqlite3_result_blob(ctx, sqlite3PagerGetData(pDbPage), pTab->szPage,
+ SQLITE_TRANSIENT);
+ }
+ sqlite3PagerUnref(pDbPage);
+ break;
+ }
+ default: { /* schema */
+ sqlite3 *db = sqlite3_context_db_handle(ctx);
+ sqlite3_result_text(ctx, db->aDb[pTab->iDb].zDbSName, -1, SQLITE_STATIC);
+ break;
+ }
+ }
+ return SQLITE_OK;
+}
+
+static int dbpageRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
+ DbpageCursor *pCsr = (DbpageCursor *)pCursor;
+ *pRowid = pCsr->pgno;
+ return SQLITE_OK;
+}
+
+static int dbpageUpdate(
+ sqlite3_vtab *pVtab,
+ int argc,
+ sqlite3_value **argv,
+ sqlite_int64 *pRowid
+){
+ DbpageTable *pTab = (DbpageTable *)pVtab;
+ int pgno;
+ DbPage *pDbPage = 0;
+ int rc = SQLITE_OK;
+ char *zErr = 0;
+
+ if( argc==1 ){
+ zErr = "cannot delete";
+ goto update_fail;
+ }
+ pgno = sqlite3_value_int(argv[0]);
+ if( pgno<1 || pgno>pTab->nPage ){
+ zErr = "bad page number";
+ goto update_fail;
+ }
+ if( sqlite3_value_int(argv[1])!=pgno ){
+ zErr = "cannot insert";
+ goto update_fail;
+ }
+ if( sqlite3_value_type(argv[3])!=SQLITE_BLOB
+ || sqlite3_value_bytes(argv[3])!=pTab->szPage
+ ){
+ zErr = "bad page value";
+ goto update_fail;
+ }
+ rc = sqlite3PagerGet(pTab->pPager, pgno, (DbPage**)&pDbPage, 0);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3PagerWrite(pDbPage);
+ if( rc==SQLITE_OK ){
+ memcpy(sqlite3PagerGetData(pDbPage),
+ sqlite3_value_blob(argv[3]),
+ pTab->szPage);
+ }
+ }
+ sqlite3PagerUnref(pDbPage);
+ return rc;
+
+update_fail:
+ sqlite3_free(pVtab->zErrMsg);
+ pVtab->zErrMsg = sqlite3_mprintf("%s", zErr);
+ return SQLITE_ERROR;
+}
+
+/*
+** Invoke this routine to register the "dbpage" virtual table module
+*/
+int sqlite3DbpageRegister(sqlite3 *db){
+ static sqlite3_module dbpage_module = {
+ 0, /* iVersion */
+ dbpageConnect, /* xCreate */
+ dbpageConnect, /* xConnect */
+ dbpageBestIndex, /* xBestIndex */
+ dbpageDisconnect, /* xDisconnect */
+ dbpageDisconnect, /* xDestroy */
+ dbpageOpen, /* xOpen - open a cursor */
+ dbpageClose, /* xClose - close a cursor */
+ dbpageFilter, /* xFilter - configure scan constraints */
+ dbpageNext, /* xNext - advance a cursor */
+ dbpageEof, /* xEof - check for end of scan */
+ dbpageColumn, /* xColumn - read data */
+ dbpageRowid, /* xRowid - read data */
+ dbpageUpdate, /* xUpdate */
+ 0, /* xBegin */
+ 0, /* xSync */
+ 0, /* xCommit */
+ 0, /* xRollback */
+ 0, /* xFindMethod */
+ 0, /* xRename */
+ 0, /* xSavepoint */
+ 0, /* xRelease */
+ 0, /* xRollbackTo */
+ };
+ return sqlite3_create_module(db, "sqlite_dbpage", &dbpage_module, 0);
+}
+#elif defined(SQLITE_ENABLE_DBPAGE_VTAB)
+int sqlite3DbpageRegister(sqlite3 *db){ return SQLITE_OK; }
+#endif /* SQLITE_ENABLE_DBSTAT_VTAB */
diff --git a/chromium/third_party/sqlite/src/src/delete.c b/chromium/third_party/sqlite/src/src/delete.c
index 79e04676b2e..2d3a9b7dcff 100644
--- a/chromium/third_party/sqlite/src/src/delete.c
+++ b/chromium/third_party/sqlite/src/src/delete.c
@@ -502,7 +502,11 @@ void sqlite3DeleteFrom(
}
}else if( pPk ){
addrLoop = sqlite3VdbeAddOp1(v, OP_Rewind, iEphCur); VdbeCoverage(v);
- sqlite3VdbeAddOp2(v, OP_RowData, iEphCur, iKey);
+ if( IsVirtual(pTab) ){
+ sqlite3VdbeAddOp3(v, OP_Column, iEphCur, 0, iKey);
+ }else{
+ sqlite3VdbeAddOp2(v, OP_RowData, iEphCur, iKey);
+ }
assert( nKey==0 ); /* OP_Found will use a composite key */
}else{
addrLoop = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, 0, iKey);
diff --git a/chromium/third_party/sqlite/src/src/expr.c b/chromium/third_party/sqlite/src/src/expr.c
index b4c63bce4bb..8e5ea51f9d9 100644
--- a/chromium/third_party/sqlite/src/src/expr.c
+++ b/chromium/third_party/sqlite/src/src/expr.c
@@ -124,6 +124,11 @@ Expr *sqlite3ExprSkipCollate(Expr *pExpr){
** Return the collation sequence for the expression pExpr. If
** there is no defined collating sequence, return NULL.
**
+** See also: sqlite3ExprNNCollSeq()
+**
+** The sqlite3ExprNNCollSeq() works the same exact that it returns the
+** default collation if pExpr has no defined collation.
+**
** The collating sequence might be determined by a COLLATE operator
** or by the presence of a column with a defined collating sequence.
** COLLATE operators take first precedence. Left operands take
@@ -189,6 +194,32 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
}
/*
+** Return the collation sequence for the expression pExpr. If
+** there is no defined collating sequence, return a pointer to the
+** defautl collation sequence.
+**
+** See also: sqlite3ExprCollSeq()
+**
+** The sqlite3ExprCollSeq() routine works the same except that it
+** returns NULL if there is no defined collation.
+*/
+CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, Expr *pExpr){
+ CollSeq *p = sqlite3ExprCollSeq(pParse, pExpr);
+ if( p==0 ) p = pParse->db->pDfltColl;
+ assert( p!=0 );
+ return p;
+}
+
+/*
+** Return TRUE if the two expressions have equivalent collating sequences.
+*/
+int sqlite3ExprCollSeqMatch(Parse *pParse, Expr *pE1, Expr *pE2){
+ CollSeq *pColl1 = sqlite3ExprNNCollSeq(pParse, pE1);
+ CollSeq *pColl2 = sqlite3ExprNNCollSeq(pParse, pE2);
+ return sqlite3StrICmp(pColl1->zName, pColl2->zName)==0;
+}
+
+/*
** pExpr is an operand of a comparison operator. aff2 is the
** type affinity of the other operand. This routine returns the
** type affinity that should be used for the comparison operator.
@@ -775,7 +806,7 @@ Expr *sqlite3Expr(
){
Token x;
x.z = zToken;
- x.n = zToken ? sqlite3Strlen30(zToken) : 0;
+ x.n = sqlite3Strlen30(zToken);
return sqlite3ExprAlloc(db, op, &x, 0);
}
@@ -1302,10 +1333,9 @@ ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
Expr *pPriorSelectCol = 0;
assert( db!=0 );
if( p==0 ) return 0;
- pNew = sqlite3DbMallocRawNN(db,
- sizeof(*pNew)+sizeof(pNew->a[0])*(p->nExpr-1) );
+ pNew = sqlite3DbMallocRawNN(db, sqlite3DbMallocSize(db, p));
if( pNew==0 ) return 0;
- pNew->nAlloc = pNew->nExpr = p->nExpr;
+ pNew->nExpr = p->nExpr;
pItem = pNew->a;
pOldItem = p->a;
for(i=0; i<p->nExpr; i++, pItem++, pOldItem++){
@@ -1459,6 +1489,13 @@ Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
** Add a new element to the end of an expression list. If pList is
** initially NULL, then create a new expression list.
**
+** The pList argument must be either NULL or a pointer to an ExprList
+** obtained from a prior call to sqlite3ExprListAppend(). This routine
+** may not be used with an ExprList obtained from sqlite3ExprListDup().
+** Reason: This routine assumes that the number of slots in pList->a[]
+** is a power of two. That is true for sqlite3ExprListAppend() returns
+** but is not necessarily true from the return value of sqlite3ExprListDup().
+**
** If a memory allocation error occurs, the entire list is freed and
** NULL is returned. If non-NULL is returned, then it is guaranteed
** that the new entry was successfully appended.
@@ -1477,16 +1514,14 @@ ExprList *sqlite3ExprListAppend(
goto no_mem;
}
pList->nExpr = 0;
- pList->nAlloc = 1;
- }else if( pList->nExpr==pList->nAlloc ){
+ }else if( (pList->nExpr & (pList->nExpr-1))==0 ){
ExprList *pNew;
pNew = sqlite3DbRealloc(db, pList,
- sizeof(*pList)+(2*pList->nAlloc - 1)*sizeof(pList->a[0]));
+ sizeof(*pList)+(2*pList->nExpr - 1)*sizeof(pList->a[0]));
if( pNew==0 ){
goto no_mem;
}
pList = pNew;
- pList->nAlloc *= 2;
}
pItem = &pList->a[pList->nExpr++];
assert( offsetof(struct ExprList_item,zName)==sizeof(pItem->pExpr) );
@@ -1677,17 +1712,29 @@ void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){
u32 sqlite3ExprListFlags(const ExprList *pList){
int i;
u32 m = 0;
- if( pList ){
- for(i=0; i<pList->nExpr; i++){
- Expr *pExpr = pList->a[i].pExpr;
- assert( pExpr!=0 );
- m |= pExpr->flags;
- }
+ assert( pList!=0 );
+ for(i=0; i<pList->nExpr; i++){
+ Expr *pExpr = pList->a[i].pExpr;
+ assert( pExpr!=0 );
+ m |= pExpr->flags;
}
return m;
}
/*
+** This is a SELECT-node callback for the expression walker that
+** always "fails". By "fail" in this case, we mean set
+** pWalker->eCode to zero and abort.
+**
+** This callback is used by multiple expression walkers.
+*/
+int sqlite3SelectWalkFail(Walker *pWalker, Select *NotUsed){
+ UNUSED_PARAMETER(NotUsed);
+ pWalker->eCode = 0;
+ return WRC_Abort;
+}
+
+/*
** These routines are Walker callbacks used to check expressions to
** see if they are "constant" for some definition of constant. The
** Walker.eCode value determines the type of "constant" we are looking
@@ -1763,21 +1810,16 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
}
/* Fall through */
default:
- testcase( pExpr->op==TK_SELECT ); /* selectNodeIsConstant will disallow */
- testcase( pExpr->op==TK_EXISTS ); /* selectNodeIsConstant will disallow */
+ testcase( pExpr->op==TK_SELECT ); /* sqlite3SelectWalkFail will disallow */
+ testcase( pExpr->op==TK_EXISTS ); /* sqlite3SelectWalkFail will disallow */
return WRC_Continue;
}
}
-static int selectNodeIsConstant(Walker *pWalker, Select *NotUsed){
- UNUSED_PARAMETER(NotUsed);
- pWalker->eCode = 0;
- return WRC_Abort;
-}
static int exprIsConst(Expr *p, int initFlag, int iCur){
Walker w;
w.eCode = initFlag;
w.xExprCallback = exprNodeIsConstant;
- w.xSelectCallback = selectNodeIsConstant;
+ w.xSelectCallback = sqlite3SelectWalkFail;
#ifdef SQLITE_DEBUG
w.xSelectCallback2 = sqlite3SelectWalkAssert2;
#endif
@@ -1831,8 +1873,8 @@ static int exprNodeIsConstantOrGroupBy(Walker *pWalker, Expr *pExpr){
for(i=0; i<pGroupBy->nExpr; i++){
Expr *p = pGroupBy->a[i].pExpr;
if( sqlite3ExprCompare(0, pExpr, p, -1)<2 ){
- CollSeq *pColl = sqlite3ExprCollSeq(pWalker->pParse, p);
- if( pColl==0 || sqlite3_stricmp("BINARY", pColl->zName)==0 ){
+ CollSeq *pColl = sqlite3ExprNNCollSeq(pWalker->pParse, p);
+ if( sqlite3_stricmp("BINARY", pColl->zName)==0 ){
return WRC_Prune;
}
}
@@ -1900,7 +1942,7 @@ int sqlite3ExprContainsSubquery(Expr *p){
Walker w;
w.eCode = 1;
w.xExprCallback = sqlite3ExprWalkNoop;
- w.xSelectCallback = selectNodeIsConstant;
+ w.xSelectCallback = sqlite3SelectWalkFail;
#ifdef SQLITE_DEBUG
w.xSelectCallback2 = sqlite3SelectWalkAssert2;
#endif
@@ -1973,8 +2015,8 @@ int sqlite3ExprCanBeNull(const Expr *p){
case TK_BLOB:
return 0;
case TK_COLUMN:
- assert( p->pTab!=0 );
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);
default:
return 1;
@@ -2636,7 +2678,7 @@ int sqlite3CodeSubselect(
/* Loop through each expression in <exprlist>. */
r1 = sqlite3GetTempReg(pParse);
r2 = sqlite3GetTempReg(pParse);
- if( isRowid ) sqlite3VdbeAddOp2(v, OP_Null, 0, r2);
+ if( isRowid ) sqlite3VdbeAddOp4(v, OP_Blob, 0, r2, 0, "", P4_STATIC);
for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){
Expr *pE2 = pItem->pExpr;
int iValToIns;
@@ -3064,7 +3106,7 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
const char *z = pExpr->u.zToken;
assert( z!=0 );
c = sqlite3DecOrHexToI64(z, &value);
- if( c==1 || (c==2 && !negFlag) || (negFlag && value==SMALLEST_INT64)){
+ if( (c==3 && !negFlag) || (c==2) || (negFlag && value==SMALLEST_INT64)){
#ifdef SQLITE_OMIT_FLOATING_POINT
sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z);
#else
@@ -3078,7 +3120,7 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
}
#endif
}else{
- if( negFlag ){ value = c==2 ? SMALLEST_INT64 : -value; }
+ if( negFlag ){ value = c==3 ? SMALLEST_INT64 : -value; }
sqlite3VdbeAddOp4Dup8(v, OP_Int64, 0, iMem, 0, (u8*)&value, P4_INT64);
}
}
@@ -4233,7 +4275,9 @@ void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){
** Generate code that pushes the value of every element of the given
** expression list into a sequence of registers beginning at target.
**
-** Return the number of elements evaluated.
+** Return the number of elements evaluated. The number returned will
+** usually be pList->nExpr but might be reduced if SQLITE_ECEL_OMITREF
+** is defined.
**
** The SQLITE_ECEL_DUP flag prevents the arguments from being
** filled using OP_SCopy. OP_Copy must be used instead.
@@ -4244,6 +4288,8 @@ void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){
** The SQLITE_ECEL_REF flag means that expressions in the list with
** ExprList.a[].u.x.iOrderByCol>0 have already been evaluated and stored
** in registers at srcReg, and so the value can be copied from there.
+** If SQLITE_ECEL_OMITREF is also set, then the values with u.x.iOrderByCol>0
+** are simply omitted rather than being copied from srcReg.
*/
int sqlite3ExprCodeExprList(
Parse *pParse, /* Parsing context */
diff --git a/chromium/third_party/sqlite/src/src/func.c b/chromium/third_party/sqlite/src/src/func.c
index b85143edc7d..6f3f02b1736 100644
--- a/chromium/third_party/sqlite/src/src/func.c
+++ b/chromium/third_party/sqlite/src/src/func.c
@@ -865,7 +865,8 @@ static void likeFunc(
#ifdef SQLITE_TEST
sqlite3_like_count++;
#endif
- sqlite3_result_int(context, patternCompare(zB, zA, pInfo, escape)==SQLITE_MATCH);
+ sqlite3_result_int(context,
+ patternCompare(zB, zA, pInfo, escape)==SQLITE_MATCH);
}
}
@@ -1706,9 +1707,14 @@ void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){
/*
** pExpr points to an expression which implements a function. If
** it is appropriate to apply the LIKE optimization to that function
-** then set aWc[0] through aWc[2] to the wildcard characters and
-** return TRUE. If the function is not a LIKE-style function then
-** return FALSE.
+** then set aWc[0] through aWc[2] to the wildcard characters and the
+** escape character and then return TRUE. If the function is not a
+** LIKE-style function then return FALSE.
+**
+** The expression "a LIKE b ESCAPE c" is only considered a valid LIKE
+** operator if c is a string literal that is exactly one byte in length.
+** That one byte is stored in aWc[3]. aWc[3] is set to zero if there is
+** no ESCAPE clause.
**
** *pIsNocase is set to true if uppercase and lowercase are equivalent for
** the function (default for LIKE). If the function makes the distinction
@@ -1717,17 +1723,26 @@ void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){
*/
int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
FuncDef *pDef;
- if( pExpr->op!=TK_FUNCTION
- || !pExpr->x.pList
- || pExpr->x.pList->nExpr!=2
- ){
+ int nExpr;
+ if( pExpr->op!=TK_FUNCTION || !pExpr->x.pList ){
return 0;
}
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
- pDef = sqlite3FindFunction(db, pExpr->u.zToken, 2, SQLITE_UTF8, 0);
+ nExpr = pExpr->x.pList->nExpr;
+ pDef = sqlite3FindFunction(db, pExpr->u.zToken, nExpr, SQLITE_UTF8, 0);
if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_FUNC_LIKE)==0 ){
return 0;
}
+ if( nExpr<3 ){
+ aWc[3] = 0;
+ }else{
+ Expr *pEscape = pExpr->x.pList->a[2].pExpr;
+ char *zEscape;
+ if( pEscape->op!=TK_STRING ) return 0;
+ zEscape = pEscape->u.zToken;
+ if( zEscape[0]==0 || zEscape[1]!=0 ) return 0;
+ aWc[3] = zEscape[0];
+ }
/* The memcpy() statement assumes that the wildcard characters are
** the first three statements in the compareInfo structure. The
diff --git a/chromium/third_party/sqlite/src/src/global.c b/chromium/third_party/sqlite/src/src/global.c
index e309aa44da4..395ca06b7d7 100644
--- a/chromium/third_party/sqlite/src/src/global.c
+++ b/chromium/third_party/sqlite/src/src/global.c
@@ -199,6 +199,7 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
SQLITE_THREADSAFE==1, /* bFullMutex */
SQLITE_USE_URI, /* bOpenUri */
SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */
+ 0, /* bSmallMalloc */
0x7ffffffe, /* mxStrlen */
0, /* neverCorrupt */
SQLITE_DEFAULT_LOOKASIDE, /* szLookaside, nLookaside */
@@ -211,9 +212,6 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
0, 0, /* mnHeap, mxHeap */
SQLITE_DEFAULT_MMAP_SIZE, /* szMmap */
SQLITE_MAX_MMAP_SIZE, /* mxMmap */
- (void*)0, /* pScratch */
- 0, /* szScratch */
- 0, /* nScratch */
(void*)0, /* pPage */
0, /* szPage */
SQLITE_DEFAULT_PCACHE_INITSZ, /* nPage */
diff --git a/chromium/third_party/sqlite/src/src/insert.c b/chromium/third_party/sqlite/src/src/insert.c
index 1ac44306744..70b18cc137a 100644
--- a/chromium/third_party/sqlite/src/src/insert.c
+++ b/chromium/third_party/sqlite/src/src/insert.c
@@ -226,7 +226,7 @@ static int autoIncBegin(
){
int memId = 0; /* Register holding maximum rowid */
if( (pTab->tabFlags & TF_Autoincrement)!=0
- && (pParse->db->flags & SQLITE_Vacuum)==0
+ && (pParse->db->mDbFlags & DBFLAG_Vacuum)==0
){
Parse *pToplevel = sqlite3ParseToplevel(pParse);
AutoincInfo *pInfo;
@@ -484,7 +484,6 @@ void sqlite3Insert(
){
sqlite3 *db; /* The main database structure */
Table *pTab; /* The table to insert into. aka TABLE */
- char *zTab; /* Name of the table into which we are inserting */
int i, j; /* Loop counters */
Vdbe *v; /* Generate code into this virtual machine */
Index *pIdx; /* For looping over indices of the table */
@@ -540,8 +539,6 @@ void sqlite3Insert(
/* Locate the table into which we will be inserting new information.
*/
assert( pTabList->nSrc==1 );
- zTab = pTabList->a[0].zName;
- if( NEVER(zTab==0) ) goto insert_cleanup;
pTab = sqlite3SrcListLookup(pParse, pTabList);
if( pTab==0 ){
goto insert_cleanup;
@@ -2059,7 +2056,7 @@ static int xferOptimization(
Column *pDestCol = &pDest->aCol[i];
Column *pSrcCol = &pSrc->aCol[i];
#ifdef SQLITE_ENABLE_HIDDEN_COLUMNS
- if( (db->flags & SQLITE_Vacuum)==0
+ if( (db->mDbFlags & DBFLAG_Vacuum)==0
&& (pDestCol->colFlags | pSrcCol->colFlags) & COLFLAG_HIDDEN
){
return 0; /* Neither table may have __hidden__ columns */
@@ -2135,15 +2132,15 @@ static int xferOptimization(
regRowid = sqlite3GetTempReg(pParse);
sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite);
assert( HasRowid(pDest) || destHasUniqueIdx );
- if( (db->flags & SQLITE_Vacuum)==0 && (
+ if( (db->mDbFlags & DBFLAG_Vacuum)==0 && (
(pDest->iPKey<0 && pDest->pIndex!=0) /* (1) */
|| destHasUniqueIdx /* (2) */
|| (onError!=OE_Abort && onError!=OE_Rollback) /* (3) */
)){
/* In some circumstances, we are able to run the xfer optimization
** only if the destination table is initially empty. Unless the
- ** SQLITE_Vacuum flag is set, this block generates code to make
- ** that determination. If SQLITE_Vacuum is set, then the destination
+ ** DBFLAG_Vacuum flag is set, this block generates code to make
+ ** that determination. If DBFLAG_Vacuum is set, then the destination
** table is always empty.
**
** Conditions under which the destination must be empty:
@@ -2179,8 +2176,8 @@ static int xferOptimization(
assert( (pDest->tabFlags & TF_Autoincrement)==0 );
}
sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
- if( db->flags & SQLITE_Vacuum ){
- sqlite3VdbeAddOp3(v, OP_Last, iDest, 0, -1);
+ if( db->mDbFlags & DBFLAG_Vacuum ){
+ sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest);
insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID|
OPFLAG_APPEND|OPFLAG_USESEEKRESULT;
}else{
@@ -2211,13 +2208,13 @@ static int xferOptimization(
VdbeComment((v, "%s", pDestIdx->zName));
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
- if( db->flags & SQLITE_Vacuum ){
+ if( db->mDbFlags & DBFLAG_Vacuum ){
/* This INSERT command is part of a VACUUM operation, which guarantees
** that the destination table is empty. If all indexed columns use
** collation sequence BINARY, then it can also be assumed that the
** index will be populated by inserting keys in strictly sorted
** order. In this case, instead of seeking within the b-tree as part
- ** of every OP_IdxInsert opcode, an OP_Last is added before the
+ ** of every OP_IdxInsert opcode, an OP_SeekEnd is added before the
** OP_IdxInsert to seek to the point within the b-tree where each key
** should be inserted. This is faster.
**
@@ -2232,7 +2229,7 @@ static int xferOptimization(
}
if( i==pSrcIdx->nColumn ){
idxInsFlags = OPFLAG_USESEEKRESULT;
- sqlite3VdbeAddOp3(v, OP_Last, iDest, 0, -1);
+ sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest);
}
}
if( !HasRowid(pSrc) && pDestIdx->idxType==2 ){
diff --git a/chromium/third_party/sqlite/src/src/main.c b/chromium/third_party/sqlite/src/src/main.c
index 0b8c18d9062..0709b3a3433 100644
--- a/chromium/third_party/sqlite/src/src/main.c
+++ b/chromium/third_party/sqlite/src/src/main.c
@@ -47,9 +47,11 @@ const char sqlite3_version[] = SQLITE_VERSION;
*/
const char *sqlite3_libversion(void){ return sqlite3_version; }
-/* IMPLEMENTATION-OF: R-63124-39300 The sqlite3_sourceid() function returns a
+/* IMPLEMENTATION-OF: R-25063-23286 The sqlite3_sourceid() function returns a
** pointer to a string constant whose value is the same as the
-** SQLITE_SOURCE_ID C preprocessor macro.
+** SQLITE_SOURCE_ID C preprocessor macro. Except if SQLite is built using
+** an edited copy of the amalgamation, then the last four characters of
+** the hash might be different from SQLITE_SOURCE_ID.
*/
const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
@@ -436,14 +438,8 @@ int sqlite3_config(int op, ...){
sqlite3GlobalConfig.bMemstat = va_arg(ap, int);
break;
}
- case SQLITE_CONFIG_SCRATCH: {
- /* EVIDENCE-OF: R-08404-60887 There are three arguments to
- ** SQLITE_CONFIG_SCRATCH: A pointer an 8-byte aligned memory buffer from
- ** which the scratch allocations will be drawn, the size of each scratch
- ** allocation (sz), and the maximum number of scratch allocations (N). */
- sqlite3GlobalConfig.pScratch = va_arg(ap, void*);
- sqlite3GlobalConfig.szScratch = va_arg(ap, int);
- sqlite3GlobalConfig.nScratch = va_arg(ap, int);
+ case SQLITE_CONFIG_SMALL_MALLOC: {
+ sqlite3GlobalConfig.bSmallMalloc = va_arg(ap, int);
break;
}
case SQLITE_CONFIG_PAGECACHE: {
@@ -664,7 +660,8 @@ int sqlite3_config(int op, ...){
static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
#ifndef SQLITE_OMIT_LOOKASIDE
void *pStart;
- if( db->lookaside.nOut ){
+
+ if( sqlite3LookasideUsed(db,0)>0 ){
return SQLITE_BUSY;
}
/* Free any existing lookaside buffer for this handle before
@@ -692,16 +689,18 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
pStart = pBuf;
}
db->lookaside.pStart = pStart;
+ db->lookaside.pInit = 0;
db->lookaside.pFree = 0;
db->lookaside.sz = (u16)sz;
if( pStart ){
int i;
LookasideSlot *p;
assert( sz > (int)sizeof(LookasideSlot*) );
+ db->lookaside.nSlot = cnt;
p = (LookasideSlot*)pStart;
for(i=cnt-1; i>=0; i--){
- p->pNext = db->lookaside.pFree;
- db->lookaside.pFree = p;
+ p->pNext = db->lookaside.pInit;
+ db->lookaside.pInit = p;
p = (LookasideSlot*)&((u8*)p)[sz];
}
db->lookaside.pEnd = p;
@@ -712,6 +711,7 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
db->lookaside.pEnd = db;
db->lookaside.bDisable = 1;
db->lookaside.bMalloced = 0;
+ db->lookaside.nSlot = 0;
}
#endif /* SQLITE_OMIT_LOOKASIDE */
return SQLITE_OK;
@@ -824,7 +824,7 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){
if( aFlagOp[i].op==op ){
int onoff = va_arg(ap, int);
int *pRes = va_arg(ap, int*);
- int oldFlags = db->flags;
+ u32 oldFlags = db->flags;
if( onoff>0 ){
db->flags |= aFlagOp[i].mask;
}else if( onoff==0 ){
@@ -1231,7 +1231,7 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
sqlite3_mutex_leave(db->mutex);
db->magic = SQLITE_MAGIC_CLOSED;
sqlite3_mutex_free(db->mutex);
- assert( db->lookaside.nOut==0 ); /* Fails on a lookaside memory leak */
+ assert( sqlite3LookasideUsed(db,0)==0 );
if( db->lookaside.bMalloced ){
sqlite3_free(db->lookaside.pStart);
}
@@ -1259,7 +1259,7 @@ void sqlite3RollbackAll(sqlite3 *db, int tripCode){
** the database rollback and schema reset, which can cause false
** corruption reports in some cases. */
sqlite3BtreeEnterAll(db);
- schemaChange = (db->flags & SQLITE_InternChanges)!=0 && db->init.busy==0;
+ schemaChange = (db->mDbFlags & DBFLAG_SchemaChange)!=0 && db->init.busy==0;
for(i=0; i<db->nDb; i++){
Btree *p = db->aDb[i].pBt;
@@ -1273,7 +1273,7 @@ void sqlite3RollbackAll(sqlite3 *db, int tripCode){
sqlite3VtabRollback(db);
sqlite3EndBenignMalloc();
- if( (db->flags&SQLITE_InternChanges)!=0 && db->init.busy==0 ){
+ if( (db->mDbFlags&DBFLAG_SchemaChange)!=0 && db->init.busy==0 ){
sqlite3ExpirePreparedStatements(db);
sqlite3ResetAllSchemasOfConnection(db);
}
@@ -2175,7 +2175,8 @@ int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){
** checkpointed. If an error is encountered it is returned immediately -
** no attempt is made to checkpoint any remaining databases.
**
-** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART.
+** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL, RESTART
+** or TRUNCATE.
*/
int sqlite3Checkpoint(sqlite3 *db, int iDb, int eMode, int *pnLog, int *pnCkpt){
int rc = SQLITE_OK; /* Return code */
@@ -3061,6 +3062,12 @@ static int openDatabase(
}
#endif
+#ifdef SQLITE_ENABLE_DBPAGE_VTAB
+ if( !db->mallocFailed && rc==SQLITE_OK){
+ rc = sqlite3DbpageRegister(db);
+ }
+#endif
+
#ifdef SQLITE_ENABLE_DBSTAT_VTAB
if( !db->mallocFailed && rc==SQLITE_OK){
rc = sqlite3DbstatRegister(db);
@@ -3720,7 +3727,7 @@ int sqlite3_test_control(int op, ...){
** This action provides a run-time test to see how the ALWAYS and
** NEVER macros were defined at compile-time.
**
- ** The return value is ALWAYS(X).
+ ** The return value is ALWAYS(X) if X is true, or 0 if X is false.
**
** The recommended test is X==2. If the return value is 2, that means
** ALWAYS() and NEVER() are both no-op pass-through macros, which is the
@@ -3743,7 +3750,7 @@ int sqlite3_test_control(int op, ...){
*/
case SQLITE_TESTCTRL_ALWAYS: {
int x = va_arg(ap,int);
- rc = ALWAYS(x);
+ rc = x ? ALWAYS(x) : 0;
break;
}
@@ -3810,22 +3817,6 @@ int sqlite3_test_control(int op, ...){
}
#endif
- /* sqlite3_test_control(SQLITE_TESTCTRL_SCRATCHMALLOC, sz, &pNew, pFree);
- **
- ** Pass pFree into sqlite3ScratchFree().
- ** If sz>0 then allocate a scratch buffer into pNew.
- */
- case SQLITE_TESTCTRL_SCRATCHMALLOC: {
- void *pFree, **ppNew;
- int sz;
- sz = va_arg(ap, int);
- ppNew = va_arg(ap, void**);
- pFree = va_arg(ap, void*);
- if( sz ) *ppNew = sqlite3ScratchMalloc(sz);
- sqlite3ScratchFree(pFree);
- break;
- }
-
/* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, int onoff);
**
** If parameter onoff is non-zero, configure the wrappers so that all
@@ -3967,7 +3958,7 @@ sqlite3_int64 sqlite3_uri_int64(
){
const char *z = sqlite3_uri_parameter(zFilename, zParam);
sqlite3_int64 v;
- if( z && sqlite3DecOrHexToI64(z, &v)==SQLITE_OK ){
+ if( z && sqlite3DecOrHexToI64(z, &v)==0 ){
bDflt = v;
}
return bDflt;
diff --git a/chromium/third_party/sqlite/src/src/malloc.c b/chromium/third_party/sqlite/src/src/malloc.c
index 42a271658d8..20857cf6b39 100644
--- a/chromium/third_party/sqlite/src/src/malloc.c
+++ b/chromium/third_party/sqlite/src/src/malloc.c
@@ -33,14 +33,6 @@ int sqlite3_release_memory(int n){
}
/*
-** An instance of the following object records the location of
-** each unused scratch buffer.
-*/
-typedef struct ScratchFreeslot {
- struct ScratchFreeslot *pNext; /* Next unused scratch buffer */
-} ScratchFreeslot;
-
-/*
** State information local to the memory allocation subsystem.
*/
static SQLITE_WSD struct Mem0Global {
@@ -48,21 +40,11 @@ static SQLITE_WSD struct Mem0Global {
sqlite3_int64 alarmThreshold; /* The soft heap limit */
/*
- ** Pointers to the end of sqlite3GlobalConfig.pScratch memory
- ** (so that a range test can be used to determine if an allocation
- ** being freed came from pScratch) and a pointer to the list of
- ** unused scratch allocations.
- */
- void *pScratchEnd;
- ScratchFreeslot *pScratchFree;
- u32 nScratchFree;
-
- /*
** True if heap is nearly "full" where "full" is defined by the
** sqlite3_soft_heap_limit() setting.
*/
int nearlyFull;
-} mem0 = { 0, 0, 0, 0, 0, 0 };
+} mem0 = { 0, 0, 0 };
#define mem0 GLOBAL(struct Mem0Global, mem0)
@@ -132,28 +114,6 @@ int sqlite3MallocInit(void){
}
memset(&mem0, 0, sizeof(mem0));
mem0.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
- if( sqlite3GlobalConfig.pScratch && sqlite3GlobalConfig.szScratch>=100
- && sqlite3GlobalConfig.nScratch>0 ){
- int i, n, sz;
- ScratchFreeslot *pSlot;
- sz = ROUNDDOWN8(sqlite3GlobalConfig.szScratch);
- sqlite3GlobalConfig.szScratch = sz;
- pSlot = (ScratchFreeslot*)sqlite3GlobalConfig.pScratch;
- n = sqlite3GlobalConfig.nScratch;
- mem0.pScratchFree = pSlot;
- mem0.nScratchFree = n;
- for(i=0; i<n-1; i++){
- pSlot->pNext = (ScratchFreeslot*)(sz+(char*)pSlot);
- pSlot = pSlot->pNext;
- }
- pSlot->pNext = 0;
- mem0.pScratchEnd = (void*)&pSlot[1];
- }else{
- mem0.pScratchEnd = 0;
- sqlite3GlobalConfig.pScratch = 0;
- sqlite3GlobalConfig.szScratch = 0;
- sqlite3GlobalConfig.nScratch = 0;
- }
if( sqlite3GlobalConfig.pPage==0 || sqlite3GlobalConfig.szPage<512
|| sqlite3GlobalConfig.nPage<=0 ){
sqlite3GlobalConfig.pPage = 0;
@@ -305,105 +265,6 @@ void *sqlite3_malloc64(sqlite3_uint64 n){
}
/*
-** Each thread may only have a single outstanding allocation from
-** xScratchMalloc(). We verify this constraint in the single-threaded
-** case by setting scratchAllocOut to 1 when an allocation
-** is outstanding clearing it when the allocation is freed.
-*/
-#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
-static int scratchAllocOut = 0;
-#endif
-
-
-/*
-** Allocate memory that is to be used and released right away.
-** This routine is similar to alloca() in that it is not intended
-** for situations where the memory might be held long-term. This
-** routine is intended to get memory to old large transient data
-** structures that would not normally fit on the stack of an
-** embedded processor.
-*/
-void *sqlite3ScratchMalloc(int n){
- void *p;
- assert( n>0 );
-
- sqlite3_mutex_enter(mem0.mutex);
- sqlite3StatusHighwater(SQLITE_STATUS_SCRATCH_SIZE, n);
- if( mem0.nScratchFree && sqlite3GlobalConfig.szScratch>=n ){
- p = mem0.pScratchFree;
- mem0.pScratchFree = mem0.pScratchFree->pNext;
- mem0.nScratchFree--;
- sqlite3StatusUp(SQLITE_STATUS_SCRATCH_USED, 1);
- sqlite3_mutex_leave(mem0.mutex);
- }else{
- sqlite3_mutex_leave(mem0.mutex);
- p = sqlite3Malloc(n);
- if( sqlite3GlobalConfig.bMemstat && p ){
- sqlite3_mutex_enter(mem0.mutex);
- sqlite3StatusUp(SQLITE_STATUS_SCRATCH_OVERFLOW, sqlite3MallocSize(p));
- sqlite3_mutex_leave(mem0.mutex);
- }
- sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH);
- }
- assert( sqlite3_mutex_notheld(mem0.mutex) );
-
-
-#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
- /* EVIDENCE-OF: R-12970-05880 SQLite will not use more than one scratch
- ** buffers per thread.
- **
- ** This can only be checked in single-threaded mode.
- */
- assert( scratchAllocOut==0 );
- if( p ) scratchAllocOut++;
-#endif
-
- return p;
-}
-void sqlite3ScratchFree(void *p){
- if( p ){
-
-#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
- /* Verify that no more than two scratch allocation per thread
- ** is outstanding at one time. (This is only checked in the
- ** single-threaded case since checking in the multi-threaded case
- ** would be much more complicated.) */
- assert( scratchAllocOut>=1 && scratchAllocOut<=2 );
- scratchAllocOut--;
-#endif
-
- if( SQLITE_WITHIN(p, sqlite3GlobalConfig.pScratch, mem0.pScratchEnd) ){
- /* Release memory from the SQLITE_CONFIG_SCRATCH allocation */
- ScratchFreeslot *pSlot;
- pSlot = (ScratchFreeslot*)p;
- sqlite3_mutex_enter(mem0.mutex);
- pSlot->pNext = mem0.pScratchFree;
- mem0.pScratchFree = pSlot;
- mem0.nScratchFree++;
- assert( mem0.nScratchFree <= (u32)sqlite3GlobalConfig.nScratch );
- sqlite3StatusDown(SQLITE_STATUS_SCRATCH_USED, 1);
- sqlite3_mutex_leave(mem0.mutex);
- }else{
- /* Release memory back to the heap */
- assert( sqlite3MemdebugHasType(p, MEMTYPE_SCRATCH) );
- assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_SCRATCH) );
- sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
- if( sqlite3GlobalConfig.bMemstat ){
- int iSize = sqlite3MallocSize(p);
- sqlite3_mutex_enter(mem0.mutex);
- sqlite3StatusDown(SQLITE_STATUS_SCRATCH_OVERFLOW, iSize);
- sqlite3StatusDown(SQLITE_STATUS_MEMORY_USED, iSize);
- sqlite3StatusDown(SQLITE_STATUS_MALLOC_COUNT, 1);
- sqlite3GlobalConfig.m.xFree(p);
- sqlite3_mutex_leave(mem0.mutex);
- }else{
- sqlite3GlobalConfig.m.xFree(p);
- }
- }
- }
-}
-
-/*
** TRUE if p is a lookaside memory allocation from db
*/
#ifndef SQLITE_OMIT_LOOKASIDE
@@ -493,7 +354,6 @@ void sqlite3DbFreeNN(sqlite3 *db, void *p){
#endif
pBuf->pNext = db->lookaside.pFree;
db->lookaside.pFree = pBuf;
- db->lookaside.nOut--;
return;
}
}
@@ -654,16 +514,16 @@ void *sqlite3DbMallocRawNN(sqlite3 *db, u64 n){
assert( db->mallocFailed==0 );
if( n>db->lookaside.sz ){
db->lookaside.anStat[1]++;
- }else if( (pBuf = db->lookaside.pFree)==0 ){
- db->lookaside.anStat[2]++;
- }else{
+ }else if( (pBuf = db->lookaside.pFree)!=0 ){
db->lookaside.pFree = pBuf->pNext;
- db->lookaside.nOut++;
db->lookaside.anStat[0]++;
- if( db->lookaside.nOut>db->lookaside.mxOut ){
- db->lookaside.mxOut = db->lookaside.nOut;
- }
return (void*)pBuf;
+ }else if( (pBuf = db->lookaside.pInit)!=0 ){
+ db->lookaside.pInit = pBuf->pNext;
+ db->lookaside.anStat[0]++;
+ return (void*)pBuf;
+ }else{
+ db->lookaside.anStat[2]++;
}
}else if( db->mallocFailed ){
return 0;
diff --git a/chromium/third_party/sqlite/src/src/memjournal.c b/chromium/third_party/sqlite/src/src/memjournal.c
index 9753199b9b3..66e5f75565e 100644
--- a/chromium/third_party/sqlite/src/src/memjournal.c
+++ b/chromium/third_party/sqlite/src/src/memjournal.c
@@ -96,7 +96,8 @@ static int memjrnlRead(
int iChunkOffset;
FileChunk *pChunk;
-#ifdef SQLITE_ENABLE_ATOMIC_WRITE
+#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \
+ || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
if( (iAmt+iOfst)>p->endpoint.iOffset ){
return SQLITE_IOERR_SHORT_READ;
}
@@ -215,7 +216,8 @@ static int memjrnlWrite(
** atomic-write optimization. In this case the first 28 bytes of the
** journal file may be written as part of committing the transaction. */
assert( iOfst==p->endpoint.iOffset || iOfst==0 );
-#ifdef SQLITE_ENABLE_ATOMIC_WRITE
+#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \
+ || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
if( iOfst==0 && p->pFirst ){
assert( p->nChunkSize>iAmt );
memcpy((u8*)p->pFirst->zChunk, zBuf, iAmt);
@@ -384,17 +386,31 @@ void sqlite3MemJournalOpen(sqlite3_file *pJfd){
sqlite3JournalOpen(0, 0, pJfd, 0, -1);
}
-#ifdef SQLITE_ENABLE_ATOMIC_WRITE
+#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \
+ || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
/*
** If the argument p points to a MemJournal structure that is not an
** in-memory-only journal file (i.e. is one that was opened with a +ve
-** nSpill parameter), and the underlying file has not yet been created,
-** create it now.
+** nSpill parameter or as SQLITE_OPEN_MAIN_JOURNAL), and the underlying
+** file has not yet been created, create it now.
*/
-int sqlite3JournalCreate(sqlite3_file *p){
+int sqlite3JournalCreate(sqlite3_file *pJfd){
int rc = SQLITE_OK;
- if( p->pMethods==&MemJournalMethods && ((MemJournal*)p)->nSpill>0 ){
- rc = memjrnlCreateFile((MemJournal*)p);
+ MemJournal *p = (MemJournal*)pJfd;
+ if( p->pMethod==&MemJournalMethods && (
+#ifdef SQLITE_ENABLE_ATOMIC_WRITE
+ p->nSpill>0
+#else
+ /* While this appears to not be possible without ATOMIC_WRITE, the
+ ** paths are complex, so it seems prudent to leave the test in as
+ ** a NEVER(), in case our analysis is subtly flawed. */
+ NEVER(p->nSpill>0)
+#endif
+#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
+ || (p->flags & SQLITE_OPEN_MAIN_JOURNAL)
+#endif
+ )){
+ rc = memjrnlCreateFile(p);
}
return rc;
}
diff --git a/chromium/third_party/sqlite/src/src/os.c b/chromium/third_party/sqlite/src/src/os.c
index 5cf00147946..26c80650636 100644
--- a/chromium/third_party/sqlite/src/src/os.c
+++ b/chromium/third_party/sqlite/src/src/os.c
@@ -98,7 +98,7 @@ int sqlite3OsTruncate(sqlite3_file *id, i64 size){
}
int sqlite3OsSync(sqlite3_file *id, int flags){
DO_OS_MALLOC_TEST(id);
- return id->pMethods->xSync(id, flags);
+ return flags ? id->pMethods->xSync(id, flags) : SQLITE_OK;
}
int sqlite3OsFileSize(sqlite3_file *id, i64 *pSize){
DO_OS_MALLOC_TEST(id);
@@ -153,6 +153,7 @@ int sqlite3OsSectorSize(sqlite3_file *id){
int sqlite3OsDeviceCharacteristics(sqlite3_file *id){
return id->pMethods->xDeviceCharacteristics(id);
}
+#ifndef SQLITE_OMIT_WAL
int sqlite3OsShmLock(sqlite3_file *id, int offset, int n, int flags){
return id->pMethods->xShmLock(id, offset, n, flags);
}
@@ -172,6 +173,7 @@ int sqlite3OsShmMap(
DO_OS_MALLOC_TEST(id);
return id->pMethods->xShmMap(id, iPage, pgsz, bExtend, pp);
}
+#endif /* SQLITE_OMIT_WAL */
#if SQLITE_MAX_MMAP_SIZE>0
/* The real implementation of xFetch and xUnfetch */
diff --git a/chromium/third_party/sqlite/src/src/os.h b/chromium/third_party/sqlite/src/src/os.h
index 52d3a490475..e6d9a8b34a2 100644
--- a/chromium/third_party/sqlite/src/src/os.h
+++ b/chromium/third_party/sqlite/src/src/os.h
@@ -174,10 +174,12 @@ void sqlite3OsFileControlHint(sqlite3_file*,int,void*);
#define SQLITE_FCNTL_DB_UNCHANGED 0xca093fa0
int sqlite3OsSectorSize(sqlite3_file *id);
int sqlite3OsDeviceCharacteristics(sqlite3_file *id);
+#ifndef SQLITE_OMIT_WAL
int sqlite3OsShmMap(sqlite3_file *,int,int,int,void volatile **);
int sqlite3OsShmLock(sqlite3_file *id, int, int, int);
void sqlite3OsShmBarrier(sqlite3_file *id);
int sqlite3OsShmUnmap(sqlite3_file *id, int);
+#endif /* SQLITE_OMIT_WAL */
int sqlite3OsFetch(sqlite3_file *id, i64, int, void **);
int sqlite3OsUnfetch(sqlite3_file *, i64, void *);
diff --git a/chromium/third_party/sqlite/src/src/os_unix.c b/chromium/third_party/sqlite/src/src/os_unix.c
index cf009da8f3e..dc3018801aa 100644
--- a/chromium/third_party/sqlite/src/src/os_unix.c
+++ b/chromium/third_party/sqlite/src/src/os_unix.c
@@ -90,6 +90,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <sys/ioctl.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
@@ -209,7 +210,7 @@ struct unixFile {
unsigned short int ctrlFlags; /* Behavioral bits. UNIXFILE_* flags */
int lastErrno; /* The unix errno from last I/O error */
void *lockingContext; /* Locking style specific state */
- UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */
+ UnixUnusedFd *pPreallocatedUnused; /* Pre-allocated UnixUnusedFd */
const char *zPath; /* Name of the file */
unixShm *pShm; /* Shared memory segment information */
int szChunk; /* Configured by FCNTL_CHUNK_SIZE */
@@ -220,10 +221,8 @@ struct unixFile {
sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */
void *pMapRegion; /* Memory mapped region */
#endif
-#ifdef __QNXNTO__
int sectorSize; /* Device sector size */
int deviceCharacteristics; /* Precomputed device characteristics */
-#endif
#if SQLITE_ENABLE_LOCKING_STYLE
int openFlags; /* The flags specified at open() */
#endif
@@ -328,6 +327,20 @@ static pid_t randomnessPid = 0;
# define lseek lseek64
#endif
+#ifdef __linux__
+/*
+** Linux-specific IOCTL magic numbers used for controlling F2FS
+*/
+#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
+#endif /* __linux__ */
+
+
/*
** Different Unix systems declare open() in different ways. Same use
** open(const char*,int,mode_t). Others use open(const char*,int,...).
@@ -500,6 +513,9 @@ static struct unix_syscall {
#endif
#define osLstat ((int(*)(const char*,struct stat*))aSyscall[27].pCurrent)
+ { "ioctl", (sqlite3_syscall_ptr)ioctl, 0 },
+#define osIoctl ((int(*)(int,int,...))aSyscall[28].pCurrent)
+
}; /* End of the overrideable system calls */
@@ -1104,7 +1120,8 @@ struct unixInodeInfo {
/*
** A lists of all unixInodeInfo objects.
*/
-static unixInodeInfo *inodeList = 0;
+static unixInodeInfo *inodeList = 0; /* All unixInodeInfo objects */
+static unsigned int nUnusedFd = 0; /* Total unused file descriptors */
/*
**
@@ -1214,6 +1231,7 @@ static void closePendingFds(unixFile *pFile){
pNext = p->pNext;
robust_close(pFile, p->fd, __LINE__);
sqlite3_free(p);
+ nUnusedFd--;
}
pInode->pUnused = 0;
}
@@ -1246,6 +1264,7 @@ static void releaseInodeInfo(unixFile *pFile){
sqlite3_free(pInode);
}
}
+ assert( inodeList!=0 || nUnusedFd==0 );
}
/*
@@ -1315,6 +1334,7 @@ static int findInodeInfo(
#else
fileId.ino = (u64)statbuf.st_ino;
#endif
+ assert( inodeList!=0 || nUnusedFd==0 );
pInode = inodeList;
while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){
pInode = pInode->pNext;
@@ -1740,11 +1760,12 @@ end_lock:
*/
static void setPendingFd(unixFile *pFile){
unixInodeInfo *pInode = pFile->pInode;
- UnixUnusedFd *p = pFile->pUnused;
+ UnixUnusedFd *p = pFile->pPreallocatedUnused;
p->pNext = pInode->pUnused;
pInode->pUnused = p;
pFile->h = -1;
- pFile->pUnused = 0;
+ pFile->pPreallocatedUnused = 0;
+ nUnusedFd++;
}
/*
@@ -1969,7 +1990,7 @@ static int closeUnixFile(sqlite3_file *id){
#endif
OSTRACE(("CLOSE %-3d\n", pFile->h));
OpenCounter(-1);
- sqlite3_free(pFile->pUnused);
+ sqlite3_free(pFile->pPreallocatedUnused);
memset(pFile, 0, sizeof(unixFile));
return SQLITE_OK;
}
@@ -2306,7 +2327,7 @@ static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
OSTRACE(("TEST WR-LOCK %d %d %d (flock)\n", pFile->h, rc, reserved));
#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
- if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){
+ if( (rc & 0xff) == SQLITE_IOERR ){
rc = SQLITE_OK;
reserved=1;
}
@@ -2373,7 +2394,7 @@ static int flockLock(sqlite3_file *id, int eFileLock) {
OSTRACE(("LOCK %d %s %s (flock)\n", pFile->h, azFileLock(eFileLock),
rc==SQLITE_OK ? "ok" : "failed"));
#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
- if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){
+ if( (rc & 0xff) == SQLITE_IOERR ){
rc = SQLITE_BUSY;
}
#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
@@ -2910,7 +2931,7 @@ static int afpLock(sqlite3_file *id, int eFileLock){
/* Can't reestablish the shared lock. Sqlite can't deal, this is
** a critical I/O error
*/
- rc = ((failed & SQLITE_IOERR) == SQLITE_IOERR) ? failed2 :
+ rc = ((failed & 0xff) == SQLITE_IOERR) ? failed2 :
SQLITE_IOERR_LOCK;
goto afp_end_lock;
}
@@ -3190,7 +3211,7 @@ static int unixRead(
/* If this is a database file (not a journal, master-journal or temp
** file), the bytes in the locking range should never be read or written. */
#if 0
- assert( pFile->pUnused==0
+ assert( pFile->pPreallocatedUnused==0
|| offset>=PENDING_BYTE+512
|| offset+amt<=PENDING_BYTE
);
@@ -3303,7 +3324,7 @@ static int unixWrite(
/* If this is a database file (not a journal, master-journal or temp
** file), the bytes in the locking range should never be read or written. */
#if 0
- assert( pFile->pUnused==0
+ assert( pFile->pPreallocatedUnused==0
|| offset>=PENDING_BYTE+512
|| offset+amt<=PENDING_BYTE
);
@@ -3783,6 +3804,21 @@ static int unixGetTempname(int nBuf, char *zBuf);
static int unixFileControl(sqlite3_file *id, int op, void *pArg){
unixFile *pFile = (unixFile*)id;
switch( op ){
+#if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
+ case SQLITE_FCNTL_BEGIN_ATOMIC_WRITE: {
+ int rc = osIoctl(pFile->h, F2FS_IOC_START_ATOMIC_WRITE);
+ return rc ? SQLITE_IOERR_BEGIN_ATOMIC : SQLITE_OK;
+ }
+ case SQLITE_FCNTL_COMMIT_ATOMIC_WRITE: {
+ int rc = osIoctl(pFile->h, F2FS_IOC_COMMIT_ATOMIC_WRITE);
+ return rc ? SQLITE_IOERR_COMMIT_ATOMIC : SQLITE_OK;
+ }
+ case SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE: {
+ int rc = osIoctl(pFile->h, F2FS_IOC_ABORT_VOLATILE_WRITE);
+ return rc ? SQLITE_IOERR_ROLLBACK_ATOMIC : SQLITE_OK;
+ }
+#endif /* __linux__ && SQLITE_ENABLE_BATCH_ATOMIC_WRITE */
+
case SQLITE_FCNTL_LOCKSTATE: {
*(int*)pArg = pFile->eFileLock;
return SQLITE_OK;
@@ -3833,6 +3869,14 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
if( newLimit>sqlite3GlobalConfig.mxMmap ){
newLimit = sqlite3GlobalConfig.mxMmap;
}
+
+ /* The value of newLimit may be eventually cast to (size_t) and passed
+ ** to mmap(). Restrict its value to 2GB if (size_t) is not at least a
+ ** 64-bit type. */
+ if( newLimit>0 && sizeof(size_t)<8 ){
+ newLimit = (newLimit & 0x7FFFFFFF);
+ }
+
*(i64*)pArg = pFile->mmapSizeMax;
if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){
pFile->mmapSizeMax = newLimit;
@@ -3866,30 +3910,41 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
}
/*
-** Return the sector size in bytes of the underlying block device for
-** the specified file. This is almost always 512 bytes, but may be
-** larger for some devices.
+** If pFd->sectorSize is non-zero when this function is called, it is a
+** no-op. Otherwise, the values of pFd->sectorSize and
+** pFd->deviceCharacteristics are set according to the file-system
+** characteristics.
**
-** SQLite code assumes this function cannot fail. It also assumes that
-** if two files are created in the same file-system directory (i.e.
-** a database and its journal file) that the sector size will be the
-** same for both.
+** There are two versions of this function. One for QNX and one for all
+** other systems.
*/
#ifndef __QNXNTO__
-static int unixSectorSize(sqlite3_file *NotUsed){
- UNUSED_PARAMETER(NotUsed);
- return SQLITE_DEFAULT_SECTOR_SIZE;
-}
-#endif
+static void setDeviceCharacteristics(unixFile *pFd){
+ assert( pFd->deviceCharacteristics==0 || pFd->sectorSize!=0 );
+ if( pFd->sectorSize==0 ){
+#if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
+ int res;
+ u32 f = 0;
-/*
-** The following version of unixSectorSize() is optimized for QNX.
-*/
-#ifdef __QNXNTO__
+ /* Check for support for F2FS atomic batch writes. */
+ res = osIoctl(pFd->h, F2FS_IOC_GET_FEATURES, &f);
+ if( res==0 && (f & F2FS_FEATURE_ATOMIC_WRITE) ){
+ pFd->deviceCharacteristics = SQLITE_IOCAP_BATCH_ATOMIC;
+ }
+#endif /* __linux__ && SQLITE_ENABLE_BATCH_ATOMIC_WRITE */
+
+ /* Set the POWERSAFE_OVERWRITE flag if requested. */
+ if( pFd->ctrlFlags & UNIXFILE_PSOW ){
+ pFd->deviceCharacteristics |= SQLITE_IOCAP_POWERSAFE_OVERWRITE;
+ }
+
+ pFd->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
+ }
+}
+#else
#include <sys/dcmd_blk.h>
#include <sys/statvfs.h>
-static int unixSectorSize(sqlite3_file *id){
- unixFile *pFile = (unixFile*)id;
+static void setDeviceCharacteristics(unixFile *pFile){
if( pFile->sectorSize == 0 ){
struct statvfs fsInfo;
@@ -3958,9 +4013,24 @@ static int unixSectorSize(sqlite3_file *id){
pFile->deviceCharacteristics = 0;
pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
}
- return pFile->sectorSize;
}
-#endif /* __QNXNTO__ */
+#endif
+
+/*
+** Return the sector size in bytes of the underlying block device for
+** the specified file. This is almost always 512 bytes, but may be
+** larger for some devices.
+**
+** SQLite code assumes this function cannot fail. It also assumes that
+** if two files are created in the same file-system directory (i.e.
+** a database and its journal file) that the sector size will be the
+** same for both.
+*/
+static int unixSectorSize(sqlite3_file *id){
+ unixFile *pFd = (unixFile*)id;
+ setDeviceCharacteristics(pFd);
+ return pFd->sectorSize;
+}
/*
** Return the device characteristics for the file.
@@ -3976,16 +4046,9 @@ static int unixSectorSize(sqlite3_file *id){
** available to turn it off and URI query parameter available to turn it off.
*/
static int unixDeviceCharacteristics(sqlite3_file *id){
- unixFile *p = (unixFile*)id;
- int rc = 0;
-#ifdef __QNXNTO__
- if( p->sectorSize==0 ) unixSectorSize(id);
- rc = p->deviceCharacteristics;
-#endif
- if( p->ctrlFlags & UNIXFILE_PSOW ){
- rc |= SQLITE_IOCAP_POWERSAFE_OVERWRITE;
- }
- return rc;
+ unixFile *pFd = (unixFile*)id;
+ setDeviceCharacteristics(pFd);
+ return pFd->deviceCharacteristics;
}
#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
@@ -5243,17 +5306,6 @@ static int fillInUnixFile(
assert( pNew->pInode==NULL );
- /* Usually the path zFilename should not be a relative pathname. The
- ** exception is when opening the proxy "conch" file in builds that
- ** include the special Apple locking styles.
- */
-#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
- assert( zFilename==0 || zFilename[0]=='/'
- || pVfs->pAppData==(void*)&autolockIoFinder );
-#else
- assert( zFilename==0 || zFilename[0]=='/' );
-#endif
-
/* No locking occurs in temporary files */
assert( zFilename!=0 || (ctrlFlags & UNIXFILE_NOLOCK)!=0 );
@@ -5512,6 +5564,8 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
#if !OS_VXWORKS
struct stat sStat; /* Results of stat() call */
+ unixEnterMutex();
+
/* A stat() call may fail for various reasons. If this happens, it is
** almost certain that an open() call on the same path will also fail.
** For this reason, if an error occurs in the stat() call here, it is
@@ -5520,10 +5574,9 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
**
** Even if a subsequent open() call does succeed, the consequences of
** not searching for a reusable file descriptor are not dire. */
- if( 0==osStat(zPath, &sStat) ){
+ if( nUnusedFd>0 && 0==osStat(zPath, &sStat) ){
unixInodeInfo *pInode;
- unixEnterMutex();
pInode = inodeList;
while( pInode && (pInode->fileId.dev!=sStat.st_dev
|| pInode->fileId.ino!=(u64)sStat.st_ino) ){
@@ -5534,11 +5587,12 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
for(pp=&pInode->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext));
pUnused = *pp;
if( pUnused ){
+ nUnusedFd--;
*pp = pUnused->pNext;
}
}
- unixLeaveMutex();
}
+ unixLeaveMutex();
#endif /* if !OS_VXWORKS */
return pUnused;
}
@@ -5614,16 +5668,11 @@ static int findCreateFileMode(
*/
nDb = sqlite3Strlen30(zPath) - 1;
while( zPath[nDb]!='-' ){
-#ifndef SQLITE_ENABLE_8_3_NAMES
- /* In the normal case (8+3 filenames disabled) the journal filename
- ** is guaranteed to contain a '-' character. */
- assert( nDb>0 );
- assert( sqlite3Isalnum(zPath[nDb]) );
-#else
- /* If 8+3 names are possible, then the journal file might not contain
- ** a '-' character. So check for that case and return early. */
+ /* In normal operation, the journal file name will always contain
+ ** a '-' character. However in 8+3 filename mode, or if a corrupt
+ ** rollback journal specifies a master journal with a goofy name, then
+ ** the '-' might be missing. */
if( nDb==0 || zPath[nDb]=='.' ) return SQLITE_OK;
-#endif
nDb--;
}
memcpy(zDb, zPath, nDb);
@@ -5665,20 +5714,21 @@ int chromium_sqlite3_fill_in_unix_sqlite3_file(sqlite3_vfs* pVfs,
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 pUnused.
+ ** fail, so directly include the failure-case setup then initialize
+ ** pPreallocatedUnused.
*/
if( eType==SQLITE_OPEN_MAIN_DB ){
- p->pUnused = sqlite3_malloc(sizeof(*p->pUnused));
- if (!p->pUnused) {
+ p->pPreallocatedUnused = sqlite3_malloc(sizeof(*p->pPreallocatedUnused));
+ if (!p->pPreallocatedUnused) {
return SQLITE_NOMEM_BKPT;
}
- p->pUnused->fd = fd;
- p->pUnused->flags = flags;
+ p->pPreallocatedUnused->fd = fd;
+ p->pPreallocatedUnused->flags = flags;
}
rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);
if( rc!=SQLITE_OK ){
- sqlite3_free(p->pUnused);
+ sqlite3_free(p->pPreallocatedUnused);
}
return rc;
}
@@ -5799,7 +5849,7 @@ static int unixOpen(
return SQLITE_NOMEM_BKPT;
}
}
- p->pUnused = pUnused;
+ p->pPreallocatedUnused = pUnused;
/* Database filenames are double-zero terminated if they are not
** URIs with parameters. Hence, they can always be passed into
@@ -5836,7 +5886,7 @@ static int unixOpen(
gid_t gid; /* Groupid for the file */
rc = findCreateFileMode(zName, flags, &openMode, &uid, &gid);
if( rc!=SQLITE_OK ){
- assert( !p->pUnused );
+ assert( !p->pPreallocatedUnused );
assert( eType==SQLITE_OPEN_WAL || eType==SQLITE_OPEN_MAIN_JOURNAL );
return rc;
}
@@ -5870,10 +5920,10 @@ static int unixOpen(
*pOutFlags = flags;
}
- if( p->pUnused ){
+ if( p->pPreallocatedUnused ){
/* Duplicated in chromium_sqlite3_fill_in_unix_sqlite3_file(). */
- p->pUnused->fd = fd;
- p->pUnused->flags = flags;
+ p->pPreallocatedUnused->fd = fd;
+ p->pPreallocatedUnused->flags = flags;
}
if( isDelete ){
@@ -5950,13 +6000,16 @@ static int unixOpen(
}
#endif
+ 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->pUnused);
+ sqlite3_free(p->pPreallocatedUnused);
}
return rc;
}
@@ -6697,7 +6750,7 @@ static int proxyCreateUnixFile(
dummyVfs.zName = "dummy";
pUnused->fd = fd;
pUnused->flags = openFlags;
- pNew->pUnused = pUnused;
+ pNew->pPreallocatedUnused = pUnused;
rc = fillInUnixFile(&dummyVfs, fd, (sqlite3_file*)pNew, path, 0);
if( rc==SQLITE_OK ){
@@ -7651,7 +7704,7 @@ int sqlite3_os_init(void){
/* Double-check that the aSyscall[] array has been constructed
** correctly. See ticket [bb3a86e890c8e96ab] */
- assert( ArraySize(aSyscall)==28 );
+ assert( ArraySize(aSyscall)==29 );
/* Register all VFSes defined in the aVfs[] array */
for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
diff --git a/chromium/third_party/sqlite/src/src/os_win.c b/chromium/third_party/sqlite/src/src/os_win.c
index 1d9abf0a8f3..eeb2c149800 100644
--- a/chromium/third_party/sqlite/src/src/os_win.c
+++ b/chromium/third_party/sqlite/src/src/os_win.c
@@ -3559,6 +3559,14 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
if( newLimit>sqlite3GlobalConfig.mxMmap ){
newLimit = sqlite3GlobalConfig.mxMmap;
}
+
+ /* The value of newLimit may be eventually cast to (SIZE_T) and passed
+ ** to MapViewOfFile(). Restrict its value to 2GB if (SIZE_T) is not at
+ ** least a 64-bit type. */
+ if( newLimit>0 && sizeof(SIZE_T)<8 ){
+ newLimit = (newLimit & 0x7FFFFFFF);
+ }
+
*(i64*)pArg = pFile->mmapSizeMax;
if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){
pFile->mmapSizeMax = newLimit;
@@ -4871,6 +4879,14 @@ static int winIsDir(const void *zConverted){
return (attr!=INVALID_FILE_ATTRIBUTES) && (attr&FILE_ATTRIBUTE_DIRECTORY);
}
+/* forward reference */
+static int winAccess(
+ sqlite3_vfs *pVfs, /* Not used on win32 */
+ const char *zFilename, /* Name of file to check */
+ int flags, /* Type of test to make on this file */
+ int *pResOut /* OUT: Result */
+);
+
/*
** Open a file.
*/
@@ -5047,37 +5063,52 @@ static int winOpen(
extendedParameters.dwSecurityQosFlags = SECURITY_ANONYMOUS;
extendedParameters.lpSecurityAttributes = NULL;
extendedParameters.hTemplateFile = NULL;
- while( (h = osCreateFile2((LPCWSTR)zConverted,
- dwDesiredAccess,
- dwShareMode,
- dwCreationDisposition,
- &extendedParameters))==INVALID_HANDLE_VALUE &&
- winRetryIoerr(&cnt, &lastErrno) ){
- /* Noop */
- }
+ do{
+ h = osCreateFile2((LPCWSTR)zConverted,
+ dwDesiredAccess,
+ dwShareMode,
+ dwCreationDisposition,
+ &extendedParameters);
+ if( h!=INVALID_HANDLE_VALUE ) break;
+ if( isReadWrite ){
+ int isRO = 0;
+ int rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO);
+ if( rc2==SQLITE_OK && isRO ) break;
+ }
+ }while( winRetryIoerr(&cnt, &lastErrno) );
#else
- while( (h = osCreateFileW((LPCWSTR)zConverted,
- dwDesiredAccess,
- dwShareMode, NULL,
- dwCreationDisposition,
- dwFlagsAndAttributes,
- NULL))==INVALID_HANDLE_VALUE &&
- winRetryIoerr(&cnt, &lastErrno) ){
- /* Noop */
- }
+ do{
+ h = osCreateFileW((LPCWSTR)zConverted,
+ dwDesiredAccess,
+ dwShareMode, NULL,
+ dwCreationDisposition,
+ dwFlagsAndAttributes,
+ NULL);
+ if( h!=INVALID_HANDLE_VALUE ) break;
+ if( isReadWrite ){
+ int isRO = 0;
+ int rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO);
+ if( rc2==SQLITE_OK && isRO ) break;
+ }
+ }while( winRetryIoerr(&cnt, &lastErrno) );
#endif
}
#ifdef SQLITE_WIN32_HAS_ANSI
else{
- while( (h = osCreateFileA((LPCSTR)zConverted,
- dwDesiredAccess,
- dwShareMode, NULL,
- dwCreationDisposition,
- dwFlagsAndAttributes,
- NULL))==INVALID_HANDLE_VALUE &&
- winRetryIoerr(&cnt, &lastErrno) ){
- /* Noop */
- }
+ do{
+ h = osCreateFileA((LPCSTR)zConverted,
+ dwDesiredAccess,
+ dwShareMode, NULL,
+ dwCreationDisposition,
+ dwFlagsAndAttributes,
+ NULL);
+ if( h!=INVALID_HANDLE_VALUE ) break;
+ if( isReadWrite ){
+ int isRO = 0;
+ int rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO);
+ if( rc2==SQLITE_OK && isRO ) break;
+ }
+ }while( winRetryIoerr(&cnt, &lastErrno) );
}
#endif
winLogIoerr(cnt, __LINE__);
@@ -5086,8 +5117,6 @@ static int winOpen(
dwDesiredAccess, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok"));
if( h==INVALID_HANDLE_VALUE ){
- pFile->lastErrno = lastErrno;
- winLogError(SQLITE_CANTOPEN, pFile->lastErrno, "winOpen", zUtf8Name);
sqlite3_free(zConverted);
sqlite3_free(zTmpname);
if( isReadWrite && !isExclusive ){
@@ -5096,6 +5125,8 @@ static int winOpen(
~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)),
pOutFlags);
}else{
+ pFile->lastErrno = lastErrno;
+ winLogError(SQLITE_CANTOPEN, pFile->lastErrno, "winOpen", zUtf8Name);
return SQLITE_CANTOPEN_BKPT;
}
}
@@ -5688,9 +5719,6 @@ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
EntropyGatherer e;
UNUSED_PARAMETER(pVfs);
memset(zBuf, 0, nBuf);
-#if defined(_MSC_VER) && _MSC_VER>=1400 && !SQLITE_OS_WINCE
- rand_s((unsigned int*)zBuf); /* rand_s() is not available with MinGW */
-#endif /* defined(_MSC_VER) && _MSC_VER>=1400 */
e.a = (unsigned char*)zBuf;
e.na = nBuf;
e.nXor = 0;
diff --git a/chromium/third_party/sqlite/src/src/pager.c b/chromium/third_party/sqlite/src/src/pager.c
index 8023dcab7ee..5b964f3cf0e 100644
--- a/chromium/third_party/sqlite/src/src/pager.c
+++ b/chromium/third_party/sqlite/src/src/pager.c
@@ -128,8 +128,8 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
** associated file-descriptor is returned. FILEHANDLEID() takes an sqlite3_file
** struct as its argument.
*/
-#define PAGERID(p) ((int)(p->fd))
-#define FILEHANDLEID(fd) ((int)fd)
+#define PAGERID(p) (SQLITE_PTR_TO_INT(p->fd))
+#define FILEHANDLEID(fd) (SQLITE_PTR_TO_INT(fd))
/*
** The Pager.eState variable stores the current 'state' of a pager. A
@@ -616,6 +616,18 @@ struct PagerSavepoint {
** is set to zero in all other states. In PAGER_ERROR state, Pager.errCode
** is always set to SQLITE_FULL, SQLITE_IOERR or one of the SQLITE_IOERR_XXX
** sub-codes.
+**
+** syncFlags, walSyncFlags
+**
+** syncFlags is either SQLITE_SYNC_NORMAL (0x02) or SQLITE_SYNC_FULL (0x03).
+** syncFlags is used for rollback mode. walSyncFlags is used for WAL mode
+** and contains the flags used to sync the checkpoint operations in the
+** lower two bits, and sync flags used for transaction commits in the WAL
+** file in bits 0x04 and 0x08. In other words, to get the correct sync flags
+** for checkpoint operations, use (walSyncFlags&0x03) and to get the correct
+** sync flags for transaction commit, use ((walSyncFlags>>2)&0x03). Note
+** that with synchronous=NORMAL in WAL mode, transaction commit is not synced
+** meaning that the 0x04 and 0x08 bits are both zero.
*/
struct Pager {
sqlite3_vfs *pVfs; /* OS functions to use for IO */
@@ -625,9 +637,8 @@ struct Pager {
u8 noSync; /* Do not sync the journal if true */
u8 fullSync; /* Do extra syncs of the journal for robustness */
u8 extraSync; /* sync directory after journal delete */
- u8 ckptSyncFlags; /* SYNC_NORMAL or SYNC_FULL for checkpoint */
- u8 walSyncFlags; /* SYNC_NORMAL or SYNC_FULL for wal writes */
u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */
+ u8 walSyncFlags; /* See description above */
u8 tempFile; /* zFilename is a temporary or immutable file */
u8 noLock; /* Do not lock (except in WAL mode) */
u8 readOnly; /* True for a read-only database */
@@ -947,6 +958,7 @@ static int assert_pager_state(Pager *p){
assert( isOpen(p->jfd)
|| p->journalMode==PAGER_JOURNALMODE_OFF
|| p->journalMode==PAGER_JOURNALMODE_WAL
+ || (sqlite3OsDeviceCharacteristics(p->fd)&SQLITE_IOCAP_BATCH_ATOMIC)
);
assert( pPager->dbOrigSize<=pPager->dbHintSize );
break;
@@ -958,6 +970,7 @@ static int assert_pager_state(Pager *p){
assert( isOpen(p->jfd)
|| p->journalMode==PAGER_JOURNALMODE_OFF
|| p->journalMode==PAGER_JOURNALMODE_WAL
+ || (sqlite3OsDeviceCharacteristics(p->fd)&SQLITE_IOCAP_BATCH_ATOMIC)
);
break;
@@ -1168,34 +1181,47 @@ static int pagerLockDb(Pager *pPager, int eLock){
}
/*
-** This function determines whether or not the atomic-write optimization
-** can be used with this pager. The optimization can be used if:
+** This function determines whether or not the atomic-write or
+** atomic-batch-write optimizations can be used with this pager. The
+** atomic-write optimization can be used if:
**
** (a) the value returned by OsDeviceCharacteristics() indicates that
** a database page may be written atomically, and
** (b) the value returned by OsSectorSize() is less than or equal
** to the page size.
**
-** The optimization is also always enabled for temporary files. It is
-** an error to call this function if pPager is opened on an in-memory
-** database.
+** If it can be used, then the value returned is the size of the journal
+** file when it contains rollback data for exactly one page.
+**
+** The atomic-batch-write optimization can be used if OsDeviceCharacteristics()
+** returns a value with the SQLITE_IOCAP_BATCH_ATOMIC bit set. -1 is
+** returned in this case.
**
-** If the optimization cannot be used, 0 is returned. If it can be used,
-** then the value returned is the size of the journal file when it
-** contains rollback data for exactly one page.
+** If neither optimization can be used, 0 is returned.
*/
-#ifdef SQLITE_ENABLE_ATOMIC_WRITE
static int jrnlBufferSize(Pager *pPager){
assert( !MEMDB );
- if( !pPager->tempFile ){
- int dc; /* Device characteristics */
- int nSector; /* Sector size */
- int szPage; /* Page size */
- assert( isOpen(pPager->fd) );
- dc = sqlite3OsDeviceCharacteristics(pPager->fd);
- nSector = pPager->sectorSize;
- szPage = pPager->pageSize;
+#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \
+ || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
+ int dc; /* Device characteristics */
+
+ assert( isOpen(pPager->fd) );
+ dc = sqlite3OsDeviceCharacteristics(pPager->fd);
+#else
+ UNUSED_PARAMETER(pPager);
+#endif
+
+#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
+ if( dc&SQLITE_IOCAP_BATCH_ATOMIC ){
+ return -1;
+ }
+#endif
+
+#ifdef SQLITE_ENABLE_ATOMIC_WRITE
+ {
+ int nSector = pPager->sectorSize;
+ int szPage = pPager->pageSize;
assert(SQLITE_IOCAP_ATOMIC512==(512>>8));
assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8));
@@ -1205,11 +1231,11 @@ static int jrnlBufferSize(Pager *pPager){
}
return JOURNAL_HDR_SZ(pPager) + JOURNAL_PG_SZ(pPager);
-}
-#else
-# define jrnlBufferSize(x) 0
#endif
+ return 0;
+}
+
/*
** If SQLITE_CHECK_PAGES is defined then we do some sanity checking
** on the cache using a hash function. This is used for testing
@@ -1291,6 +1317,7 @@ static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, u32 nMaster){
|| szJ<16
|| SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len))
|| len>=nMaster
+ || len>szJ-16
|| len==0
|| SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum))
|| SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8))
@@ -2012,7 +2039,9 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
}
releaseAllSavepoints(pPager);
- assert( isOpen(pPager->jfd) || pPager->pInJournal==0 );
+ assert( isOpen(pPager->jfd) || pPager->pInJournal==0
+ || (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_BATCH_ATOMIC)
+ );
if( isOpen(pPager->jfd) ){
assert( !pagerUseWal(pPager) );
@@ -2780,6 +2809,7 @@ static int pager_playback(Pager *pPager, int isHot){
char *zMaster = 0; /* Name of master journal file if any */
int needPagerReset; /* True to reset page prior to first page rollback */
int nPlayback = 0; /* Total number of pages restored from journal */
+ u32 savedPageSize = pPager->pageSize;
/* Figure out how many records are in the journal. Abort early if
** the journal is empty.
@@ -2909,6 +2939,9 @@ static int pager_playback(Pager *pPager, int isHot){
assert( 0 );
end_playback:
+ if( rc==SQLITE_OK ){
+ rc = sqlite3PagerSetPagesize(pPager, &savedPageSize, -1);
+ }
/* Following a rollback, the database file should be back in its original
** state prior to the start of the transaction, so invoke the
** SQLITE_FCNTL_DB_UNCHANGED file-control method to disable the
@@ -2967,7 +3000,8 @@ end_playback:
/*
-** Read the content for page pPg out of the database file and into
+** Read the content for page pPg out of the database file (or out of
+** the WAL if that is where the most recent copy if found) into
** pPg->pData. A shared lock or greater must be held on the database
** file before this function is called.
**
@@ -2977,30 +3011,33 @@ end_playback:
** If an IO error occurs, then the IO error is returned to the caller.
** Otherwise, SQLITE_OK is returned.
*/
-static int readDbPage(PgHdr *pPg, u32 iFrame){
+static int readDbPage(PgHdr *pPg){
Pager *pPager = pPg->pPager; /* Pager object associated with page pPg */
- Pgno pgno = pPg->pgno; /* Page number to read */
int rc = SQLITE_OK; /* Return code */
- int pgsz = pPager->pageSize; /* Number of bytes to read */
+
+#ifndef SQLITE_OMIT_WAL
+ u32 iFrame = 0; /* Frame of WAL containing pgno */
assert( pPager->eState>=PAGER_READER && !MEMDB );
assert( isOpen(pPager->fd) );
-#ifndef SQLITE_OMIT_WAL
+ if( pagerUseWal(pPager) ){
+ rc = sqlite3WalFindFrame(pPager->pWal, pPg->pgno, &iFrame);
+ if( rc ) return rc;
+ }
if( iFrame ){
- /* Try to pull the page from the write-ahead log. */
- rc = sqlite3WalReadFrame(pPager->pWal, iFrame, pgsz, pPg->pData);
+ rc = sqlite3WalReadFrame(pPager->pWal, iFrame,pPager->pageSize,pPg->pData);
}else
#endif
{
- i64 iOffset = (pgno-1)*(i64)pPager->pageSize;
- rc = sqlite3OsRead(pPager->fd, pPg->pData, pgsz, iOffset);
+ i64 iOffset = (pPg->pgno-1)*(i64)pPager->pageSize;
+ rc = sqlite3OsRead(pPager->fd, pPg->pData, pPager->pageSize, iOffset);
if( rc==SQLITE_IOERR_SHORT_READ ){
rc = SQLITE_OK;
}
}
- if( pgno==1 ){
+ if( pPg->pgno==1 ){
if( rc ){
/* If the read is unsuccessful, set the dbFileVers[] to something
** that will never be a valid file version. dbFileVers[] is a copy
@@ -3020,13 +3057,13 @@ static int readDbPage(PgHdr *pPg, u32 iFrame){
memcpy(&pPager->dbFileVers, dbFileVers, sizeof(pPager->dbFileVers));
}
}
- CODEC1(pPager, pPg->pData, pgno, 3, rc = SQLITE_NOMEM_BKPT);
+ CODEC1(pPager, pPg->pData, pPg->pgno, 3, rc = SQLITE_NOMEM_BKPT);
PAGER_INCR(sqlite3_pager_readdb_count);
PAGER_INCR(pPager->nRead);
- IOTRACE(("PGIN %p %d\n", pPager, pgno));
+ IOTRACE(("PGIN %p %d\n", pPager, pPg->pgno));
PAGERTRACE(("FETCH %d page %d hash(%08x)\n",
- PAGERID(pPager), pgno, pager_pagehash(pPg)));
+ PAGERID(pPager), pPg->pgno, pager_pagehash(pPg)));
return rc;
}
@@ -3077,11 +3114,7 @@ static int pagerUndoCallback(void *pCtx, Pgno iPg){
if( sqlite3PcachePageRefcount(pPg)==1 ){
sqlite3PcacheDrop(pPg);
}else{
- u32 iFrame = 0;
- rc = sqlite3WalFindFrame(pPager->pWal, pPg->pgno, &iFrame);
- if( rc==SQLITE_OK ){
- rc = readDbPage(pPg, iFrame);
- }
+ rc = readDbPage(pPg);
if( rc==SQLITE_OK ){
pPager->xReiniter(pPg);
}
@@ -3587,20 +3620,17 @@ void sqlite3PagerSetFlags(
}
if( pPager->noSync ){
pPager->syncFlags = 0;
- pPager->ckptSyncFlags = 0;
}else if( pgFlags & PAGER_FULLFSYNC ){
pPager->syncFlags = SQLITE_SYNC_FULL;
- pPager->ckptSyncFlags = SQLITE_SYNC_FULL;
- }else if( pgFlags & PAGER_CKPT_FULLFSYNC ){
- pPager->syncFlags = SQLITE_SYNC_NORMAL;
- pPager->ckptSyncFlags = SQLITE_SYNC_FULL;
}else{
pPager->syncFlags = SQLITE_SYNC_NORMAL;
- pPager->ckptSyncFlags = SQLITE_SYNC_NORMAL;
}
- pPager->walSyncFlags = pPager->syncFlags;
+ pPager->walSyncFlags = (pPager->syncFlags<<2);
if( pPager->fullSync ){
- pPager->walSyncFlags |= WAL_SYNC_TRANSACTIONS;
+ pPager->walSyncFlags |= pPager->syncFlags;
+ }
+ if( (pgFlags & PAGER_CKPT_FULLFSYNC) && !pPager->noSync ){
+ pPager->walSyncFlags |= (SQLITE_SYNC_FULL<<2);
}
if( pgFlags & PAGER_CACHESPILL ){
pPager->doNotSpill &= ~SPILLFLAG_OFF;
@@ -4099,7 +4129,7 @@ int sqlite3PagerClose(Pager *pPager, sqlite3 *db){
pPager->exclusiveMode = 0;
#ifndef SQLITE_OMIT_WAL
assert( db || pPager->pWal==0 );
- sqlite3WalClose(pPager->pWal, db, pPager->ckptSyncFlags, pPager->pageSize,
+ sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags, pPager->pageSize,
(db && (db->flags & SQLITE_NoCkptOnClose) ? 0 : pTmp)
);
pPager->pWal = 0;
@@ -4568,6 +4598,13 @@ static int pagerStress(void *p, PgHdr *pPg){
}
}else{
+#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
+ if( pPager->tempFile==0 ){
+ rc = sqlite3JournalCreate(pPager->jfd);
+ if( rc!=SQLITE_OK ) return pager_error(pPager, rc);
+ }
+#endif
+
/* Sync the journal file if required. */
if( pPg->flags&PGHDR_NEED_SYNC
|| pPager->eState==PAGER_WRITER_CACHEMOD
@@ -4900,13 +4937,11 @@ act_like_temp_file:
assert( pPager->extraSync==0 );
assert( pPager->syncFlags==0 );
assert( pPager->walSyncFlags==0 );
- assert( pPager->ckptSyncFlags==0 );
}else{
pPager->fullSync = 1;
pPager->extraSync = 0;
pPager->syncFlags = SQLITE_SYNC_NORMAL;
- pPager->walSyncFlags = SQLITE_SYNC_NORMAL | WAL_SYNC_TRANSACTIONS;
- pPager->ckptSyncFlags = SQLITE_SYNC_NORMAL;
+ pPager->walSyncFlags = SQLITE_SYNC_NORMAL | (SQLITE_SYNC_NORMAL<<2);
}
/* pPager->pFirst = 0; */
/* pPager->pFirstSynced = 0; */
@@ -5326,7 +5361,8 @@ int sqlite3PagerSharedLock(Pager *pPager){
** nothing to rollback, so this routine is a no-op.
*/
static void pagerUnlockIfUnused(Pager *pPager){
- if( pPager->nMmapOut==0 && (sqlite3PcacheRefCount(pPager->pPCache)==0) ){
+ if( sqlite3PcacheRefCount(pPager->pPCache)==0 ){
+ assert( pPager->nMmapOut==0 ); /* because page1 is never memory mapped */
pagerUnlockAndRollback(pPager);
}
}
@@ -5467,14 +5503,9 @@ static int getPageNormal(
memset(pPg->pData, 0, pPager->pageSize);
IOTRACE(("ZERO %p %d\n", pPager, pgno));
}else{
- u32 iFrame = 0; /* Frame to read from WAL file */
- if( pagerUseWal(pPager) ){
- rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iFrame);
- if( rc!=SQLITE_OK ) goto pager_acquire_err;
- }
assert( pPg->pPager==pPager );
pPager->aStat[PAGER_STAT_MISS]++;
- rc = readDbPage(pPg, iFrame);
+ rc = readDbPage(pPg);
if( rc!=SQLITE_OK ){
goto pager_acquire_err;
}
@@ -5617,25 +5648,39 @@ DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){
/*
** Release a page reference.
**
-** If the number of references to the page drop to zero, then the
-** page is added to the LRU list. When all references to all pages
-** are released, a rollback occurs and the lock on the database is
-** removed.
+** The sqlite3PagerUnref() and sqlite3PagerUnrefNotNull() may only be
+** used if we know that the page being released is not the last page.
+** The btree layer always holds page1 open until the end, so these first
+** to routines can be used to release any page other than BtShared.pPage1.
+**
+** Use sqlite3PagerUnrefPageOne() to release page1. This latter routine
+** checks the total number of outstanding pages and if the number of
+** pages reaches zero it drops the database lock.
*/
void sqlite3PagerUnrefNotNull(DbPage *pPg){
- Pager *pPager;
+ TESTONLY( Pager *pPager = pPg->pPager; )
assert( pPg!=0 );
- pPager = pPg->pPager;
if( pPg->flags & PGHDR_MMAP ){
+ assert( pPg->pgno!=1 ); /* Page1 is never memory mapped */
pagerReleaseMapPage(pPg);
}else{
sqlite3PcacheRelease(pPg);
}
- pagerUnlockIfUnused(pPager);
+ /* Do not use this routine to release the last reference to page1 */
+ assert( sqlite3PcacheRefCount(pPager->pPCache)>0 );
}
void sqlite3PagerUnref(DbPage *pPg){
if( pPg ) sqlite3PagerUnrefNotNull(pPg);
}
+void sqlite3PagerUnrefPageOne(DbPage *pPg){
+ Pager *pPager;
+ assert( pPg!=0 );
+ assert( pPg->pgno==1 );
+ assert( (pPg->flags & PGHDR_MMAP)==0 ); /* Page1 is never memory mapped */
+ pPager = pPg->pPager;
+ sqlite3PcacheRelease(pPg);
+ pagerUnlockIfUnused(pPager);
+}
/*
** This function is called at the start of every write transaction.
@@ -6347,6 +6392,21 @@ int sqlite3PagerCommitPhaseOne(
sqlite3PcacheCleanAll(pPager->pPCache);
}
}else{
+ /* The bBatch boolean is true if the batch-atomic-write commit method
+ ** should be used. No rollback journal is created if batch-atomic-write
+ ** is enabled.
+ */
+ sqlite3_file *fd = pPager->fd;
+#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
+ const int bBatch = zMaster==0 /* An SQLITE_IOCAP_BATCH_ATOMIC commit */
+ && (sqlite3OsDeviceCharacteristics(fd) & SQLITE_IOCAP_BATCH_ATOMIC)
+ && !pPager->noSync
+ && sqlite3JournalIsInMemory(pPager->jfd);
+#else
+# define bBatch 0
+#endif
+
+#ifdef SQLITE_ENABLE_ATOMIC_WRITE
/* The following block updates the change-counter. Exactly how it
** does this depends on whether or not the atomic-update optimization
** was enabled at compile time, and if this transaction meets the
@@ -6370,33 +6430,40 @@ int sqlite3PagerCommitPhaseOne(
** in 'direct' mode. In this case the journal file will never be
** created for this transaction.
*/
- #ifdef SQLITE_ENABLE_ATOMIC_WRITE
- PgHdr *pPg;
- assert( isOpen(pPager->jfd)
- || pPager->journalMode==PAGER_JOURNALMODE_OFF
- || pPager->journalMode==PAGER_JOURNALMODE_WAL
- );
- if( !zMaster && isOpen(pPager->jfd)
- && pPager->journalOff==jrnlBufferSize(pPager)
- && pPager->dbSize>=pPager->dbOrigSize
- && (0==(pPg = sqlite3PcacheDirtyList(pPager->pPCache)) || 0==pPg->pDirty)
- ){
- /* Update the db file change counter via the direct-write method. The
- ** following call will modify the in-memory representation of page 1
- ** to include the updated change counter and then write page 1
- ** directly to the database file. Because of the atomic-write
- ** property of the host file-system, this is safe.
- */
- rc = pager_incr_changecounter(pPager, 1);
- }else{
- rc = sqlite3JournalCreate(pPager->jfd);
- if( rc==SQLITE_OK ){
- rc = pager_incr_changecounter(pPager, 0);
+ if( bBatch==0 ){
+ PgHdr *pPg;
+ assert( isOpen(pPager->jfd)
+ || pPager->journalMode==PAGER_JOURNALMODE_OFF
+ || pPager->journalMode==PAGER_JOURNALMODE_WAL
+ );
+ if( !zMaster && isOpen(pPager->jfd)
+ && pPager->journalOff==jrnlBufferSize(pPager)
+ && pPager->dbSize>=pPager->dbOrigSize
+ && (!(pPg = sqlite3PcacheDirtyList(pPager->pPCache)) || 0==pPg->pDirty)
+ ){
+ /* Update the db file change counter via the direct-write method. The
+ ** following call will modify the in-memory representation of page 1
+ ** to include the updated change counter and then write page 1
+ ** directly to the database file. Because of the atomic-write
+ ** property of the host file-system, this is safe.
+ */
+ rc = pager_incr_changecounter(pPager, 1);
+ }else{
+ rc = sqlite3JournalCreate(pPager->jfd);
+ if( rc==SQLITE_OK ){
+ rc = pager_incr_changecounter(pPager, 0);
+ }
}
}
- #else
+#else
+#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
+ if( zMaster ){
+ rc = sqlite3JournalCreate(pPager->jfd);
+ if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
+ }
+#endif
rc = pager_incr_changecounter(pPager, 0);
- #endif
+#endif
if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
/* Write the master journal name into the journal file. If a master
@@ -6420,7 +6487,23 @@ int sqlite3PagerCommitPhaseOne(
rc = syncJournal(pPager, 0);
if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
+ if( bBatch ){
+ /* The pager is now in DBMOD state. But regardless of what happens
+ ** next, attempting to play the journal back into the database would
+ ** be unsafe. Close it now to make sure that does not happen. */
+ sqlite3OsClose(pPager->jfd);
+ rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_BEGIN_ATOMIC_WRITE, 0);
+ if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
+ }
rc = pager_write_pagelist(pPager,sqlite3PcacheDirtyList(pPager->pPCache));
+ if( bBatch ){
+ if( rc==SQLITE_OK ){
+ rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_COMMIT_ATOMIC_WRITE, 0);
+ }else{
+ sqlite3OsFileControl(fd, SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE, 0);
+ }
+ }
+
if( rc!=SQLITE_OK ){
assert( rc!=SQLITE_IOERR_BLOCKED );
goto commit_phase_one_exit;
@@ -7321,7 +7404,7 @@ int sqlite3PagerCheckpoint(
rc = sqlite3WalCheckpoint(pPager->pWal, db, eMode,
(eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler),
pPager->pBusyHandlerArg,
- pPager->ckptSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
+ pPager->walSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
pnLog, pnCkpt
);
}
@@ -7478,7 +7561,7 @@ int sqlite3PagerCloseWal(Pager *pPager, sqlite3 *db){
if( rc==SQLITE_OK && pPager->pWal ){
rc = pagerExclusiveLock(pPager);
if( rc==SQLITE_OK ){
- rc = sqlite3WalClose(pPager->pWal, db, pPager->ckptSyncFlags,
+ rc = sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags,
pPager->pageSize, (u8*)pPager->pTmpSpace);
pPager->pWal = 0;
pagerFixMaplimit(pPager);
diff --git a/chromium/third_party/sqlite/src/src/pager.h b/chromium/third_party/sqlite/src/src/pager.h
index 3522a4e3dca..01ea900bd28 100644
--- a/chromium/third_party/sqlite/src/src/pager.h
+++ b/chromium/third_party/sqlite/src/src/pager.h
@@ -151,6 +151,7 @@ DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno);
void sqlite3PagerRef(DbPage*);
void sqlite3PagerUnref(DbPage*);
void sqlite3PagerUnrefNotNull(DbPage*);
+void sqlite3PagerUnrefPageOne(DbPage*);
/* Operations on page references. */
int sqlite3PagerWrite(DbPage*);
diff --git a/chromium/third_party/sqlite/src/src/parse.y b/chromium/third_party/sqlite/src/src/parse.y
index 81f41164a17..7ad42b4a4c4 100644
--- a/chromium/third_party/sqlite/src/src/parse.y
+++ b/chromium/third_party/sqlite/src/src/parse.y
@@ -192,6 +192,19 @@ columnlist ::= columnlist COMMA columnname carglist.
columnlist ::= columnname carglist.
columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,&A,&Y);}
+// Declare some tokens early in order to influence their values, to
+// improve performance and reduce the executable size. The goal here is
+// to get the "jump" operations in ISNULL through ESCAPE to have numeric
+// values that are early enough so that all jump operations are clustered
+// at the beginning, but also so that the comparison tokens NE through GE
+// are as large as possible so that they are near to FUNCTION, which is a
+// token synthesized by addopcodes.tcl.
+//
+%token ABORT ACTION AFTER ANALYZE ASC ATTACH BEFORE BEGIN BY CASCADE CAST.
+%token CONFLICT DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL.
+%token OR AND NOT IS MATCH LIKE_KW BETWEEN IN ISNULL NOTNULL NE EQ.
+%token GT LE LT GE ESCAPE.
+
// The following directive causes tokens ABORT, AFTER, ASC, etc. to
// fallback to ID if they will not parse as their original value.
// This obviates the need for the "id" nonterminal.
diff --git a/chromium/third_party/sqlite/src/src/pcache.c b/chromium/third_party/sqlite/src/src/pcache.c
index ee6024e3422..9a43a59627f 100644
--- a/chromium/third_party/sqlite/src/src/pcache.c
+++ b/chromium/third_party/sqlite/src/src/pcache.c
@@ -191,12 +191,9 @@ static void pcacheManageDirtyList(PgHdr *pPage, u8 addRemove){
p->eCreate = 2;
}
}
- pPage->pDirtyNext = 0;
- pPage->pDirtyPrev = 0;
}
if( addRemove & PCACHE_DIRTYLIST_ADD ){
- assert( pPage->pDirtyNext==0 && pPage->pDirtyPrev==0 && p->pDirty!=pPage );
-
+ pPage->pDirtyPrev = 0;
pPage->pDirtyNext = p->pDirty;
if( pPage->pDirtyNext ){
assert( pPage->pDirtyNext->pDirtyPrev==0 );
@@ -513,11 +510,7 @@ void SQLITE_NOINLINE sqlite3PcacheRelease(PgHdr *p){
if( (--p->nRef)==0 ){
if( p->flags&PGHDR_CLEAN ){
pcacheUnpin(p);
- }else if( p->pDirtyPrev!=0 ){ /*OPTIMIZATION-IF-FALSE*/
- /* Move the page to the head of the dirty list. If p->pDirtyPrev==0,
- ** then page p is already at the head of the dirty list and the
- ** following call would be a no-op. Hence the OPTIMIZATION-IF-FALSE
- ** tag above. */
+ }else{
pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT);
}
}
diff --git a/chromium/third_party/sqlite/src/src/pcache.h b/chromium/third_party/sqlite/src/src/pcache.h
index 570688a6f9b..8aadd023e11 100644
--- a/chromium/third_party/sqlite/src/src/pcache.h
+++ b/chromium/third_party/sqlite/src/src/pcache.h
@@ -43,6 +43,8 @@ struct PgHdr {
i16 nRef; /* Number of users of this page */
PgHdr *pDirtyNext; /* Next element in list of dirty pages */
PgHdr *pDirtyPrev; /* Previous element in list of dirty pages */
+ /* NB: pDirtyNext and pDirtyPrev are undefined if the
+ ** PgHdr object is not dirty */
};
/* Bit values for PgHdr.flags */
diff --git a/chromium/third_party/sqlite/src/src/pcache1.c b/chromium/third_party/sqlite/src/src/pcache1.c
index 4b09e9805e8..c93294a9df7 100644
--- a/chromium/third_party/sqlite/src/src/pcache1.c
+++ b/chromium/third_party/sqlite/src/src/pcache1.c
@@ -96,7 +96,6 @@ typedef struct PGroup PGroup;
struct PgHdr1 {
sqlite3_pcache_page page; /* Base class. Must be first. pBuf & pExtra */
unsigned int iKey; /* Key value (page number) */
- u8 isPinned; /* Page in use, not on the LRU list */
u8 isBulkLocal; /* This page from bulk local storage */
u8 isAnchor; /* This is the PGroup.lru element */
PgHdr1 *pNext; /* Next in hash table chain */
@@ -105,6 +104,12 @@ struct PgHdr1 {
PgHdr1 *pLruPrev; /* Previous in LRU list of unpinned pages */
};
+/*
+** A page is pinned if it is no on the LRU list
+*/
+#define PAGE_IS_PINNED(p) ((p)->pLruNext==0)
+#define PAGE_IS_UNPINNED(p) ((p)->pLruNext!=0)
+
/* Each page cache (or PCache) belongs to a PGroup. A PGroup is a set
** of one or more PCaches that are able to recycle each other's unpinned
** pages when they are under memory pressure. A PGroup is an instance of
@@ -132,7 +137,7 @@ struct PGroup {
unsigned int nMaxPage; /* Sum of nMax for purgeable caches */
unsigned int nMinPage; /* Sum of nMin for purgeable caches */
unsigned int mxPinned; /* nMaxpage + 10 - nMinPage */
- unsigned int nCurrentPage; /* Number of purgeable pages allocated */
+ unsigned int nPurgeable; /* Number of purgeable pages allocated */
PgHdr1 lru; /* The beginning and end of the LRU list */
};
@@ -146,11 +151,13 @@ struct PGroup {
*/
struct PCache1 {
/* Cache configuration parameters. Page size (szPage) and the purgeable
- ** flag (bPurgeable) are set when the cache is created. nMax may be
+ ** flag (bPurgeable) and the pnPurgeable pointer are all set when the
+ ** cache is created and are never changed thereafter. nMax may be
** modified at any time by a call to the pcache1Cachesize() method.
** The PGroup mutex must be held when accessing nMax.
*/
PGroup *pGroup; /* PGroup this cache belongs to */
+ unsigned int *pnPurgeable; /* Pointer to pGroup->nPurgeable */
int szPage; /* Size of database content section */
int szExtra; /* sizeof(MemPage)+sizeof(PgHdr) */
int szAlloc; /* Total size of one pcache line */
@@ -245,6 +252,7 @@ void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
if( pcache1.isInit ){
PgFreeslot *p;
if( pBuf==0 ) sz = n = 0;
+ if( n==0 ) sz = 0;
sz = ROUNDDOWN8(sz);
pcache1.szSlot = sz;
pcache1.nSlot = pcache1.nFreeSlot = n;
@@ -437,9 +445,7 @@ static PgHdr1 *pcache1AllocPage(PCache1 *pCache, int benignMalloc){
p->isBulkLocal = 0;
p->isAnchor = 0;
}
- if( pCache->bPurgeable ){
- pCache->pGroup->nCurrentPage++;
- }
+ (*pCache->pnPurgeable)++;
return p;
}
@@ -460,9 +466,7 @@ static void pcache1FreePage(PgHdr1 *p){
sqlite3_free(p);
#endif
}
- if( pCache->bPurgeable ){
- pCache->pGroup->nCurrentPage--;
- }
+ (*pCache->pnPurgeable)--;
}
/*
@@ -557,22 +561,18 @@ static void pcache1ResizeHash(PCache1 *p){
** The PGroup mutex must be held when this function is called.
*/
static PgHdr1 *pcache1PinPage(PgHdr1 *pPage){
- PCache1 *pCache;
-
assert( pPage!=0 );
- assert( pPage->isPinned==0 );
- pCache = pPage->pCache;
+ assert( PAGE_IS_UNPINNED(pPage) );
assert( pPage->pLruNext );
assert( pPage->pLruPrev );
- assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
+ assert( sqlite3_mutex_held(pPage->pCache->pGroup->mutex) );
pPage->pLruPrev->pLruNext = pPage->pLruNext;
pPage->pLruNext->pLruPrev = pPage->pLruPrev;
pPage->pLruNext = 0;
pPage->pLruPrev = 0;
- pPage->isPinned = 1;
assert( pPage->isAnchor==0 );
- assert( pCache->pGroup->lru.isAnchor==1 );
- pCache->nRecyclable--;
+ assert( pPage->pCache->pGroup->lru.isAnchor==1 );
+ pPage->pCache->nRecyclable--;
return pPage;
}
@@ -606,11 +606,11 @@ static void pcache1EnforceMaxPage(PCache1 *pCache){
PGroup *pGroup = pCache->pGroup;
PgHdr1 *p;
assert( sqlite3_mutex_held(pGroup->mutex) );
- while( pGroup->nCurrentPage>pGroup->nMaxPage
+ while( pGroup->nPurgeable>pGroup->nMaxPage
&& (p=pGroup->lru.pLruPrev)->isAnchor==0
){
assert( p->pCache->pGroup==pGroup );
- assert( p->isPinned==0 );
+ assert( PAGE_IS_UNPINNED(p) );
pcache1PinPage(p);
pcache1RemoveFromHash(p, 1);
}
@@ -659,7 +659,7 @@ static void pcache1TruncateUnsafe(
if( pPage->iKey>=iLimit ){
pCache->nPage--;
*pp = pPage->pNext;
- if( !pPage->isPinned ) pcache1PinPage(pPage);
+ if( PAGE_IS_UNPINNED(pPage) ) pcache1PinPage(pPage);
pcache1FreePage(pPage);
}else{
pp = &pPage->pNext;
@@ -781,6 +781,10 @@ static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){
pCache->nMin = 10;
pGroup->nMinPage += pCache->nMin;
pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
+ pCache->pnPurgeable = &pGroup->nPurgeable;
+ }else{
+ static unsigned int dummyCurrentPage;
+ pCache->pnPurgeable = &dummyCurrentPage;
}
pcache1LeaveMutex(pGroup);
if( pCache->nHash==0 ){
@@ -882,7 +886,7 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
){
PCache1 *pOther;
pPage = pGroup->lru.pLruPrev;
- assert( pPage->isPinned==0 );
+ assert( PAGE_IS_UNPINNED(pPage) );
pcache1RemoveFromHash(pPage, 0);
pcache1PinPage(pPage);
pOther = pPage->pCache;
@@ -890,7 +894,7 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
pcache1FreePage(pPage);
pPage = 0;
}else{
- pGroup->nCurrentPage -= (pOther->bPurgeable - pCache->bPurgeable);
+ pGroup->nPurgeable -= (pOther->bPurgeable - pCache->bPurgeable);
}
}
@@ -909,7 +913,6 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
pPage->pCache = pCache;
pPage->pLruPrev = 0;
pPage->pLruNext = 0;
- pPage->isPinned = 1;
*(void **)pPage->page.pExtra = 0;
pCache->apHash[h] = pPage;
if( iKey>pCache->iMaxKey ){
@@ -995,7 +998,7 @@ static PgHdr1 *pcache1FetchNoMutex(
** Otherwise (page not in hash and createFlag!=0) continue with
** subsequent steps to try to create the page. */
if( pPage ){
- if( !pPage->isPinned ){
+ if( PAGE_IS_UNPINNED(pPage) ){
return pcache1PinPage(pPage);
}else{
return pPage;
@@ -1070,9 +1073,9 @@ static void pcache1Unpin(
** part of the PGroup LRU list.
*/
assert( pPage->pLruPrev==0 && pPage->pLruNext==0 );
- assert( pPage->isPinned==1 );
+ assert( PAGE_IS_PINNED(pPage) );
- if( reuseUnlikely || pGroup->nCurrentPage>pGroup->nMaxPage ){
+ if( reuseUnlikely || pGroup->nPurgeable>pGroup->nMaxPage ){
pcache1RemoveFromHash(pPage, 1);
}else{
/* Add the page to the PGroup LRU list. */
@@ -1081,7 +1084,6 @@ static void pcache1Unpin(
(pPage->pLruNext = *ppFirst)->pLruPrev = pPage;
*ppFirst = pPage;
pCache->nRecyclable++;
- pPage->isPinned = 0;
}
pcache1LeaveMutex(pCache->pGroup);
@@ -1225,7 +1227,7 @@ int sqlite3PcacheReleaseMemory(int nReq){
#ifdef SQLITE_PCACHE_SEPARATE_HEADER
nFree += sqlite3MemSize(p);
#endif
- assert( p->isPinned==0 );
+ assert( PAGE_IS_UNPINNED(p) );
pcache1PinPage(p);
pcache1RemoveFromHash(p, 1);
}
@@ -1249,10 +1251,10 @@ void sqlite3PcacheStats(
PgHdr1 *p;
int nRecyclable = 0;
for(p=pcache1.grp.lru.pLruNext; p && !p->isAnchor; p=p->pLruNext){
- assert( p->isPinned==0 );
+ assert( PAGE_IS_UNPINNED(p) );
nRecyclable++;
}
- *pnCurrent = pcache1.grp.nCurrentPage;
+ *pnCurrent = pcache1.grp.nPurgeable;
*pnMax = (int)pcache1.grp.nMaxPage;
*pnMin = (int)pcache1.grp.nMinPage;
*pnRecyclable = nRecyclable;
diff --git a/chromium/third_party/sqlite/src/src/pragma.c b/chromium/third_party/sqlite/src/src/pragma.c
index c247f74ca23..c1a2781b554 100644
--- a/chromium/third_party/sqlite/src/src/pragma.c
+++ b/chromium/third_party/sqlite/src/src/pragma.c
@@ -298,16 +298,16 @@ static const PragmaName *pragmaLocate(const char *zName){
/*
** Helper subroutine for PRAGMA integrity_check:
**
-** Generate code to output a single-column result row with the result
-** held in register regResult. Decrement the result count and halt if
-** the maximum number of result rows have been issued.
+** Generate code to output a single-column result row with a value of the
+** string held in register 3. Decrement the result count in register 1
+** and halt if the maximum number of result rows have been issued.
*/
-static int integrityCheckResultRow(Vdbe *v, int regResult){
+static int integrityCheckResultRow(Vdbe *v){
int addr;
- sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 1);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1);
addr = sqlite3VdbeAddOp3(v, OP_IfPos, 1, sqlite3VdbeCurrentAddr(v)+2, 1);
VdbeCoverage(v);
- sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
+ sqlite3VdbeAddOp0(v, OP_Halt);
return addr;
}
@@ -1255,13 +1255,11 @@ void sqlite3Pragma(
for(i=0; i<SQLITE_FUNC_HASH_SZ; i++){
for(p=sqlite3BuiltinFunctions.a[i]; p; p=p->u.pHash ){
sqlite3VdbeMultiLoad(v, 1, "si", p->zName, 1);
- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2);
}
}
for(j=sqliteHashFirst(&db->aFunc); j; j=sqliteHashNext(j)){
p = (FuncDef*)sqliteHashData(j);
sqlite3VdbeMultiLoad(v, 1, "si", p->zName, 0);
- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2);
}
}
break;
@@ -1273,7 +1271,6 @@ void sqlite3Pragma(
for(j=sqliteHashFirst(&db->aModule); j; j=sqliteHashNext(j)){
Module *pMod = (Module*)sqliteHashData(j);
sqlite3VdbeMultiLoad(v, 1, "s", pMod->zName);
- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
}
}
break;
@@ -1283,7 +1280,6 @@ void sqlite3Pragma(
int i;
for(i=0; i<ArraySize(aPragmaName); i++){
sqlite3VdbeMultiLoad(v, 1, "s", aPragmaName[i].zName);
- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
}
}
break;
@@ -1509,12 +1505,11 @@ void sqlite3Pragma(
/* Do an integrity check on each database file */
for(i=0; i<db->nDb; i++){
- HashElem *x;
- Hash *pTbls;
- int *aRoot;
- int cnt = 0;
- int mxIdx = 0;
- int nIdx;
+ HashElem *x; /* For looping over tables in the schema */
+ Hash *pTbls; /* Set of all tables in the schema */
+ int *aRoot; /* Array of root page numbers of all btrees */
+ int cnt = 0; /* Number of entries in aRoot[] */
+ int mxIdx = 0; /* Maximum number of indexes for any table */
if( OMIT_TEMPDB && i==1 ) continue;
if( iDb>=0 && i!=iDb ) continue;
@@ -1529,8 +1524,9 @@ void sqlite3Pragma(
assert( sqlite3SchemaMutexHeld(db, i, 0) );
pTbls = &db->aDb[i].pSchema->tblHash;
for(cnt=0, x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
- Table *pTab = sqliteHashData(x);
- Index *pIdx;
+ Table *pTab = sqliteHashData(x); /* Current table */
+ Index *pIdx; /* An index on pTab */
+ int nIdx; /* Number of indexes on pTab */
if( HasRowid(pTab) ) cnt++;
for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ cnt++; }
if( nIdx>mxIdx ) mxIdx = nIdx;
@@ -1558,9 +1554,8 @@ void sqlite3Pragma(
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zDbSName),
P4_DYNAMIC);
- sqlite3VdbeAddOp3(v, OP_Move, 2, 4, 1);
- sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 2);
- integrityCheckResultRow(v, 2);
+ sqlite3VdbeAddOp3(v, OP_Concat, 2, 3, 3);
+ integrityCheckResultRow(v);
sqlite3VdbeJumpHere(v, addr);
/* Make sure all the indices are constructed correctly.
@@ -1574,16 +1569,13 @@ void sqlite3Pragma(
int r1 = -1;
if( pTab->tnum<1 ) continue; /* Skip VIEWs or VIRTUAL TABLEs */
- if( pTab->pCheck==0
- && (pTab->tabFlags & TF_HasNotNull)==0
- && (pTab->pIndex==0 || isQuick)
- ){
- continue; /* No additional checks needed for this table */
- }
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
sqlite3ExprCacheClear(pParse);
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0,
1, 0, &iDataCur, &iIdxCur);
+ /* reg[7] counts the number of entries in the table.
+ ** reg[8+i] counts the number of entries in the i-th index
+ */
sqlite3VdbeAddOp2(v, OP_Integer, 0, 7);
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
sqlite3VdbeAddOp2(v, OP_Integer, 0, 8+j); /* index entries counter */
@@ -1604,7 +1596,7 @@ void sqlite3Pragma(
zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
pTab->aCol[j].zName);
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
- integrityCheckResultRow(v, 3);
+ integrityCheckResultRow(v);
sqlite3VdbeJumpHere(v, jmp2);
}
/* Verify CHECK constraints */
@@ -1627,57 +1619,62 @@ void sqlite3Pragma(
zErr = sqlite3MPrintf(db, "CHECK constraint failed in %s",
pTab->zName);
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
- integrityCheckResultRow(v, 3);
+ integrityCheckResultRow(v);
sqlite3VdbeResolveLabel(v, addrCkOk);
sqlite3ExprCachePop(pParse);
}
sqlite3ExprListDelete(db, pCheck);
}
- /* Validate index entries for the current row */
- for(j=0, pIdx=pTab->pIndex; pIdx && !isQuick; pIdx=pIdx->pNext, j++){
- int jmp2, jmp3, jmp4, jmp5;
- int ckUniq = sqlite3VdbeMakeLabel(v);
- if( pPk==pIdx ) continue;
- r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3,
- pPrior, r1);
- pPrior = pIdx;
- sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1); /* increment entry count */
- /* Verify that an index entry exists for the current table row */
- jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, ckUniq, r1,
- pIdx->nColumn); VdbeCoverage(v);
- sqlite3VdbeLoadString(v, 3, "row ");
- sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3);
- sqlite3VdbeLoadString(v, 4, " missing from index ");
- sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
- jmp5 = sqlite3VdbeLoadString(v, 4, pIdx->zName);
- sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
- jmp4 = integrityCheckResultRow(v, 3);
- sqlite3VdbeJumpHere(v, jmp2);
- /* For UNIQUE indexes, verify that only one entry exists with the
- ** current key. The entry is unique if (1) any column is NULL
- ** or (2) the next entry has a different key */
- if( IsUniqueIndex(pIdx) ){
- int uniqOk = sqlite3VdbeMakeLabel(v);
- int jmp6;
- int kk;
- for(kk=0; kk<pIdx->nKeyCol; kk++){
- int iCol = pIdx->aiColumn[kk];
- assert( iCol!=XN_ROWID && iCol<pTab->nCol );
- if( iCol>=0 && pTab->aCol[iCol].notNull ) continue;
- sqlite3VdbeAddOp2(v, OP_IsNull, r1+kk, uniqOk);
- VdbeCoverage(v);
+ if( !isQuick ){ /* Omit the remaining tests for quick_check */
+ /* Sanity check on record header decoding */
+ sqlite3VdbeAddOp3(v, OP_Column, iDataCur, pTab->nCol-1, 3);
+ sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
+ /* Validate index entries for the current row */
+ for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
+ int jmp2, jmp3, jmp4, jmp5;
+ int ckUniq = sqlite3VdbeMakeLabel(v);
+ if( pPk==pIdx ) continue;
+ r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3,
+ pPrior, r1);
+ pPrior = pIdx;
+ sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1);/* increment entry count */
+ /* Verify that an index entry exists for the current table row */
+ jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, ckUniq, r1,
+ pIdx->nColumn); VdbeCoverage(v);
+ sqlite3VdbeLoadString(v, 3, "row ");
+ sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3);
+ sqlite3VdbeLoadString(v, 4, " missing from index ");
+ sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
+ jmp5 = sqlite3VdbeLoadString(v, 4, pIdx->zName);
+ sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
+ jmp4 = integrityCheckResultRow(v);
+ sqlite3VdbeJumpHere(v, jmp2);
+ /* For UNIQUE indexes, verify that only one entry exists with the
+ ** current key. The entry is unique if (1) any column is NULL
+ ** or (2) the next entry has a different key */
+ if( IsUniqueIndex(pIdx) ){
+ int uniqOk = sqlite3VdbeMakeLabel(v);
+ int jmp6;
+ int kk;
+ for(kk=0; kk<pIdx->nKeyCol; kk++){
+ int iCol = pIdx->aiColumn[kk];
+ assert( iCol!=XN_ROWID && iCol<pTab->nCol );
+ if( iCol>=0 && pTab->aCol[iCol].notNull ) continue;
+ sqlite3VdbeAddOp2(v, OP_IsNull, r1+kk, uniqOk);
+ VdbeCoverage(v);
+ }
+ jmp6 = sqlite3VdbeAddOp1(v, OP_Next, iIdxCur+j); VdbeCoverage(v);
+ sqlite3VdbeGoto(v, uniqOk);
+ sqlite3VdbeJumpHere(v, jmp6);
+ sqlite3VdbeAddOp4Int(v, OP_IdxGT, iIdxCur+j, uniqOk, r1,
+ pIdx->nKeyCol); VdbeCoverage(v);
+ sqlite3VdbeLoadString(v, 3, "non-unique entry in index ");
+ sqlite3VdbeGoto(v, jmp5);
+ sqlite3VdbeResolveLabel(v, uniqOk);
}
- jmp6 = sqlite3VdbeAddOp1(v, OP_Next, iIdxCur+j); VdbeCoverage(v);
- sqlite3VdbeGoto(v, uniqOk);
- sqlite3VdbeJumpHere(v, jmp6);
- sqlite3VdbeAddOp4Int(v, OP_IdxGT, iIdxCur+j, uniqOk, r1,
- pIdx->nKeyCol); VdbeCoverage(v);
- sqlite3VdbeLoadString(v, 3, "non-unique entry in index ");
- sqlite3VdbeGoto(v, jmp5);
- sqlite3VdbeResolveLabel(v, uniqOk);
+ sqlite3VdbeJumpHere(v, jmp4);
+ sqlite3ResolvePartIdxLabel(pParse, jmp3);
}
- sqlite3VdbeJumpHere(v, jmp4);
- sqlite3ResolvePartIdxLabel(pParse, jmp3);
}
sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, loopTop-1);
@@ -1689,9 +1686,9 @@ void sqlite3Pragma(
sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3);
addr = sqlite3VdbeAddOp3(v, OP_Eq, 8+j, 0, 3); VdbeCoverage(v);
sqlite3VdbeChangeP5(v, SQLITE_NOTNULL);
- sqlite3VdbeLoadString(v, 3, pIdx->zName);
- sqlite3VdbeAddOp3(v, OP_Concat, 3, 2, 7);
- integrityCheckResultRow(v, 7);
+ sqlite3VdbeLoadString(v, 4, pIdx->zName);
+ sqlite3VdbeAddOp3(v, OP_Concat, 4, 2, 3);
+ integrityCheckResultRow(v);
sqlite3VdbeJumpHere(v, addr);
}
}
@@ -1705,6 +1702,9 @@ void sqlite3Pragma(
{ OP_IfNotZero, 1, 4, 0}, /* 1 */
{ OP_String8, 0, 3, 0}, /* 2 */
{ OP_ResultRow, 3, 1, 0}, /* 3 */
+ { OP_Halt, 0, 0, 0}, /* 4 */
+ { OP_String8, 0, 3, 0}, /* 5 */
+ { OP_Goto, 0, 3, 0}, /* 6 */
};
VdbeOp *aOp;
@@ -1713,7 +1713,10 @@ void sqlite3Pragma(
aOp[0].p2 = 1-mxErr;
aOp[2].p4type = P4_STATIC;
aOp[2].p4.z = "ok";
+ aOp[5].p4type = P4_STATIC;
+ aOp[5].p4.z = (char*)sqlite3ErrStr(SQLITE_CORRUPT);
}
+ sqlite3VdbeChangeP3(v, 0, sqlite3VdbeCurrentAddr(v)-2);
}
}
break;
diff --git a/chromium/third_party/sqlite/src/src/prepare.c b/chromium/third_party/sqlite/src/src/prepare.c
index b209799b104..330cff9d8c1 100644
--- a/chromium/third_party/sqlite/src/src/prepare.c
+++ b/chromium/third_party/sqlite/src/src/prepare.c
@@ -85,7 +85,7 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
rc = db->errCode;
assert( (rc&0xFF)==(rcp&0xFF) );
db->init.iDb = saved_iDb;
- assert( saved_iDb==0 || (db->flags & SQLITE_Vacuum)!=0 );
+ assert( saved_iDb==0 || (db->mDbFlags & DBFLAG_Vacuum)!=0 );
if( SQLITE_OK!=rc ){
if( db->init.orphanTrigger ){
assert( iDb==1 );
@@ -150,6 +150,8 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
assert( sqlite3_mutex_held(db->mutex) );
assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
+ db->init.busy = 1;
+
/* Construct the in-memory representation schema tables (sqlite_master or
** sqlite_temp_master) by invoking the parser directly. The appropriate
** table name will be inserted automatically by the parser so we can just
@@ -158,7 +160,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
azArg[0] = zMasterName = SCHEMA_TABLE(iDb);
azArg[1] = "1";
azArg[2] = "CREATE TABLE x(type text,name text,tbl_name text,"
- "rootpage integer,sql text)";
+ "rootpage int,sql text)";
azArg[3] = 0;
initData.db = db;
initData.iDb = iDb;
@@ -174,10 +176,10 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
*/
pDb = &db->aDb[iDb];
if( pDb->pBt==0 ){
- if( !OMIT_TEMPDB && ALWAYS(iDb==1) ){
- DbSetProperty(db, 1, DB_SchemaLoaded);
- }
- return SQLITE_OK;
+ assert( iDb==1 );
+ DbSetProperty(db, 1, DB_SchemaLoaded);
+ rc = SQLITE_OK;
+ goto error_out;
}
/* If there is not already a read-only (or read-write) transaction opened
@@ -336,9 +338,13 @@ initone_error_out:
sqlite3BtreeLeave(pDb->pBt);
error_out:
- if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
- sqlite3OomFault(db);
+ if( rc ){
+ if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
+ sqlite3OomFault(db);
+ }
+ sqlite3ResetOneSchema(db, iDb);
}
+ db->init.busy = 0;
return rc;
}
@@ -354,42 +360,29 @@ error_out:
*/
int sqlite3Init(sqlite3 *db, char **pzErrMsg){
int i, rc;
- int commit_internal = !(db->flags&SQLITE_InternChanges);
+ int commit_internal = !(db->mDbFlags&DBFLAG_SchemaChange);
assert( sqlite3_mutex_held(db->mutex) );
assert( sqlite3BtreeHoldsMutex(db->aDb[0].pBt) );
assert( db->init.busy==0 );
- rc = SQLITE_OK;
- db->init.busy = 1;
ENC(db) = SCHEMA_ENC(db);
- for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
- if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue;
- rc = sqlite3InitOne(db, i, pzErrMsg);
- if( rc ){
- sqlite3ResetOneSchema(db, i);
- }
- }
-
- /* Once all the other databases have been initialized, load the schema
- ** for the TEMP database. This is loaded last, as the TEMP database
- ** schema may contain references to objects in other databases.
- */
-#ifndef SQLITE_OMIT_TEMPDB
- assert( db->nDb>1 );
- if( rc==SQLITE_OK && !DbHasProperty(db, 1, DB_SchemaLoaded) ){
- rc = sqlite3InitOne(db, 1, pzErrMsg);
- if( rc ){
- sqlite3ResetOneSchema(db, 1);
+ assert( db->nDb>0 );
+ /* Do the main schema first */
+ if( !DbHasProperty(db, 0, DB_SchemaLoaded) ){
+ rc = sqlite3InitOne(db, 0, pzErrMsg);
+ if( rc ) return rc;
+ }
+ /* All other schemas after the main schema. The "temp" schema must be last */
+ for(i=db->nDb-1; i>0; i--){
+ if( !DbHasProperty(db, i, DB_SchemaLoaded) ){
+ rc = sqlite3InitOne(db, i, pzErrMsg);
+ if( rc ) return rc;
}
}
-#endif
-
- db->init.busy = 0;
- if( rc==SQLITE_OK && commit_internal ){
+ if( commit_internal ){
sqlite3CommitInternalChanges(db);
}
-
- return rc;
+ return SQLITE_OK;
}
/*
@@ -494,16 +487,14 @@ int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){
** Free all memory allocations in the pParse object
*/
void sqlite3ParserReset(Parse *pParse){
- if( pParse ){
- sqlite3 *db = pParse->db;
- sqlite3DbFree(db, pParse->aLabel);
- sqlite3ExprListDelete(db, pParse->pConstExpr);
- if( db ){
- assert( db->lookaside.bDisable >= pParse->disableLookaside );
- db->lookaside.bDisable -= pParse->disableLookaside;
- }
- pParse->disableLookaside = 0;
+ sqlite3 *db = pParse->db;
+ sqlite3DbFree(db, pParse->aLabel);
+ sqlite3ExprListDelete(db, pParse->pConstExpr);
+ if( db ){
+ assert( db->lookaside.bDisable >= pParse->disableLookaside );
+ db->lookaside.bDisable -= pParse->disableLookaside;
}
+ pParse->disableLookaside = 0;
}
/*
@@ -689,6 +680,7 @@ static int sqlite3LockAndPrepare(
sqlite3BtreeEnterAll(db);
rc = sqlite3Prepare(db, zSql, nBytes, prepFlags, pOld, ppStmt, pzTail);
if( rc==SQLITE_SCHEMA ){
+ sqlite3ResetOneSchema(db, -1);
sqlite3_finalize(*ppStmt);
rc = sqlite3Prepare(db, zSql, nBytes, prepFlags, pOld, ppStmt, pzTail);
}
diff --git a/chromium/third_party/sqlite/src/src/printf.c b/chromium/third_party/sqlite/src/src/printf.c
index 6cca4d62552..b43c08e24f5 100644
--- a/chromium/third_party/sqlite/src/src/printf.c
+++ b/chromium/third_party/sqlite/src/src/printf.c
@@ -656,7 +656,7 @@ void sqlite3VXPrintf(
if( precision>=0 ){
for(length=0; length<precision && bufpt[length]; length++){}
}else{
- length = sqlite3Strlen30(bufpt);
+ length = 0x7fffffff & (int)strlen(bufpt);
}
break;
case etSQLESCAPE: /* Escape ' characters */
@@ -782,7 +782,6 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
}else{
char *zOld = isMalloced(p) ? p->zText : 0;
i64 szNew = p->nChar;
- assert( (p->zText==0 || p->zText==p->zBase)==!isMalloced(p) );
szNew += N + 1;
if( szNew+p->nChar<=p->mxAlloc ){
/* Force exponential buffer size growth as long as it does not overflow,
@@ -824,7 +823,6 @@ void sqlite3AppendChar(StrAccum *p, int N, char c){
if( p->nChar+(i64)N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ){
return;
}
- assert( (p->zText==p->zBase)==!isMalloced(p) );
while( (N--)>0 ) p->zText[p->nChar++] = c;
}
@@ -842,7 +840,6 @@ static void SQLITE_NOINLINE enlargeAndAppend(StrAccum *p, const char *z, int N){
memcpy(&p->zText[p->nChar], z, N);
p->nChar += N;
}
- assert( (p->zText==0 || p->zText==p->zBase)==!isMalloced(p) );
}
/*
@@ -877,19 +874,20 @@ void sqlite3StrAccumAppendAll(StrAccum *p, const char *z){
** pointer if any kind of error was encountered.
*/
static SQLITE_NOINLINE char *strAccumFinishRealloc(StrAccum *p){
+ char *zText;
assert( p->mxAlloc>0 && !isMalloced(p) );
- p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 );
- if( p->zText ){
- memcpy(p->zText, p->zBase, p->nChar+1);
+ zText = sqlite3DbMallocRaw(p->db, p->nChar+1 );
+ if( zText ){
+ memcpy(zText, p->zText, p->nChar+1);
p->printfFlags |= SQLITE_PRINTF_MALLOCED;
}else{
setStrAccumError(p, STRACCUM_NOMEM);
}
- return p->zText;
+ p->zText = zText;
+ return zText;
}
char *sqlite3StrAccumFinish(StrAccum *p){
if( p->zText ){
- assert( (p->zText==p->zBase)==!isMalloced(p) );
p->zText[p->nChar] = 0;
if( p->mxAlloc>0 && !isMalloced(p) ){
return strAccumFinishRealloc(p);
@@ -902,7 +900,6 @@ char *sqlite3StrAccumFinish(StrAccum *p){
** Reset an StrAccum string. Reclaim all malloced memory.
*/
void sqlite3StrAccumReset(StrAccum *p){
- assert( (p->zText==0 || p->zText==p->zBase)==!isMalloced(p) );
if( isMalloced(p) ){
sqlite3DbFree(p->db, p->zText);
p->printfFlags &= ~SQLITE_PRINTF_MALLOCED;
@@ -925,11 +922,11 @@ void sqlite3StrAccumReset(StrAccum *p){
** allocations will ever occur.
*/
void sqlite3StrAccumInit(StrAccum *p, sqlite3 *db, char *zBase, int n, int mx){
- p->zText = p->zBase = zBase;
+ p->zText = zBase;
p->db = db;
- p->nChar = 0;
p->nAlloc = n;
p->mxAlloc = mx;
+ p->nChar = 0;
p->accError = 0;
p->printfFlags = 0;
}
diff --git a/chromium/third_party/sqlite/src/src/resolve.c b/chromium/third_party/sqlite/src/src/resolve.c
index 3cced4ba4c4..5fa91ffbce7 100644
--- a/chromium/third_party/sqlite/src/src/resolve.c
+++ b/chromium/third_party/sqlite/src/src/resolve.c
@@ -959,12 +959,10 @@ static int resolveCompoundOrderBy(
pOrderBy = pSelect->pOrderBy;
if( pOrderBy==0 ) return 0;
db = pParse->db;
-#if SQLITE_MAX_COLUMN
if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
sqlite3ErrorMsg(pParse, "too many terms in ORDER BY clause");
return 1;
}
-#endif
for(i=0; i<pOrderBy->nExpr; i++){
pOrderBy->a[i].done = 0;
}
@@ -1056,12 +1054,10 @@ int sqlite3ResolveOrderGroupBy(
struct ExprList_item *pItem;
if( pOrderBy==0 || pParse->db->mallocFailed ) return 0;
-#if SQLITE_MAX_COLUMN
if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
sqlite3ErrorMsg(pParse, "too many terms in %s BY clause", zType);
return 1;
}
-#endif
pEList = pSelect->pEList;
assert( pEList!=0 ); /* sqlite3SelectNew() guarantees this */
for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
diff --git a/chromium/third_party/sqlite/src/src/select.c b/chromium/third_party/sqlite/src/src/select.c
index 21ed01f7923..13122ee52fe 100644
--- a/chromium/third_party/sqlite/src/src/select.c
+++ b/chromium/third_party/sqlite/src/src/select.c
@@ -75,7 +75,7 @@ static void clearSelect(sqlite3 *db, Select *p, int bFree){
sqlite3ExprListDelete(db, p->pOrderBy);
sqlite3ExprDelete(db, p->pLimit);
sqlite3ExprDelete(db, p->pOffset);
- if( p->pWith ) sqlite3WithDelete(db, p->pWith);
+ if( OK_IF_ALWAYS_TRUE(p->pWith) ) sqlite3WithDelete(db, p->pWith);
if( bFree ) sqlite3DbFreeNN(db, p);
p = pPrior;
bFree = 1;
@@ -118,7 +118,8 @@ Select *sqlite3SelectNew(
pNew = &standin;
}
if( pEList==0 ){
- pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(pParse->db,TK_ASTERISK,0));
+ pEList = sqlite3ExprListAppend(pParse, 0,
+ sqlite3Expr(pParse->db,TK_ASTERISK,0));
}
pNew->pEList = pEList;
pNew->op = TK_SELECT;
@@ -142,7 +143,8 @@ Select *sqlite3SelectNew(
pNew->pLimit = pLimit;
pNew->pOffset = pOffset;
pNew->pWith = 0;
- assert( pOffset==0 || pLimit!=0 || pParse->nErr>0 || pParse->db->mallocFailed!=0 );
+ assert( pOffset==0 || pLimit!=0 || pParse->nErr>0
+ || pParse->db->mallocFailed!=0 );
if( pParse->db->mallocFailed ) {
clearSelect(pParse->db, pNew, pNew!=&standin);
pNew = 0;
@@ -169,7 +171,7 @@ void sqlite3SelectSetName(Select *p, const char *zName){
** Delete the given Select structure and all of its substructures.
*/
void sqlite3SelectDelete(sqlite3 *db, Select *p){
- if( p ) clearSelect(db, p, 1);
+ if( OK_IF_ALWAYS_TRUE(p) ) clearSelect(db, p, 1);
}
/*
@@ -410,11 +412,10 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
pLeft = &pSrc->a[0];
pRight = &pLeft[1];
for(i=0; i<pSrc->nSrc-1; i++, pRight++, pLeft++){
- Table *pLeftTab = pLeft->pTab;
Table *pRightTab = pRight->pTab;
int isOuter;
- if( NEVER(pLeftTab==0 || pRightTab==0) ) continue;
+ if( NEVER(pLeft->pTab==0 || pRightTab==0) ) continue;
isOuter = (pRight->fg.jointype & JT_OUTER)!=0;
/* When the NATURAL keyword is present, add WHERE clause terms for
@@ -562,11 +563,11 @@ static void pushOntoSorter(
if( pParse->db->mallocFailed ) return;
pOp->p2 = nKey + nData;
pKI = pOp->p4.pKeyInfo;
- memset(pKI->aSortOrder, 0, pKI->nField); /* Makes OP_Jump below testable */
+ memset(pKI->aSortOrder, 0, pKI->nKeyField); /* Makes OP_Jump testable */
sqlite3VdbeChangeP4(v, -1, (char*)pKI, P4_KEYINFO);
- testcase( pKI->nXField>2 );
+ testcase( pKI->nAllField > pKI->nKeyField+2 );
pOp->p4.pKeyInfo = keyInfoFromExprList(pParse, pSort->pOrderBy, nOBSat,
- pKI->nXField-1);
+ pKI->nAllField-pKI->nKeyField-1);
addrJmp = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp3(v, OP_Jump, addrJmp+1, 0, addrJmp+1); VdbeCoverage(v);
pSort->labelBkOut = sqlite3VdbeMakeLabel(v);
@@ -664,16 +665,15 @@ static void codeDistinct(
** This routine generates the code for the inside of the inner loop
** of a SELECT.
**
-** If srcTab is negative, then the pEList expressions
+** If srcTab is negative, then the p->pEList expressions
** are evaluated in order to get the data for this row. If srcTab is
-** zero or more, then data is pulled from srcTab and pEList is used only
+** zero or more, then data is pulled from srcTab and p->pEList is used only
** to get the number of columns and the collation sequence for each column.
*/
static void selectInnerLoop(
Parse *pParse, /* The parser context */
Select *p, /* The complete select statement being coded */
- ExprList *pEList, /* List of values being extracted */
- int srcTab, /* Pull data from this table */
+ int srcTab, /* Pull data from this table if non-negative */
SortCtx *pSort, /* If not NULL, info on how to process ORDER BY */
DistinctCtx *pDistinct, /* If not NULL, info on how to process DISTINCT */
SelectDest *pDest, /* How to dispose of the results */
@@ -697,7 +697,7 @@ static void selectInnerLoop(
int regOrig; /* Start of memory holding full result (or 0) */
assert( v );
- assert( pEList!=0 );
+ assert( p->pEList!=0 );
hasDistinct = pDistinct ? pDistinct->eTnctType : WHERE_DISTINCT_NOOP;
if( pSort && pSort->pOrderBy==0 ) pSort = 0;
if( pSort==0 && !hasDistinct ){
@@ -707,7 +707,7 @@ static void selectInnerLoop(
/* Pull the requested columns.
*/
- nResultCol = pEList->nExpr;
+ nResultCol = p->pEList->nExpr;
if( pDest->iSdst==0 ){
if( pSort ){
@@ -730,7 +730,7 @@ static void selectInnerLoop(
if( srcTab>=0 ){
for(i=0; i<nResultCol; i++){
sqlite3VdbeAddOp3(v, OP_Column, srcTab, i, regResult+i);
- VdbeComment((v, "%s", pEList->a[i].zName));
+ VdbeComment((v, "%s", p->pEList->a[i].zName));
}
}else if( eDest!=SRT_Exists ){
/* If the destination is an EXISTS(...) expression, the actual
@@ -743,24 +743,25 @@ static void selectInnerLoop(
ecelFlags = 0;
}
if( pSort && hasDistinct==0 && eDest!=SRT_EphemTab && eDest!=SRT_Table ){
- /* For each expression in pEList that is a copy of an expression in
+ /* For each expression in p->pEList that is a copy of an expression in
** the ORDER BY clause (pSort->pOrderBy), set the associated
** iOrderByCol value to one more than the index of the ORDER BY
** expression within the sort-key that pushOntoSorter() will generate.
- ** This allows the pEList field to be omitted from the sorted record,
+ ** This allows the p->pEList field to be omitted from the sorted record,
** saving space and CPU cycles. */
ecelFlags |= (SQLITE_ECEL_OMITREF|SQLITE_ECEL_REF);
for(i=pSort->nOBSat; i<pSort->pOrderBy->nExpr; i++){
int j;
if( (j = pSort->pOrderBy->a[i].u.x.iOrderByCol)>0 ){
- pEList->a[j-1].u.x.iOrderByCol = i+1-pSort->nOBSat;
+ p->pEList->a[j-1].u.x.iOrderByCol = i+1-pSort->nOBSat;
}
}
regOrig = 0;
assert( eDest==SRT_Set || eDest==SRT_Mem
|| eDest==SRT_Coroutine || eDest==SRT_Output );
}
- nResultCol = sqlite3ExprCodeExprList(pParse,pEList,regResult,0,ecelFlags);
+ nResultCol = sqlite3ExprCodeExprList(pParse,p->pEList,regResult,
+ 0,ecelFlags);
}
/* If the DISTINCT keyword was present on the SELECT statement
@@ -792,7 +793,7 @@ static void selectInnerLoop(
iJump = sqlite3VdbeCurrentAddr(v) + nResultCol;
for(i=0; i<nResultCol; i++){
- CollSeq *pColl = sqlite3ExprCollSeq(pParse, pEList->a[i].pExpr);
+ CollSeq *pColl = sqlite3ExprCollSeq(pParse, p->pEList->a[i].pExpr);
if( i<nResultCol-1 ){
sqlite3VdbeAddOp3(v, OP_Ne, regResult+i, iJump, regPrev+i);
VdbeCoverage(v);
@@ -1035,8 +1036,8 @@ KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){
KeyInfo *p = sqlite3DbMallocRawNN(db, sizeof(KeyInfo) + nExtra);
if( p ){
p->aSortOrder = (u8*)&p->aColl[N+X];
- p->nField = (u16)N;
- p->nXField = (u16)X;
+ p->nKeyField = (u16)N;
+ p->nAllField = (u16)(N+X);
p->enc = ENC(db);
p->db = db;
p->nRef = 1;
@@ -1110,10 +1111,7 @@ static KeyInfo *keyInfoFromExprList(
if( pInfo ){
assert( sqlite3KeyInfoIsWriteable(pInfo) );
for(i=iStart, pItem=pList->a+iStart; i<nExpr; i++, pItem++){
- CollSeq *pColl;
- pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr);
- if( !pColl ) pColl = db->pDfltColl;
- pInfo->aColl[i-iStart] = pColl;
+ pInfo->aColl[i-iStart] = sqlite3ExprNNCollSeq(pParse, pItem->pExpr);
pInfo->aSortOrder[i-iStart] = pItem->sortOrder;
}
}
@@ -1363,23 +1361,23 @@ static void generateSortTail(
** the SQLITE_ENABLE_COLUMN_METADATA compile-time option is used.
*/
#ifdef SQLITE_ENABLE_COLUMN_METADATA
-# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,C,D,E,F)
+# define columnType(A,B,C,D,E) columnTypeImpl(A,B,C,D,E)
#else /* if !defined(SQLITE_ENABLE_COLUMN_METADATA) */
-# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,F)
+# define columnType(A,B,C,D,E) columnTypeImpl(A,B)
#endif
static const char *columnTypeImpl(
NameContext *pNC,
+#ifndef SQLITE_ENABLE_COLUMN_METADATA
+ Expr *pExpr
+#else
Expr *pExpr,
-#ifdef SQLITE_ENABLE_COLUMN_METADATA
const char **pzOrigDb,
const char **pzOrigTab,
- const char **pzOrigCol,
+ const char **pzOrigCol
#endif
- u8 *pEstWidth
){
char const *zType = 0;
int j;
- u8 estWidth = 1;
#ifdef SQLITE_ENABLE_COLUMN_METADATA
char const *zOrigDb = 0;
char const *zOrigTab = 0;
@@ -1448,33 +1446,32 @@ static const char *columnTypeImpl(
sNC.pSrcList = pS->pSrc;
sNC.pNext = pNC;
sNC.pParse = pNC->pParse;
- zType = columnType(&sNC, p,&zOrigDb,&zOrigTab,&zOrigCol, &estWidth);
+ zType = columnType(&sNC, p,&zOrigDb,&zOrigTab,&zOrigCol);
}
- }else if( pTab->pSchema ){
- /* A real table */
+ }else{
+ /* A real table or a CTE table */
assert( !pS );
- if( iCol<0 ) iCol = pTab->iPKey;
- assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
#ifdef SQLITE_ENABLE_COLUMN_METADATA
+ if( iCol<0 ) iCol = pTab->iPKey;
+ assert( iCol==XN_ROWID || (iCol>=0 && iCol<pTab->nCol) );
if( iCol<0 ){
zType = "INTEGER";
zOrigCol = "rowid";
}else{
zOrigCol = pTab->aCol[iCol].zName;
zType = sqlite3ColumnType(&pTab->aCol[iCol],0);
- estWidth = pTab->aCol[iCol].szEst;
}
zOrigTab = pTab->zName;
- if( pNC->pParse ){
+ if( pNC->pParse && pTab->pSchema ){
int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema);
zOrigDb = pNC->pParse->db->aDb[iDb].zDbSName;
}
#else
+ assert( iCol==XN_ROWID || (iCol>=0 && iCol<pTab->nCol) );
if( iCol<0 ){
zType = "INTEGER";
}else{
zType = sqlite3ColumnType(&pTab->aCol[iCol],0);
- estWidth = pTab->aCol[iCol].szEst;
}
#endif
}
@@ -1493,7 +1490,7 @@ static const char *columnTypeImpl(
sNC.pSrcList = pS->pSrc;
sNC.pNext = pNC;
sNC.pParse = pNC->pParse;
- zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol, &estWidth);
+ zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol);
break;
}
#endif
@@ -1507,7 +1504,6 @@ static const char *columnTypeImpl(
*pzOrigCol = zOrigCol;
}
#endif
- if( pEstWidth ) *pEstWidth = estWidth;
return zType;
}
@@ -1534,7 +1530,7 @@ static void generateColumnTypes(
const char *zOrigDb = 0;
const char *zOrigTab = 0;
const char *zOrigCol = 0;
- zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol, 0);
+ zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol);
/* The vdbe must make its own copy of the column-type and other
** column specific strings, in case the schema is reset before this
@@ -1544,7 +1540,7 @@ static void generateColumnTypes(
sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, SQLITE_TRANSIENT);
sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, SQLITE_TRANSIENT);
#else
- zType = columnType(&sNC, p, 0, 0, 0, 0);
+ zType = columnType(&sNC, p, 0, 0, 0);
#endif
sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, SQLITE_TRANSIENT);
}
@@ -1574,9 +1570,9 @@ static void generateColumnTypes(
** other words, the zSpan of the result expression.
**
** short=ON, full=OFF: (This is the default setting). If the result
-** refers directly to a table column, then the result
-** column name is just the table column name: COLUMN.
-** Otherwise use zSpan.
+** refers directly to a table column, then the
+** result column name is just the table column
+** name: COLUMN. Otherwise use zSpan.
**
** full=ON, short=ANY: If the result refers directly to a table column,
** then the result column name with the table name
@@ -1617,6 +1613,8 @@ static void generateColumnNames(
Expr *p = pEList->a[i].pExpr;
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 */
if( pEList->a[i].zName ){
/* An AS clause always takes first priority */
char *zName = pEList->a[i].zName;
@@ -1691,6 +1689,7 @@ int sqlite3ColumnsFromExprList(
nCol = pEList->nExpr;
aCol = sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol);
testcase( aCol==0 );
+ if( nCol>32767 ) nCol = 32767;
}else{
nCol = 0;
aCol = 0;
@@ -1710,7 +1709,9 @@ int sqlite3ColumnsFromExprList(
pColExpr = pColExpr->pRight;
assert( pColExpr!=0 );
}
- if( pColExpr->op==TK_COLUMN && pColExpr->pTab!=0 ){
+ if( (pColExpr->op==TK_COLUMN || pColExpr->op==TK_AGG_COLUMN)
+ && pColExpr->pTab!=0
+ ){
/* For columns use the column name name */
int iCol = pColExpr->iColumn;
Table *pTab = pColExpr->pTab;
@@ -1785,7 +1786,6 @@ void sqlite3SelectAddColumnTypeAndCollation(
int i;
Expr *p;
struct ExprList_item *a;
- u64 szAll = 0;
assert( pSelect!=0 );
assert( (pSelect->selFlags & SF_Resolved)!=0 );
@@ -1798,10 +1798,11 @@ void sqlite3SelectAddColumnTypeAndCollation(
const char *zType;
int n, m;
p = a[i].pExpr;
- zType = columnType(&sNC, p, 0, 0, 0, &pCol->szEst);
- szAll += pCol->szEst;
+ zType = columnType(&sNC, p, 0, 0, 0);
+ /* pCol->szEst = ... // Column size est for SELECT tables never used */
pCol->affinity = sqlite3ExprAffinity(p);
- if( zType && (m = sqlite3Strlen30(zType))>0 ){
+ if( zType ){
+ m = sqlite3Strlen30(zType);
n = sqlite3Strlen30(pCol->zName);
pCol->zName = sqlite3DbReallocOrFree(db, pCol->zName, n+m+2);
if( pCol->zName ){
@@ -1815,7 +1816,7 @@ void sqlite3SelectAddColumnTypeAndCollation(
pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
}
}
- pTab->szTabRow = sqlite3LogEst(szAll*4);
+ pTab->szTabRow = 1; /* Any non-zero value works */
}
/*
@@ -1858,19 +1859,16 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){
** Get a VDBE for the given parser context. Create a new one if necessary.
** If an error occurs, return NULL and leave a message in pParse.
*/
-static SQLITE_NOINLINE Vdbe *allocVdbe(Parse *pParse){
- Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(pParse);
- if( v ) sqlite3VdbeAddOp2(v, OP_Init, 0, 1);
+Vdbe *sqlite3GetVdbe(Parse *pParse){
+ if( pParse->pVdbe ){
+ return pParse->pVdbe;
+ }
if( pParse->pToplevel==0
&& OptimizationEnabled(pParse->db,SQLITE_FactorOutConst)
){
pParse->okConstFactor = 1;
}
- return v;
-}
-Vdbe *sqlite3GetVdbe(Parse *pParse){
- Vdbe *v = pParse->pVdbe;
- return v ? v : allocVdbe(pParse);
+ return sqlite3VdbeCreate(pParse);
}
@@ -2143,7 +2141,7 @@ static void generateWithRecursiveQuery(
/* Output the single row in Current */
addrCont = sqlite3VdbeMakeLabel(v);
codeOffset(v, regOffset, addrCont);
- selectInnerLoop(pParse, p, p->pEList, iCurrent,
+ selectInnerLoop(pParse, p, iCurrent,
0, 0, pDest, addrCont, addrBreak);
if( regLimit ){
sqlite3VdbeAddOp2(v, OP_DecrJumpZero, regLimit, addrBreak);
@@ -2281,15 +2279,9 @@ static int multiSelect(
db = pParse->db;
pPrior = p->pPrior;
dest = *pDest;
- if( pPrior->pOrderBy ){
- sqlite3ErrorMsg(pParse,"ORDER BY clause should come after %s not before",
- selectOpName(p->op));
- rc = 1;
- goto multi_select_end;
- }
- if( pPrior->pLimit ){
- sqlite3ErrorMsg(pParse,"LIMIT clause should come after %s not before",
- selectOpName(p->op));
+ if( pPrior->pOrderBy || pPrior->pLimit ){
+ sqlite3ErrorMsg(pParse,"%s clause should come after %s not before",
+ pPrior->pOrderBy!=0 ? "ORDER BY" : "LIMIT", selectOpName(p->op));
rc = 1;
goto multi_select_end;
}
@@ -2462,7 +2454,7 @@ static int multiSelect(
computeLimitRegisters(pParse, p, iBreak);
sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); VdbeCoverage(v);
iStart = sqlite3VdbeCurrentAddr(v);
- selectInnerLoop(pParse, p, p->pEList, unionTab,
+ selectInnerLoop(pParse, p, unionTab,
0, 0, &dest, iCont, iBreak);
sqlite3VdbeResolveLabel(v, iCont);
sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); VdbeCoverage(v);
@@ -2535,7 +2527,7 @@ static int multiSelect(
iStart = sqlite3VdbeAddOp2(v, OP_RowData, tab1, r1);
sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0); VdbeCoverage(v);
sqlite3ReleaseTempReg(pParse, r1);
- selectInnerLoop(pParse, p, p->pEList, tab1,
+ selectInnerLoop(pParse, p, tab1,
0, 0, &dest, iCont, iBreak);
sqlite3VdbeResolveLabel(v, iCont);
sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); VdbeCoverage(v);
@@ -3187,7 +3179,9 @@ static Expr *substExpr(
Expr *pExpr /* Expr in which substitution occurs */
){
if( pExpr==0 ) return 0;
- if( ExprHasProperty(pExpr, EP_FromJoin) && pExpr->iRightJoinTable==pSubst->iTable ){
+ if( ExprHasProperty(pExpr, EP_FromJoin)
+ && pExpr->iRightJoinTable==pSubst->iTable
+ ){
pExpr->iRightJoinTable = pSubst->iNewTable;
}
if( pExpr->op==TK_COLUMN && pExpr->iTable==pSubst->iTable ){
@@ -3300,68 +3294,74 @@ static void substSelect(
** exist on the table t1, a complete scan of the data might be
** avoided.
**
-** Flattening is only attempted if all of the following are true:
+** Flattening is subject to the following constraints:
**
-** (1) The subquery and the outer query do not both use aggregates.
+** (**) We no longer attempt to flatten aggregate subqueries. Was:
+** The subquery and the outer query cannot both be aggregates.
**
-** (2) The subquery is not an aggregate or (2a) the outer query is not a join
-** and (2b) the outer query does not use subqueries other than the one
-** FROM-clause subquery that is a candidate for flattening. (2b is
-** due to ticket [2f7170d73bf9abf80] from 2015-02-09.)
+** (**) We no longer attempt to flatten aggregate subqueries. Was:
+** (2) If the subquery is an aggregate then
+** (2a) the outer query must not be a join and
+** (2b) the outer query must not use subqueries
+** other than the one FROM-clause subquery that is a candidate
+** for flattening. (This is due to ticket [2f7170d73bf9abf80]
+** from 2015-02-09.)
**
-** (3) The subquery is not the right operand of a LEFT JOIN
-** or (a) the subquery is not itself a join and (b) the FROM clause
-** of the subquery does not contain a virtual table and (c) the
-** outer query is not an aggregate.
+** (3) If the subquery is the right operand of a LEFT JOIN then
+** (3a) the subquery may not be a join and
+** (3b) the FROM clause of the subquery may not contain a virtual
+** table and
+** (3c) the outer query may not be an aggregate.
**
-** (4) The subquery is not DISTINCT.
+** (4) The subquery can not be DISTINCT.
**
** (**) At one point restrictions (4) and (5) defined a subset of DISTINCT
** sub-queries that were excluded from this optimization. Restriction
** (4) has since been expanded to exclude all DISTINCT subqueries.
**
-** (6) The subquery does not use aggregates or the outer query is not
-** DISTINCT.
+** (**) We no longer attempt to flatten aggregate subqueries. Was:
+** If the subquery is aggregate, the outer query may not be DISTINCT.
**
-** (7) The subquery has a FROM clause. TODO: For subqueries without
+** (7) The subquery must have a FROM clause. TODO: For subqueries without
** A FROM clause, consider adding a FROM clause with the special
** table sqlite_once that consists of a single row containing a
** single NULL.
**
-** (8) The subquery does not use LIMIT or the outer query is not a join.
+** (8) If the subquery uses LIMIT then the outer query may not be a join.
**
-** (9) The subquery does not use LIMIT or the outer query does not use
-** aggregates.
+** (9) If the subquery uses LIMIT then the outer query may not be aggregate.
**
** (**) Restriction (10) was removed from the code on 2005-02-05 but we
** accidently carried the comment forward until 2014-09-15. Original
-** text: "The subquery does not use aggregates or the outer query
-** does not use LIMIT."
+** constraint: "If the subquery is aggregate then the outer query
+** may not use LIMIT."
**
-** (11) The subquery and the outer query do not both have ORDER BY clauses.
+** (11) The subquery and the outer query may not both have ORDER BY clauses.
**
** (**) Not implemented. Subsumed into restriction (3). Was previously
** a separate restriction deriving from ticket #350.
**
-** (13) The subquery and outer query do not both use LIMIT.
+** (13) The subquery and outer query may not both use LIMIT.
**
-** (14) The subquery does not use OFFSET.
+** (14) The subquery may not use OFFSET.
**
-** (15) The outer query is not part of a compound select or the
-** subquery does not have a LIMIT clause.
+** (15) If the outer query is part of a compound select, then the
+** subquery may not use LIMIT.
** (See ticket #2339 and ticket [02a8e81d44]).
**
-** (16) The outer query is not an aggregate or the subquery does
-** not contain ORDER BY. (Ticket #2942) This used to not matter
+** (16) If the outer query is aggregate, then the subquery may not
+** use ORDER BY. (Ticket #2942) This used to not matter
** until we introduced the group_concat() function.
**
-** (17) The sub-query is not a compound select, or it is a UNION ALL
-** compound clause made up entirely of non-aggregate queries, and
-** the parent query:
-**
-** * is not itself part of a compound select,
-** * is not an aggregate or DISTINCT query, and
-** * is not a join
+** (17) If the subquery is a compound select, then
+** (17a) all compound operators must be a UNION ALL, and
+** (17b) no terms within the subquery compound may be aggregate
+** or DISTINCT, and
+** (17c) every term within the subquery compound must have a FROM clause
+** (17d) the outer query may not be
+** (17d1) aggregate, or
+** (17d2) DISTINCT, or
+** (17d3) a join.
**
** The parent and sub-query may contain WHERE clauses. Subject to
** rules (11), (13) and (14), they may also contain ORDER BY,
@@ -3377,29 +3377,32 @@ static void substSelect(
** syntax error and return a detailed message.
**
** (18) If the sub-query is a compound select, then all terms of the
-** ORDER by clause of the parent must be simple references to
+** ORDER BY clause of the parent must be simple references to
** columns of the sub-query.
**
-** (19) The subquery does not use LIMIT or the outer query does not
+** (19) If the subquery uses LIMIT then the outer query may not
** have a WHERE clause.
**
-** (20) If the sub-query is a compound select, then it must not use
-** an ORDER BY clause. Ticket #3773. We could relax this constraint
-** somewhat by saying that the terms of the ORDER BY clause must
-** appear as unmodified result columns in the outer query. But we
-** have other optimizations in mind to deal with that case.
+** (**) Subsumed into (17d3). Was: If the sub-query is a compound select,
+** then it must not use an ORDER BY clause - Ticket #3773. Because
+** of (17d3), then only way to have a compound subquery is if it is
+** the only term in the FROM clause of the outer query. But if the
+** only term in the FROM clause has an ORDER BY, then it will be
+** implemented as a co-routine and the flattener will never be called.
**
-** (21) The subquery does not use LIMIT or the outer query is not
+** (21) If the subquery uses LIMIT then the outer query may not be
** DISTINCT. (See ticket [752e1646fc]).
**
-** (22) The subquery is not a recursive CTE.
+** (22) The subquery may not be a recursive CTE.
**
-** (23) The parent is not a recursive CTE, or the sub-query is not a
-** compound query. This restriction is because transforming the
+** (**) Subsumed into restriction (17d3). Was: If the outer query is
+** a recursive CTE, then the sub-query may not be a compound query.
+** This restriction is because transforming the
** parent to a compound query confuses the code that handles
** recursive queries in multiSelect().
**
-** (24) The subquery is not an aggregate that uses the built-in min() or
+** (**) We no longer attempt to flatten aggregate subqueries. Was:
+** The subquery may not be an aggregate that uses the built-in min() or
** or max() functions. (Without this restriction, a query like:
** "SELECT x FROM (SELECT max(y), x FROM t1)" would not necessarily
** return the value X for which Y was maximal.)
@@ -3407,7 +3410,7 @@ static void substSelect(
**
** In this routine, the "p" parameter is a pointer to the outer query.
** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query
-** uses aggregates and subqueryIsAgg is true if the subquery uses aggregates.
+** uses aggregates.
**
** If flattening is not attempted, this routine is a no-op and returns 0.
** If flattening is attempted this routine returns 1.
@@ -3419,8 +3422,7 @@ static int flattenSubquery(
Parse *pParse, /* Parsing context */
Select *p, /* The parent or outer SELECT statement */
int iFrom, /* Index in p->pSrc->a[] of the inner subquery */
- int isAgg, /* True if outer SELECT uses aggregate functions */
- int subqueryIsAgg /* True if the subquery uses aggregate functions */
+ int isAgg /* True if outer SELECT uses aggregate functions */
){
const char *zSavedAuthContext = pParse->zAuthContext;
Select *pParent; /* Current UNION ALL term of the other query */
@@ -3439,7 +3441,7 @@ static int flattenSubquery(
/* Check to see if flattening is permitted. Return 0 if not.
*/
assert( p!=0 );
- assert( p->pPrior==0 ); /* Unable to flatten compound queries */
+ assert( p->pPrior==0 );
if( OptimizationDisabled(db, SQLITE_QueryFlattener) ) return 0;
pSrc = p->pSrc;
assert( pSrc && iFrom>=0 && iFrom<pSrc->nSrc );
@@ -3447,16 +3449,6 @@ static int flattenSubquery(
iParent = pSubitem->iCursor;
pSub = pSubitem->pSelect;
assert( pSub!=0 );
- if( subqueryIsAgg ){
- if( isAgg ) return 0; /* Restriction (1) */
- if( pSrc->nSrc>1 ) return 0; /* Restriction (2a) */
- if( (p->pWhere && ExprHasProperty(p->pWhere,EP_Subquery))
- || (sqlite3ExprListFlags(p->pEList) & EP_Subquery)!=0
- || (sqlite3ExprListFlags(p->pOrderBy) & EP_Subquery)!=0
- ){
- return 0; /* Restriction (2b) */
- }
- }
pSubSrc = pSub->pSrc;
assert( pSubSrc );
@@ -3471,13 +3463,10 @@ static int flattenSubquery(
return 0; /* Restriction (15) */
}
if( pSubSrc->nSrc==0 ) return 0; /* Restriction (7) */
- if( pSub->selFlags & SF_Distinct ) return 0; /* Restriction (5) */
+ if( pSub->selFlags & SF_Distinct ) return 0; /* Restriction (4) */
if( pSub->pLimit && (pSrc->nSrc>1 || isAgg) ){
return 0; /* Restrictions (8)(9) */
}
- if( (p->selFlags & SF_Distinct)!=0 && subqueryIsAgg ){
- return 0; /* Restriction (6) */
- }
if( p->pOrderBy && pSub->pOrderBy ){
return 0; /* Restriction (11) */
}
@@ -3486,18 +3475,14 @@ static int flattenSubquery(
if( pSub->pLimit && (p->selFlags & SF_Distinct)!=0 ){
return 0; /* Restriction (21) */
}
- testcase( pSub->selFlags & SF_Recursive );
- testcase( pSub->selFlags & SF_MinMaxAgg );
- if( pSub->selFlags & (SF_Recursive|SF_MinMaxAgg) ){
- return 0; /* Restrictions (22) and (24) */
- }
- if( (p->selFlags & SF_Recursive) && pSub->pPrior ){
- return 0; /* Restriction (23) */
+ if( pSub->selFlags & (SF_Recursive) ){
+ return 0; /* Restrictions (22) */
}
/*
** If the subquery is the right operand of a LEFT JOIN, then the
- ** subquery may not be a join itself. Example of why this is not allowed:
+ ** subquery may not be a join itself (3a). Example of why this is not
+ ** allowed:
**
** t1 LEFT OUTER JOIN (t2 JOIN t3)
**
@@ -3508,54 +3493,53 @@ static int flattenSubquery(
** which is not at all the same thing.
**
** If the subquery is the right operand of a LEFT JOIN, then the outer
- ** query cannot be an aggregate. This is an artifact of the way aggregates
- ** are processed - there is no mechanism to determine if the LEFT JOIN
- ** table should be all-NULL.
+ ** query cannot be an aggregate. (3c) This is an artifact of the way
+ ** aggregates are processed - there is no mechanism to determine if
+ ** the LEFT JOIN table should be all-NULL.
**
** See also tickets #306, #350, and #3300.
*/
if( (pSubitem->fg.jointype & JT_OUTER)!=0 ){
isLeftJoin = 1;
if( pSubSrc->nSrc>1 || isAgg || IsVirtual(pSubSrc->a[0].pTab) ){
- return 0; /* Restriction (3) */
+ /* (3a) (3c) (3b) */
+ return 0;
}
}
#ifdef SQLITE_EXTRA_IFNULLROW
else if( iFrom>0 && !isAgg ){
/* Setting isLeftJoin to -1 causes OP_IfNullRow opcodes to be generated for
- ** every reference to any result column from subquery in a join, even though
- ** they are not necessary. This will stress-test the OP_IfNullRow opcode. */
+ ** every reference to any result column from subquery in a join, even
+ ** though they are not necessary. This will stress-test the OP_IfNullRow
+ ** opcode. */
isLeftJoin = -1;
}
#endif
- /* Restriction 17: If the sub-query is a compound SELECT, then it must
+ /* Restriction (17): If the sub-query is a compound SELECT, then it must
** use only the UNION ALL operator. And none of the simple select queries
** that make up the compound SELECT are allowed to be aggregate or distinct
** queries.
*/
if( pSub->pPrior ){
- if( pSub->pOrderBy ){
- return 0; /* Restriction 20 */
- }
if( isAgg || (p->selFlags & SF_Distinct)!=0 || pSrc->nSrc!=1 ){
- return 0;
+ return 0; /* (17d1), (17d2), or (17d3) */
}
for(pSub1=pSub; pSub1; pSub1=pSub1->pPrior){
testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct );
testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate );
assert( pSub->pSrc!=0 );
assert( pSub->pEList->nExpr==pSub1->pEList->nExpr );
- if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0
- || (pSub1->pPrior && pSub1->op!=TK_ALL)
- || pSub1->pSrc->nSrc<1
+ if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0 /* (17b) */
+ || (pSub1->pPrior && pSub1->op!=TK_ALL) /* (17a) */
+ || pSub1->pSrc->nSrc<1 /* (17c) */
){
return 0;
}
testcase( pSub1->pSrc->nSrc>1 );
}
- /* Restriction 18. */
+ /* Restriction (18). */
if( p->pOrderBy ){
int ii;
for(ii=0; ii<p->pOrderBy->nExpr; ii++){
@@ -3564,6 +3548,23 @@ static int flattenSubquery(
}
}
+ /* Ex-restriction (23):
+ ** The only way that the recursive part of a CTE can contain a compound
+ ** subquery is for the subquery to be one term of a join. But if the
+ ** subquery is a join, then the flattening has already been stopped by
+ ** restriction (17d3)
+ */
+ assert( (p->selFlags & SF_Recursive)==0 || pSub->pPrior==0 );
+
+ /* Ex-restriction (20):
+ ** A compound subquery must be the only term in the FROM clause of the
+ ** outer query by restriction (17d3). But if that term also has an
+ ** ORDER BY clause, then the subquery will be implemented by co-routine
+ ** and so the flattener will never be invoked. Hence, it is not possible
+ ** for the subquery to be a compound and have an ORDER BY clause.
+ */
+ assert( pSub->pPrior==0 || pSub->pOrderBy==0 );
+
/***** If we reach this point, flattening is permitted. *****/
SELECTTRACE(1,pParse,p,("flatten %s.%p from term %d\n",
pSub->zSelName, pSub, iFrom));
@@ -3776,18 +3777,7 @@ static int flattenSubquery(
if( isLeftJoin>0 ){
setJoinExpr(pWhere, iNewParent);
}
- if( subqueryIsAgg ){
- assert( pParent->pHaving==0 );
- pParent->pHaving = pParent->pWhere;
- pParent->pWhere = pWhere;
- pParent->pHaving = sqlite3ExprAnd(db,
- sqlite3ExprDup(db, pSub->pHaving, 0), pParent->pHaving
- );
- assert( pParent->pGroupBy==0 );
- pParent->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy, 0);
- }else{
- pParent->pWhere = sqlite3ExprAnd(db, pWhere, pParent->pWhere);
- }
+ pParent->pWhere = sqlite3ExprAnd(db, pWhere, pParent->pWhere);
if( db->mallocFailed==0 ){
SubstContext x;
x.pParse = pParse;
@@ -3850,9 +3840,13 @@ static int flattenSubquery(
**
** Do not attempt this optimization if:
**
-** (1) The inner query is an aggregate. (In that case, we'd really want
-** to copy the outer WHERE-clause terms onto the HAVING clause of the
-** inner query. But they probably won't help there so do not bother.)
+** (1) (** This restriction was removed on 2017-09-29. We used to
+** disallow this optimization for aggregate subqueries, but now
+** it is allowed by putting the extra terms on the HAVING clause.
+** The added HAVING clause is pointless if the subquery lacks
+** a GROUP BY clause. But such a HAVING clause is also harmless
+** so there does not appear to be any reason to add extra logic
+** to suppress it. **)
**
** (2) The inner query is the recursive part of a common table expression.
**
@@ -3877,16 +3871,22 @@ static int pushDownWhereTerms(
){
Expr *pNew;
int nChng = 0;
- Select *pX; /* For looping over compound SELECTs in pSubq */
if( pWhere==0 ) return 0;
- for(pX=pSubq; pX; pX=pX->pPrior){
- if( (pX->selFlags & (SF_Aggregate|SF_Recursive))!=0 ){
- testcase( pX->selFlags & SF_Aggregate );
- testcase( pX->selFlags & SF_Recursive );
- testcase( pX!=pSubq );
- return 0; /* restrictions (1) and (2) */
+ if( pSubq->selFlags & SF_Recursive ) return 0; /* restriction (2) */
+
+#ifdef SQLITE_DEBUG
+ /* Only the first term of a compound can have a WITH clause. But make
+ ** sure no other terms are marked SF_Recursive in case something changes
+ ** in the future.
+ */
+ {
+ Select *pX;
+ for(pX=pSubq; pX; pX=pX->pPrior){
+ assert( (pX->selFlags & (SF_Recursive))==0 );
}
}
+#endif
+
if( pSubq->pLimit!=0 ){
return 0; /* restriction (3) */
}
@@ -3894,7 +3894,7 @@ static int pushDownWhereTerms(
nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, iCursor);
pWhere = pWhere->pLeft;
}
- if( ExprHasProperty(pWhere,EP_FromJoin) ) return 0; /* restriction 5 */
+ if( ExprHasProperty(pWhere,EP_FromJoin) ) return 0; /* restriction (5) */
if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){
nChng++;
while( pSubq ){
@@ -3906,7 +3906,11 @@ static int pushDownWhereTerms(
x.isLeftJoin = 0;
x.pEList = pSubq->pEList;
pNew = substExpr(&x, pNew);
- pSubq->pWhere = sqlite3ExprAnd(pParse->db, pSubq->pWhere, pNew);
+ if( pSubq->selFlags & SF_Aggregate ){
+ pSubq->pHaving = sqlite3ExprAnd(pParse->db, pSubq->pHaving, pNew);
+ }else{
+ pSubq->pWhere = sqlite3ExprAnd(pParse->db, pSubq->pWhere, pNew);
+ }
pSubq = pSubq->pPrior;
}
}
@@ -4234,7 +4238,8 @@ static int withExpand(
);
return SQLITE_ERROR;
}
- assert( pTab->nTabRef==1 || ((pSel->selFlags&SF_Recursive) && pTab->nTabRef==2 ));
+ assert( pTab->nTabRef==1 ||
+ ((pSel->selFlags&SF_Recursive) && pTab->nTabRef==2 ));
pCte->zCteErr = "circular reference: %s";
pSavedWith = pParse->pWith;
@@ -4291,7 +4296,7 @@ static int withExpand(
*/
static void selectPopWith(Walker *pWalker, Select *p){
Parse *pParse = pWalker->pParse;
- if( pParse->pWith && p->pPrior==0 ){
+ if( OK_IF_ALWAYS_TRUE(pParse->pWith) && p->pPrior==0 ){
With *pWith = findRightmost(p)->pWith;
if( pWith!=0 ){
assert( pParse->pWith==pWith );
@@ -4346,7 +4351,7 @@ static int selectExpander(Walker *pWalker, Select *p){
}
pTabList = p->pSrc;
pEList = p->pEList;
- if( p->pWith ){
+ if( OK_IF_ALWAYS_TRUE(p->pWith) ){
sqlite3WithPush(pParse, p->pWith, 0);
}
@@ -4378,7 +4383,11 @@ static int selectExpander(Walker *pWalker, Select *p){
pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
if( pTab==0 ) return WRC_Abort;
pTab->nTabRef = 1;
- pTab->zName = sqlite3MPrintf(db, "sqlite_sq_%p", (void*)pTab);
+ if( pFrom->zAlias ){
+ pTab->zName = sqlite3DbStrDup(db, pFrom->zAlias);
+ }else{
+ pTab->zName = sqlite3MPrintf(db, "subquery_%p", (void*)pTab);
+ }
while( pSel->pPrior ){ pSel = pSel->pPrior; }
sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol);
pTab->iPKey = -1;
@@ -4588,12 +4597,10 @@ static int selectExpander(Walker *pWalker, Select *p){
sqlite3ExprListDelete(db, pEList);
p->pEList = pNew;
}
-#if SQLITE_MAX_COLUMN
if( p->pEList && p->pEList->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
sqlite3ErrorMsg(pParse, "too many columns in result set");
return WRC_Abort;
}
-#endif
return WRC_Continue;
}
@@ -4647,7 +4654,7 @@ static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){
Walker w;
w.xExprCallback = sqlite3ExprWalkNoop;
w.pParse = pParse;
- if( pParse->hasCompound ){
+ if( OK_IF_ALWAYS_TRUE(pParse->hasCompound) ){
w.xSelectCallback = convertCompoundSelectToSubquery;
w.xSelectCallback2 = 0;
sqlite3WalkSelect(&w, pSelect);
@@ -4735,15 +4742,13 @@ void sqlite3SelectPrep(
Select *p, /* The SELECT statement being coded. */
NameContext *pOuterNC /* Name context for container */
){
- sqlite3 *db;
- if( NEVER(p==0) ) return;
- db = pParse->db;
- if( db->mallocFailed ) return;
+ assert( p!=0 || pParse->db->mallocFailed );
+ if( pParse->db->mallocFailed ) return;
if( p->selFlags & SF_HasTypeInfo ) return;
sqlite3SelectExpand(pParse, p);
- if( pParse->nErr || db->mallocFailed ) return;
+ if( pParse->nErr || pParse->db->mallocFailed ) return;
sqlite3ResolveSelectNames(pParse, p, pOuterNC);
- if( pParse->nErr || db->mallocFailed ) return;
+ if( pParse->nErr || pParse->db->mallocFailed ) return;
sqlite3SelectAddTypeInfo(pParse, p);
}
@@ -5038,24 +5043,24 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
Expr *pExpr;
Expr *pCount;
sqlite3 *db;
- if( (p->selFlags & SF_Aggregate)==0 ) return 0; /* This is an aggregate query */
+ if( (p->selFlags & SF_Aggregate)==0 ) return 0; /* This is an aggregate */
if( p->pEList->nExpr!=1 ) return 0; /* Single result column */
pExpr = p->pEList->a[0].pExpr;
if( pExpr->op!=TK_AGG_FUNCTION ) return 0; /* Result is an aggregate */
- if( sqlite3_stricmp(pExpr->u.zToken,"count") ) return 0; /* Must be count() */
+ if( sqlite3_stricmp(pExpr->u.zToken,"count") ) return 0; /* Is count() */
if( pExpr->x.pList!=0 ) return 0; /* Must be count(*) */
- if( p->pSrc->nSrc!=1 ) return 0; /* One table in the FROM clause */
+ if( p->pSrc->nSrc!=1 ) return 0; /* One table in FROM */
pSub = p->pSrc->a[0].pSelect;
if( pSub==0 ) return 0; /* The FROM is a subquery */
- if( pSub->pPrior==0 ) return 0; /* Must be a compound subquery */
+ if( pSub->pPrior==0 ) return 0; /* Must be a compound ry */
do{
if( pSub->op!=TK_ALL && pSub->pPrior ) return 0; /* Must be UNION ALL */
if( pSub->pWhere ) return 0; /* No WHERE clause */
if( pSub->selFlags & SF_Aggregate ) return 0; /* Not an aggregate */
- pSub = pSub->pPrior; /* Repeat over compound terms */
+ pSub = pSub->pPrior; /* Repeat over compound */
}while( pSub );
- /* If we reach this point, that means it is OK to perform the transformation */
+ /* If we reach this point then it is OK to perform the transformation */
db = pParse->db;
pCount = pExpr;
@@ -5195,7 +5200,6 @@ int sqlite3Select(
for(i=0; !p->pPrior && i<pTabList->nSrc; i++){
struct SrcList_item *pItem = &pTabList->a[i];
Select *pSub = pItem->pSelect;
- int isAggSub;
Table *pTab = pItem->pTab;
if( pSub==0 ) continue;
@@ -5207,13 +5211,36 @@ int sqlite3Select(
goto select_end;
}
- isAggSub = (pSub->selFlags & SF_Aggregate)!=0;
- if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){
+ /* Do not try to flatten an aggregate subquery.
+ **
+ ** Flattening an aggregate subquery is only possible if the outer query
+ ** is not a join. But if the outer query is not a join, then the subquery
+ ** will be implemented as a co-routine and there is no advantage to
+ ** flattening in that case.
+ */
+ if( (pSub->selFlags & SF_Aggregate)!=0 ) continue;
+ assert( pSub->pGroupBy==0 );
+
+ /* If the subquery contains an ORDER BY clause and if
+ ** it will be implemented as a co-routine, then do not flatten. This
+ ** restriction allows SQL constructs like this:
+ **
+ ** SELECT expensive_function(x)
+ ** FROM (SELECT x FROM tab ORDER BY y LIMIT 10);
+ **
+ ** The expensive_function() is only computed on the 10 rows that
+ ** are output, rather than every row of the table.
+ */
+ if( pSub->pOrderBy!=0
+ && i==0
+ && (pTabList->nSrc==1
+ || (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0)
+ ){
+ continue;
+ }
+
+ if( flattenSubquery(pParse, p, i, isAgg) ){
/* This subquery can be absorbed into its parent. */
- if( isAggSub ){
- isAgg = 1;
- p->selFlags |= SF_Aggregate;
- }
i = -1;
}
pTabList = p->pSrc;
@@ -5247,10 +5274,14 @@ int sqlite3Select(
struct SrcList_item *pItem = &pTabList->a[i];
SelectDest dest;
Select *pSub;
+#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
+ const char *zSavedAuthContext;
+#endif
- /* Issue SQLITE_READ authorizations with a fake column name for any tables that
- ** are referenced but from which no values are extracted. Examples of where these
- ** kinds of null SQLITE_READ authorizations would occur:
+ /* Issue SQLITE_READ authorizations with a fake column name for any
+ ** tables that are referenced but from which no values are extracted.
+ ** Examples of where these kinds of null SQLITE_READ authorizations
+ ** would occur:
**
** SELECT count(*) FROM t1; -- SQLITE_READ t1.""
** SELECT t1.* FROM t1, t2; -- SQLITE_READ t2.""
@@ -5258,10 +5289,10 @@ int sqlite3Select(
** The fake column name is an empty string. It is possible for a table to
** have a column named by the empty string, in which case there is no way to
** distinguish between an unreferenced table and an actual reference to the
- ** "" column. The original design was for the fake column name to be a NULL,
+ ** "" column. The original design was for the fake column name to be a NULL,
** which would be unambiguous. But legacy authorization callbacks might
- ** assume the column name is non-NULL and segfault. The use of an empty string
- ** for the fake column name seems safer.
+ ** assume the column name is non-NULL and segfault. The use of an empty
+ ** string for the fake column name seems safer.
*/
if( pItem->colUsed==0 ){
sqlite3AuthCheck(pParse, SQLITE_READ, pItem->zName, "", pItem->zDatabase);
@@ -5313,16 +5344,14 @@ int sqlite3Select(
#endif
}
+ zSavedAuthContext = pParse->zAuthContext;
+ pParse->zAuthContext = pItem->zName;
+
/* Generate code to implement the subquery
**
- ** The subquery is implemented as a co-routine if all of these are true:
- ** (1) The subquery is guaranteed to be the outer loop (so that it
- ** does not need to be computed more than once)
- ** (2) The ALL keyword after SELECT is omitted. (Applications are
- ** allowed to say "SELECT ALL" instead of just "SELECT" to disable
- ** the use of co-routines.)
- ** (3) Co-routines are not disabled using sqlite3_test_control()
- ** with SQLITE_TESTCTRL_OPTIMIZATIONS.
+ ** The subquery is implemented as a co-routine if the subquery is
+ ** guaranteed to be the outer loop (so that it does not need to be
+ ** computed more than once)
**
** TODO: Are there other reasons beside (1) to use a co-routine
** implementation?
@@ -5330,13 +5359,12 @@ int sqlite3Select(
if( i==0
&& (pTabList->nSrc==1
|| (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0) /* (1) */
- && (p->selFlags & SF_All)==0 /* (2) */
- && OptimizationEnabled(db, SQLITE_SubqCoroutine) /* (3) */
){
/* Implement a co-routine that will return a single row of the result
** set on each invocation.
*/
int addrTop = sqlite3VdbeCurrentAddr(v)+1;
+
pItem->regReturn = ++pParse->nMem;
sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop);
VdbeComment((v, "%s", pItem->pTab->zName));
@@ -5394,6 +5422,7 @@ int sqlite3Select(
}
if( db->mallocFailed ) goto select_end;
pParse->nHeight -= sqlite3SelectExprHeight(p);
+ pParse->zAuthContext = zSavedAuthContext;
#endif
}
@@ -5541,7 +5570,8 @@ int sqlite3Select(
}
/* Use the standard inner loop. */
- selectInnerLoop(pParse, p, pEList, -1, &sSort, &sDistinct, pDest,
+ assert( p->pEList==pEList );
+ selectInnerLoop(pParse, p, -1, &sSort, &sDistinct, pDest,
sqlite3WhereContinueLabel(pWInfo),
sqlite3WhereBreakLabel(pWInfo));
@@ -5844,7 +5874,7 @@ int sqlite3Select(
sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
finalizeAggFunctions(pParse, &sAggInfo);
sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL);
- selectInnerLoop(pParse, p, p->pEList, -1, &sSort,
+ selectInnerLoop(pParse, p, -1, &sSort,
&sDistinct, pDest,
addrOutputRow+1, addrSetAbort);
sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
@@ -5988,7 +6018,7 @@ int sqlite3Select(
sSort.pOrderBy = 0;
sqlite3ExprIfFalse(pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL);
- selectInnerLoop(pParse, p, p->pEList, -1, 0, 0,
+ selectInnerLoop(pParse, p, -1, 0, 0,
pDest, addrEnd, addrEnd);
sqlite3ExprListDelete(db, pDel);
}
diff --git a/chromium/third_party/sqlite/src/src/shell.c b/chromium/third_party/sqlite/src/src/shell.c
deleted file mode 100644
index fbf7c08bd8a..00000000000
--- a/chromium/third_party/sqlite/src/src/shell.c
+++ /dev/null
@@ -1,8408 +0,0 @@
-/* DO NOT EDIT!
-** This file is automatically generated by the script in the canonical
-** SQLite source tree at tool/mkshellc.tcl. That script combines source
-** code from various constituent source files of SQLite into this single
-** "shell.c" file used to implement the SQLite command-line shell.
-**
-** Most of the code found below comes from the "src/shell.c.in" file in
-** the canonical SQLite source tree. That main file contains "INCLUDE"
-** lines that specify other files in the canonical source tree that are
-** inserted to getnerate this complete program source file.
-**
-** The code from multiple files is combined into this single "shell.c"
-** source file to help make the command-line program easier to compile.
-**
-** To modify this program, get a copy of the canonical SQLite source tree,
-** edit the src/shell.c.in" and/or some of the other files that are included
-** by "src/shell.c.in", then rerun the tool/mkshellc.tcl script.
-*/
-/*
-** 2001 September 15
-**
-** 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 "sqlite" command line
-** utility for accessing SQLite databases.
-*/
-#if (defined(_WIN32) || defined(WIN32)) && !defined(_CRT_SECURE_NO_WARNINGS)
-/* This needs to come before any includes for MSVC compiler */
-#define _CRT_SECURE_NO_WARNINGS
-#endif
-
-/*
-** Warning pragmas copied from msvc.h in the core.
-*/
-#if defined(_MSC_VER)
-#pragma warning(disable : 4054)
-#pragma warning(disable : 4055)
-#pragma warning(disable : 4100)
-#pragma warning(disable : 4127)
-#pragma warning(disable : 4130)
-#pragma warning(disable : 4152)
-#pragma warning(disable : 4189)
-#pragma warning(disable : 4206)
-#pragma warning(disable : 4210)
-#pragma warning(disable : 4232)
-#pragma warning(disable : 4244)
-#pragma warning(disable : 4305)
-#pragma warning(disable : 4306)
-#pragma warning(disable : 4702)
-#pragma warning(disable : 4706)
-#endif /* defined(_MSC_VER) */
-
-/*
-** No support for loadable extensions in VxWorks.
-*/
-#if (defined(__RTP__) || defined(_WRS_KERNEL)) && !SQLITE_OMIT_LOAD_EXTENSION
-# define SQLITE_OMIT_LOAD_EXTENSION 1
-#endif
-
-/*
-** Enable large-file support for fopen() and friends on unix.
-*/
-#ifndef SQLITE_DISABLE_LFS
-# define _LARGE_FILE 1
-# ifndef _FILE_OFFSET_BITS
-# define _FILE_OFFSET_BITS 64
-# endif
-# define _LARGEFILE_SOURCE 1
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <assert.h>
-#include "sqlite3.h"
-#if SQLITE_USER_AUTHENTICATION
-# include "sqlite3userauth.h"
-#endif
-#include <ctype.h>
-#include <stdarg.h>
-
-#if !defined(_WIN32) && !defined(WIN32)
-# include <signal.h>
-# if !defined(__RTP__) && !defined(_WRS_KERNEL)
-# include <pwd.h>
-# endif
-# include <unistd.h>
-# include <sys/types.h>
-#endif
-
-#if HAVE_READLINE
-# include <readline/readline.h>
-# include <readline/history.h>
-#endif
-
-#if HAVE_EDITLINE
-# include <editline/readline.h>
-#endif
-
-#if HAVE_EDITLINE || HAVE_READLINE
-
-# define shell_add_history(X) add_history(X)
-# define shell_read_history(X) read_history(X)
-# define shell_write_history(X) write_history(X)
-# define shell_stifle_history(X) stifle_history(X)
-# define shell_readline(X) readline(X)
-
-#elif HAVE_LINENOISE
-
-# include "linenoise.h"
-# define shell_add_history(X) linenoiseHistoryAdd(X)
-# define shell_read_history(X) linenoiseHistoryLoad(X)
-# define shell_write_history(X) linenoiseHistorySave(X)
-# define shell_stifle_history(X) linenoiseHistorySetMaxLen(X)
-# define shell_readline(X) linenoise(X)
-
-#else
-
-# define shell_read_history(X)
-# define shell_write_history(X)
-# define shell_stifle_history(X)
-
-# define SHELL_USE_LOCAL_GETLINE 1
-#endif
-
-
-#if defined(_WIN32) || defined(WIN32)
-# include <io.h>
-# include <fcntl.h>
-# define isatty(h) _isatty(h)
-# ifndef access
-# define access(f,m) _access((f),(m))
-# endif
-# undef popen
-# define popen _popen
-# undef pclose
-# define pclose _pclose
-#else
- /* Make sure isatty() has a prototype. */
- extern int isatty(int);
-
-# if !defined(__RTP__) && !defined(_WRS_KERNEL)
- /* popen and pclose are not C89 functions and so are
- ** sometimes omitted from the <stdio.h> header */
- extern FILE *popen(const char*,const char*);
- extern int pclose(FILE*);
-# else
-# define SQLITE_OMIT_POPEN 1
-# endif
-#endif
-
-#if defined(_WIN32_WCE)
-/* Windows CE (arm-wince-mingw32ce-gcc) does not provide isatty()
- * thus we always assume that we have a console. That can be
- * overridden with the -batch command line option.
- */
-#define isatty(x) 1
-#endif
-
-/* ctype macros that work with signed characters */
-#define IsSpace(X) isspace((unsigned char)X)
-#define IsDigit(X) isdigit((unsigned char)X)
-#define ToLower(X) (char)tolower((unsigned char)X)
-
-#if defined(_WIN32) || defined(WIN32)
-#include <windows.h>
-
-/* string conversion routines only needed on Win32 */
-extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR);
-extern char *sqlite3_win32_mbcs_to_utf8_v2(const char *, int);
-extern char *sqlite3_win32_utf8_to_mbcs_v2(const char *, int);
-extern LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText);
-#endif
-
-/* On Windows, we normally run with output mode of TEXT so that \n characters
-** are automatically translated into \r\n. However, this behavior needs
-** to be disabled in some cases (ex: when generating CSV output and when
-** rendering quoted strings that contain \n characters). The following
-** routines take care of that.
-*/
-#if defined(_WIN32) || defined(WIN32)
-static void setBinaryMode(FILE *file, int isOutput){
- if( isOutput ) fflush(file);
- _setmode(_fileno(file), _O_BINARY);
-}
-static void setTextMode(FILE *file, int isOutput){
- if( isOutput ) fflush(file);
- _setmode(_fileno(file), _O_TEXT);
-}
-#else
-# define setBinaryMode(X,Y)
-# define setTextMode(X,Y)
-#endif
-
-
-/* True if the timer is enabled */
-static int enableTimer = 0;
-
-/* Return the current wall-clock time */
-static sqlite3_int64 timeOfDay(void){
- static sqlite3_vfs *clockVfs = 0;
- sqlite3_int64 t;
- if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0);
- if( clockVfs->iVersion>=2 && clockVfs->xCurrentTimeInt64!=0 ){
- clockVfs->xCurrentTimeInt64(clockVfs, &t);
- }else{
- double r;
- clockVfs->xCurrentTime(clockVfs, &r);
- t = (sqlite3_int64)(r*86400000.0);
- }
- return t;
-}
-
-#if !defined(_WIN32) && !defined(WIN32) && !defined(__minux)
-#include <sys/time.h>
-#include <sys/resource.h>
-
-/* VxWorks does not support getrusage() as far as we can determine */
-#if defined(_WRS_KERNEL) || defined(__RTP__)
-struct rusage {
- struct timeval ru_utime; /* user CPU time used */
- struct timeval ru_stime; /* system CPU time used */
-};
-#define getrusage(A,B) memset(B,0,sizeof(*B))
-#endif
-
-/* Saved resource information for the beginning of an operation */
-static struct rusage sBegin; /* CPU time at start */
-static sqlite3_int64 iBegin; /* Wall-clock time at start */
-
-/*
-** Begin timing an operation
-*/
-static void beginTimer(void){
- if( enableTimer ){
- getrusage(RUSAGE_SELF, &sBegin);
- iBegin = timeOfDay();
- }
-}
-
-/* Return the difference of two time_structs in seconds */
-static double timeDiff(struct timeval *pStart, struct timeval *pEnd){
- return (pEnd->tv_usec - pStart->tv_usec)*0.000001 +
- (double)(pEnd->tv_sec - pStart->tv_sec);
-}
-
-/*
-** Print the timing results.
-*/
-static void endTimer(void){
- if( enableTimer ){
- sqlite3_int64 iEnd = timeOfDay();
- struct rusage sEnd;
- getrusage(RUSAGE_SELF, &sEnd);
- printf("Run Time: real %.3f user %f sys %f\n",
- (iEnd - iBegin)*0.001,
- timeDiff(&sBegin.ru_utime, &sEnd.ru_utime),
- timeDiff(&sBegin.ru_stime, &sEnd.ru_stime));
- }
-}
-
-#define BEGIN_TIMER beginTimer()
-#define END_TIMER endTimer()
-#define HAS_TIMER 1
-
-#elif (defined(_WIN32) || defined(WIN32))
-
-/* Saved resource information for the beginning of an operation */
-static HANDLE hProcess;
-static FILETIME ftKernelBegin;
-static FILETIME ftUserBegin;
-static sqlite3_int64 ftWallBegin;
-typedef BOOL (WINAPI *GETPROCTIMES)(HANDLE, LPFILETIME, LPFILETIME,
- LPFILETIME, LPFILETIME);
-static GETPROCTIMES getProcessTimesAddr = NULL;
-
-/*
-** Check to see if we have timer support. Return 1 if necessary
-** support found (or found previously).
-*/
-static int hasTimer(void){
- if( getProcessTimesAddr ){
- return 1;
- } else {
- /* GetProcessTimes() isn't supported in WIN95 and some other Windows
- ** versions. See if the version we are running on has it, and if it
- ** does, save off a pointer to it and the current process handle.
- */
- hProcess = GetCurrentProcess();
- if( hProcess ){
- HINSTANCE hinstLib = LoadLibrary(TEXT("Kernel32.dll"));
- if( NULL != hinstLib ){
- getProcessTimesAddr =
- (GETPROCTIMES) GetProcAddress(hinstLib, "GetProcessTimes");
- if( NULL != getProcessTimesAddr ){
- return 1;
- }
- FreeLibrary(hinstLib);
- }
- }
- }
- return 0;
-}
-
-/*
-** Begin timing an operation
-*/
-static void beginTimer(void){
- if( enableTimer && getProcessTimesAddr ){
- FILETIME ftCreation, ftExit;
- getProcessTimesAddr(hProcess,&ftCreation,&ftExit,
- &ftKernelBegin,&ftUserBegin);
- ftWallBegin = timeOfDay();
- }
-}
-
-/* Return the difference of two FILETIME structs in seconds */
-static double timeDiff(FILETIME *pStart, FILETIME *pEnd){
- sqlite_int64 i64Start = *((sqlite_int64 *) pStart);
- sqlite_int64 i64End = *((sqlite_int64 *) pEnd);
- return (double) ((i64End - i64Start) / 10000000.0);
-}
-
-/*
-** Print the timing results.
-*/
-static void endTimer(void){
- if( enableTimer && getProcessTimesAddr){
- FILETIME ftCreation, ftExit, ftKernelEnd, ftUserEnd;
- sqlite3_int64 ftWallEnd = timeOfDay();
- getProcessTimesAddr(hProcess,&ftCreation,&ftExit,&ftKernelEnd,&ftUserEnd);
- printf("Run Time: real %.3f user %f sys %f\n",
- (ftWallEnd - ftWallBegin)*0.001,
- timeDiff(&ftUserBegin, &ftUserEnd),
- timeDiff(&ftKernelBegin, &ftKernelEnd));
- }
-}
-
-#define BEGIN_TIMER beginTimer()
-#define END_TIMER endTimer()
-#define HAS_TIMER hasTimer()
-
-#else
-#define BEGIN_TIMER
-#define END_TIMER
-#define HAS_TIMER 0
-#endif
-
-/*
-** Used to prevent warnings about unused parameters
-*/
-#define UNUSED_PARAMETER(x) (void)(x)
-
-/*
-** If the following flag is set, then command execution stops
-** at an error if we are not interactive.
-*/
-static int bail_on_error = 0;
-
-/*
-** Threat stdin as an interactive input if the following variable
-** is true. Otherwise, assume stdin is connected to a file or pipe.
-*/
-static int stdin_is_interactive = 1;
-
-/*
-** On Windows systems we have to know if standard output is a console
-** in order to translate UTF-8 into MBCS. The following variable is
-** true if translation is required.
-*/
-static int stdout_is_console = 1;
-
-/*
-** The following is the open SQLite database. We make a pointer
-** to this database a static variable so that it can be accessed
-** by the SIGINT handler to interrupt database processing.
-*/
-static sqlite3 *globalDb = 0;
-
-/*
-** True if an interrupt (Control-C) has been received.
-*/
-static volatile int seenInterrupt = 0;
-
-/*
-** This is the name of our program. It is set in main(), used
-** in a number of other places, mostly for error messages.
-*/
-static char *Argv0;
-
-/*
-** Prompt strings. Initialized in main. Settable with
-** .prompt main continue
-*/
-static char mainPrompt[20]; /* First line prompt. default: "sqlite> "*/
-static char continuePrompt[20]; /* Continuation prompt. default: " ...> " */
-
-/*
-** Render output like fprintf(). Except, if the output is going to the
-** console and if this is running on a Windows machine, translate the
-** output from UTF-8 into MBCS.
-*/
-#if defined(_WIN32) || defined(WIN32)
-void utf8_printf(FILE *out, const char *zFormat, ...){
- va_list ap;
- va_start(ap, zFormat);
- if( stdout_is_console && (out==stdout || out==stderr) ){
- char *z1 = sqlite3_vmprintf(zFormat, ap);
- char *z2 = sqlite3_win32_utf8_to_mbcs_v2(z1, 0);
- sqlite3_free(z1);
- fputs(z2, out);
- sqlite3_free(z2);
- }else{
- vfprintf(out, zFormat, ap);
- }
- va_end(ap);
-}
-#elif !defined(utf8_printf)
-# define utf8_printf fprintf
-#endif
-
-/*
-** Render output like fprintf(). This should not be used on anything that
-** includes string formatting (e.g. "%s").
-*/
-#if !defined(raw_printf)
-# define raw_printf fprintf
-#endif
-
-/*
-** Write I/O traces to the following stream.
-*/
-#ifdef SQLITE_ENABLE_IOTRACE
-static FILE *iotrace = 0;
-#endif
-
-/*
-** This routine works like printf in that its first argument is a
-** format string and subsequent arguments are values to be substituted
-** in place of % fields. The result of formatting this string
-** is written to iotrace.
-*/
-#ifdef SQLITE_ENABLE_IOTRACE
-static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){
- va_list ap;
- char *z;
- if( iotrace==0 ) return;
- va_start(ap, zFormat);
- z = sqlite3_vmprintf(zFormat, ap);
- va_end(ap);
- utf8_printf(iotrace, "%s", z);
- sqlite3_free(z);
-}
-#endif
-
-/*
-** Output string zUtf to stream pOut as w characters. If w is negative,
-** then right-justify the text. W is the width in UTF-8 characters, not
-** in bytes. This is different from the %*.*s specification in printf
-** since with %*.*s the width is measured in bytes, not characters.
-*/
-static void utf8_width_print(FILE *pOut, int w, const char *zUtf){
- int i;
- int n;
- int aw = w<0 ? -w : w;
- char zBuf[1000];
- if( aw>(int)sizeof(zBuf)/3 ) aw = (int)sizeof(zBuf)/3;
- for(i=n=0; zUtf[i]; i++){
- if( (zUtf[i]&0xc0)!=0x80 ){
- n++;
- if( n==aw ){
- do{ i++; }while( (zUtf[i]&0xc0)==0x80 );
- break;
- }
- }
- }
- if( n>=aw ){
- utf8_printf(pOut, "%.*s", i, zUtf);
- }else if( w<0 ){
- utf8_printf(pOut, "%*s%s", aw-n, "", zUtf);
- }else{
- utf8_printf(pOut, "%s%*s", zUtf, aw-n, "");
- }
-}
-
-
-/*
-** Determines if a string is a number of not.
-*/
-static int isNumber(const char *z, int *realnum){
- if( *z=='-' || *z=='+' ) z++;
- if( !IsDigit(*z) ){
- return 0;
- }
- z++;
- if( realnum ) *realnum = 0;
- while( IsDigit(*z) ){ z++; }
- if( *z=='.' ){
- z++;
- if( !IsDigit(*z) ) return 0;
- while( IsDigit(*z) ){ z++; }
- if( realnum ) *realnum = 1;
- }
- if( *z=='e' || *z=='E' ){
- z++;
- if( *z=='+' || *z=='-' ) z++;
- if( !IsDigit(*z) ) return 0;
- while( IsDigit(*z) ){ z++; }
- if( realnum ) *realnum = 1;
- }
- return *z==0;
-}
-
-/*
-** Compute a string length that is limited to what can be stored in
-** lower 30 bits of a 32-bit signed integer.
-*/
-static int strlen30(const char *z){
- const char *z2 = z;
- while( *z2 ){ z2++; }
- return 0x3fffffff & (int)(z2 - z);
-}
-
-/*
-** Return the length of a string in characters. Multibyte UTF8 characters
-** count as a single character.
-*/
-static int strlenChar(const char *z){
- int n = 0;
- while( *z ){
- if( (0xc0&*(z++))!=0x80 ) n++;
- }
- return n;
-}
-
-/*
-** This routine reads a line of text from FILE in, stores
-** the text in memory obtained from malloc() and returns a pointer
-** to the text. NULL is returned at end of file, or if malloc()
-** fails.
-**
-** If zLine is not NULL then it is a malloced buffer returned from
-** a previous call to this routine that may be reused.
-*/
-static char *local_getline(char *zLine, FILE *in){
- int nLine = zLine==0 ? 0 : 100;
- int n = 0;
-
- while( 1 ){
- if( n+100>nLine ){
- nLine = nLine*2 + 100;
- zLine = realloc(zLine, nLine);
- if( zLine==0 ) return 0;
- }
- if( fgets(&zLine[n], nLine - n, in)==0 ){
- if( n==0 ){
- free(zLine);
- return 0;
- }
- zLine[n] = 0;
- break;
- }
- while( zLine[n] ) n++;
- if( n>0 && zLine[n-1]=='\n' ){
- n--;
- if( n>0 && zLine[n-1]=='\r' ) n--;
- zLine[n] = 0;
- break;
- }
- }
-#if defined(_WIN32) || defined(WIN32)
- /* For interactive input on Windows systems, translate the
- ** multi-byte characterset characters into UTF-8. */
- if( stdin_is_interactive && in==stdin ){
- char *zTrans = sqlite3_win32_mbcs_to_utf8_v2(zLine, 0);
- if( zTrans ){
- int nTrans = strlen30(zTrans)+1;
- if( nTrans>nLine ){
- zLine = realloc(zLine, nTrans);
- if( zLine==0 ){
- sqlite3_free(zTrans);
- return 0;
- }
- }
- memcpy(zLine, zTrans, nTrans);
- sqlite3_free(zTrans);
- }
- }
-#endif /* defined(_WIN32) || defined(WIN32) */
- return zLine;
-}
-
-/*
-** Retrieve a single line of input text.
-**
-** If in==0 then read from standard input and prompt before each line.
-** If isContinuation is true, then a continuation prompt is appropriate.
-** If isContinuation is zero, then the main prompt should be used.
-**
-** If zPrior is not NULL then it is a buffer from a prior call to this
-** routine that can be reused.
-**
-** The result is stored in space obtained from malloc() and must either
-** be freed by the caller or else passed back into this routine via the
-** zPrior argument for reuse.
-*/
-static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
- char *zPrompt;
- char *zResult;
- if( in!=0 ){
- zResult = local_getline(zPrior, in);
- }else{
- zPrompt = isContinuation ? continuePrompt : mainPrompt;
-#if SHELL_USE_LOCAL_GETLINE
- printf("%s", zPrompt);
- fflush(stdout);
- zResult = local_getline(zPrior, stdin);
-#else
- free(zPrior);
- zResult = shell_readline(zPrompt);
- if( zResult && *zResult ) shell_add_history(zResult);
-#endif
- }
- return zResult;
-}
-/*
-** A variable length string to which one can append text.
-*/
-typedef struct ShellText ShellText;
-struct ShellText {
- char *z;
- int n;
- int nAlloc;
-};
-
-/*
-** Initialize and destroy a ShellText object
-*/
-static void initText(ShellText *p){
- memset(p, 0, sizeof(*p));
-}
-static void freeText(ShellText *p){
- free(p->z);
- initText(p);
-}
-
-/* zIn is either a pointer to a NULL-terminated string in memory obtained
-** from malloc(), or a NULL pointer. The string pointed to by zAppend is
-** added to zIn, and the result returned in memory obtained from malloc().
-** zIn, if it was not NULL, is freed.
-**
-** If the third argument, quote, is not '\0', then it is used as a
-** quote character for zAppend.
-*/
-static void appendText(ShellText *p, char const *zAppend, char quote){
- int len;
- int i;
- int nAppend = strlen30(zAppend);
-
- len = nAppend+p->n+1;
- if( quote ){
- len += 2;
- for(i=0; i<nAppend; i++){
- if( zAppend[i]==quote ) len++;
- }
- }
-
- if( p->n+len>=p->nAlloc ){
- p->nAlloc = p->nAlloc*2 + len + 20;
- p->z = realloc(p->z, p->nAlloc);
- if( p->z==0 ){
- memset(p, 0, sizeof(*p));
- return;
- }
- }
-
- if( quote ){
- char *zCsr = p->z+p->n;
- *zCsr++ = quote;
- for(i=0; i<nAppend; i++){
- *zCsr++ = zAppend[i];
- if( zAppend[i]==quote ) *zCsr++ = quote;
- }
- *zCsr++ = quote;
- p->n = (int)(zCsr - p->z);
- *zCsr = '\0';
- }else{
- memcpy(p->z+p->n, zAppend, nAppend);
- p->n += nAppend;
- p->z[p->n] = '\0';
- }
-}
-
-/*
-** Attempt to determine if identifier zName needs to be quoted, either
-** because it contains non-alphanumeric characters, or because it is an
-** SQLite keyword. Be conservative in this estimate: When in doubt assume
-** that quoting is required.
-**
-** Return '"' if quoting is required. Return 0 if no quoting is required.
-*/
-static char quoteChar(const char *zName){
- /* All SQLite keywords, in alphabetical order */
- static const char *azKeywords[] = {
- "ABORT", "ACTION", "ADD", "AFTER", "ALL", "ALTER", "ANALYZE", "AND", "AS",
- "ASC", "ATTACH", "AUTOINCREMENT", "BEFORE", "BEGIN", "BETWEEN", "BY",
- "CASCADE", "CASE", "CAST", "CHECK", "COLLATE", "COLUMN", "COMMIT",
- "CONFLICT", "CONSTRAINT", "CREATE", "CROSS", "CURRENT_DATE",
- "CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DEFAULT", "DEFERRABLE",
- "DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DROP", "EACH",
- "ELSE", "END", "ESCAPE", "EXCEPT", "EXCLUSIVE", "EXISTS", "EXPLAIN",
- "FAIL", "FOR", "FOREIGN", "FROM", "FULL", "GLOB", "GROUP", "HAVING", "IF",
- "IGNORE", "IMMEDIATE", "IN", "INDEX", "INDEXED", "INITIALLY", "INNER",
- "INSERT", "INSTEAD", "INTERSECT", "INTO", "IS", "ISNULL", "JOIN", "KEY",
- "LEFT", "LIKE", "LIMIT", "MATCH", "NATURAL", "NO", "NOT", "NOTNULL",
- "NULL", "OF", "OFFSET", "ON", "OR", "ORDER", "OUTER", "PLAN", "PRAGMA",
- "PRIMARY", "QUERY", "RAISE", "RECURSIVE", "REFERENCES", "REGEXP",
- "REINDEX", "RELEASE", "RENAME", "REPLACE", "RESTRICT", "RIGHT",
- "ROLLBACK", "ROW", "SAVEPOINT", "SELECT", "SET", "TABLE", "TEMP",
- "TEMPORARY", "THEN", "TO", "TRANSACTION", "TRIGGER", "UNION", "UNIQUE",
- "UPDATE", "USING", "VACUUM", "VALUES", "VIEW", "VIRTUAL", "WHEN", "WHERE",
- "WITH", "WITHOUT",
- };
- int i, lwr, upr, mid, c;
- if( !isalpha((unsigned char)zName[0]) && zName[0]!='_' ) return '"';
- for(i=0; zName[i]; i++){
- if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ) return '"';
- }
- lwr = 0;
- upr = sizeof(azKeywords)/sizeof(azKeywords[0]) - 1;
- while( lwr<=upr ){
- mid = (lwr+upr)/2;
- c = sqlite3_stricmp(azKeywords[mid], zName);
- if( c==0 ) return '"';
- if( c<0 ){
- lwr = mid+1;
- }else{
- upr = mid-1;
- }
- }
- return 0;
-}
-
-/*
-** SQL function: shell_add_schema(S,X)
-**
-** Add the schema name X to the CREATE statement in S and return the result.
-** Examples:
-**
-** CREATE TABLE t1(x) -> CREATE TABLE xyz.t1(x);
-**
-** Also works on
-**
-** CREATE INDEX
-** CREATE UNIQUE INDEX
-** CREATE VIEW
-** CREATE TRIGGER
-** CREATE VIRTUAL TABLE
-**
-** This UDF is used by the .schema command to insert the schema name of
-** attached databases into the middle of the sqlite_master.sql field.
-*/
-static void shellAddSchemaName(
- sqlite3_context *pCtx,
- int nVal,
- sqlite3_value **apVal
-){
- static const char *aPrefix[] = {
- "TABLE",
- "INDEX",
- "UNIQUE INDEX",
- "VIEW",
- "TRIGGER",
- "VIRTUAL TABLE"
- };
- int i = 0;
- const char *zIn = (const char*)sqlite3_value_text(apVal[0]);
- const char *zSchema = (const char*)sqlite3_value_text(apVal[1]);
- assert( nVal==2 );
- if( zIn!=0 && strncmp(zIn, "CREATE ", 7)==0 ){
- for(i=0; i<(int)(sizeof(aPrefix)/sizeof(aPrefix[0])); i++){
- int n = strlen30(aPrefix[i]);
- if( strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){
- char cQuote = quoteChar(zSchema);
- char *z;
- if( cQuote ){
- z = sqlite3_mprintf("%.*s \"%w\".%s", n+7, zIn, zSchema, zIn+n+8);
- }else{
- z = sqlite3_mprintf("%.*s %s.%s", n+7, zIn, zSchema, zIn+n+8);
- }
- sqlite3_result_text(pCtx, z, -1, sqlite3_free);
- return;
- }
- }
- }
- sqlite3_result_value(pCtx, apVal[0]);
-}
-
-/*
-** The source code for several run-time loadable extensions is inserted
-** below by the ../tool/mkshellc.tcl script. Before processing that included
-** code, we need to override some macros to make the included program code
-** work here in the middle of this regular program.
-*/
-#define SQLITE_EXTENSION_INIT1
-#define SQLITE_EXTENSION_INIT2(X) (void)(X)
-
-/************************* Begin ../ext/misc/shathree.c ******************/
-/*
-** 2017-03-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.
-**
-******************************************************************************
-**
-** This SQLite extension implements a functions that compute SHA1 hashes.
-** Two SQL functions are implemented:
-**
-** sha3(X,SIZE)
-** sha3_query(Y,SIZE)
-**
-** The sha3(X) function computes the SHA3 hash of the input X, or NULL if
-** X is NULL.
-**
-** The sha3_query(Y) function evalutes all queries in the SQL statements of Y
-** and returns a hash of their results.
-**
-** The SIZE argument is optional. If omitted, the SHA3-256 hash algorithm
-** is used. If SIZE is included it must be one of the integers 224, 256,
-** 384, or 512, to determine SHA3 hash variant that is computed.
-*/
-SQLITE_EXTENSION_INIT1
-#include <assert.h>
-#include <string.h>
-#include <stdarg.h>
-typedef sqlite3_uint64 u64;
-
-/******************************************************************************
-** The Hash Engine
-*/
-/*
-** Macros to determine whether the machine is big or little endian,
-** and whether or not that determination is run-time or compile-time.
-**
-** For best performance, an attempt is made to guess at the byte-order
-** using C-preprocessor macros. If that is unsuccessful, or if
-** -DSHA3_BYTEORDER=0 is set, then byte-order is determined
-** at run-time.
-*/
-#ifndef SHA3_BYTEORDER
-# if defined(i386) || defined(__i386__) || defined(_M_IX86) || \
- defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
- defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \
- defined(__arm__)
-# define SHA3_BYTEORDER 1234
-# elif defined(sparc) || defined(__ppc__)
-# define SHA3_BYTEORDER 4321
-# else
-# define SHA3_BYTEORDER 0
-# endif
-#endif
-
-
-/*
-** State structure for a SHA3 hash in progress
-*/
-typedef struct SHA3Context SHA3Context;
-struct SHA3Context {
- union {
- u64 s[25]; /* Keccak state. 5x5 lines of 64 bits each */
- unsigned char x[1600]; /* ... or 1600 bytes */
- } u;
- unsigned nRate; /* Bytes of input accepted per Keccak iteration */
- unsigned nLoaded; /* Input bytes loaded into u.x[] so far this cycle */
- unsigned ixMask; /* Insert next input into u.x[nLoaded^ixMask]. */
-};
-
-/*
-** A single step of the Keccak mixing function for a 1600-bit state
-*/
-static void KeccakF1600Step(SHA3Context *p){
- int i;
- u64 B0, B1, B2, B3, B4;
- u64 C0, C1, C2, C3, C4;
- u64 D0, D1, D2, D3, D4;
- static const u64 RC[] = {
- 0x0000000000000001ULL, 0x0000000000008082ULL,
- 0x800000000000808aULL, 0x8000000080008000ULL,
- 0x000000000000808bULL, 0x0000000080000001ULL,
- 0x8000000080008081ULL, 0x8000000000008009ULL,
- 0x000000000000008aULL, 0x0000000000000088ULL,
- 0x0000000080008009ULL, 0x000000008000000aULL,
- 0x000000008000808bULL, 0x800000000000008bULL,
- 0x8000000000008089ULL, 0x8000000000008003ULL,
- 0x8000000000008002ULL, 0x8000000000000080ULL,
- 0x000000000000800aULL, 0x800000008000000aULL,
- 0x8000000080008081ULL, 0x8000000000008080ULL,
- 0x0000000080000001ULL, 0x8000000080008008ULL
- };
-# define A00 (p->u.s[0])
-# define A01 (p->u.s[1])
-# define A02 (p->u.s[2])
-# define A03 (p->u.s[3])
-# define A04 (p->u.s[4])
-# define A10 (p->u.s[5])
-# define A11 (p->u.s[6])
-# define A12 (p->u.s[7])
-# define A13 (p->u.s[8])
-# define A14 (p->u.s[9])
-# define A20 (p->u.s[10])
-# define A21 (p->u.s[11])
-# define A22 (p->u.s[12])
-# define A23 (p->u.s[13])
-# define A24 (p->u.s[14])
-# define A30 (p->u.s[15])
-# define A31 (p->u.s[16])
-# define A32 (p->u.s[17])
-# define A33 (p->u.s[18])
-# define A34 (p->u.s[19])
-# define A40 (p->u.s[20])
-# define A41 (p->u.s[21])
-# define A42 (p->u.s[22])
-# define A43 (p->u.s[23])
-# define A44 (p->u.s[24])
-# define ROL64(a,x) ((a<<x)|(a>>(64-x)))
-
- for(i=0; i<24; i+=4){
- C0 = A00^A10^A20^A30^A40;
- C1 = A01^A11^A21^A31^A41;
- C2 = A02^A12^A22^A32^A42;
- C3 = A03^A13^A23^A33^A43;
- C4 = A04^A14^A24^A34^A44;
- D0 = C4^ROL64(C1, 1);
- D1 = C0^ROL64(C2, 1);
- D2 = C1^ROL64(C3, 1);
- D3 = C2^ROL64(C4, 1);
- D4 = C3^ROL64(C0, 1);
-
- B0 = (A00^D0);
- B1 = ROL64((A11^D1), 44);
- B2 = ROL64((A22^D2), 43);
- B3 = ROL64((A33^D3), 21);
- B4 = ROL64((A44^D4), 14);
- A00 = B0 ^((~B1)& B2 );
- A00 ^= RC[i];
- A11 = B1 ^((~B2)& B3 );
- A22 = B2 ^((~B3)& B4 );
- A33 = B3 ^((~B4)& B0 );
- A44 = B4 ^((~B0)& B1 );
-
- B2 = ROL64((A20^D0), 3);
- B3 = ROL64((A31^D1), 45);
- B4 = ROL64((A42^D2), 61);
- B0 = ROL64((A03^D3), 28);
- B1 = ROL64((A14^D4), 20);
- A20 = B0 ^((~B1)& B2 );
- A31 = B1 ^((~B2)& B3 );
- A42 = B2 ^((~B3)& B4 );
- A03 = B3 ^((~B4)& B0 );
- A14 = B4 ^((~B0)& B1 );
-
- B4 = ROL64((A40^D0), 18);
- B0 = ROL64((A01^D1), 1);
- B1 = ROL64((A12^D2), 6);
- B2 = ROL64((A23^D3), 25);
- B3 = ROL64((A34^D4), 8);
- A40 = B0 ^((~B1)& B2 );
- A01 = B1 ^((~B2)& B3 );
- A12 = B2 ^((~B3)& B4 );
- A23 = B3 ^((~B4)& B0 );
- A34 = B4 ^((~B0)& B1 );
-
- B1 = ROL64((A10^D0), 36);
- B2 = ROL64((A21^D1), 10);
- B3 = ROL64((A32^D2), 15);
- B4 = ROL64((A43^D3), 56);
- B0 = ROL64((A04^D4), 27);
- A10 = B0 ^((~B1)& B2 );
- A21 = B1 ^((~B2)& B3 );
- A32 = B2 ^((~B3)& B4 );
- A43 = B3 ^((~B4)& B0 );
- A04 = B4 ^((~B0)& B1 );
-
- B3 = ROL64((A30^D0), 41);
- B4 = ROL64((A41^D1), 2);
- B0 = ROL64((A02^D2), 62);
- B1 = ROL64((A13^D3), 55);
- B2 = ROL64((A24^D4), 39);
- A30 = B0 ^((~B1)& B2 );
- A41 = B1 ^((~B2)& B3 );
- A02 = B2 ^((~B3)& B4 );
- A13 = B3 ^((~B4)& B0 );
- A24 = B4 ^((~B0)& B1 );
-
- C0 = A00^A20^A40^A10^A30;
- C1 = A11^A31^A01^A21^A41;
- C2 = A22^A42^A12^A32^A02;
- C3 = A33^A03^A23^A43^A13;
- C4 = A44^A14^A34^A04^A24;
- D0 = C4^ROL64(C1, 1);
- D1 = C0^ROL64(C2, 1);
- D2 = C1^ROL64(C3, 1);
- D3 = C2^ROL64(C4, 1);
- D4 = C3^ROL64(C0, 1);
-
- B0 = (A00^D0);
- B1 = ROL64((A31^D1), 44);
- B2 = ROL64((A12^D2), 43);
- B3 = ROL64((A43^D3), 21);
- B4 = ROL64((A24^D4), 14);
- A00 = B0 ^((~B1)& B2 );
- A00 ^= RC[i+1];
- A31 = B1 ^((~B2)& B3 );
- A12 = B2 ^((~B3)& B4 );
- A43 = B3 ^((~B4)& B0 );
- A24 = B4 ^((~B0)& B1 );
-
- B2 = ROL64((A40^D0), 3);
- B3 = ROL64((A21^D1), 45);
- B4 = ROL64((A02^D2), 61);
- B0 = ROL64((A33^D3), 28);
- B1 = ROL64((A14^D4), 20);
- A40 = B0 ^((~B1)& B2 );
- A21 = B1 ^((~B2)& B3 );
- A02 = B2 ^((~B3)& B4 );
- A33 = B3 ^((~B4)& B0 );
- A14 = B4 ^((~B0)& B1 );
-
- B4 = ROL64((A30^D0), 18);
- B0 = ROL64((A11^D1), 1);
- B1 = ROL64((A42^D2), 6);
- B2 = ROL64((A23^D3), 25);
- B3 = ROL64((A04^D4), 8);
- A30 = B0 ^((~B1)& B2 );
- A11 = B1 ^((~B2)& B3 );
- A42 = B2 ^((~B3)& B4 );
- A23 = B3 ^((~B4)& B0 );
- A04 = B4 ^((~B0)& B1 );
-
- B1 = ROL64((A20^D0), 36);
- B2 = ROL64((A01^D1), 10);
- B3 = ROL64((A32^D2), 15);
- B4 = ROL64((A13^D3), 56);
- B0 = ROL64((A44^D4), 27);
- A20 = B0 ^((~B1)& B2 );
- A01 = B1 ^((~B2)& B3 );
- A32 = B2 ^((~B3)& B4 );
- A13 = B3 ^((~B4)& B0 );
- A44 = B4 ^((~B0)& B1 );
-
- B3 = ROL64((A10^D0), 41);
- B4 = ROL64((A41^D1), 2);
- B0 = ROL64((A22^D2), 62);
- B1 = ROL64((A03^D3), 55);
- B2 = ROL64((A34^D4), 39);
- A10 = B0 ^((~B1)& B2 );
- A41 = B1 ^((~B2)& B3 );
- A22 = B2 ^((~B3)& B4 );
- A03 = B3 ^((~B4)& B0 );
- A34 = B4 ^((~B0)& B1 );
-
- C0 = A00^A40^A30^A20^A10;
- C1 = A31^A21^A11^A01^A41;
- C2 = A12^A02^A42^A32^A22;
- C3 = A43^A33^A23^A13^A03;
- C4 = A24^A14^A04^A44^A34;
- D0 = C4^ROL64(C1, 1);
- D1 = C0^ROL64(C2, 1);
- D2 = C1^ROL64(C3, 1);
- D3 = C2^ROL64(C4, 1);
- D4 = C3^ROL64(C0, 1);
-
- B0 = (A00^D0);
- B1 = ROL64((A21^D1), 44);
- B2 = ROL64((A42^D2), 43);
- B3 = ROL64((A13^D3), 21);
- B4 = ROL64((A34^D4), 14);
- A00 = B0 ^((~B1)& B2 );
- A00 ^= RC[i+2];
- A21 = B1 ^((~B2)& B3 );
- A42 = B2 ^((~B3)& B4 );
- A13 = B3 ^((~B4)& B0 );
- A34 = B4 ^((~B0)& B1 );
-
- B2 = ROL64((A30^D0), 3);
- B3 = ROL64((A01^D1), 45);
- B4 = ROL64((A22^D2), 61);
- B0 = ROL64((A43^D3), 28);
- B1 = ROL64((A14^D4), 20);
- A30 = B0 ^((~B1)& B2 );
- A01 = B1 ^((~B2)& B3 );
- A22 = B2 ^((~B3)& B4 );
- A43 = B3 ^((~B4)& B0 );
- A14 = B4 ^((~B0)& B1 );
-
- B4 = ROL64((A10^D0), 18);
- B0 = ROL64((A31^D1), 1);
- B1 = ROL64((A02^D2), 6);
- B2 = ROL64((A23^D3), 25);
- B3 = ROL64((A44^D4), 8);
- A10 = B0 ^((~B1)& B2 );
- A31 = B1 ^((~B2)& B3 );
- A02 = B2 ^((~B3)& B4 );
- A23 = B3 ^((~B4)& B0 );
- A44 = B4 ^((~B0)& B1 );
-
- B1 = ROL64((A40^D0), 36);
- B2 = ROL64((A11^D1), 10);
- B3 = ROL64((A32^D2), 15);
- B4 = ROL64((A03^D3), 56);
- B0 = ROL64((A24^D4), 27);
- A40 = B0 ^((~B1)& B2 );
- A11 = B1 ^((~B2)& B3 );
- A32 = B2 ^((~B3)& B4 );
- A03 = B3 ^((~B4)& B0 );
- A24 = B4 ^((~B0)& B1 );
-
- B3 = ROL64((A20^D0), 41);
- B4 = ROL64((A41^D1), 2);
- B0 = ROL64((A12^D2), 62);
- B1 = ROL64((A33^D3), 55);
- B2 = ROL64((A04^D4), 39);
- A20 = B0 ^((~B1)& B2 );
- A41 = B1 ^((~B2)& B3 );
- A12 = B2 ^((~B3)& B4 );
- A33 = B3 ^((~B4)& B0 );
- A04 = B4 ^((~B0)& B1 );
-
- C0 = A00^A30^A10^A40^A20;
- C1 = A21^A01^A31^A11^A41;
- C2 = A42^A22^A02^A32^A12;
- C3 = A13^A43^A23^A03^A33;
- C4 = A34^A14^A44^A24^A04;
- D0 = C4^ROL64(C1, 1);
- D1 = C0^ROL64(C2, 1);
- D2 = C1^ROL64(C3, 1);
- D3 = C2^ROL64(C4, 1);
- D4 = C3^ROL64(C0, 1);
-
- B0 = (A00^D0);
- B1 = ROL64((A01^D1), 44);
- B2 = ROL64((A02^D2), 43);
- B3 = ROL64((A03^D3), 21);
- B4 = ROL64((A04^D4), 14);
- A00 = B0 ^((~B1)& B2 );
- A00 ^= RC[i+3];
- A01 = B1 ^((~B2)& B3 );
- A02 = B2 ^((~B3)& B4 );
- A03 = B3 ^((~B4)& B0 );
- A04 = B4 ^((~B0)& B1 );
-
- B2 = ROL64((A10^D0), 3);
- B3 = ROL64((A11^D1), 45);
- B4 = ROL64((A12^D2), 61);
- B0 = ROL64((A13^D3), 28);
- B1 = ROL64((A14^D4), 20);
- A10 = B0 ^((~B1)& B2 );
- A11 = B1 ^((~B2)& B3 );
- A12 = B2 ^((~B3)& B4 );
- A13 = B3 ^((~B4)& B0 );
- A14 = B4 ^((~B0)& B1 );
-
- B4 = ROL64((A20^D0), 18);
- B0 = ROL64((A21^D1), 1);
- B1 = ROL64((A22^D2), 6);
- B2 = ROL64((A23^D3), 25);
- B3 = ROL64((A24^D4), 8);
- A20 = B0 ^((~B1)& B2 );
- A21 = B1 ^((~B2)& B3 );
- A22 = B2 ^((~B3)& B4 );
- A23 = B3 ^((~B4)& B0 );
- A24 = B4 ^((~B0)& B1 );
-
- B1 = ROL64((A30^D0), 36);
- B2 = ROL64((A31^D1), 10);
- B3 = ROL64((A32^D2), 15);
- B4 = ROL64((A33^D3), 56);
- B0 = ROL64((A34^D4), 27);
- A30 = B0 ^((~B1)& B2 );
- A31 = B1 ^((~B2)& B3 );
- A32 = B2 ^((~B3)& B4 );
- A33 = B3 ^((~B4)& B0 );
- A34 = B4 ^((~B0)& B1 );
-
- B3 = ROL64((A40^D0), 41);
- B4 = ROL64((A41^D1), 2);
- B0 = ROL64((A42^D2), 62);
- B1 = ROL64((A43^D3), 55);
- B2 = ROL64((A44^D4), 39);
- A40 = B0 ^((~B1)& B2 );
- A41 = B1 ^((~B2)& B3 );
- A42 = B2 ^((~B3)& B4 );
- A43 = B3 ^((~B4)& B0 );
- A44 = B4 ^((~B0)& B1 );
- }
-}
-
-/*
-** Initialize a new hash. iSize determines the size of the hash
-** in bits and should be one of 224, 256, 384, or 512. Or iSize
-** can be zero to use the default hash size of 256 bits.
-*/
-static void SHA3Init(SHA3Context *p, int iSize){
- memset(p, 0, sizeof(*p));
- if( iSize>=128 && iSize<=512 ){
- p->nRate = (1600 - ((iSize + 31)&~31)*2)/8;
- }else{
- p->nRate = (1600 - 2*256)/8;
- }
-#if SHA3_BYTEORDER==1234
- /* Known to be little-endian at compile-time. No-op */
-#elif SHA3_BYTEORDER==4321
- p->ixMask = 7; /* Big-endian */
-#else
- {
- static unsigned int one = 1;
- if( 1==*(unsigned char*)&one ){
- /* Little endian. No byte swapping. */
- p->ixMask = 0;
- }else{
- /* Big endian. Byte swap. */
- p->ixMask = 7;
- }
- }
-#endif
-}
-
-/*
-** Make consecutive calls to the SHA3Update function to add new content
-** to the hash
-*/
-static void SHA3Update(
- SHA3Context *p,
- const unsigned char *aData,
- unsigned int nData
-){
- unsigned int i = 0;
-#if SHA3_BYTEORDER==1234
- if( (p->nLoaded % 8)==0 && ((aData - (const unsigned char*)0)&7)==0 ){
- for(; i+7<nData; i+=8){
- p->u.s[p->nLoaded/8] ^= *(u64*)&aData[i];
- p->nLoaded += 8;
- if( p->nLoaded>=p->nRate ){
- KeccakF1600Step(p);
- p->nLoaded = 0;
- }
- }
- }
-#endif
- for(; i<nData; i++){
-#if SHA3_BYTEORDER==1234
- p->u.x[p->nLoaded] ^= aData[i];
-#elif SHA3_BYTEORDER==4321
- p->u.x[p->nLoaded^0x07] ^= aData[i];
-#else
- p->u.x[p->nLoaded^p->ixMask] ^= aData[i];
-#endif
- p->nLoaded++;
- if( p->nLoaded==p->nRate ){
- KeccakF1600Step(p);
- p->nLoaded = 0;
- }
- }
-}
-
-/*
-** After all content has been added, invoke SHA3Final() to compute
-** the final hash. The function returns a pointer to the binary
-** hash value.
-*/
-static unsigned char *SHA3Final(SHA3Context *p){
- unsigned int i;
- if( p->nLoaded==p->nRate-1 ){
- const unsigned char c1 = 0x86;
- SHA3Update(p, &c1, 1);
- }else{
- const unsigned char c2 = 0x06;
- const unsigned char c3 = 0x80;
- SHA3Update(p, &c2, 1);
- p->nLoaded = p->nRate - 1;
- SHA3Update(p, &c3, 1);
- }
- for(i=0; i<p->nRate; i++){
- p->u.x[i+p->nRate] = p->u.x[i^p->ixMask];
- }
- return &p->u.x[p->nRate];
-}
-/* End of the hashing logic
-*****************************************************************************/
-
-/*
-** Implementation of the sha3(X,SIZE) function.
-**
-** Return a BLOB which is the SIZE-bit SHA3 hash of X. The default
-** size is 256. If X is a BLOB, it is hashed as is.
-** For all other non-NULL types of input, X is converted into a UTF-8 string
-** and the string is hashed without the trailing 0x00 terminator. The hash
-** of a NULL value is NULL.
-*/
-static void sha3Func(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- SHA3Context cx;
- int eType = sqlite3_value_type(argv[0]);
- int nByte = sqlite3_value_bytes(argv[0]);
- int iSize;
- if( argc==1 ){
- iSize = 256;
- }else{
- iSize = sqlite3_value_int(argv[1]);
- if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){
- sqlite3_result_error(context, "SHA3 size should be one of: 224 256 "
- "384 512", -1);
- return;
- }
- }
- if( eType==SQLITE_NULL ) return;
- SHA3Init(&cx, iSize);
- if( eType==SQLITE_BLOB ){
- SHA3Update(&cx, sqlite3_value_blob(argv[0]), nByte);
- }else{
- SHA3Update(&cx, sqlite3_value_text(argv[0]), nByte);
- }
- sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT);
-}
-
-/* Compute a string using sqlite3_vsnprintf() with a maximum length
-** of 50 bytes and add it to the hash.
-*/
-static void hash_step_vformat(
- SHA3Context *p, /* Add content to this context */
- const char *zFormat,
- ...
-){
- va_list ap;
- int n;
- char zBuf[50];
- va_start(ap, zFormat);
- sqlite3_vsnprintf(sizeof(zBuf),zBuf,zFormat,ap);
- va_end(ap);
- n = (int)strlen(zBuf);
- SHA3Update(p, (unsigned char*)zBuf, n);
-}
-
-/*
-** Implementation of the sha3_query(SQL,SIZE) function.
-**
-** This function compiles and runs the SQL statement(s) given in the
-** argument. The results are hashed using a SIZE-bit SHA3. The default
-** size is 256.
-**
-** The format of the byte stream that is hashed is summarized as follows:
-**
-** S<n>:<sql>
-** R
-** N
-** I<int>
-** F<ieee-float>
-** B<size>:<bytes>
-** T<size>:<text>
-**
-** <sql> is the original SQL text for each statement run and <n> is
-** the size of that text. The SQL text is UTF-8. A single R character
-** occurs before the start of each row. N means a NULL value.
-** I mean an 8-byte little-endian integer <int>. F is a floating point
-** number with an 8-byte little-endian IEEE floating point value <ieee-float>.
-** B means blobs of <size> bytes. T means text rendered as <size>
-** bytes of UTF-8. The <n> and <size> values are expressed as an ASCII
-** text integers.
-**
-** For each SQL statement in the X input, there is one S segment. Each
-** S segment is followed by zero or more R segments, one for each row in the
-** result set. After each R, there are one or more N, I, F, B, or T segments,
-** one for each column in the result set. Segments are concatentated directly
-** with no delimiters of any kind.
-*/
-static void sha3QueryFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- sqlite3 *db = sqlite3_context_db_handle(context);
- const char *zSql = (const char*)sqlite3_value_text(argv[0]);
- sqlite3_stmt *pStmt = 0;
- int nCol; /* Number of columns in the result set */
- int i; /* Loop counter */
- int rc;
- int n;
- const char *z;
- SHA3Context cx;
- int iSize;
-
- if( argc==1 ){
- iSize = 256;
- }else{
- iSize = sqlite3_value_int(argv[1]);
- if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){
- sqlite3_result_error(context, "SHA3 size should be one of: 224 256 "
- "384 512", -1);
- return;
- }
- }
- if( zSql==0 ) return;
- SHA3Init(&cx, iSize);
- while( zSql[0] ){
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zSql);
- if( rc ){
- char *zMsg = sqlite3_mprintf("error SQL statement [%s]: %s",
- zSql, sqlite3_errmsg(db));
- sqlite3_finalize(pStmt);
- sqlite3_result_error(context, zMsg, -1);
- sqlite3_free(zMsg);
- return;
- }
- if( !sqlite3_stmt_readonly(pStmt) ){
- char *zMsg = sqlite3_mprintf("non-query: [%s]", sqlite3_sql(pStmt));
- sqlite3_finalize(pStmt);
- sqlite3_result_error(context, zMsg, -1);
- sqlite3_free(zMsg);
- return;
- }
- nCol = sqlite3_column_count(pStmt);
- z = sqlite3_sql(pStmt);
- n = (int)strlen(z);
- hash_step_vformat(&cx,"S%d:",n);
- SHA3Update(&cx,(unsigned char*)z,n);
-
- /* Compute a hash over the result of the query */
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- SHA3Update(&cx,(const unsigned char*)"R",1);
- for(i=0; i<nCol; i++){
- switch( sqlite3_column_type(pStmt,i) ){
- case SQLITE_NULL: {
- SHA3Update(&cx, (const unsigned char*)"N",1);
- break;
- }
- case SQLITE_INTEGER: {
- sqlite3_uint64 u;
- int j;
- unsigned char x[9];
- sqlite3_int64 v = sqlite3_column_int64(pStmt,i);
- memcpy(&u, &v, 8);
- for(j=8; j>=1; j--){
- x[j] = u & 0xff;
- u >>= 8;
- }
- x[0] = 'I';
- SHA3Update(&cx, x, 9);
- break;
- }
- case SQLITE_FLOAT: {
- sqlite3_uint64 u;
- int j;
- unsigned char x[9];
- double r = sqlite3_column_double(pStmt,i);
- memcpy(&u, &r, 8);
- for(j=8; j>=1; j--){
- x[j] = u & 0xff;
- u >>= 8;
- }
- x[0] = 'F';
- SHA3Update(&cx,x,9);
- break;
- }
- case SQLITE_TEXT: {
- int n2 = sqlite3_column_bytes(pStmt, i);
- const unsigned char *z2 = sqlite3_column_text(pStmt, i);
- hash_step_vformat(&cx,"T%d:",n2);
- SHA3Update(&cx, z2, n2);
- break;
- }
- case SQLITE_BLOB: {
- int n2 = sqlite3_column_bytes(pStmt, i);
- const unsigned char *z2 = sqlite3_column_blob(pStmt, i);
- hash_step_vformat(&cx,"B%d:",n2);
- SHA3Update(&cx, z2, n2);
- break;
- }
- }
- }
- }
- sqlite3_finalize(pStmt);
- }
- sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT);
-}
-
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_shathree_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int rc = SQLITE_OK;
- SQLITE_EXTENSION_INIT2(pApi);
- (void)pzErrMsg; /* Unused parameter */
- rc = sqlite3_create_function(db, "sha3", 1, SQLITE_UTF8, 0,
- sha3Func, 0, 0);
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(db, "sha3", 2, SQLITE_UTF8, 0,
- sha3Func, 0, 0);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(db, "sha3_query", 1, SQLITE_UTF8, 0,
- sha3QueryFunc, 0, 0);
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(db, "sha3_query", 2, SQLITE_UTF8, 0,
- sha3QueryFunc, 0, 0);
- }
- return rc;
-}
-
-/************************* End ../ext/misc/shathree.c ********************/
-/************************* Begin ../ext/misc/fileio.c ******************/
-/*
-** 2014-06-13
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-******************************************************************************
-**
-** This SQLite extension implements SQL functions readfile() and
-** writefile().
-*/
-SQLITE_EXTENSION_INIT1
-#include <stdio.h>
-
-/*
-** Implementation of the "readfile(X)" SQL function. The entire content
-** of the file named X is read and returned as a BLOB. NULL is returned
-** if the file does not exist or is unreadable.
-*/
-static void readfileFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- const char *zName;
- FILE *in;
- long nIn;
- void *pBuf;
-
- (void)(argc); /* Unused parameter */
- zName = (const char*)sqlite3_value_text(argv[0]);
- if( zName==0 ) return;
- in = fopen(zName, "rb");
- if( in==0 ) return;
- fseek(in, 0, SEEK_END);
- nIn = ftell(in);
- rewind(in);
- pBuf = sqlite3_malloc( nIn );
- if( pBuf && 1==fread(pBuf, nIn, 1, in) ){
- sqlite3_result_blob(context, pBuf, nIn, sqlite3_free);
- }else{
- sqlite3_free(pBuf);
- }
- fclose(in);
-}
-
-/*
-** Implementation of the "writefile(X,Y)" SQL function. The argument Y
-** is written into file X. The number of bytes written is returned. Or
-** NULL is returned if something goes wrong, such as being unable to open
-** file X for writing.
-*/
-static void writefileFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- FILE *out;
- const char *z;
- sqlite3_int64 rc;
- const char *zFile;
-
- (void)(argc); /* Unused parameter */
- zFile = (const char*)sqlite3_value_text(argv[0]);
- if( zFile==0 ) return;
- out = fopen(zFile, "wb");
- if( out==0 ) return;
- z = (const char*)sqlite3_value_blob(argv[1]);
- if( z==0 ){
- rc = 0;
- }else{
- rc = fwrite(z, 1, sqlite3_value_bytes(argv[1]), out);
- }
- fclose(out);
- sqlite3_result_int64(context, rc);
-}
-
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_fileio_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int rc = SQLITE_OK;
- SQLITE_EXTENSION_INIT2(pApi);
- (void)pzErrMsg; /* Unused parameter */
- rc = sqlite3_create_function(db, "readfile", 1, SQLITE_UTF8, 0,
- readfileFunc, 0, 0);
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(db, "writefile", 2, SQLITE_UTF8, 0,
- writefileFunc, 0, 0);
- }
- return rc;
-}
-
-/************************* End ../ext/misc/fileio.c ********************/
-/************************* Begin ../ext/misc/completion.c ******************/
-/*
-** 2017-07-10
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-**
-** This file implements an eponymous virtual table that returns suggested
-** completions for a partial SQL input.
-**
-** Suggested usage:
-**
-** SELECT DISTINCT candidate COLLATE nocase
-** FROM completion($prefix,$wholeline)
-** ORDER BY 1;
-**
-** The two query parameters are optional. $prefix is the text of the
-** current word being typed and that is to be completed. $wholeline is
-** the complete input line, used for context.
-**
-** The raw completion() table might return the same candidate multiple
-** times, for example if the same column name is used to two or more
-** tables. And the candidates are returned in an arbitrary order. Hence,
-** the DISTINCT and ORDER BY are recommended.
-**
-** This virtual table operates at the speed of human typing, and so there
-** is no attempt to make it fast. Even a slow implementation will be much
-** faster than any human can type.
-**
-*/
-SQLITE_EXTENSION_INIT1
-#include <assert.h>
-#include <string.h>
-#include <ctype.h>
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-
-/* completion_vtab is a subclass of sqlite3_vtab which will
-** serve as the underlying representation of a completion virtual table
-*/
-typedef struct completion_vtab completion_vtab;
-struct completion_vtab {
- sqlite3_vtab base; /* Base class - must be first */
- sqlite3 *db; /* Database connection for this completion vtab */
-};
-
-/* completion_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 completion_cursor completion_cursor;
-struct completion_cursor {
- sqlite3_vtab_cursor base; /* Base class - must be first */
- sqlite3 *db; /* Database connection for this cursor */
- int nPrefix, nLine; /* Number of bytes in zPrefix and zLine */
- char *zPrefix; /* The prefix for the word we want to complete */
- char *zLine; /* The whole that we want to complete */
- const char *zCurrentRow; /* Current output row */
- sqlite3_stmt *pStmt; /* Current statement */
- sqlite3_int64 iRowid; /* The rowid */
- int ePhase; /* Current phase */
- int j; /* inter-phase counter */
-};
-
-/* Values for ePhase:
-*/
-#define COMPLETION_FIRST_PHASE 1
-#define COMPLETION_KEYWORDS 1
-#define COMPLETION_PRAGMAS 2
-#define COMPLETION_FUNCTIONS 3
-#define COMPLETION_COLLATIONS 4
-#define COMPLETION_INDEXES 5
-#define COMPLETION_TRIGGERS 6
-#define COMPLETION_DATABASES 7
-#define COMPLETION_TABLES 8
-#define COMPLETION_COLUMNS 9
-#define COMPLETION_MODULES 10
-#define COMPLETION_EOF 11
-
-/*
-** The completionConnect() method is invoked to create a new
-** completion_vtab that describes the completion virtual table.
-**
-** Think of this routine as the constructor for completion_vtab objects.
-**
-** All this routine needs to do is:
-**
-** (1) Allocate the completion_vtab object and initialize all fields.
-**
-** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
-** result set of queries against completion will look like.
-*/
-static int completionConnect(
- sqlite3 *db,
- void *pAux,
- int argc, const char *const*argv,
- sqlite3_vtab **ppVtab,
- char **pzErr
-){
- completion_vtab *pNew;
- int rc;
-
- (void)(pAux); /* Unused parameter */
- (void)(argc); /* Unused parameter */
- (void)(argv); /* Unused parameter */
- (void)(pzErr); /* Unused parameter */
-
-/* Column numbers */
-#define COMPLETION_COLUMN_CANDIDATE 0 /* Suggested completion of the input */
-#define COMPLETION_COLUMN_PREFIX 1 /* Prefix of the word to be completed */
-#define COMPLETION_COLUMN_WHOLELINE 2 /* Entire line seen so far */
-#define COMPLETION_COLUMN_PHASE 3 /* ePhase - used for debugging only */
-
- rc = sqlite3_declare_vtab(db,
- "CREATE TABLE x("
- " candidate TEXT,"
- " prefix TEXT HIDDEN,"
- " wholeline TEXT HIDDEN,"
- " phase INT HIDDEN" /* Used for debugging only */
- ")");
- 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 completion_cursor objects.
-*/
-static int completionDisconnect(sqlite3_vtab *pVtab){
- sqlite3_free(pVtab);
- return SQLITE_OK;
-}
-
-/*
-** Constructor for a new completion_cursor object.
-*/
-static int completionOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
- completion_cursor *pCur;
- pCur = sqlite3_malloc( sizeof(*pCur) );
- if( pCur==0 ) return SQLITE_NOMEM;
- memset(pCur, 0, sizeof(*pCur));
- pCur->db = ((completion_vtab*)p)->db;
- *ppCursor = &pCur->base;
- return SQLITE_OK;
-}
-
-/*
-** Reset the completion_cursor.
-*/
-static void completionCursorReset(completion_cursor *pCur){
- sqlite3_free(pCur->zPrefix); pCur->zPrefix = 0; pCur->nPrefix = 0;
- sqlite3_free(pCur->zLine); pCur->zLine = 0; pCur->nLine = 0;
- sqlite3_finalize(pCur->pStmt); pCur->pStmt = 0;
- pCur->j = 0;
-}
-
-/*
-** Destructor for a completion_cursor.
-*/
-static int completionClose(sqlite3_vtab_cursor *cur){
- completionCursorReset((completion_cursor*)cur);
- sqlite3_free(cur);
- return SQLITE_OK;
-}
-
-/*
-** All SQL keywords understood by SQLite
-*/
-static const char *completionKwrds[] = {
- "ABORT", "ACTION", "ADD", "AFTER", "ALL", "ALTER", "ANALYZE", "AND", "AS",
- "ASC", "ATTACH", "AUTOINCREMENT", "BEFORE", "BEGIN", "BETWEEN", "BY",
- "CASCADE", "CASE", "CAST", "CHECK", "COLLATE", "COLUMN", "COMMIT",
- "CONFLICT", "CONSTRAINT", "CREATE", "CROSS", "CURRENT_DATE",
- "CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DEFAULT", "DEFERRABLE",
- "DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DROP", "EACH",
- "ELSE", "END", "ESCAPE", "EXCEPT", "EXCLUSIVE", "EXISTS", "EXPLAIN",
- "FAIL", "FOR", "FOREIGN", "FROM", "FULL", "GLOB", "GROUP", "HAVING", "IF",
- "IGNORE", "IMMEDIATE", "IN", "INDEX", "INDEXED", "INITIALLY", "INNER",
- "INSERT", "INSTEAD", "INTERSECT", "INTO", "IS", "ISNULL", "JOIN", "KEY",
- "LEFT", "LIKE", "LIMIT", "MATCH", "NATURAL", "NO", "NOT", "NOTNULL",
- "NULL", "OF", "OFFSET", "ON", "OR", "ORDER", "OUTER", "PLAN", "PRAGMA",
- "PRIMARY", "QUERY", "RAISE", "RECURSIVE", "REFERENCES", "REGEXP",
- "REINDEX", "RELEASE", "RENAME", "REPLACE", "RESTRICT", "RIGHT",
- "ROLLBACK", "ROW", "SAVEPOINT", "SELECT", "SET", "TABLE", "TEMP",
- "TEMPORARY", "THEN", "TO", "TRANSACTION", "TRIGGER", "UNION", "UNIQUE",
- "UPDATE", "USING", "VACUUM", "VALUES", "VIEW", "VIRTUAL", "WHEN", "WHERE",
- "WITH", "WITHOUT",
-};
-#define completionKwCount \
- (int)(sizeof(completionKwrds)/sizeof(completionKwrds[0]))
-
-/*
-** Advance a completion_cursor to its next row of output.
-**
-** The ->ePhase, ->j, and ->pStmt fields of the completion_cursor object
-** record the current state of the scan. This routine sets ->zCurrentRow
-** to the current row of output and then returns. If no more rows remain,
-** then ->ePhase is set to COMPLETION_EOF which will signal the virtual
-** table that has reached the end of its scan.
-**
-** The current implementation just lists potential identifiers and
-** keywords and filters them by zPrefix. Future enhancements should
-** take zLine into account to try to restrict the set of identifiers and
-** keywords based on what would be legal at the current point of input.
-*/
-static int completionNext(sqlite3_vtab_cursor *cur){
- completion_cursor *pCur = (completion_cursor*)cur;
- int eNextPhase = 0; /* Next phase to try if current phase reaches end */
- int iCol = -1; /* If >=0, step pCur->pStmt and use the i-th column */
- pCur->iRowid++;
- while( pCur->ePhase!=COMPLETION_EOF ){
- switch( pCur->ePhase ){
- case COMPLETION_KEYWORDS: {
- if( pCur->j >= completionKwCount ){
- pCur->zCurrentRow = 0;
- pCur->ePhase = COMPLETION_DATABASES;
- }else{
- pCur->zCurrentRow = completionKwrds[pCur->j++];
- }
- iCol = -1;
- break;
- }
- case COMPLETION_DATABASES: {
- if( pCur->pStmt==0 ){
- sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1,
- &pCur->pStmt, 0);
- }
- iCol = 1;
- eNextPhase = COMPLETION_TABLES;
- break;
- }
- case COMPLETION_TABLES: {
- if( pCur->pStmt==0 ){
- sqlite3_stmt *pS2;
- char *zSql = 0;
- const char *zSep = "";
- sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pS2, 0);
- while( sqlite3_step(pS2)==SQLITE_ROW ){
- const char *zDb = (const char*)sqlite3_column_text(pS2, 1);
- zSql = sqlite3_mprintf(
- "%z%s"
- "SELECT name FROM \"%w\".sqlite_master"
- " WHERE type='table'",
- zSql, zSep, zDb
- );
- if( zSql==0 ) return SQLITE_NOMEM;
- zSep = " UNION ";
- }
- sqlite3_finalize(pS2);
- sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pStmt, 0);
- sqlite3_free(zSql);
- }
- iCol = 0;
- eNextPhase = COMPLETION_COLUMNS;
- break;
- }
- case COMPLETION_COLUMNS: {
- if( pCur->pStmt==0 ){
- sqlite3_stmt *pS2;
- char *zSql = 0;
- const char *zSep = "";
- sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pS2, 0);
- while( sqlite3_step(pS2)==SQLITE_ROW ){
- const char *zDb = (const char*)sqlite3_column_text(pS2, 1);
- zSql = sqlite3_mprintf(
- "%z%s"
- "SELECT pti.name FROM \"%w\".sqlite_master AS sm"
- " JOIN pragma_table_info(sm.name,%Q) AS pti"
- " WHERE sm.type='table'",
- zSql, zSep, zDb, zDb
- );
- if( zSql==0 ) return SQLITE_NOMEM;
- zSep = " UNION ";
- }
- sqlite3_finalize(pS2);
- sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pStmt, 0);
- sqlite3_free(zSql);
- }
- iCol = 0;
- eNextPhase = COMPLETION_EOF;
- break;
- }
- }
- if( iCol<0 ){
- /* This case is when the phase presets zCurrentRow */
- if( pCur->zCurrentRow==0 ) continue;
- }else{
- if( sqlite3_step(pCur->pStmt)==SQLITE_ROW ){
- /* Extract the next row of content */
- pCur->zCurrentRow = (const char*)sqlite3_column_text(pCur->pStmt, iCol);
- }else{
- /* When all rows are finished, advance to the next phase */
- sqlite3_finalize(pCur->pStmt);
- pCur->pStmt = 0;
- pCur->ePhase = eNextPhase;
- continue;
- }
- }
- if( pCur->nPrefix==0 ) break;
- if( sqlite3_strnicmp(pCur->zPrefix, pCur->zCurrentRow, pCur->nPrefix)==0 ){
- break;
- }
- }
-
- return SQLITE_OK;
-}
-
-/*
-** Return values of columns for the row at which the completion_cursor
-** is currently pointing.
-*/
-static int completionColumn(
- sqlite3_vtab_cursor *cur, /* The cursor */
- sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
- int i /* Which column to return */
-){
- completion_cursor *pCur = (completion_cursor*)cur;
- switch( i ){
- case COMPLETION_COLUMN_CANDIDATE: {
- sqlite3_result_text(ctx, pCur->zCurrentRow, -1, SQLITE_TRANSIENT);
- break;
- }
- case COMPLETION_COLUMN_PREFIX: {
- sqlite3_result_text(ctx, pCur->zPrefix, -1, SQLITE_TRANSIENT);
- break;
- }
- case COMPLETION_COLUMN_WHOLELINE: {
- sqlite3_result_text(ctx, pCur->zLine, -1, SQLITE_TRANSIENT);
- break;
- }
- case COMPLETION_COLUMN_PHASE: {
- sqlite3_result_int(ctx, pCur->ePhase);
- 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 completionRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
- completion_cursor *pCur = (completion_cursor*)cur;
- *pRowid = pCur->iRowid;
- return SQLITE_OK;
-}
-
-/*
-** Return TRUE if the cursor has been moved off of the last
-** row of output.
-*/
-static int completionEof(sqlite3_vtab_cursor *cur){
- completion_cursor *pCur = (completion_cursor*)cur;
- return pCur->ePhase >= COMPLETION_EOF;
-}
-
-/*
-** This method is called to "rewind" the completion_cursor object back
-** to the first row of output. This method is always called at least
-** once prior to any call to completionColumn() or completionRowid() or
-** completionEof().
-*/
-static int completionFilter(
- sqlite3_vtab_cursor *pVtabCursor,
- int idxNum, const char *idxStr,
- int argc, sqlite3_value **argv
-){
- completion_cursor *pCur = (completion_cursor *)pVtabCursor;
- int iArg = 0;
- (void)(idxStr); /* Unused parameter */
- (void)(argc); /* Unused parameter */
- completionCursorReset(pCur);
- if( idxNum & 1 ){
- pCur->nPrefix = sqlite3_value_bytes(argv[iArg]);
- if( pCur->nPrefix>0 ){
- pCur->zPrefix = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg]));
- if( pCur->zPrefix==0 ) return SQLITE_NOMEM;
- }
- iArg++;
- }
- if( idxNum & 2 ){
- pCur->nLine = sqlite3_value_bytes(argv[iArg]);
- if( pCur->nLine>0 ){
- pCur->zLine = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg]));
- if( pCur->zLine==0 ) return SQLITE_NOMEM;
- }
- iArg++;
- }
- if( pCur->zLine!=0 && pCur->zPrefix==0 ){
- int i = pCur->nLine;
- while( i>0 && (isalnum(pCur->zLine[i-1]) || pCur->zLine[i-1]=='_') ){
- i--;
- }
- pCur->nPrefix = pCur->nLine - i;
- if( pCur->nPrefix>0 ){
- pCur->zPrefix = sqlite3_mprintf("%.*s", pCur->nPrefix, pCur->zLine + i);
- if( pCur->zPrefix==0 ) return SQLITE_NOMEM;
- }
- }
- pCur->iRowid = 0;
- pCur->ePhase = COMPLETION_FIRST_PHASE;
- return completionNext(pVtabCursor);
-}
-
-/*
-** SQLite will invoke this method one or more times while planning a query
-** that uses the completion virtual table. This routine needs to create
-** a query plan for each invocation and compute an estimated cost for that
-** plan.
-**
-** There are two hidden parameters that act as arguments to the table-valued
-** function: "prefix" and "wholeline". Bit 0 of idxNum is set if "prefix"
-** is available and bit 1 is set if "wholeline" is available.
-*/
-static int completionBestIndex(
- sqlite3_vtab *tab,
- sqlite3_index_info *pIdxInfo
-){
- int i; /* Loop over constraints */
- int idxNum = 0; /* The query plan bitmask */
- int prefixIdx = -1; /* Index of the start= constraint, or -1 if none */
- int wholelineIdx = -1; /* Index of the stop= constraint, or -1 if none */
- int nArg = 0; /* Number of arguments that completeFilter() expects */
- const struct sqlite3_index_constraint *pConstraint;
-
- (void)(tab); /* Unused parameter */
- 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 COMPLETION_COLUMN_PREFIX:
- prefixIdx = i;
- idxNum |= 1;
- break;
- case COMPLETION_COLUMN_WHOLELINE:
- wholelineIdx = i;
- idxNum |= 2;
- break;
- }
- }
- if( prefixIdx>=0 ){
- pIdxInfo->aConstraintUsage[prefixIdx].argvIndex = ++nArg;
- pIdxInfo->aConstraintUsage[prefixIdx].omit = 1;
- }
- if( wholelineIdx>=0 ){
- pIdxInfo->aConstraintUsage[wholelineIdx].argvIndex = ++nArg;
- pIdxInfo->aConstraintUsage[wholelineIdx].omit = 1;
- }
- pIdxInfo->idxNum = idxNum;
- pIdxInfo->estimatedCost = (double)5000 - 1000*nArg;
- pIdxInfo->estimatedRows = 500 - 100*nArg;
- return SQLITE_OK;
-}
-
-/*
-** This following structure defines all the methods for the
-** completion virtual table.
-*/
-static sqlite3_module completionModule = {
- 0, /* iVersion */
- 0, /* xCreate */
- completionConnect, /* xConnect */
- completionBestIndex, /* xBestIndex */
- completionDisconnect, /* xDisconnect */
- 0, /* xDestroy */
- completionOpen, /* xOpen - open a cursor */
- completionClose, /* xClose - close a cursor */
- completionFilter, /* xFilter - configure scan constraints */
- completionNext, /* xNext - advance a cursor */
- completionEof, /* xEof - check for end of scan */
- completionColumn, /* xColumn - read data */
- completionRowid, /* xRowid - read data */
- 0, /* xUpdate */
- 0, /* xBegin */
- 0, /* xSync */
- 0, /* xCommit */
- 0, /* xRollback */
- 0, /* xFindMethod */
- 0, /* xRename */
- 0, /* xSavepoint */
- 0, /* xRelease */
- 0 /* xRollbackTo */
-};
-
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
-int sqlite3CompletionVtabInit(sqlite3 *db){
- int rc = SQLITE_OK;
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- rc = sqlite3_create_module(db, "completion", &completionModule, 0);
-#endif
- return rc;
-}
-
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_completion_init(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pApi
-){
- int rc = SQLITE_OK;
- SQLITE_EXTENSION_INIT2(pApi);
- (void)(pzErrMsg); /* Unused parameter */
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- rc = sqlite3CompletionVtabInit(db);
-#endif
- return rc;
-}
-
-/************************* End ../ext/misc/completion.c ********************/
-
-#if defined(SQLITE_ENABLE_SESSION)
-/*
-** State information for a single open session
-*/
-typedef struct OpenSession OpenSession;
-struct OpenSession {
- char *zName; /* Symbolic name for this session */
- int nFilter; /* Number of xFilter rejection GLOB patterns */
- char **azFilter; /* Array of xFilter rejection GLOB patterns */
- sqlite3_session *p; /* The open session */
-};
-#endif
-
-/*
-** Shell output mode information from before ".explain on",
-** saved so that it can be restored by ".explain off"
-*/
-typedef struct SavedModeInfo SavedModeInfo;
-struct SavedModeInfo {
- int valid; /* Is there legit data in here? */
- int mode; /* Mode prior to ".explain on" */
- int showHeader; /* The ".header" setting prior to ".explain on" */
- int colWidth[100]; /* Column widths prior to ".explain on" */
-};
-
-/*
-** State information about the database connection is contained in an
-** instance of the following structure.
-*/
-typedef struct ShellState ShellState;
-struct ShellState {
- sqlite3 *db; /* The database */
- int autoExplain; /* Automatically turn on .explain mode */
- int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
- int statsOn; /* True to display memory stats before each finalize */
- int scanstatsOn; /* True to display scan stats before each finalize */
- int outCount; /* Revert to stdout when reaching zero */
- int cnt; /* Number of records displayed so far */
- FILE *out; /* Write results here */
- FILE *traceOut; /* Output for sqlite3_trace() */
- int nErr; /* Number of errors seen */
- int mode; /* An output mode setting */
- int cMode; /* temporary output mode for the current query */
- int normalMode; /* Output mode before ".explain on" */
- int writableSchema; /* True if PRAGMA writable_schema=ON */
- int showHeader; /* True to show column names in List or Column mode */
- int nCheck; /* Number of ".check" commands run */
- unsigned shellFlgs; /* Various flags */
- char *zDestTable; /* Name of destination table when MODE_Insert */
- char zTestcase[30]; /* Name of current test case */
- char colSeparator[20]; /* Column separator character for several modes */
- char rowSeparator[20]; /* Row separator character for MODE_Ascii */
- int colWidth[100]; /* Requested width of each column when in column mode*/
- int actualWidth[100]; /* Actual width of each column */
- char nullValue[20]; /* The text to print when a NULL comes back from
- ** the database */
- char outfile[FILENAME_MAX]; /* Filename for *out */
- const char *zDbFilename; /* name of the database file */
- char *zFreeOnClose; /* Filename to free when closing */
- const char *zVfs; /* Name of VFS to use */
- sqlite3_stmt *pStmt; /* Current statement if any. */
- FILE *pLog; /* Write log output here */
- int *aiIndent; /* Array of indents used in MODE_Explain */
- int nIndent; /* Size of array aiIndent[] */
- int iIndent; /* Index of current op in aiIndent[] */
-#if defined(SQLITE_ENABLE_SESSION)
- int nSession; /* Number of active sessions */
- OpenSession aSession[4]; /* Array of sessions. [0] is in focus. */
-#endif
-};
-
-/*
-** These are the allowed shellFlgs values
-*/
-#define SHFLG_Scratch 0x00000001 /* The --scratch option is used */
-#define SHFLG_Pagecache 0x00000002 /* The --pagecache option is used */
-#define SHFLG_Lookaside 0x00000004 /* Lookaside memory is used */
-#define SHFLG_Backslash 0x00000008 /* The --backslash option is used */
-#define SHFLG_PreserveRowid 0x00000010 /* .dump preserves rowid values */
-#define SHFLG_Newlines 0x00000020 /* .dump --newline flag */
-#define SHFLG_CountChanges 0x00000040 /* .changes setting */
-#define SHFLG_Echo 0x00000080 /* .echo or --echo setting */
-
-/*
-** Macros for testing and setting shellFlgs
-*/
-#define ShellHasFlag(P,X) (((P)->shellFlgs & (X))!=0)
-#define ShellSetFlag(P,X) ((P)->shellFlgs|=(X))
-#define ShellClearFlag(P,X) ((P)->shellFlgs&=(~(X)))
-
-/*
-** These are the allowed modes.
-*/
-#define MODE_Line 0 /* One column per line. Blank line between records */
-#define MODE_Column 1 /* One record per line in neat columns */
-#define MODE_List 2 /* One record per line with a separator */
-#define MODE_Semi 3 /* Same as MODE_List but append ";" to each line */
-#define MODE_Html 4 /* Generate an XHTML table */
-#define MODE_Insert 5 /* Generate SQL "insert" statements */
-#define MODE_Quote 6 /* Quote values as for SQL */
-#define MODE_Tcl 7 /* Generate ANSI-C or TCL quoted elements */
-#define MODE_Csv 8 /* Quote strings, numbers are plain */
-#define MODE_Explain 9 /* Like MODE_Column, but do not truncate data */
-#define MODE_Ascii 10 /* Use ASCII unit and record separators (0x1F/0x1E) */
-#define MODE_Pretty 11 /* Pretty-print schemas */
-
-static const char *modeDescr[] = {
- "line",
- "column",
- "list",
- "semi",
- "html",
- "insert",
- "quote",
- "tcl",
- "csv",
- "explain",
- "ascii",
- "prettyprint",
-};
-
-/*
-** These are the column/row/line separators used by the various
-** import/export modes.
-*/
-#define SEP_Column "|"
-#define SEP_Row "\n"
-#define SEP_Tab "\t"
-#define SEP_Space " "
-#define SEP_Comma ","
-#define SEP_CrLf "\r\n"
-#define SEP_Unit "\x1F"
-#define SEP_Record "\x1E"
-
-/*
-** Number of elements in an array
-*/
-#define ArraySize(X) (int)(sizeof(X)/sizeof(X[0]))
-
-/*
-** A callback for the sqlite3_log() interface.
-*/
-static void shellLog(void *pArg, int iErrCode, const char *zMsg){
- ShellState *p = (ShellState*)pArg;
- if( p->pLog==0 ) return;
- utf8_printf(p->pLog, "(%d) %s\n", iErrCode, zMsg);
- fflush(p->pLog);
-}
-
-/*
-** Output the given string as a hex-encoded blob (eg. X'1234' )
-*/
-static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){
- int i;
- char *zBlob = (char *)pBlob;
- raw_printf(out,"X'");
- for(i=0; i<nBlob; i++){ raw_printf(out,"%02x",zBlob[i]&0xff); }
- raw_printf(out,"'");
-}
-
-/*
-** Find a string that is not found anywhere in z[]. Return a pointer
-** to that string.
-**
-** Try to use zA and zB first. If both of those are already found in z[]
-** then make up some string and store it in the buffer zBuf.
-*/
-static const char *unused_string(
- const char *z, /* Result must not appear anywhere in z */
- const char *zA, const char *zB, /* Try these first */
- char *zBuf /* Space to store a generated string */
-){
- unsigned i = 0;
- if( strstr(z, zA)==0 ) return zA;
- if( strstr(z, zB)==0 ) return zB;
- do{
- sqlite3_snprintf(20,zBuf,"(%s%u)", zA, i++);
- }while( strstr(z,zBuf)!=0 );
- return zBuf;
-}
-
-/*
-** Output the given string as a quoted string using SQL quoting conventions.
-**
-** See also: output_quoted_escaped_string()
-*/
-static void output_quoted_string(FILE *out, const char *z){
- int i;
- char c;
- setBinaryMode(out, 1);
- for(i=0; (c = z[i])!=0 && c!='\''; i++){}
- if( c==0 ){
- utf8_printf(out,"'%s'",z);
- }else{
- raw_printf(out, "'");
- while( *z ){
- for(i=0; (c = z[i])!=0 && c!='\''; i++){}
- if( c=='\'' ) i++;
- if( i ){
- utf8_printf(out, "%.*s", i, z);
- z += i;
- }
- if( c=='\'' ){
- raw_printf(out, "'");
- continue;
- }
- if( c==0 ){
- break;
- }
- z++;
- }
- raw_printf(out, "'");
- }
- setTextMode(out, 1);
-}
-
-/*
-** Output the given string as a quoted string using SQL quoting conventions.
-** Additionallly , escape the "\n" and "\r" characters so that they do not
-** get corrupted by end-of-line translation facilities in some operating
-** systems.
-**
-** This is like output_quoted_string() but with the addition of the \r\n
-** escape mechanism.
-*/
-static void output_quoted_escaped_string(FILE *out, const char *z){
- int i;
- char c;
- setBinaryMode(out, 1);
- for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){}
- if( c==0 ){
- utf8_printf(out,"'%s'",z);
- }else{
- const char *zNL = 0;
- const char *zCR = 0;
- int nNL = 0;
- int nCR = 0;
- char zBuf1[20], zBuf2[20];
- for(i=0; z[i]; i++){
- if( z[i]=='\n' ) nNL++;
- if( z[i]=='\r' ) nCR++;
- }
- if( nNL ){
- raw_printf(out, "replace(");
- zNL = unused_string(z, "\\n", "\\012", zBuf1);
- }
- if( nCR ){
- raw_printf(out, "replace(");
- zCR = unused_string(z, "\\r", "\\015", zBuf2);
- }
- raw_printf(out, "'");
- while( *z ){
- for(i=0; (c = z[i])!=0 && c!='\n' && c!='\r' && c!='\''; i++){}
- if( c=='\'' ) i++;
- if( i ){
- utf8_printf(out, "%.*s", i, z);
- z += i;
- }
- if( c=='\'' ){
- raw_printf(out, "'");
- continue;
- }
- if( c==0 ){
- break;
- }
- z++;
- if( c=='\n' ){
- raw_printf(out, "%s", zNL);
- continue;
- }
- raw_printf(out, "%s", zCR);
- }
- raw_printf(out, "'");
- if( nCR ){
- raw_printf(out, ",'%s',char(13))", zCR);
- }
- if( nNL ){
- raw_printf(out, ",'%s',char(10))", zNL);
- }
- }
- setTextMode(out, 1);
-}
-
-/*
-** Output the given string as a quoted according to C or TCL quoting rules.
-*/
-static void output_c_string(FILE *out, const char *z){
- unsigned int c;
- fputc('"', out);
- while( (c = *(z++))!=0 ){
- if( c=='\\' ){
- fputc(c, out);
- fputc(c, out);
- }else if( c=='"' ){
- fputc('\\', out);
- fputc('"', out);
- }else if( c=='\t' ){
- fputc('\\', out);
- fputc('t', out);
- }else if( c=='\n' ){
- fputc('\\', out);
- fputc('n', out);
- }else if( c=='\r' ){
- fputc('\\', out);
- fputc('r', out);
- }else if( !isprint(c&0xff) ){
- raw_printf(out, "\\%03o", c&0xff);
- }else{
- fputc(c, out);
- }
- }
- fputc('"', out);
-}
-
-/*
-** Output the given string with characters that are special to
-** HTML escaped.
-*/
-static void output_html_string(FILE *out, const char *z){
- int i;
- if( z==0 ) z = "";
- while( *z ){
- for(i=0; z[i]
- && z[i]!='<'
- && z[i]!='&'
- && z[i]!='>'
- && z[i]!='\"'
- && z[i]!='\'';
- i++){}
- if( i>0 ){
- utf8_printf(out,"%.*s",i,z);
- }
- if( z[i]=='<' ){
- raw_printf(out,"&lt;");
- }else if( z[i]=='&' ){
- raw_printf(out,"&amp;");
- }else if( z[i]=='>' ){
- raw_printf(out,"&gt;");
- }else if( z[i]=='\"' ){
- raw_printf(out,"&quot;");
- }else if( z[i]=='\'' ){
- raw_printf(out,"&#39;");
- }else{
- break;
- }
- z += i + 1;
- }
-}
-
-/*
-** If a field contains any character identified by a 1 in the following
-** array, then the string must be quoted for CSV.
-*/
-static const char needCsvQuote[] = {
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-};
-
-/*
-** Output a single term of CSV. Actually, p->colSeparator is used for
-** the separator, which may or may not be a comma. p->nullValue is
-** the null value. Strings are quoted if necessary. The separator
-** is only issued if bSep is true.
-*/
-static void output_csv(ShellState *p, const char *z, int bSep){
- FILE *out = p->out;
- if( z==0 ){
- utf8_printf(out,"%s",p->nullValue);
- }else{
- int i;
- int nSep = strlen30(p->colSeparator);
- for(i=0; z[i]; i++){
- if( needCsvQuote[((unsigned char*)z)[i]]
- || (z[i]==p->colSeparator[0] &&
- (nSep==1 || memcmp(z, p->colSeparator, nSep)==0)) ){
- i = 0;
- break;
- }
- }
- if( i==0 ){
- putc('"', out);
- for(i=0; z[i]; i++){
- if( z[i]=='"' ) putc('"', out);
- putc(z[i], out);
- }
- putc('"', out);
- }else{
- utf8_printf(out, "%s", z);
- }
- }
- if( bSep ){
- utf8_printf(p->out, "%s", p->colSeparator);
- }
-}
-
-#ifdef SIGINT
-/*
-** This routine runs when the user presses Ctrl-C
-*/
-static void interrupt_handler(int NotUsed){
- UNUSED_PARAMETER(NotUsed);
- seenInterrupt++;
- if( seenInterrupt>2 ) exit(1);
- if( globalDb ) sqlite3_interrupt(globalDb);
-}
-#endif
-
-#ifndef SQLITE_OMIT_AUTHORIZATION
-/*
-** When the ".auth ON" is set, the following authorizer callback is
-** invoked. It always returns SQLITE_OK.
-*/
-static int shellAuth(
- void *pClientData,
- int op,
- const char *zA1,
- const char *zA2,
- const char *zA3,
- const char *zA4
-){
- ShellState *p = (ShellState*)pClientData;
- static const char *azAction[] = { 0,
- "CREATE_INDEX", "CREATE_TABLE", "CREATE_TEMP_INDEX",
- "CREATE_TEMP_TABLE", "CREATE_TEMP_TRIGGER", "CREATE_TEMP_VIEW",
- "CREATE_TRIGGER", "CREATE_VIEW", "DELETE",
- "DROP_INDEX", "DROP_TABLE", "DROP_TEMP_INDEX",
- "DROP_TEMP_TABLE", "DROP_TEMP_TRIGGER", "DROP_TEMP_VIEW",
- "DROP_TRIGGER", "DROP_VIEW", "INSERT",
- "PRAGMA", "READ", "SELECT",
- "TRANSACTION", "UPDATE", "ATTACH",
- "DETACH", "ALTER_TABLE", "REINDEX",
- "ANALYZE", "CREATE_VTABLE", "DROP_VTABLE",
- "FUNCTION", "SAVEPOINT", "RECURSIVE"
- };
- int i;
- const char *az[4];
- az[0] = zA1;
- az[1] = zA2;
- az[2] = zA3;
- az[3] = zA4;
- utf8_printf(p->out, "authorizer: %s", azAction[op]);
- for(i=0; i<4; i++){
- raw_printf(p->out, " ");
- if( az[i] ){
- output_c_string(p->out, az[i]);
- }else{
- raw_printf(p->out, "NULL");
- }
- }
- raw_printf(p->out, "\n");
- return SQLITE_OK;
-}
-#endif
-
-/*
-** Print a schema statement. Part of MODE_Semi and MODE_Pretty output.
-**
-** This routine converts some CREATE TABLE statements for shadow tables
-** in FTS3/4/5 into CREATE TABLE IF NOT EXISTS statements.
-*/
-static void printSchemaLine(FILE *out, const char *z, const char *zTail){
- if( sqlite3_strglob("CREATE TABLE ['\"]*", z)==0 ){
- utf8_printf(out, "CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail);
- }else{
- utf8_printf(out, "%s%s", z, zTail);
- }
-}
-static void printSchemaLineN(FILE *out, char *z, int n, const char *zTail){
- char c = z[n];
- z[n] = 0;
- printSchemaLine(out, z, zTail);
- z[n] = c;
-}
-
-/*
-** This is the callback routine that the shell
-** invokes for each row of a query result.
-*/
-static int shell_callback(
- void *pArg,
- int nArg, /* Number of result columns */
- char **azArg, /* Text of each result column */
- char **azCol, /* Column names */
- int *aiType /* Column types */
-){
- int i;
- ShellState *p = (ShellState*)pArg;
-
- switch( p->cMode ){
- case MODE_Line: {
- int w = 5;
- if( azArg==0 ) break;
- for(i=0; i<nArg; i++){
- int len = strlen30(azCol[i] ? azCol[i] : "");
- if( len>w ) w = len;
- }
- if( p->cnt++>0 ) utf8_printf(p->out, "%s", p->rowSeparator);
- for(i=0; i<nArg; i++){
- utf8_printf(p->out,"%*s = %s%s", w, azCol[i],
- azArg[i] ? azArg[i] : p->nullValue, p->rowSeparator);
- }
- break;
- }
- case MODE_Explain:
- case MODE_Column: {
- static const int aExplainWidths[] = {4, 13, 4, 4, 4, 13, 2, 13};
- const int *colWidth;
- int showHdr;
- char *rowSep;
- if( p->cMode==MODE_Column ){
- colWidth = p->colWidth;
- showHdr = p->showHeader;
- rowSep = p->rowSeparator;
- }else{
- colWidth = aExplainWidths;
- showHdr = 1;
- rowSep = SEP_Row;
- }
- if( p->cnt++==0 ){
- for(i=0; i<nArg; i++){
- int w, n;
- if( i<ArraySize(p->colWidth) ){
- w = colWidth[i];
- }else{
- w = 0;
- }
- if( w==0 ){
- w = strlenChar(azCol[i] ? azCol[i] : "");
- if( w<10 ) w = 10;
- n = strlenChar(azArg && azArg[i] ? azArg[i] : p->nullValue);
- if( w<n ) w = n;
- }
- if( i<ArraySize(p->actualWidth) ){
- p->actualWidth[i] = w;
- }
- if( showHdr ){
- utf8_width_print(p->out, w, azCol[i]);
- utf8_printf(p->out, "%s", i==nArg-1 ? rowSep : " ");
- }
- }
- if( showHdr ){
- for(i=0; i<nArg; i++){
- int w;
- if( i<ArraySize(p->actualWidth) ){
- w = p->actualWidth[i];
- if( w<0 ) w = -w;
- }else{
- w = 10;
- }
- utf8_printf(p->out,"%-*.*s%s",w,w,
- "----------------------------------------------------------"
- "----------------------------------------------------------",
- i==nArg-1 ? rowSep : " ");
- }
- }
- }
- if( azArg==0 ) break;
- for(i=0; i<nArg; i++){
- int w;
- if( i<ArraySize(p->actualWidth) ){
- w = p->actualWidth[i];
- }else{
- w = 10;
- }
- if( p->cMode==MODE_Explain && azArg[i] && strlenChar(azArg[i])>w ){
- w = strlenChar(azArg[i]);
- }
- if( i==1 && p->aiIndent && p->pStmt ){
- if( p->iIndent<p->nIndent ){
- utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], "");
- }
- p->iIndent++;
- }
- utf8_width_print(p->out, w, azArg[i] ? azArg[i] : p->nullValue);
- utf8_printf(p->out, "%s", i==nArg-1 ? rowSep : " ");
- }
- break;
- }
- case MODE_Semi: { /* .schema and .fullschema output */
- printSchemaLine(p->out, azArg[0], ";\n");
- break;
- }
- case MODE_Pretty: { /* .schema and .fullschema with --indent */
- char *z;
- int j;
- int nParen = 0;
- char cEnd = 0;
- char c;
- int nLine = 0;
- assert( nArg==1 );
- if( azArg[0]==0 ) break;
- if( sqlite3_strlike("CREATE VIEW%", azArg[0], 0)==0
- || sqlite3_strlike("CREATE TRIG%", azArg[0], 0)==0
- ){
- utf8_printf(p->out, "%s;\n", azArg[0]);
- break;
- }
- z = sqlite3_mprintf("%s", azArg[0]);
- j = 0;
- for(i=0; IsSpace(z[i]); i++){}
- for(; (c = z[i])!=0; i++){
- if( IsSpace(c) ){
- if( IsSpace(z[j-1]) || z[j-1]=='(' ) continue;
- }else if( (c=='(' || c==')') && j>0 && IsSpace(z[j-1]) ){
- j--;
- }
- z[j++] = c;
- }
- while( j>0 && IsSpace(z[j-1]) ){ j--; }
- z[j] = 0;
- if( strlen30(z)>=79 ){
- for(i=j=0; (c = z[i])!=0; i++){
- if( c==cEnd ){
- cEnd = 0;
- }else if( c=='"' || c=='\'' || c=='`' ){
- cEnd = c;
- }else if( c=='[' ){
- cEnd = ']';
- }else if( c=='(' ){
- nParen++;
- }else if( c==')' ){
- nParen--;
- if( nLine>0 && nParen==0 && j>0 ){
- printSchemaLineN(p->out, z, j, "\n");
- j = 0;
- }
- }
- z[j++] = c;
- if( nParen==1 && (c=='(' || c==',' || c=='\n') ){
- if( c=='\n' ) j--;
- printSchemaLineN(p->out, z, j, "\n ");
- j = 0;
- nLine++;
- while( IsSpace(z[i+1]) ){ i++; }
- }
- }
- z[j] = 0;
- }
- printSchemaLine(p->out, z, ";\n");
- sqlite3_free(z);
- break;
- }
- case MODE_List: {
- if( p->cnt++==0 && p->showHeader ){
- for(i=0; i<nArg; i++){
- utf8_printf(p->out,"%s%s",azCol[i],
- i==nArg-1 ? p->rowSeparator : p->colSeparator);
- }
- }
- if( azArg==0 ) break;
- for(i=0; i<nArg; i++){
- char *z = azArg[i];
- if( z==0 ) z = p->nullValue;
- utf8_printf(p->out, "%s", z);
- if( i<nArg-1 ){
- utf8_printf(p->out, "%s", p->colSeparator);
- }else{
- utf8_printf(p->out, "%s", p->rowSeparator);
- }
- }
- break;
- }
- case MODE_Html: {
- if( p->cnt++==0 && p->showHeader ){
- raw_printf(p->out,"<TR>");
- for(i=0; i<nArg; i++){
- raw_printf(p->out,"<TH>");
- output_html_string(p->out, azCol[i]);
- raw_printf(p->out,"</TH>\n");
- }
- raw_printf(p->out,"</TR>\n");
- }
- if( azArg==0 ) break;
- raw_printf(p->out,"<TR>");
- for(i=0; i<nArg; i++){
- raw_printf(p->out,"<TD>");
- output_html_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
- raw_printf(p->out,"</TD>\n");
- }
- raw_printf(p->out,"</TR>\n");
- break;
- }
- case MODE_Tcl: {
- if( p->cnt++==0 && p->showHeader ){
- for(i=0; i<nArg; i++){
- output_c_string(p->out,azCol[i] ? azCol[i] : "");
- if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
- }
- utf8_printf(p->out, "%s", p->rowSeparator);
- }
- if( azArg==0 ) break;
- for(i=0; i<nArg; i++){
- output_c_string(p->out, azArg[i] ? azArg[i] : p->nullValue);
- if(i<nArg-1) utf8_printf(p->out, "%s", p->colSeparator);
- }
- utf8_printf(p->out, "%s", p->rowSeparator);
- break;
- }
- case MODE_Csv: {
- setBinaryMode(p->out, 1);
- if( p->cnt++==0 && p->showHeader ){
- for(i=0; i<nArg; i++){
- output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
- }
- utf8_printf(p->out, "%s", p->rowSeparator);
- }
- if( nArg>0 ){
- for(i=0; i<nArg; i++){
- output_csv(p, azArg[i], i<nArg-1);
- }
- utf8_printf(p->out, "%s", p->rowSeparator);
- }
- setTextMode(p->out, 1);
- break;
- }
- case MODE_Insert: {
- if( azArg==0 ) break;
- utf8_printf(p->out,"INSERT INTO %s",p->zDestTable);
- if( p->showHeader ){
- raw_printf(p->out,"(");
- for(i=0; i<nArg; i++){
- if( i>0 ) raw_printf(p->out, ",");
- if( quoteChar(azCol[i]) ){
- char *z = sqlite3_mprintf("\"%w\"", azCol[i]);
- utf8_printf(p->out, "%s", z);
- sqlite3_free(z);
- }else{
- raw_printf(p->out, "%s", azCol[i]);
- }
- }
- raw_printf(p->out,")");
- }
- p->cnt++;
- for(i=0; i<nArg; i++){
- raw_printf(p->out, i>0 ? "," : " VALUES(");
- if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
- utf8_printf(p->out,"NULL");
- }else if( aiType && aiType[i]==SQLITE_TEXT ){
- if( ShellHasFlag(p, SHFLG_Newlines) ){
- output_quoted_string(p->out, azArg[i]);
- }else{
- output_quoted_escaped_string(p->out, azArg[i]);
- }
- }else if( aiType && aiType[i]==SQLITE_INTEGER ){
- utf8_printf(p->out,"%s", azArg[i]);
- }else if( aiType && aiType[i]==SQLITE_FLOAT ){
- char z[50];
- double r = sqlite3_column_double(p->pStmt, i);
- sqlite3_snprintf(50,z,"%!.20g", r);
- raw_printf(p->out, "%s", z);
- }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
- const void *pBlob = sqlite3_column_blob(p->pStmt, i);
- int nBlob = sqlite3_column_bytes(p->pStmt, i);
- output_hex_blob(p->out, pBlob, nBlob);
- }else if( isNumber(azArg[i], 0) ){
- utf8_printf(p->out,"%s", azArg[i]);
- }else if( ShellHasFlag(p, SHFLG_Newlines) ){
- output_quoted_string(p->out, azArg[i]);
- }else{
- output_quoted_escaped_string(p->out, azArg[i]);
- }
- }
- raw_printf(p->out,");\n");
- break;
- }
- case MODE_Quote: {
- if( azArg==0 ) break;
- if( p->cnt==0 && p->showHeader ){
- for(i=0; i<nArg; i++){
- if( i>0 ) raw_printf(p->out, ",");
- output_quoted_string(p->out, azCol[i]);
- }
- raw_printf(p->out,"\n");
- }
- p->cnt++;
- for(i=0; i<nArg; i++){
- if( i>0 ) raw_printf(p->out, ",");
- if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
- utf8_printf(p->out,"NULL");
- }else if( aiType && aiType[i]==SQLITE_TEXT ){
- output_quoted_string(p->out, azArg[i]);
- }else if( aiType && aiType[i]==SQLITE_INTEGER ){
- utf8_printf(p->out,"%s", azArg[i]);
- }else if( aiType && aiType[i]==SQLITE_FLOAT ){
- char z[50];
- double r = sqlite3_column_double(p->pStmt, i);
- sqlite3_snprintf(50,z,"%!.20g", r);
- raw_printf(p->out, "%s", z);
- }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
- const void *pBlob = sqlite3_column_blob(p->pStmt, i);
- int nBlob = sqlite3_column_bytes(p->pStmt, i);
- output_hex_blob(p->out, pBlob, nBlob);
- }else if( isNumber(azArg[i], 0) ){
- utf8_printf(p->out,"%s", azArg[i]);
- }else{
- output_quoted_string(p->out, azArg[i]);
- }
- }
- raw_printf(p->out,"\n");
- break;
- }
- case MODE_Ascii: {
- if( p->cnt++==0 && p->showHeader ){
- for(i=0; i<nArg; i++){
- if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
- utf8_printf(p->out,"%s",azCol[i] ? azCol[i] : "");
- }
- utf8_printf(p->out, "%s", p->rowSeparator);
- }
- if( azArg==0 ) break;
- for(i=0; i<nArg; i++){
- if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
- utf8_printf(p->out,"%s",azArg[i] ? azArg[i] : p->nullValue);
- }
- utf8_printf(p->out, "%s", p->rowSeparator);
- break;
- }
- }
- return 0;
-}
-
-/*
-** This is the callback routine that the SQLite library
-** invokes for each row of a query result.
-*/
-static int callback(void *pArg, int nArg, char **azArg, char **azCol){
- /* since we don't have type info, call the shell_callback with a NULL value */
- return shell_callback(pArg, nArg, azArg, azCol, NULL);
-}
-
-/*
-** This is the callback routine from sqlite3_exec() that appends all
-** output onto the end of a ShellText object.
-*/
-static int captureOutputCallback(void *pArg, int nArg, char **azArg, char **az){
- ShellText *p = (ShellText*)pArg;
- int i;
- UNUSED_PARAMETER(az);
- if( p->n ) appendText(p, "|", 0);
- for(i=0; i<nArg; i++){
- if( i ) appendText(p, ",", 0);
- if( azArg[i] ) appendText(p, azArg[i], 0);
- }
- return 0;
-}
-
-/*
-** Generate an appropriate SELFTEST table in the main database.
-*/
-static void createSelftestTable(ShellState *p){
- char *zErrMsg = 0;
- sqlite3_exec(p->db,
- "SAVEPOINT selftest_init;\n"
- "CREATE TABLE IF NOT EXISTS selftest(\n"
- " tno INTEGER PRIMARY KEY,\n" /* Test number */
- " op TEXT,\n" /* Operator: memo run */
- " cmd TEXT,\n" /* Command text */
- " ans TEXT\n" /* Desired answer */
- ");"
- "CREATE TEMP TABLE [_shell$self](op,cmd,ans);\n"
- "INSERT INTO [_shell$self](rowid,op,cmd)\n"
- " VALUES(coalesce((SELECT (max(tno)+100)/10 FROM selftest),10),\n"
- " 'memo','Tests generated by --init');\n"
- "INSERT INTO [_shell$self]\n"
- " SELECT 'run',\n"
- " 'SELECT hex(sha3_query(''SELECT type,name,tbl_name,sql "
- "FROM sqlite_master ORDER BY 2'',224))',\n"
- " hex(sha3_query('SELECT type,name,tbl_name,sql "
- "FROM sqlite_master ORDER BY 2',224));\n"
- "INSERT INTO [_shell$self]\n"
- " SELECT 'run',"
- " 'SELECT hex(sha3_query(''SELECT * FROM \"' ||"
- " printf('%w',name) || '\" NOT INDEXED'',224))',\n"
- " hex(sha3_query(printf('SELECT * FROM \"%w\" NOT INDEXED',name),224))\n"
- " FROM (\n"
- " SELECT name FROM sqlite_master\n"
- " WHERE type='table'\n"
- " AND name<>'selftest'\n"
- " AND coalesce(rootpage,0)>0\n"
- " )\n"
- " ORDER BY name;\n"
- "INSERT INTO [_shell$self]\n"
- " VALUES('run','PRAGMA integrity_check','ok');\n"
- "INSERT INTO selftest(tno,op,cmd,ans)"
- " SELECT rowid*10,op,cmd,ans FROM [_shell$self];\n"
- "DROP TABLE [_shell$self];"
- ,0,0,&zErrMsg);
- if( zErrMsg ){
- utf8_printf(stderr, "SELFTEST initialization failure: %s\n", zErrMsg);
- sqlite3_free(zErrMsg);
- }
- sqlite3_exec(p->db, "RELEASE selftest_init",0,0,0);
-}
-
-
-/*
-** Set the destination table field of the ShellState structure to
-** the name of the table given. Escape any quote characters in the
-** table name.
-*/
-static void set_table_name(ShellState *p, const char *zName){
- int i, n;
- int cQuote;
- char *z;
-
- if( p->zDestTable ){
- free(p->zDestTable);
- p->zDestTable = 0;
- }
- if( zName==0 ) return;
- cQuote = quoteChar(zName);
- n = strlen30(zName);
- if( cQuote ) n += n+2;
- z = p->zDestTable = malloc( n+1 );
- if( z==0 ){
- raw_printf(stderr,"Error: out of memory\n");
- exit(1);
- }
- n = 0;
- if( cQuote ) z[n++] = cQuote;
- for(i=0; zName[i]; i++){
- z[n++] = zName[i];
- if( zName[i]==cQuote ) z[n++] = cQuote;
- }
- if( cQuote ) z[n++] = cQuote;
- z[n] = 0;
-}
-
-
-/*
-** Execute a query statement that will generate SQL output. Print
-** the result columns, comma-separated, on a line and then add a
-** semicolon terminator to the end of that line.
-**
-** If the number of columns is 1 and that column contains text "--"
-** then write the semicolon on a separate line. That way, if a
-** "--" comment occurs at the end of the statement, the comment
-** won't consume the semicolon terminator.
-*/
-static int run_table_dump_query(
- ShellState *p, /* Query context */
- const char *zSelect, /* SELECT statement to extract content */
- const char *zFirstRow /* Print before first row, if not NULL */
-){
- sqlite3_stmt *pSelect;
- int rc;
- int nResult;
- int i;
- const char *z;
- rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0);
- if( rc!=SQLITE_OK || !pSelect ){
- utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
- sqlite3_errmsg(p->db));
- if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
- return rc;
- }
- rc = sqlite3_step(pSelect);
- nResult = sqlite3_column_count(pSelect);
- while( rc==SQLITE_ROW ){
- if( zFirstRow ){
- utf8_printf(p->out, "%s", zFirstRow);
- zFirstRow = 0;
- }
- z = (const char*)sqlite3_column_text(pSelect, 0);
- utf8_printf(p->out, "%s", z);
- for(i=1; i<nResult; i++){
- utf8_printf(p->out, ",%s", sqlite3_column_text(pSelect, i));
- }
- if( z==0 ) z = "";
- while( z[0] && (z[0]!='-' || z[1]!='-') ) z++;
- if( z[0] ){
- raw_printf(p->out, "\n;\n");
- }else{
- raw_printf(p->out, ";\n");
- }
- rc = sqlite3_step(pSelect);
- }
- rc = sqlite3_finalize(pSelect);
- if( rc!=SQLITE_OK ){
- utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
- sqlite3_errmsg(p->db));
- if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
- }
- return rc;
-}
-
-/*
-** Allocate space and save off current error string.
-*/
-static char *save_err_msg(
- sqlite3 *db /* Database to query */
-){
- int nErrMsg = 1+strlen30(sqlite3_errmsg(db));
- char *zErrMsg = sqlite3_malloc64(nErrMsg);
- if( zErrMsg ){
- memcpy(zErrMsg, sqlite3_errmsg(db), nErrMsg);
- }
- return zErrMsg;
-}
-
-#ifdef __linux__
-/*
-** Attempt to display I/O stats on Linux using /proc/PID/io
-*/
-static void displayLinuxIoStats(FILE *out){
- FILE *in;
- char z[200];
- sqlite3_snprintf(sizeof(z), z, "/proc/%d/io", getpid());
- in = fopen(z, "rb");
- if( in==0 ) return;
- while( fgets(z, sizeof(z), in)!=0 ){
- static const struct {
- const char *zPattern;
- const char *zDesc;
- } aTrans[] = {
- { "rchar: ", "Bytes received by read():" },
- { "wchar: ", "Bytes sent to write():" },
- { "syscr: ", "Read() system calls:" },
- { "syscw: ", "Write() system calls:" },
- { "read_bytes: ", "Bytes read from storage:" },
- { "write_bytes: ", "Bytes written to storage:" },
- { "cancelled_write_bytes: ", "Cancelled write bytes:" },
- };
- int i;
- for(i=0; i<ArraySize(aTrans); i++){
- int n = (int)strlen(aTrans[i].zPattern);
- if( strncmp(aTrans[i].zPattern, z, n)==0 ){
- utf8_printf(out, "%-36s %s", aTrans[i].zDesc, &z[n]);
- break;
- }
- }
- }
- fclose(in);
-}
-#endif
-
-/*
-** Display a single line of status using 64-bit values.
-*/
-static void displayStatLine(
- ShellState *p, /* The shell context */
- char *zLabel, /* Label for this one line */
- char *zFormat, /* Format for the result */
- int iStatusCtrl, /* Which status to display */
- int bReset /* True to reset the stats */
-){
- sqlite3_int64 iCur = -1;
- sqlite3_int64 iHiwtr = -1;
- int i, nPercent;
- char zLine[200];
- sqlite3_status64(iStatusCtrl, &iCur, &iHiwtr, bReset);
- for(i=0, nPercent=0; zFormat[i]; i++){
- if( zFormat[i]=='%' ) nPercent++;
- }
- if( nPercent>1 ){
- sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iCur, iHiwtr);
- }else{
- sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iHiwtr);
- }
- raw_printf(p->out, "%-36s %s\n", zLabel, zLine);
-}
-
-/*
-** Display memory stats.
-*/
-static int display_stats(
- sqlite3 *db, /* Database to query */
- ShellState *pArg, /* Pointer to ShellState */
- int bReset /* True to reset the stats */
-){
- int iCur;
- int iHiwtr;
-
- if( pArg && pArg->out ){
- displayStatLine(pArg, "Memory Used:",
- "%lld (max %lld) bytes", SQLITE_STATUS_MEMORY_USED, bReset);
- displayStatLine(pArg, "Number of Outstanding Allocations:",
- "%lld (max %lld)", SQLITE_STATUS_MALLOC_COUNT, bReset);
- if( pArg->shellFlgs & SHFLG_Pagecache ){
- displayStatLine(pArg, "Number of Pcache Pages Used:",
- "%lld (max %lld) pages", SQLITE_STATUS_PAGECACHE_USED, bReset);
- }
- displayStatLine(pArg, "Number of Pcache Overflow Bytes:",
- "%lld (max %lld) bytes", SQLITE_STATUS_PAGECACHE_OVERFLOW, bReset);
- if( pArg->shellFlgs & SHFLG_Scratch ){
- displayStatLine(pArg, "Number of Scratch Allocations Used:",
- "%lld (max %lld)", SQLITE_STATUS_SCRATCH_USED, bReset);
- }
- displayStatLine(pArg, "Number of Scratch Overflow Bytes:",
- "%lld (max %lld) bytes", SQLITE_STATUS_SCRATCH_OVERFLOW, bReset);
- displayStatLine(pArg, "Largest Allocation:",
- "%lld bytes", SQLITE_STATUS_MALLOC_SIZE, bReset);
- displayStatLine(pArg, "Largest Pcache Allocation:",
- "%lld bytes", SQLITE_STATUS_PAGECACHE_SIZE, bReset);
- displayStatLine(pArg, "Largest Scratch Allocation:",
- "%lld bytes", SQLITE_STATUS_SCRATCH_SIZE, bReset);
-#ifdef YYTRACKMAXSTACKDEPTH
- displayStatLine(pArg, "Deepest Parser Stack:",
- "%lld (max %lld)", SQLITE_STATUS_PARSER_STACK, bReset);
-#endif
- }
-
- if( pArg && pArg->out && db ){
- if( pArg->shellFlgs & SHFLG_Lookaside ){
- iHiwtr = iCur = -1;
- sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED,
- &iCur, &iHiwtr, bReset);
- raw_printf(pArg->out,
- "Lookaside Slots Used: %d (max %d)\n",
- iCur, iHiwtr);
- sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_HIT,
- &iCur, &iHiwtr, bReset);
- raw_printf(pArg->out, "Successful lookaside attempts: %d\n",
- iHiwtr);
- sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE,
- &iCur, &iHiwtr, bReset);
- raw_printf(pArg->out, "Lookaside failures due to size: %d\n",
- iHiwtr);
- sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL,
- &iCur, &iHiwtr, bReset);
- raw_printf(pArg->out, "Lookaside failures due to OOM: %d\n",
- iHiwtr);
- }
- iHiwtr = iCur = -1;
- sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset);
- raw_printf(pArg->out, "Pager Heap Usage: %d bytes\n",
- iCur);
- iHiwtr = iCur = -1;
- sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_HIT, &iCur, &iHiwtr, 1);
- raw_printf(pArg->out, "Page cache hits: %d\n", iCur);
- iHiwtr = iCur = -1;
- sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_MISS, &iCur, &iHiwtr, 1);
- raw_printf(pArg->out, "Page cache misses: %d\n", iCur);
- iHiwtr = iCur = -1;
- sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
- raw_printf(pArg->out, "Page cache writes: %d\n", iCur);
- iHiwtr = iCur = -1;
- sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
- raw_printf(pArg->out, "Schema Heap Usage: %d bytes\n",
- iCur);
- iHiwtr = iCur = -1;
- sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
- raw_printf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n",
- iCur);
- }
-
- if( pArg && pArg->out && db && pArg->pStmt ){
- iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP,
- bReset);
- raw_printf(pArg->out, "Fullscan Steps: %d\n", iCur);
- iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
- raw_printf(pArg->out, "Sort Operations: %d\n", iCur);
- iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset);
- raw_printf(pArg->out, "Autoindex Inserts: %d\n", iCur);
- iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
- raw_printf(pArg->out, "Virtual Machine Steps: %d\n", iCur);
- }
-
-#ifdef __linux__
- displayLinuxIoStats(pArg->out);
-#endif
-
- /* Do not remove this machine readable comment: extra-stats-output-here */
-
- return 0;
-}
-
-/*
-** Display scan stats.
-*/
-static void display_scanstats(
- sqlite3 *db, /* Database to query */
- ShellState *pArg /* Pointer to ShellState */
-){
-#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
- UNUSED_PARAMETER(db);
- UNUSED_PARAMETER(pArg);
-#else
- int i, k, n, mx;
- raw_printf(pArg->out, "-------- scanstats --------\n");
- mx = 0;
- for(k=0; k<=mx; k++){
- double rEstLoop = 1.0;
- for(i=n=0; 1; i++){
- sqlite3_stmt *p = pArg->pStmt;
- sqlite3_int64 nLoop, nVisit;
- double rEst;
- int iSid;
- const char *zExplain;
- if( sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop) ){
- break;
- }
- sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_SELECTID, (void*)&iSid);
- if( iSid>mx ) mx = iSid;
- if( iSid!=k ) continue;
- if( n==0 ){
- rEstLoop = (double)nLoop;
- if( k>0 ) raw_printf(pArg->out, "-------- subquery %d -------\n", k);
- }
- n++;
- sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
- sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EST, (void*)&rEst);
- sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
- utf8_printf(pArg->out, "Loop %2d: %s\n", n, zExplain);
- rEstLoop *= rEst;
- raw_printf(pArg->out,
- " nLoop=%-8lld nRow=%-8lld estRow=%-8lld estRow/Loop=%-8g\n",
- nLoop, nVisit, (sqlite3_int64)(rEstLoop+0.5), rEst
- );
- }
- }
- raw_printf(pArg->out, "---------------------------\n");
-#endif
-}
-
-/*
-** Parameter azArray points to a zero-terminated array of strings. zStr
-** points to a single nul-terminated string. Return non-zero if zStr
-** is equal, according to strcmp(), to any of the strings in the array.
-** Otherwise, return zero.
-*/
-static int str_in_array(const char *zStr, const char **azArray){
- int i;
- for(i=0; azArray[i]; i++){
- if( 0==strcmp(zStr, azArray[i]) ) return 1;
- }
- return 0;
-}
-
-/*
-** If compiled statement pSql appears to be an EXPLAIN statement, allocate
-** and populate the ShellState.aiIndent[] array with the number of
-** spaces each opcode should be indented before it is output.
-**
-** The indenting rules are:
-**
-** * For each "Next", "Prev", "VNext" or "VPrev" instruction, indent
-** all opcodes that occur between the p2 jump destination and the opcode
-** itself by 2 spaces.
-**
-** * For each "Goto", if the jump destination is earlier in the program
-** and ends on one of:
-** Yield SeekGt SeekLt RowSetRead Rewind
-** or if the P1 parameter is one instead of zero,
-** then indent all opcodes between the earlier instruction
-** and "Goto" by 2 spaces.
-*/
-static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
- const char *zSql; /* The text of the SQL statement */
- const char *z; /* Used to check if this is an EXPLAIN */
- int *abYield = 0; /* True if op is an OP_Yield */
- int nAlloc = 0; /* Allocated size of p->aiIndent[], abYield */
- int iOp; /* Index of operation in p->aiIndent[] */
-
- const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext",
- "NextIfOpen", "PrevIfOpen", 0 };
- const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead",
- "Rewind", 0 };
- const char *azGoto[] = { "Goto", 0 };
-
- /* Try to figure out if this is really an EXPLAIN statement. If this
- ** cannot be verified, return early. */
- if( sqlite3_column_count(pSql)!=8 ){
- p->cMode = p->mode;
- return;
- }
- zSql = sqlite3_sql(pSql);
- if( zSql==0 ) return;
- for(z=zSql; *z==' ' || *z=='\t' || *z=='\n' || *z=='\f' || *z=='\r'; z++);
- if( sqlite3_strnicmp(z, "explain", 7) ){
- p->cMode = p->mode;
- return;
- }
-
- for(iOp=0; SQLITE_ROW==sqlite3_step(pSql); iOp++){
- int i;
- int iAddr = sqlite3_column_int(pSql, 0);
- const char *zOp = (const char*)sqlite3_column_text(pSql, 1);
-
- /* Set p2 to the P2 field of the current opcode. Then, assuming that
- ** p2 is an instruction address, set variable p2op to the index of that
- ** instruction in the aiIndent[] array. p2 and p2op may be different if
- ** the current instruction is part of a sub-program generated by an
- ** SQL trigger or foreign key. */
- int p2 = sqlite3_column_int(pSql, 3);
- int p2op = (p2 + (iOp-iAddr));
-
- /* Grow the p->aiIndent array as required */
- if( iOp>=nAlloc ){
- if( iOp==0 ){
- /* Do further verfication that this is explain output. Abort if
- ** it is not */
- static const char *explainCols[] = {
- "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment" };
- int jj;
- for(jj=0; jj<ArraySize(explainCols); jj++){
- if( strcmp(sqlite3_column_name(pSql,jj),explainCols[jj])!=0 ){
- p->cMode = p->mode;
- sqlite3_reset(pSql);
- return;
- }
- }
- }
- nAlloc += 100;
- p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int));
- abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int));
- }
- abYield[iOp] = str_in_array(zOp, azYield);
- p->aiIndent[iOp] = 0;
- p->nIndent = iOp+1;
-
- if( str_in_array(zOp, azNext) ){
- for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
- }
- if( str_in_array(zOp, azGoto) && p2op<p->nIndent
- && (abYield[p2op] || sqlite3_column_int(pSql, 2))
- ){
- for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
- }
- }
-
- p->iIndent = 0;
- sqlite3_free(abYield);
- sqlite3_reset(pSql);
-}
-
-/*
-** Free the array allocated by explain_data_prepare().
-*/
-static void explain_data_delete(ShellState *p){
- sqlite3_free(p->aiIndent);
- p->aiIndent = 0;
- p->nIndent = 0;
- p->iIndent = 0;
-}
-
-/*
-** Disable and restore .wheretrace and .selecttrace settings.
-*/
-#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
-extern int sqlite3SelectTrace;
-static int savedSelectTrace;
-#endif
-#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
-extern int sqlite3WhereTrace;
-static int savedWhereTrace;
-#endif
-static void disable_debug_trace_modes(void){
-#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
- savedSelectTrace = sqlite3SelectTrace;
- sqlite3SelectTrace = 0;
-#endif
-#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
- savedWhereTrace = sqlite3WhereTrace;
- sqlite3WhereTrace = 0;
-#endif
-}
-static void restore_debug_trace_modes(void){
-#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
- sqlite3SelectTrace = savedSelectTrace;
-#endif
-#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
- sqlite3WhereTrace = savedWhereTrace;
-#endif
-}
-
-/*
-** Run a prepared statement
-*/
-static void exec_prepared_stmt(
- ShellState *pArg, /* Pointer to ShellState */
- sqlite3_stmt *pStmt, /* Statment to run */
- int (*xCallback)(void*,int,char**,char**,int*) /* Callback function */
-){
- int rc;
-
- /* perform the first step. this will tell us if we
- ** have a result set or not and how wide it is.
- */
- rc = sqlite3_step(pStmt);
- /* if we have a result set... */
- if( SQLITE_ROW == rc ){
- /* if we have a callback... */
- if( xCallback ){
- /* allocate space for col name ptr, value ptr, and type */
- int nCol = sqlite3_column_count(pStmt);
- void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1);
- if( !pData ){
- rc = SQLITE_NOMEM;
- }else{
- char **azCols = (char **)pData; /* Names of result columns */
- char **azVals = &azCols[nCol]; /* Results */
- int *aiTypes = (int *)&azVals[nCol]; /* Result types */
- int i, x;
- assert(sizeof(int) <= sizeof(char *));
- /* save off ptrs to column names */
- for(i=0; i<nCol; i++){
- azCols[i] = (char *)sqlite3_column_name(pStmt, i);
- }
- do{
- /* extract the data and data types */
- for(i=0; i<nCol; i++){
- aiTypes[i] = x = sqlite3_column_type(pStmt, i);
- if( x==SQLITE_BLOB && pArg && pArg->cMode==MODE_Insert ){
- azVals[i] = "";
- }else{
- azVals[i] = (char*)sqlite3_column_text(pStmt, i);
- }
- if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
- rc = SQLITE_NOMEM;
- break; /* from for */
- }
- } /* end for */
-
- /* if data and types extracted successfully... */
- if( SQLITE_ROW == rc ){
- /* call the supplied callback with the result row data */
- if( xCallback(pArg, nCol, azVals, azCols, aiTypes) ){
- rc = SQLITE_ABORT;
- }else{
- rc = sqlite3_step(pStmt);
- }
- }
- } while( SQLITE_ROW == rc );
- sqlite3_free(pData);
- }
- }else{
- do{
- rc = sqlite3_step(pStmt);
- } while( rc == SQLITE_ROW );
- }
- }
-}
-
-/*
-** Execute a statement or set of statements. Print
-** any result rows/columns depending on the current mode
-** set via the supplied callback.
-**
-** This is very similar to SQLite's built-in sqlite3_exec()
-** function except it takes a slightly different callback
-** and callback data argument.
-*/
-static int shell_exec(
- sqlite3 *db, /* An open database */
- const char *zSql, /* SQL to be evaluated */
- int (*xCallback)(void*,int,char**,char**,int*), /* Callback function */
- /* (not the same as sqlite3_exec) */
- ShellState *pArg, /* Pointer to ShellState */
- char **pzErrMsg /* Error msg written here */
-){
- sqlite3_stmt *pStmt = NULL; /* Statement to execute. */
- int rc = SQLITE_OK; /* Return Code */
- int rc2;
- const char *zLeftover; /* Tail of unprocessed SQL */
-
- if( pzErrMsg ){
- *pzErrMsg = NULL;
- }
-
- while( zSql[0] && (SQLITE_OK == rc) ){
- static const char *zStmtSql;
- rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
- if( SQLITE_OK != rc ){
- if( pzErrMsg ){
- *pzErrMsg = save_err_msg(db);
- }
- }else{
- if( !pStmt ){
- /* this happens for a comment or white-space */
- zSql = zLeftover;
- while( IsSpace(zSql[0]) ) zSql++;
- continue;
- }
- zStmtSql = sqlite3_sql(pStmt);
- if( zStmtSql==0 ) zStmtSql = "";
- while( IsSpace(zStmtSql[0]) ) zStmtSql++;
-
- /* save off the prepared statment handle and reset row count */
- if( pArg ){
- pArg->pStmt = pStmt;
- pArg->cnt = 0;
- }
-
- /* echo the sql statement if echo on */
- if( pArg && ShellHasFlag(pArg, SHFLG_Echo) ){
- utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
- }
-
- /* Show the EXPLAIN QUERY PLAN if .eqp is on */
- if( pArg && pArg->autoEQP && sqlite3_strlike("EXPLAIN%",zStmtSql,0)!=0 ){
- sqlite3_stmt *pExplain;
- char *zEQP;
- disable_debug_trace_modes();
- zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zStmtSql);
- rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
- if( rc==SQLITE_OK ){
- while( sqlite3_step(pExplain)==SQLITE_ROW ){
- raw_printf(pArg->out,"--EQP-- %d,",sqlite3_column_int(pExplain, 0));
- raw_printf(pArg->out,"%d,", sqlite3_column_int(pExplain, 1));
- raw_printf(pArg->out,"%d,", sqlite3_column_int(pExplain, 2));
- utf8_printf(pArg->out,"%s\n", sqlite3_column_text(pExplain, 3));
- }
- }
- sqlite3_finalize(pExplain);
- sqlite3_free(zEQP);
- if( pArg->autoEQP>=2 ){
- /* Also do an EXPLAIN for ".eqp full" mode */
- zEQP = sqlite3_mprintf("EXPLAIN %s", zStmtSql);
- rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
- if( rc==SQLITE_OK ){
- pArg->cMode = MODE_Explain;
- explain_data_prepare(pArg, pExplain);
- exec_prepared_stmt(pArg, pExplain, xCallback);
- explain_data_delete(pArg);
- }
- sqlite3_finalize(pExplain);
- sqlite3_free(zEQP);
- }
- restore_debug_trace_modes();
- }
-
- if( pArg ){
- pArg->cMode = pArg->mode;
- if( pArg->autoExplain
- && sqlite3_column_count(pStmt)==8
- && sqlite3_strlike("EXPLAIN%", zStmtSql,0)==0
- ){
- pArg->cMode = MODE_Explain;
- }
-
- /* If the shell is currently in ".explain" mode, gather the extra
- ** data required to add indents to the output.*/
- if( pArg->cMode==MODE_Explain ){
- explain_data_prepare(pArg, pStmt);
- }
- }
-
- exec_prepared_stmt(pArg, pStmt, xCallback);
- explain_data_delete(pArg);
-
- /* print usage stats if stats on */
- if( pArg && pArg->statsOn ){
- display_stats(db, pArg, 0);
- }
-
- /* print loop-counters if required */
- if( pArg && pArg->scanstatsOn ){
- display_scanstats(db, pArg);
- }
-
- /* Finalize the statement just executed. If this fails, save a
- ** copy of the error message. Otherwise, set zSql to point to the
- ** next statement to execute. */
- rc2 = sqlite3_finalize(pStmt);
- if( rc!=SQLITE_NOMEM ) rc = rc2;
- if( rc==SQLITE_OK ){
- zSql = zLeftover;
- while( IsSpace(zSql[0]) ) zSql++;
- }else if( pzErrMsg ){
- *pzErrMsg = save_err_msg(db);
- }
-
- /* clear saved stmt handle */
- if( pArg ){
- pArg->pStmt = NULL;
- }
- }
- } /* end while */
-
- return rc;
-}
-
-/*
-** Release memory previously allocated by tableColumnList().
-*/
-static void freeColumnList(char **azCol){
- int i;
- for(i=1; azCol[i]; i++){
- sqlite3_free(azCol[i]);
- }
- /* azCol[0] is a static string */
- sqlite3_free(azCol);
-}
-
-/*
-** Return a list of pointers to strings which are the names of all
-** columns in table zTab. The memory to hold the names is dynamically
-** allocated and must be released by the caller using a subsequent call
-** to freeColumnList().
-**
-** The azCol[0] entry is usually NULL. However, if zTab contains a rowid
-** value that needs to be preserved, then azCol[0] is filled in with the
-** name of the rowid column.
-**
-** The first regular column in the table is azCol[1]. The list is terminated
-** by an entry with azCol[i]==0.
-*/
-static char **tableColumnList(ShellState *p, const char *zTab){
- char **azCol = 0;
- sqlite3_stmt *pStmt;
- char *zSql;
- int nCol = 0;
- int nAlloc = 0;
- int nPK = 0; /* Number of PRIMARY KEY columns seen */
- int isIPK = 0; /* True if one PRIMARY KEY column of type INTEGER */
- int preserveRowid = ShellHasFlag(p, SHFLG_PreserveRowid);
- int rc;
-
- zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab);
- rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
- sqlite3_free(zSql);
- if( rc ) return 0;
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- if( nCol>=nAlloc-2 ){
- nAlloc = nAlloc*2 + nCol + 10;
- azCol = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0]));
- if( azCol==0 ){
- raw_printf(stderr, "Error: out of memory\n");
- exit(1);
- }
- }
- azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
- if( sqlite3_column_int(pStmt, 5) ){
- nPK++;
- if( nPK==1
- && sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2),
- "INTEGER")==0
- ){
- isIPK = 1;
- }else{
- isIPK = 0;
- }
- }
- }
- sqlite3_finalize(pStmt);
- azCol[0] = 0;
- azCol[nCol+1] = 0;
-
- /* The decision of whether or not a rowid really needs to be preserved
- ** is tricky. We never need to preserve a rowid for a WITHOUT ROWID table
- ** or a table with an INTEGER PRIMARY KEY. We are unable to preserve
- ** rowids on tables where the rowid is inaccessible because there are other
- ** columns in the table named "rowid", "_rowid_", and "oid".
- */
- if( preserveRowid && isIPK ){
- /* If a single PRIMARY KEY column with type INTEGER was seen, then it
- ** might be an alise for the ROWID. But it might also be a WITHOUT ROWID
- ** table or a INTEGER PRIMARY KEY DESC column, neither of which are
- ** ROWID aliases. To distinguish these cases, check to see if
- ** there is a "pk" entry in "PRAGMA index_list". There will be
- ** no "pk" index if the PRIMARY KEY really is an alias for the ROWID.
- */
- zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)"
- " WHERE origin='pk'", zTab);
- rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
- sqlite3_free(zSql);
- if( rc ){
- freeColumnList(azCol);
- return 0;
- }
- rc = sqlite3_step(pStmt);
- sqlite3_finalize(pStmt);
- preserveRowid = rc==SQLITE_ROW;
- }
- if( preserveRowid ){
- /* Only preserve the rowid if we can find a name to use for the
- ** rowid */
- static char *azRowid[] = { "rowid", "_rowid_", "oid" };
- int i, j;
- for(j=0; j<3; j++){
- for(i=1; i<=nCol; i++){
- if( sqlite3_stricmp(azRowid[j],azCol[i])==0 ) break;
- }
- if( i>nCol ){
- /* At this point, we know that azRowid[j] is not the name of any
- ** ordinary column in the table. Verify that azRowid[j] is a valid
- ** name for the rowid before adding it to azCol[0]. WITHOUT ROWID
- ** tables will fail this last check */
- rc = sqlite3_table_column_metadata(p->db,0,zTab,azRowid[j],0,0,0,0,0);
- if( rc==SQLITE_OK ) azCol[0] = azRowid[j];
- break;
- }
- }
- }
- return azCol;
-}
-
-/*
-** Toggle the reverse_unordered_selects setting.
-*/
-static void toggleSelectOrder(sqlite3 *db){
- sqlite3_stmt *pStmt = 0;
- int iSetting = 0;
- char zStmt[100];
- sqlite3_prepare_v2(db, "PRAGMA reverse_unordered_selects", -1, &pStmt, 0);
- if( sqlite3_step(pStmt)==SQLITE_ROW ){
- iSetting = sqlite3_column_int(pStmt, 0);
- }
- sqlite3_finalize(pStmt);
- sqlite3_snprintf(sizeof(zStmt), zStmt,
- "PRAGMA reverse_unordered_selects(%d)", !iSetting);
- sqlite3_exec(db, zStmt, 0, 0, 0);
-}
-
-/*
-** This is a different callback routine used for dumping the database.
-** Each row received by this callback consists of a table name,
-** the table type ("index" or "table") and SQL to create the table.
-** This routine should print text sufficient to recreate the table.
-*/
-static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
- int rc;
- const char *zTable;
- const char *zType;
- const char *zSql;
- ShellState *p = (ShellState *)pArg;
-
- UNUSED_PARAMETER(azNotUsed);
- if( nArg!=3 ) return 1;
- zTable = azArg[0];
- zType = azArg[1];
- zSql = azArg[2];
-
- if( strcmp(zTable, "sqlite_sequence")==0 ){
- raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
- }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){
- raw_printf(p->out, "ANALYZE sqlite_master;\n");
- }else if( strncmp(zTable, "sqlite_", 7)==0 ){
- return 0;
- }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
- char *zIns;
- if( !p->writableSchema ){
- raw_printf(p->out, "PRAGMA writable_schema=ON;\n");
- p->writableSchema = 1;
- }
- zIns = sqlite3_mprintf(
- "INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)"
- "VALUES('table','%q','%q',0,'%q');",
- zTable, zTable, zSql);
- utf8_printf(p->out, "%s\n", zIns);
- sqlite3_free(zIns);
- return 0;
- }else{
- printSchemaLine(p->out, zSql, ";\n");
- }
-
- if( strcmp(zType, "table")==0 ){
- ShellText sSelect;
- ShellText sTable;
- char **azCol;
- int i;
- char *savedDestTable;
- int savedMode;
-
- azCol = tableColumnList(p, zTable);
- if( azCol==0 ){
- p->nErr++;
- return 0;
- }
-
- /* Always quote the table name, even if it appears to be pure ascii,
- ** in case it is a keyword. Ex: INSERT INTO "table" ... */
- initText(&sTable);
- appendText(&sTable, zTable, quoteChar(zTable));
- /* If preserving the rowid, add a column list after the table name.
- ** In other words: "INSERT INTO tab(rowid,a,b,c,...) VALUES(...)"
- ** instead of the usual "INSERT INTO tab VALUES(...)".
- */
- if( azCol[0] ){
- appendText(&sTable, "(", 0);
- appendText(&sTable, azCol[0], 0);
- for(i=1; azCol[i]; i++){
- appendText(&sTable, ",", 0);
- appendText(&sTable, azCol[i], quoteChar(azCol[i]));
- }
- appendText(&sTable, ")", 0);
- }
-
- /* Build an appropriate SELECT statement */
- initText(&sSelect);
- appendText(&sSelect, "SELECT ", 0);
- if( azCol[0] ){
- appendText(&sSelect, azCol[0], 0);
- appendText(&sSelect, ",", 0);
- }
- for(i=1; azCol[i]; i++){
- appendText(&sSelect, azCol[i], quoteChar(azCol[i]));
- if( azCol[i+1] ){
- appendText(&sSelect, ",", 0);
- }
- }
- freeColumnList(azCol);
- appendText(&sSelect, " FROM ", 0);
- appendText(&sSelect, zTable, quoteChar(zTable));
-
- savedDestTable = p->zDestTable;
- savedMode = p->mode;
- p->zDestTable = sTable.z;
- p->mode = p->cMode = MODE_Insert;
- rc = shell_exec(p->db, sSelect.z, shell_callback, p, 0);
- if( (rc&0xff)==SQLITE_CORRUPT ){
- raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
- toggleSelectOrder(p->db);
- shell_exec(p->db, sSelect.z, shell_callback, p, 0);
- toggleSelectOrder(p->db);
- }
- p->zDestTable = savedDestTable;
- p->mode = savedMode;
- freeText(&sTable);
- freeText(&sSelect);
- if( rc ) p->nErr++;
- }
- return 0;
-}
-
-/*
-** Run zQuery. Use dump_callback() as the callback routine so that
-** the contents of the query are output as SQL statements.
-**
-** If we get a SQLITE_CORRUPT error, rerun the query after appending
-** "ORDER BY rowid DESC" to the end.
-*/
-static int run_schema_dump_query(
- ShellState *p,
- const char *zQuery
-){
- int rc;
- char *zErr = 0;
- rc = sqlite3_exec(p->db, zQuery, dump_callback, p, &zErr);
- if( rc==SQLITE_CORRUPT ){
- char *zQ2;
- int len = strlen30(zQuery);
- raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
- if( zErr ){
- utf8_printf(p->out, "/****** %s ******/\n", zErr);
- sqlite3_free(zErr);
- zErr = 0;
- }
- zQ2 = malloc( len+100 );
- if( zQ2==0 ) return rc;
- sqlite3_snprintf(len+100, zQ2, "%s ORDER BY rowid DESC", zQuery);
- rc = sqlite3_exec(p->db, zQ2, dump_callback, p, &zErr);
- if( rc ){
- utf8_printf(p->out, "/****** ERROR: %s ******/\n", zErr);
- }else{
- rc = SQLITE_CORRUPT;
- }
- sqlite3_free(zErr);
- free(zQ2);
- }
- return rc;
-}
-
-/*
-** Text of a help message
-*/
-static char zHelp[] =
-#ifndef SQLITE_OMIT_AUTHORIZATION
- ".auth ON|OFF Show authorizer callbacks\n"
-#endif
- ".backup ?DB? FILE Backup DB (default \"main\") to FILE\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"
- ".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"
- ".exit Exit this program\n"
-/* 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"
-#ifndef SQLITE_OMIT_TEST_CONTROL
- ".imposter INDEX TABLE Create imposter table TABLE on index INDEX\n"
-#endif
- ".indexes ?TABLE? Show names of all indexes\n"
- " If TABLE specified, only show indexes for tables\n"
- " matching LIKE pattern TABLE.\n"
-#ifdef SQLITE_ENABLE_IOTRACE
- ".iotrace FILE Enable I/O diagnostic logging to FILE\n"
-#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"
-#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 FILENAME Output for the next SQL command only to FILENAME\n"
- ".open ?OPTIONS? ?FILE? Close existing database and reopen FILE\n"
- " The --new option starts with an empty file\n"
- ".output ?FILENAME? Send output to FILENAME 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"
-#if defined(SQLITE_ENABLE_SESSION)
- ".session CMD ... Create or control sessions\n"
-#endif
- ".sha3sum ?OPTIONS...? Compute a SHA3 hash of database content\n"
- ".shell CMD ARGS... Run CMD ARGS... in a system shell\n"
- ".show Show the current values for various settings\n"
- ".stats ?on|off? Show stats or turn stats on or off\n"
- ".system CMD ARGS... Run CMD ARGS... in a system shell\n"
- ".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"
-;
-
-#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"
- );
-}
-#endif
-
-
-/* Forward reference */
-static int process_input(ShellState *p, FILE *in);
-
-/*
-** Read the content of file zName into memory obtained from sqlite3_malloc64()
-** and return a pointer to the buffer. The caller is responsible for freeing
-** the memory.
-**
-** If parameter pnByte is not NULL, (*pnByte) is set to the number of bytes
-** read.
-**
-** For convenience, a nul-terminator byte is always appended to the data read
-** from the file before the buffer is returned. This byte is not included in
-** the final value of (*pnByte), if applicable.
-**
-** NULL is returned if any error is encountered. The final value of *pnByte
-** is undefined in this case.
-*/
-static char *readFile(const char *zName, int *pnByte){
- FILE *in = fopen(zName, "rb");
- long nIn;
- size_t nRead;
- char *pBuf;
- if( in==0 ) return 0;
- fseek(in, 0, SEEK_END);
- nIn = ftell(in);
- rewind(in);
- pBuf = sqlite3_malloc64( nIn+1 );
- if( pBuf==0 ) return 0;
- nRead = fread(pBuf, nIn, 1, in);
- fclose(in);
- if( nRead!=1 ){
- sqlite3_free(pBuf);
- return 0;
- }
- pBuf[nIn] = 0;
- if( pnByte ) *pnByte = nIn;
- return pBuf;
-}
-
-#if defined(SQLITE_ENABLE_SESSION)
-/*
-** Close a single OpenSession object and release all of its associated
-** resources.
-*/
-static void session_close(OpenSession *pSession){
- int i;
- sqlite3session_delete(pSession->p);
- sqlite3_free(pSession->zName);
- for(i=0; i<pSession->nFilter; i++){
- sqlite3_free(pSession->azFilter[i]);
- }
- sqlite3_free(pSession->azFilter);
- memset(pSession, 0, sizeof(OpenSession));
-}
-#endif
-
-/*
-** Close all OpenSession objects and release all associated resources.
-*/
-#if defined(SQLITE_ENABLE_SESSION)
-static void session_close_all(ShellState *p){
- int i;
- for(i=0; i<p->nSession; i++){
- session_close(&p->aSession[i]);
- }
- p->nSession = 0;
-}
-#else
-# define session_close_all(X)
-#endif
-
-/*
-** Implementation of the xFilter function for an open session. Omit
-** any tables named by ".session filter" but let all other table through.
-*/
-#if defined(SQLITE_ENABLE_SESSION)
-static int session_filter(void *pCtx, const char *zTab){
- OpenSession *pSession = (OpenSession*)pCtx;
- int i;
- for(i=0; i<pSession->nFilter; i++){
- if( sqlite3_strglob(pSession->azFilter[i], zTab)==0 ) return 0;
- }
- return 1;
-}
-#endif
-
-/*
-** Make sure the database is open. If it is not, then open it. If
-** the database fails to open, print an error message and exit.
-*/
-static void open_db(ShellState *p, int keepAlive){
- if( p->db==0 ){
- sqlite3_initialize();
- sqlite3_open(p->zDbFilename, &p->db);
- globalDb = p->db;
- if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
- utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",
- p->zDbFilename, sqlite3_errmsg(p->db));
- if( keepAlive ) return;
- exit(1);
- }
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
- sqlite3_enable_load_extension(p->db, 1);
-#endif
- sqlite3_fileio_init(p->db, 0, 0);
- sqlite3_shathree_init(p->db, 0, 0);
- sqlite3_completion_init(p->db, 0, 0);
- sqlite3_create_function(p->db, "shell_add_schema", 2, SQLITE_UTF8, 0,
- shellAddSchemaName, 0, 0);
- }
-}
-
-#if HAVE_READLINE || HAVE_EDITLINE
-/*
-** Readline completion callbacks
-*/
-static char *readline_completion_generator(const char *text, int state){
- static sqlite3_stmt *pStmt = 0;
- char *zRet;
- if( state==0 ){
- char *zSql;
- sqlite3_finalize(pStmt);
- zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
- " FROM completion(%Q) ORDER BY 1", text);
- sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
- sqlite3_free(zSql);
- }
- if( sqlite3_step(pStmt)==SQLITE_ROW ){
- zRet = strdup((const char*)sqlite3_column_text(pStmt, 0));
- }else{
- sqlite3_finalize(pStmt);
- pStmt = 0;
- zRet = 0;
- }
- return zRet;
-}
-static char **readline_completion(const char *zText, int iStart, int iEnd){
- rl_attempted_completion_over = 1;
- return rl_completion_matches(zText, readline_completion_generator);
-}
-
-#elif HAVE_LINENOISE
-/*
-** Linenoise completion callback
-*/
-static void linenoise_completion(const char *zLine, linenoiseCompletions *lc){
- int nLine = (int)strlen(zLine);
- int i, iStart;
- sqlite3_stmt *pStmt = 0;
- char *zSql;
- char zBuf[1000];
-
- if( nLine>sizeof(zBuf)-30 ) return;
- if( zLine[0]=='.' ) return;
- for(i=nLine-1; i>=0 && (isalnum(zLine[i]) || zLine[i]=='_'); i--){}
- if( i==nLine-1 ) return;
- iStart = i+1;
- memcpy(zBuf, zLine, iStart);
- zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
- " FROM completion(%Q,%Q) ORDER BY 1",
- &zLine[iStart], zLine);
- sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
- sqlite3_free(zSql);
- sqlite3_exec(globalDb, "PRAGMA page_count", 0, 0, 0); /* Load the schema */
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- const char *zCompletion = (const char*)sqlite3_column_text(pStmt, 0);
- int nCompletion = sqlite3_column_bytes(pStmt, 0);
- if( iStart+nCompletion < sizeof(zBuf)-1 ){
- memcpy(zBuf+iStart, zCompletion, nCompletion+1);
- linenoiseAddCompletion(lc, zBuf);
- }
- }
- sqlite3_finalize(pStmt);
-}
-#endif
-
-/*
-** Do C-language style dequoting.
-**
-** \a -> alarm
-** \b -> backspace
-** \t -> tab
-** \n -> newline
-** \v -> vertical tab
-** \f -> form feed
-** \r -> carriage return
-** \s -> space
-** \" -> "
-** \' -> '
-** \\ -> backslash
-** \NNN -> ascii character NNN in octal
-*/
-static void resolve_backslashes(char *z){
- int i, j;
- char c;
- while( *z && *z!='\\' ) z++;
- for(i=j=0; (c = z[i])!=0; i++, j++){
- if( c=='\\' && z[i+1]!=0 ){
- c = z[++i];
- if( c=='a' ){
- c = '\a';
- }else if( c=='b' ){
- c = '\b';
- }else if( c=='t' ){
- c = '\t';
- }else if( c=='n' ){
- c = '\n';
- }else if( c=='v' ){
- c = '\v';
- }else if( c=='f' ){
- c = '\f';
- }else if( c=='r' ){
- c = '\r';
- }else if( c=='"' ){
- c = '"';
- }else if( c=='\'' ){
- c = '\'';
- }else if( c=='\\' ){
- c = '\\';
- }else if( c>='0' && c<='7' ){
- c -= '0';
- if( z[i+1]>='0' && z[i+1]<='7' ){
- i++;
- c = (c<<3) + z[i] - '0';
- if( z[i+1]>='0' && z[i+1]<='7' ){
- i++;
- c = (c<<3) + z[i] - '0';
- }
- }
- }
- }
- z[j] = c;
- }
- if( j<i ) z[j] = 0;
-}
-
-/*
-** Return the value of a hexadecimal digit. Return -1 if the input
-** is not a hex digit.
-*/
-static int hexDigitValue(char c){
- if( c>='0' && c<='9' ) return c - '0';
- if( c>='a' && c<='f' ) return c - 'a' + 10;
- if( c>='A' && c<='F' ) return c - 'A' + 10;
- return -1;
-}
-
-/*
-** Interpret zArg as an integer value, possibly with suffixes.
-*/
-static sqlite3_int64 integerValue(const char *zArg){
- sqlite3_int64 v = 0;
- static const struct { char *zSuffix; int iMult; } aMult[] = {
- { "KiB", 1024 },
- { "MiB", 1024*1024 },
- { "GiB", 1024*1024*1024 },
- { "KB", 1000 },
- { "MB", 1000000 },
- { "GB", 1000000000 },
- { "K", 1000 },
- { "M", 1000000 },
- { "G", 1000000000 },
- };
- int i;
- int isNeg = 0;
- if( zArg[0]=='-' ){
- isNeg = 1;
- zArg++;
- }else if( zArg[0]=='+' ){
- zArg++;
- }
- if( zArg[0]=='0' && zArg[1]=='x' ){
- int x;
- zArg += 2;
- while( (x = hexDigitValue(zArg[0]))>=0 ){
- v = (v<<4) + x;
- zArg++;
- }
- }else{
- while( IsDigit(zArg[0]) ){
- v = v*10 + zArg[0] - '0';
- zArg++;
- }
- }
- for(i=0; i<ArraySize(aMult); i++){
- if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
- v *= aMult[i].iMult;
- break;
- }
- }
- return isNeg? -v : v;
-}
-
-/*
-** Interpret zArg as either an integer or a boolean value. Return 1 or 0
-** for TRUE and FALSE. Return the integer value if appropriate.
-*/
-static int booleanValue(const char *zArg){
- int i;
- if( zArg[0]=='0' && zArg[1]=='x' ){
- for(i=2; hexDigitValue(zArg[i])>=0; i++){}
- }else{
- for(i=0; zArg[i]>='0' && zArg[i]<='9'; i++){}
- }
- if( i>0 && zArg[i]==0 ) return (int)(integerValue(zArg) & 0xffffffff);
- if( sqlite3_stricmp(zArg, "on")==0 || sqlite3_stricmp(zArg,"yes")==0 ){
- return 1;
- }
- if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){
- return 0;
- }
- utf8_printf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n",
- zArg);
- return 0;
-}
-
-/*
-** Set or clear a shell flag according to a boolean value.
-*/
-static void setOrClearFlag(ShellState *p, unsigned mFlag, const char *zArg){
- if( booleanValue(zArg) ){
- ShellSetFlag(p, mFlag);
- }else{
- ShellClearFlag(p, mFlag);
- }
-}
-
-/*
-** Close an output file, assuming it is not stderr or stdout
-*/
-static void output_file_close(FILE *f){
- if( f && f!=stdout && f!=stderr ) fclose(f);
-}
-
-/*
-** Try to open an output file. The names "stdout" and "stderr" are
-** recognized and do the right thing. NULL is returned if the output
-** filename is "off".
-*/
-static FILE *output_file_open(const char *zFile){
- FILE *f;
- if( strcmp(zFile,"stdout")==0 ){
- f = stdout;
- }else if( strcmp(zFile, "stderr")==0 ){
- f = stderr;
- }else if( strcmp(zFile, "off")==0 ){
- f = 0;
- }else{
- f = fopen(zFile, "wb");
- if( f==0 ){
- utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
- }
- }
- return f;
-}
-
-#if !defined(SQLITE_UNTESTABLE)
-#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT)
-/*
-** A routine for handling output from sqlite3_trace().
-*/
-static int sql_trace_callback(
- unsigned mType,
- void *pArg,
- void *pP,
- void *pX
-){
- FILE *f = (FILE*)pArg;
- UNUSED_PARAMETER(mType);
- UNUSED_PARAMETER(pP);
- if( f ){
- const char *z = (const char*)pX;
- int i = (int)strlen(z);
- while( i>0 && z[i-1]==';' ){ i--; }
- utf8_printf(f, "%.*s;\n", i, z);
- }
- return 0;
-}
-#endif
-#endif
-
-/*
-** A no-op routine that runs with the ".breakpoint" doc-command. This is
-** a useful spot to set a debugger breakpoint.
-*/
-static void test_breakpoint(void){
- static int nCall = 0;
- nCall++;
-}
-
-/*
-** An object used to read a CSV and other files for import.
-*/
-typedef struct ImportCtx ImportCtx;
-struct ImportCtx {
- const char *zFile; /* Name of the input file */
- FILE *in; /* Read the CSV text from this input stream */
- char *z; /* Accumulated text for a field */
- int n; /* Number of bytes in z */
- int nAlloc; /* Space allocated for z[] */
- int nLine; /* Current line number */
- int bNotFirst; /* True if one or more bytes already read */
- int cTerm; /* Character that terminated the most recent field */
- int cColSep; /* The column separator character. (Usually ",") */
- int cRowSep; /* The row separator character. (Usually "\n") */
-};
-
-/* Append a single byte to z[] */
-static void import_append_char(ImportCtx *p, int c){
- if( p->n+1>=p->nAlloc ){
- p->nAlloc += p->nAlloc + 100;
- p->z = sqlite3_realloc64(p->z, p->nAlloc);
- if( p->z==0 ){
- raw_printf(stderr, "out of memory\n");
- exit(1);
- }
- }
- p->z[p->n++] = (char)c;
-}
-
-/* Read a single field of CSV text. Compatible with rfc4180 and extended
-** with the option of having a separator other than ",".
-**
-** + Input comes from p->in.
-** + Store results in p->z of length p->n. Space to hold p->z comes
-** from sqlite3_malloc64().
-** + Use p->cSep as the column separator. The default is ",".
-** + Use p->rSep as the row separator. The default is "\n".
-** + Keep track of the line number in p->nLine.
-** + Store the character that terminates the field in p->cTerm. Store
-** EOF on end-of-file.
-** + Report syntax errors on stderr
-*/
-static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){
- int c;
- int cSep = p->cColSep;
- int rSep = p->cRowSep;
- p->n = 0;
- c = fgetc(p->in);
- if( c==EOF || seenInterrupt ){
- p->cTerm = EOF;
- return 0;
- }
- if( c=='"' ){
- int pc, ppc;
- int startLine = p->nLine;
- int cQuote = c;
- pc = ppc = 0;
- while( 1 ){
- c = fgetc(p->in);
- if( c==rSep ) p->nLine++;
- if( c==cQuote ){
- if( pc==cQuote ){
- pc = 0;
- continue;
- }
- }
- if( (c==cSep && pc==cQuote)
- || (c==rSep && pc==cQuote)
- || (c==rSep && pc=='\r' && ppc==cQuote)
- || (c==EOF && pc==cQuote)
- ){
- do{ p->n--; }while( p->z[p->n]!=cQuote );
- p->cTerm = c;
- break;
- }
- if( pc==cQuote && c!='\r' ){
- utf8_printf(stderr, "%s:%d: unescaped %c character\n",
- p->zFile, p->nLine, cQuote);
- }
- if( c==EOF ){
- utf8_printf(stderr, "%s:%d: unterminated %c-quoted field\n",
- p->zFile, startLine, cQuote);
- p->cTerm = c;
- break;
- }
- import_append_char(p, c);
- ppc = pc;
- pc = c;
- }
- }else{
- /* If this is the first field being parsed and it begins with the
- ** UTF-8 BOM (0xEF BB BF) then skip the BOM */
- if( (c&0xff)==0xef && p->bNotFirst==0 ){
- import_append_char(p, c);
- c = fgetc(p->in);
- if( (c&0xff)==0xbb ){
- import_append_char(p, c);
- c = fgetc(p->in);
- if( (c&0xff)==0xbf ){
- p->bNotFirst = 1;
- p->n = 0;
- return csv_read_one_field(p);
- }
- }
- }
- while( c!=EOF && c!=cSep && c!=rSep ){
- import_append_char(p, c);
- c = fgetc(p->in);
- }
- if( c==rSep ){
- p->nLine++;
- if( p->n>0 && p->z[p->n-1]=='\r' ) p->n--;
- }
- p->cTerm = c;
- }
- if( p->z ) p->z[p->n] = 0;
- p->bNotFirst = 1;
- return p->z;
-}
-
-/* Read a single field of ASCII delimited text.
-**
-** + Input comes from p->in.
-** + Store results in p->z of length p->n. Space to hold p->z comes
-** from sqlite3_malloc64().
-** + Use p->cSep as the column separator. The default is "\x1F".
-** + Use p->rSep as the row separator. The default is "\x1E".
-** + Keep track of the row number in p->nLine.
-** + Store the character that terminates the field in p->cTerm. Store
-** EOF on end-of-file.
-** + Report syntax errors on stderr
-*/
-static char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){
- int c;
- int cSep = p->cColSep;
- int rSep = p->cRowSep;
- p->n = 0;
- c = fgetc(p->in);
- if( c==EOF || seenInterrupt ){
- p->cTerm = EOF;
- return 0;
- }
- while( c!=EOF && c!=cSep && c!=rSep ){
- import_append_char(p, c);
- c = fgetc(p->in);
- }
- if( c==rSep ){
- p->nLine++;
- }
- p->cTerm = c;
- if( p->z ) p->z[p->n] = 0;
- return p->z;
-}
-
-/*
-** Try to transfer data for table zTable. If an error is seen while
-** moving forward, try to go backwards. The backwards movement won't
-** work for WITHOUT ROWID tables.
-*/
-static void tryToCloneData(
- ShellState *p,
- sqlite3 *newDb,
- const char *zTable
-){
- sqlite3_stmt *pQuery = 0;
- sqlite3_stmt *pInsert = 0;
- char *zQuery = 0;
- char *zInsert = 0;
- int rc;
- int i, j, n;
- int nTable = (int)strlen(zTable);
- int k = 0;
- int cnt = 0;
- const int spinRate = 10000;
-
- zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
- rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
- if( rc ){
- utf8_printf(stderr, "Error %d: %s on [%s]\n",
- sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
- zQuery);
- goto end_data_xfer;
- }
- n = sqlite3_column_count(pQuery);
- zInsert = sqlite3_malloc64(200 + nTable + n*3);
- if( zInsert==0 ){
- raw_printf(stderr, "out of memory\n");
- goto end_data_xfer;
- }
- sqlite3_snprintf(200+nTable,zInsert,
- "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable);
- i = (int)strlen(zInsert);
- for(j=1; j<n; j++){
- memcpy(zInsert+i, ",?", 2);
- i += 2;
- }
- memcpy(zInsert+i, ");", 3);
- rc = sqlite3_prepare_v2(newDb, zInsert, -1, &pInsert, 0);
- if( rc ){
- utf8_printf(stderr, "Error %d: %s on [%s]\n",
- sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb),
- zQuery);
- goto end_data_xfer;
- }
- for(k=0; k<2; k++){
- while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
- for(i=0; i<n; i++){
- switch( sqlite3_column_type(pQuery, i) ){
- case SQLITE_NULL: {
- sqlite3_bind_null(pInsert, i+1);
- break;
- }
- case SQLITE_INTEGER: {
- sqlite3_bind_int64(pInsert, i+1, sqlite3_column_int64(pQuery,i));
- break;
- }
- case SQLITE_FLOAT: {
- sqlite3_bind_double(pInsert, i+1, sqlite3_column_double(pQuery,i));
- break;
- }
- case SQLITE_TEXT: {
- sqlite3_bind_text(pInsert, i+1,
- (const char*)sqlite3_column_text(pQuery,i),
- -1, SQLITE_STATIC);
- break;
- }
- case SQLITE_BLOB: {
- sqlite3_bind_blob(pInsert, i+1, sqlite3_column_blob(pQuery,i),
- sqlite3_column_bytes(pQuery,i),
- SQLITE_STATIC);
- break;
- }
- }
- } /* End for */
- rc = sqlite3_step(pInsert);
- if( rc!=SQLITE_OK && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
- utf8_printf(stderr, "Error %d: %s\n", sqlite3_extended_errcode(newDb),
- sqlite3_errmsg(newDb));
- }
- sqlite3_reset(pInsert);
- cnt++;
- if( (cnt%spinRate)==0 ){
- printf("%c\b", "|/-\\"[(cnt/spinRate)%4]);
- fflush(stdout);
- }
- } /* End while */
- if( rc==SQLITE_DONE ) break;
- sqlite3_finalize(pQuery);
- sqlite3_free(zQuery);
- zQuery = sqlite3_mprintf("SELECT * FROM \"%w\" ORDER BY rowid DESC;",
- zTable);
- rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
- if( rc ){
- utf8_printf(stderr, "Warning: cannot step \"%s\" backwards", zTable);
- break;
- }
- } /* End for(k=0...) */
-
-end_data_xfer:
- sqlite3_finalize(pQuery);
- sqlite3_finalize(pInsert);
- sqlite3_free(zQuery);
- sqlite3_free(zInsert);
-}
-
-
-/*
-** Try to transfer all rows of the schema that match zWhere. For
-** each row, invoke xForEach() on the object defined by that row.
-** If an error is encountered while moving forward through the
-** sqlite_master table, try again moving backwards.
-*/
-static void tryToCloneSchema(
- ShellState *p,
- sqlite3 *newDb,
- const char *zWhere,
- void (*xForEach)(ShellState*,sqlite3*,const char*)
-){
- sqlite3_stmt *pQuery = 0;
- char *zQuery = 0;
- int rc;
- const unsigned char *zName;
- const unsigned char *zSql;
- char *zErrMsg = 0;
-
- zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_master"
- " WHERE %s", zWhere);
- rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
- if( rc ){
- utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
- sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
- zQuery);
- goto end_schema_xfer;
- }
- while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
- zName = sqlite3_column_text(pQuery, 0);
- zSql = sqlite3_column_text(pQuery, 1);
- printf("%s... ", zName); fflush(stdout);
- sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
- if( zErrMsg ){
- utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
- sqlite3_free(zErrMsg);
- zErrMsg = 0;
- }
- if( xForEach ){
- xForEach(p, newDb, (const char*)zName);
- }
- printf("done\n");
- }
- if( rc!=SQLITE_DONE ){
- sqlite3_finalize(pQuery);
- sqlite3_free(zQuery);
- zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_master"
- " WHERE %s ORDER BY rowid DESC", zWhere);
- rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
- if( rc ){
- utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
- sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
- zQuery);
- goto end_schema_xfer;
- }
- while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
- zName = sqlite3_column_text(pQuery, 0);
- zSql = sqlite3_column_text(pQuery, 1);
- printf("%s... ", zName); fflush(stdout);
- sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
- if( zErrMsg ){
- utf8_printf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
- sqlite3_free(zErrMsg);
- zErrMsg = 0;
- }
- if( xForEach ){
- xForEach(p, newDb, (const char*)zName);
- }
- printf("done\n");
- }
- }
-end_schema_xfer:
- sqlite3_finalize(pQuery);
- sqlite3_free(zQuery);
-}
-
-/*
-** Open a new database file named "zNewDb". Try to recover as much information
-** as possible out of the main database (which might be corrupt) and write it
-** into zNewDb.
-*/
-static void tryToClone(ShellState *p, const char *zNewDb){
- int rc;
- sqlite3 *newDb = 0;
- if( access(zNewDb,0)==0 ){
- utf8_printf(stderr, "File \"%s\" already exists.\n", zNewDb);
- return;
- }
- rc = sqlite3_open(zNewDb, &newDb);
- if( rc ){
- utf8_printf(stderr, "Cannot create output database: %s\n",
- sqlite3_errmsg(newDb));
- }else{
- sqlite3_exec(p->db, "PRAGMA writable_schema=ON;", 0, 0, 0);
- sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0);
- tryToCloneSchema(p, newDb, "type='table'", tryToCloneData);
- tryToCloneSchema(p, newDb, "type!='table'", 0);
- sqlite3_exec(newDb, "COMMIT;", 0, 0, 0);
- sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
- }
- sqlite3_close(newDb);
-}
-
-/*
-** Change the output file back to stdout
-*/
-static void output_reset(ShellState *p){
- if( p->outfile[0]=='|' ){
-#ifndef SQLITE_OMIT_POPEN
- pclose(p->out);
-#endif
- }else{
- output_file_close(p->out);
- }
- p->outfile[0] = 0;
- p->out = stdout;
-}
-
-/*
-** Run an SQL command and return the single integer result.
-*/
-static int db_int(ShellState *p, const char *zSql){
- sqlite3_stmt *pStmt;
- int res = 0;
- sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
- if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
- res = sqlite3_column_int(pStmt,0);
- }
- sqlite3_finalize(pStmt);
- return res;
-}
-
-/*
-** Convert a 2-byte or 4-byte big-endian integer into a native integer
-*/
-static unsigned int get2byteInt(unsigned char *a){
- return (a[0]<<8) + a[1];
-}
-static unsigned int get4byteInt(unsigned char *a){
- return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + a[3];
-}
-
-/*
-** Implementation of the ".info" command.
-**
-** Return 1 on error, 2 to exit, and 0 otherwise.
-*/
-static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
- static const struct { const char *zName; int ofst; } aField[] = {
- { "file change counter:", 24 },
- { "database page count:", 28 },
- { "freelist page count:", 36 },
- { "schema cookie:", 40 },
- { "schema format:", 44 },
- { "default cache size:", 48 },
- { "autovacuum top root:", 52 },
- { "incremental vacuum:", 64 },
- { "text encoding:", 56 },
- { "user version:", 60 },
- { "application id:", 68 },
- { "software version:", 96 },
- };
- static const struct { const char *zName; const char *zSql; } aQuery[] = {
- { "number of tables:",
- "SELECT count(*) FROM %s WHERE type='table'" },
- { "number of indexes:",
- "SELECT count(*) FROM %s WHERE type='index'" },
- { "number of triggers:",
- "SELECT count(*) FROM %s WHERE type='trigger'" },
- { "number of views:",
- "SELECT count(*) FROM %s WHERE type='view'" },
- { "schema size:",
- "SELECT total(length(sql)) FROM %s" },
- };
- sqlite3_file *pFile = 0;
- int i;
- char *zSchemaTab;
- char *zDb = nArg>=2 ? azArg[1] : "main";
- unsigned char aHdr[100];
- open_db(p, 0);
- if( p->db==0 ) return 1;
- sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_FILE_POINTER, &pFile);
- if( pFile==0 || pFile->pMethods==0 || pFile->pMethods->xRead==0 ){
- return 1;
- }
- i = pFile->pMethods->xRead(pFile, aHdr, 100, 0);
- if( i!=SQLITE_OK ){
- raw_printf(stderr, "unable to read database header\n");
- return 1;
- }
- i = get2byteInt(aHdr+16);
- if( i==1 ) i = 65536;
- utf8_printf(p->out, "%-20s %d\n", "database page size:", i);
- utf8_printf(p->out, "%-20s %d\n", "write format:", aHdr[18]);
- utf8_printf(p->out, "%-20s %d\n", "read format:", aHdr[19]);
- utf8_printf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]);
- for(i=0; i<ArraySize(aField); i++){
- int ofst = aField[i].ofst;
- unsigned int val = get4byteInt(aHdr + ofst);
- utf8_printf(p->out, "%-20s %u", aField[i].zName, val);
- switch( ofst ){
- case 56: {
- if( val==1 ) raw_printf(p->out, " (utf8)");
- if( val==2 ) raw_printf(p->out, " (utf16le)");
- if( val==3 ) raw_printf(p->out, " (utf16be)");
- }
- }
- raw_printf(p->out, "\n");
- }
- if( zDb==0 ){
- zSchemaTab = sqlite3_mprintf("main.sqlite_master");
- }else if( strcmp(zDb,"temp")==0 ){
- zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_master");
- }else{
- zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_master", zDb);
- }
- for(i=0; i<ArraySize(aQuery); i++){
- char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
- int val = db_int(p, zSql);
- sqlite3_free(zSql);
- utf8_printf(p->out, "%-20s %d\n", aQuery[i].zName, val);
- }
- sqlite3_free(zSchemaTab);
- return 0;
-}
-
-/*
-** Print the current sqlite3_errmsg() value to stderr and return 1.
-*/
-static int shellDatabaseError(sqlite3 *db){
- const char *zErr = sqlite3_errmsg(db);
- utf8_printf(stderr, "Error: %s\n", zErr);
- return 1;
-}
-
-/*
-** Print an out-of-memory message to stderr and return 1.
-*/
-static int shellNomemError(void){
- raw_printf(stderr, "Error: out of memory\n");
- return 1;
-}
-
-/*
-** Compare the pattern in zGlob[] against the text in z[]. Return TRUE
-** if they match and FALSE (0) if they do not match.
-**
-** Globbing rules:
-**
-** '*' Matches any sequence of zero or more characters.
-**
-** '?' Matches exactly one character.
-**
-** [...] Matches one character from the enclosed list of
-** characters.
-**
-** [^...] Matches one character not in the enclosed list.
-**
-** '#' Matches any sequence of one or more digits with an
-** optional + or - sign in front
-**
-** ' ' Any span of whitespace matches any other span of
-** whitespace.
-**
-** Extra whitespace at the end of z[] is ignored.
-*/
-static int testcase_glob(const char *zGlob, const char *z){
- int c, c2;
- int invert;
- int seen;
-
- while( (c = (*(zGlob++)))!=0 ){
- if( IsSpace(c) ){
- if( !IsSpace(*z) ) return 0;
- while( IsSpace(*zGlob) ) zGlob++;
- while( IsSpace(*z) ) z++;
- }else if( c=='*' ){
- while( (c=(*(zGlob++))) == '*' || c=='?' ){
- if( c=='?' && (*(z++))==0 ) return 0;
- }
- if( c==0 ){
- return 1;
- }else if( c=='[' ){
- while( *z && testcase_glob(zGlob-1,z)==0 ){
- z++;
- }
- return (*z)!=0;
- }
- while( (c2 = (*(z++)))!=0 ){
- while( c2!=c ){
- c2 = *(z++);
- if( c2==0 ) return 0;
- }
- if( testcase_glob(zGlob,z) ) return 1;
- }
- return 0;
- }else if( c=='?' ){
- if( (*(z++))==0 ) return 0;
- }else if( c=='[' ){
- int prior_c = 0;
- seen = 0;
- invert = 0;
- c = *(z++);
- if( c==0 ) return 0;
- c2 = *(zGlob++);
- if( c2=='^' ){
- invert = 1;
- c2 = *(zGlob++);
- }
- if( c2==']' ){
- if( c==']' ) seen = 1;
- c2 = *(zGlob++);
- }
- while( c2 && c2!=']' ){
- if( c2=='-' && zGlob[0]!=']' && zGlob[0]!=0 && prior_c>0 ){
- c2 = *(zGlob++);
- if( c>=prior_c && c<=c2 ) seen = 1;
- prior_c = 0;
- }else{
- if( c==c2 ){
- seen = 1;
- }
- prior_c = c2;
- }
- c2 = *(zGlob++);
- }
- if( c2==0 || (seen ^ invert)==0 ) return 0;
- }else if( c=='#' ){
- if( (z[0]=='-' || z[0]=='+') && IsDigit(z[1]) ) z++;
- if( !IsDigit(z[0]) ) return 0;
- z++;
- while( IsDigit(z[0]) ){ z++; }
- }else{
- if( c!=(*(z++)) ) return 0;
- }
- }
- while( IsSpace(*z) ){ z++; }
- return *z==0;
-}
-
-
-/*
-** Compare the string as a command-line option with either one or two
-** initial "-" characters.
-*/
-static int optionMatch(const char *zStr, const char *zOpt){
- if( zStr[0]!='-' ) return 0;
- zStr++;
- if( zStr[0]=='-' ) zStr++;
- return strcmp(zStr, zOpt)==0;
-}
-
-/*
-** Delete a file.
-*/
-int shellDeleteFile(const char *zFilename){
- int rc;
-#ifdef _WIN32
- wchar_t *z = sqlite3_win32_utf8_to_unicode(zFilename);
- rc = _wunlink(z);
- sqlite3_free(z);
-#else
- rc = unlink(zFilename);
-#endif
- return rc;
-}
-
-
-/*
-** The implementation of SQL scalar function fkey_collate_clause(), used
-** by the ".lint fkey-indexes" command. This scalar function is always
-** called with four arguments - the parent table name, the parent column name,
-** the child table name and the child column name.
-**
-** fkey_collate_clause('parent-tab', 'parent-col', 'child-tab', 'child-col')
-**
-** If either of the named tables or columns do not exist, this function
-** returns an empty string. An empty string is also returned if both tables
-** and columns exist but have the same default collation sequence. Or,
-** if both exist but the default collation sequences are different, this
-** function returns the string " COLLATE <parent-collation>", where
-** <parent-collation> is the default collation sequence of the parent column.
-*/
-static void shellFkeyCollateClause(
- sqlite3_context *pCtx,
- int nVal,
- sqlite3_value **apVal
-){
- sqlite3 *db = sqlite3_context_db_handle(pCtx);
- const char *zParent;
- const char *zParentCol;
- const char *zParentSeq;
- const char *zChild;
- const char *zChildCol;
- const char *zChildSeq = 0; /* Initialize to avoid false-positive warning */
- int rc;
-
- assert( nVal==4 );
- zParent = (const char*)sqlite3_value_text(apVal[0]);
- zParentCol = (const char*)sqlite3_value_text(apVal[1]);
- zChild = (const char*)sqlite3_value_text(apVal[2]);
- zChildCol = (const char*)sqlite3_value_text(apVal[3]);
-
- sqlite3_result_text(pCtx, "", -1, SQLITE_STATIC);
- rc = sqlite3_table_column_metadata(
- db, "main", zParent, zParentCol, 0, &zParentSeq, 0, 0, 0
- );
- if( rc==SQLITE_OK ){
- rc = sqlite3_table_column_metadata(
- db, "main", zChild, zChildCol, 0, &zChildSeq, 0, 0, 0
- );
- }
-
- if( rc==SQLITE_OK && sqlite3_stricmp(zParentSeq, zChildSeq) ){
- char *z = sqlite3_mprintf(" COLLATE %s", zParentSeq);
- sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
- sqlite3_free(z);
- }
-}
-
-
-/*
-** The implementation of dot-command ".lint fkey-indexes".
-*/
-static int lintFkeyIndexes(
- ShellState *pState, /* Current shell tool state */
- char **azArg, /* Array of arguments passed to dot command */
- int nArg /* Number of entries in azArg[] */
-){
- sqlite3 *db = pState->db; /* Database handle to query "main" db of */
- FILE *out = pState->out; /* Stream to write non-error output to */
- int bVerbose = 0; /* If -verbose is present */
- int bGroupByParent = 0; /* If -groupbyparent is present */
- int i; /* To iterate through azArg[] */
- const char *zIndent = ""; /* How much to indent CREATE INDEX by */
- int rc; /* Return code */
- sqlite3_stmt *pSql = 0; /* Compiled version of SQL statement below */
-
- /*
- ** This SELECT statement returns one row for each foreign key constraint
- ** in the schema of the main database. The column values are:
- **
- ** 0. The text of an SQL statement similar to:
- **
- ** "EXPLAIN QUERY PLAN SELECT rowid FROM child_table WHERE child_key=?"
- **
- ** This is the same SELECT that the foreign keys implementation needs
- ** to run internally on child tables. If there is an index that can
- ** be used to optimize this query, then it can also be used by the FK
- ** implementation to optimize DELETE or UPDATE statements on the parent
- ** table.
- **
- ** 1. A GLOB pattern suitable for sqlite3_strglob(). If the plan output by
- ** the EXPLAIN QUERY PLAN command matches this pattern, then the schema
- ** contains an index that can be used to optimize the query.
- **
- ** 2. Human readable text that describes the child table and columns. e.g.
- **
- ** "child_table(child_key1, child_key2)"
- **
- ** 3. Human readable text that describes the parent table and columns. e.g.
- **
- ** "parent_table(parent_key1, parent_key2)"
- **
- ** 4. A full CREATE INDEX statement for an index that could be used to
- ** optimize DELETE or UPDATE statements on the parent table. e.g.
- **
- ** "CREATE INDEX child_table_child_key ON child_table(child_key)"
- **
- ** 5. The name of the parent table.
- **
- ** These six values are used by the C logic below to generate the report.
- */
- const char *zSql =
- "SELECT "
- " 'EXPLAIN QUERY PLAN SELECT rowid FROM ' || quote(s.name) || ' WHERE '"
- " || group_concat(quote(s.name) || '.' || quote(f.[from]) || '=?' "
- " || fkey_collate_clause("
- " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]),' AND ')"
- ", "
- " 'SEARCH TABLE ' || s.name || ' USING COVERING INDEX*('"
- " || group_concat('*=?', ' AND ') || ')'"
- ", "
- " s.name || '(' || group_concat(f.[from], ', ') || ')'"
- ", "
- " f.[table] || '(' || group_concat(COALESCE(f.[to], p.[name])) || ')'"
- ", "
- " 'CREATE INDEX ' || quote(s.name ||'_'|| group_concat(f.[from], '_'))"
- " || ' ON ' || quote(s.name) || '('"
- " || group_concat(quote(f.[from]) ||"
- " fkey_collate_clause("
- " f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]), ', ')"
- " || ');'"
- ", "
- " f.[table] "
- "FROM sqlite_master AS s, pragma_foreign_key_list(s.name) AS f "
- "LEFT JOIN pragma_table_info AS p ON (pk-1=seq AND p.arg=f.[table]) "
- "GROUP BY s.name, f.id "
- "ORDER BY (CASE WHEN ? THEN f.[table] ELSE s.name END)"
- ;
- const char *zGlobIPK = "SEARCH TABLE * USING INTEGER PRIMARY KEY (rowid=?)";
-
- for(i=2; i<nArg; i++){
- int n = (int)strlen(azArg[i]);
- if( n>1 && sqlite3_strnicmp("-verbose", azArg[i], n)==0 ){
- bVerbose = 1;
- }
- else if( n>1 && sqlite3_strnicmp("-groupbyparent", azArg[i], n)==0 ){
- bGroupByParent = 1;
- zIndent = " ";
- }
- else{
- raw_printf(stderr, "Usage: %s %s ?-verbose? ?-groupbyparent?\n",
- azArg[0], azArg[1]
- );
- return SQLITE_ERROR;
- }
- }
-
- /* Register the fkey_collate_clause() SQL function */
- rc = sqlite3_create_function(db, "fkey_collate_clause", 4, SQLITE_UTF8,
- 0, shellFkeyCollateClause, 0, 0
- );
-
-
- if( rc==SQLITE_OK ){
- rc = sqlite3_prepare_v2(db, zSql, -1, &pSql, 0);
- }
- if( rc==SQLITE_OK ){
- sqlite3_bind_int(pSql, 1, bGroupByParent);
- }
-
- if( rc==SQLITE_OK ){
- int rc2;
- char *zPrev = 0;
- while( SQLITE_ROW==sqlite3_step(pSql) ){
- int res = -1;
- sqlite3_stmt *pExplain = 0;
- const char *zEQP = (const char*)sqlite3_column_text(pSql, 0);
- const char *zGlob = (const char*)sqlite3_column_text(pSql, 1);
- const char *zFrom = (const char*)sqlite3_column_text(pSql, 2);
- const char *zTarget = (const char*)sqlite3_column_text(pSql, 3);
- const char *zCI = (const char*)sqlite3_column_text(pSql, 4);
- const char *zParent = (const char*)sqlite3_column_text(pSql, 5);
-
- rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
- if( rc!=SQLITE_OK ) break;
- if( SQLITE_ROW==sqlite3_step(pExplain) ){
- const char *zPlan = (const char*)sqlite3_column_text(pExplain, 3);
- res = (
- 0==sqlite3_strglob(zGlob, zPlan)
- || 0==sqlite3_strglob(zGlobIPK, zPlan)
- );
- }
- rc = sqlite3_finalize(pExplain);
- if( rc!=SQLITE_OK ) break;
-
- if( res<0 ){
- raw_printf(stderr, "Error: internal error");
- break;
- }else{
- if( bGroupByParent
- && (bVerbose || res==0)
- && (zPrev==0 || sqlite3_stricmp(zParent, zPrev))
- ){
- raw_printf(out, "-- Parent table %s\n", zParent);
- sqlite3_free(zPrev);
- zPrev = sqlite3_mprintf("%s", zParent);
- }
-
- if( res==0 ){
- raw_printf(out, "%s%s --> %s\n", zIndent, zCI, zTarget);
- }else if( bVerbose ){
- raw_printf(out, "%s/* no extra indexes required for %s -> %s */\n",
- zIndent, zFrom, zTarget
- );
- }
- }
- }
- sqlite3_free(zPrev);
-
- if( rc!=SQLITE_OK ){
- raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
- }
-
- rc2 = sqlite3_finalize(pSql);
- if( rc==SQLITE_OK && rc2!=SQLITE_OK ){
- rc = rc2;
- raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
- }
- }else{
- raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
- }
-
- return rc;
-}
-
-/*
-** Implementation of ".lint" dot command.
-*/
-static int lintDotCommand(
- ShellState *pState, /* Current shell tool state */
- char **azArg, /* Array of arguments passed to dot command */
- int nArg /* Number of entries in azArg[] */
-){
- int n;
- n = (nArg>=2 ? (int)strlen(azArg[1]) : 0);
- if( n<1 || sqlite3_strnicmp(azArg[1], "fkey-indexes", n) ) goto usage;
- return lintFkeyIndexes(pState, azArg, nArg);
-
- usage:
- raw_printf(stderr, "Usage %s sub-command ?switches...?\n", azArg[0]);
- raw_printf(stderr, "Where sub-commands are:\n");
- raw_printf(stderr, " fkey-indexes\n");
- return SQLITE_ERROR;
-}
-
-
-/*
-** If an input line begins with "." then invoke this routine to
-** process that line.
-**
-** Return 1 on error, 2 to exit, and 0 otherwise.
-*/
-static int do_meta_command(char *zLine, ShellState *p){
- int h = 1;
- int nArg = 0;
- int n, c;
- int rc = 0;
- char *azArg[50];
-
- /* Parse the input line into tokens.
- */
- while( zLine[h] && nArg<ArraySize(azArg) ){
- while( IsSpace(zLine[h]) ){ h++; }
- if( zLine[h]==0 ) break;
- if( zLine[h]=='\'' || zLine[h]=='"' ){
- int delim = zLine[h++];
- azArg[nArg++] = &zLine[h];
- while( zLine[h] && zLine[h]!=delim ){
- if( zLine[h]=='\\' && delim=='"' && zLine[h+1]!=0 ) h++;
- h++;
- }
- if( zLine[h]==delim ){
- zLine[h++] = 0;
- }
- if( delim=='"' ) resolve_backslashes(azArg[nArg-1]);
- }else{
- azArg[nArg++] = &zLine[h];
- while( zLine[h] && !IsSpace(zLine[h]) ){ h++; }
- if( zLine[h] ) zLine[h++] = 0;
- resolve_backslashes(azArg[nArg-1]);
- }
- }
-
- /* Process the input line.
- */
- if( nArg==0 ) return 0; /* no tokens, no error */
- n = strlen30(azArg[0]);
- c = azArg[0][0];
-
-#ifndef SQLITE_OMIT_AUTHORIZATION
- if( c=='a' && strncmp(azArg[0], "auth", n)==0 ){
- if( nArg!=2 ){
- raw_printf(stderr, "Usage: .auth ON|OFF\n");
- rc = 1;
- goto meta_command_exit;
- }
- open_db(p, 0);
- if( booleanValue(azArg[1]) ){
- sqlite3_set_authorizer(p->db, shellAuth, p);
- }else{
- sqlite3_set_authorizer(p->db, 0, 0);
- }
- }else
-#endif
-
- if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0)
- || (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0)
- ){
- const char *zDestFile = 0;
- const char *zDb = 0;
- sqlite3 *pDest;
- sqlite3_backup *pBackup;
- int j;
- for(j=1; j<nArg; j++){
- const char *z = azArg[j];
- if( z[0]=='-' ){
- while( z[0]=='-' ) z++;
- /* No options to process at this time */
- {
- utf8_printf(stderr, "unknown option: %s\n", azArg[j]);
- return 1;
- }
- }else if( zDestFile==0 ){
- zDestFile = azArg[j];
- }else if( zDb==0 ){
- zDb = zDestFile;
- zDestFile = azArg[j];
- }else{
- raw_printf(stderr, "too many arguments to .backup\n");
- return 1;
- }
- }
- if( zDestFile==0 ){
- raw_printf(stderr, "missing FILENAME argument on .backup\n");
- return 1;
- }
- if( zDb==0 ) zDb = "main";
- rc = sqlite3_open(zDestFile, &pDest);
- if( rc!=SQLITE_OK ){
- utf8_printf(stderr, "Error: cannot open \"%s\"\n", zDestFile);
- sqlite3_close(pDest);
- return 1;
- }
- open_db(p, 0);
- pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);
- if( pBackup==0 ){
- utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
- sqlite3_close(pDest);
- return 1;
- }
- while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){}
- sqlite3_backup_finish(pBackup);
- if( rc==SQLITE_DONE ){
- rc = 0;
- }else{
- utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
- rc = 1;
- }
- sqlite3_close(pDest);
- }else
-
- if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){
- if( nArg==2 ){
- bail_on_error = booleanValue(azArg[1]);
- }else{
- raw_printf(stderr, "Usage: .bail on|off\n");
- rc = 1;
- }
- }else
-
- if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){
- if( nArg==2 ){
- if( booleanValue(azArg[1]) ){
- setBinaryMode(p->out, 1);
- }else{
- setTextMode(p->out, 1);
- }
- }else{
- raw_printf(stderr, "Usage: .binary on|off\n");
- rc = 1;
- }
- }else
-
- if( c=='c' && strcmp(azArg[0],"cd")==0 ){
- if( nArg==2 ){
-#if defined(_WIN32) || defined(WIN32)
- wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]);
- rc = !SetCurrentDirectoryW(z);
- sqlite3_free(z);
-#else
- rc = chdir(azArg[1]);
-#endif
- if( rc ){
- utf8_printf(stderr, "Cannot change to directory \"%s\"\n", azArg[1]);
- rc = 1;
- }
- }else{
- raw_printf(stderr, "Usage: .cd DIRECTORY\n");
- rc = 1;
- }
- }else
-
- /* The undocumented ".breakpoint" command causes a call to the no-op
- ** routine named test_breakpoint().
- */
- if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){
- test_breakpoint();
- }else
-
- if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){
- if( nArg==2 ){
- setOrClearFlag(p, SHFLG_CountChanges, azArg[1]);
- }else{
- raw_printf(stderr, "Usage: .changes on|off\n");
- rc = 1;
- }
- }else
-
- /* Cancel output redirection, if it is currently set (by .testcase)
- ** Then read the content of the testcase-out.txt file and compare against
- ** azArg[1]. If there are differences, report an error and exit.
- */
- if( c=='c' && n>=3 && strncmp(azArg[0], "check", n)==0 ){
- char *zRes = 0;
- output_reset(p);
- if( nArg!=2 ){
- raw_printf(stderr, "Usage: .check GLOB-PATTERN\n");
- rc = 2;
- }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){
- raw_printf(stderr, "Error: cannot read 'testcase-out.txt'\n");
- rc = 2;
- }else if( testcase_glob(azArg[1],zRes)==0 ){
- utf8_printf(stderr,
- "testcase-%s FAILED\n Expected: [%s]\n Got: [%s]\n",
- p->zTestcase, azArg[1], zRes);
- rc = 2;
- }else{
- utf8_printf(stdout, "testcase-%s ok\n", p->zTestcase);
- p->nCheck++;
- }
- sqlite3_free(zRes);
- }else
-
- if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){
- if( nArg==2 ){
- tryToClone(p, azArg[1]);
- }else{
- raw_printf(stderr, "Usage: .clone FILENAME\n");
- rc = 1;
- }
- }else
-
- if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
- ShellState data;
- char *zErrMsg = 0;
- open_db(p, 0);
- memcpy(&data, p, sizeof(data));
- data.showHeader = 0;
- data.cMode = data.mode = MODE_List;
- sqlite3_snprintf(sizeof(data.colSeparator),data.colSeparator,": ");
- data.cnt = 0;
- sqlite3_exec(p->db, "SELECT name, file FROM pragma_database_list",
- callback, &data, &zErrMsg);
- if( zErrMsg ){
- utf8_printf(stderr,"Error: %s\n", zErrMsg);
- sqlite3_free(zErrMsg);
- rc = 1;
- }
- }else
-
- if( c=='d' && strncmp(azArg[0], "dbinfo", n)==0 ){
- rc = shell_dbinfo_command(p, nArg, azArg);
- }else
-
- if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
- const char *zLike = 0;
- int i;
- int savedShowHeader = p->showHeader;
- ShellClearFlag(p, SHFLG_PreserveRowid|SHFLG_Newlines);
- for(i=1; i<nArg; i++){
- if( azArg[i][0]=='-' ){
- const char *z = azArg[i]+1;
- if( z[0]=='-' ) z++;
- if( strcmp(z,"preserve-rowids")==0 ){
-#ifdef SQLITE_OMIT_VIRTUALTABLE
- raw_printf(stderr, "The --preserve-rowids option is not compatible"
- " with SQLITE_OMIT_VIRTUALTABLE\n");
- rc = 1;
- goto meta_command_exit;
-#else
- ShellSetFlag(p, SHFLG_PreserveRowid);
-#endif
- }else
- if( strcmp(z,"newlines")==0 ){
- ShellSetFlag(p, SHFLG_Newlines);
- }else
- {
- raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
- rc = 1;
- goto meta_command_exit;
- }
- }else if( zLike ){
- raw_printf(stderr, "Usage: .dump ?--preserve-rowids? "
- "?--newlines? ?LIKE-PATTERN?\n");
- rc = 1;
- goto meta_command_exit;
- }else{
- zLike = azArg[i];
- }
- }
- open_db(p, 0);
- /* When playing back a "dump", the content might appear in an order
- ** which causes immediate foreign key constraints to be violated.
- ** So disable foreign-key constraint enforcement to prevent problems. */
- raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
- raw_printf(p->out, "BEGIN TRANSACTION;\n");
- p->writableSchema = 0;
- p->showHeader = 0;
- /* Set writable_schema=ON since doing so forces SQLite to initialize
- ** as much of the schema as it can even if the sqlite_master table is
- ** corrupt. */
- sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
- p->nErr = 0;
- if( zLike==0 ){
- run_schema_dump_query(p,
- "SELECT name, type, sql FROM sqlite_master "
- "WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'"
- );
- run_schema_dump_query(p,
- "SELECT name, type, sql FROM sqlite_master "
- "WHERE name=='sqlite_sequence'"
- );
- run_table_dump_query(p,
- "SELECT sql FROM sqlite_master "
- "WHERE sql NOT NULL AND type IN ('index','trigger','view')", 0
- );
- }else{
- char *zSql;
- zSql = sqlite3_mprintf(
- "SELECT name, type, sql FROM sqlite_master "
- "WHERE tbl_name LIKE %Q AND type=='table'"
- " AND sql NOT NULL", zLike);
- run_schema_dump_query(p,zSql);
- sqlite3_free(zSql);
- zSql = sqlite3_mprintf(
- "SELECT sql FROM sqlite_master "
- "WHERE sql NOT NULL"
- " AND type IN ('index','trigger','view')"
- " AND tbl_name LIKE %Q", zLike);
- run_table_dump_query(p, zSql, 0);
- sqlite3_free(zSql);
- }
- if( p->writableSchema ){
- raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
- p->writableSchema = 0;
- }
- sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
- sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
- raw_printf(p->out, p->nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n");
- p->showHeader = savedShowHeader;
- }else
-
- if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){
- if( nArg==2 ){
- setOrClearFlag(p, SHFLG_Echo, azArg[1]);
- }else{
- raw_printf(stderr, "Usage: .echo on|off\n");
- rc = 1;
- }
- }else
-
- if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){
- if( nArg==2 ){
- if( strcmp(azArg[1],"full")==0 ){
- p->autoEQP = 2;
- }else{
- p->autoEQP = booleanValue(azArg[1]);
- }
- }else{
- raw_printf(stderr, "Usage: .eqp on|off|full\n");
- rc = 1;
- }
- }else
-
- if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
- if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
- rc = 2;
- }else
-
- /* The ".explain" command is automatic now. It is largely pointless. It
- ** retained purely for backwards compatibility */
- if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
- int val = 1;
- if( nArg>=2 ){
- if( strcmp(azArg[1],"auto")==0 ){
- val = 99;
- }else{
- val = booleanValue(azArg[1]);
- }
- }
- if( val==1 && p->mode!=MODE_Explain ){
- p->normalMode = p->mode;
- p->mode = MODE_Explain;
- p->autoExplain = 0;
- }else if( val==0 ){
- if( p->mode==MODE_Explain ) p->mode = p->normalMode;
- p->autoExplain = 0;
- }else if( val==99 ){
- if( p->mode==MODE_Explain ) p->mode = p->normalMode;
- p->autoExplain = 1;
- }
- }else
-
- if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){
- ShellState data;
- char *zErrMsg = 0;
- int doStats = 0;
- memcpy(&data, p, sizeof(data));
- data.showHeader = 0;
- data.cMode = data.mode = MODE_Semi;
- if( nArg==2 && optionMatch(azArg[1], "indent") ){
- data.cMode = data.mode = MODE_Pretty;
- nArg = 1;
- }
- if( nArg!=1 ){
- raw_printf(stderr, "Usage: .fullschema ?--indent?\n");
- rc = 1;
- goto meta_command_exit;
- }
- open_db(p, 0);
- rc = sqlite3_exec(p->db,
- "SELECT sql FROM"
- " (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
- " FROM sqlite_master UNION ALL"
- " SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) "
- "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
- "ORDER BY rowid",
- callback, &data, &zErrMsg
- );
- if( rc==SQLITE_OK ){
- sqlite3_stmt *pStmt;
- rc = sqlite3_prepare_v2(p->db,
- "SELECT rowid FROM sqlite_master"
- " WHERE name GLOB 'sqlite_stat[134]'",
- -1, &pStmt, 0);
- doStats = sqlite3_step(pStmt)==SQLITE_ROW;
- sqlite3_finalize(pStmt);
- }
- if( doStats==0 ){
- raw_printf(p->out, "/* No STAT tables available */\n");
- }else{
- raw_printf(p->out, "ANALYZE sqlite_master;\n");
- sqlite3_exec(p->db, "SELECT 'ANALYZE sqlite_master'",
- callback, &data, &zErrMsg);
- data.cMode = data.mode = MODE_Insert;
- data.zDestTable = "sqlite_stat1";
- shell_exec(p->db, "SELECT * FROM sqlite_stat1",
- shell_callback, &data,&zErrMsg);
- data.zDestTable = "sqlite_stat3";
- shell_exec(p->db, "SELECT * FROM sqlite_stat3",
- shell_callback, &data,&zErrMsg);
- data.zDestTable = "sqlite_stat4";
- shell_exec(p->db, "SELECT * FROM sqlite_stat4",
- shell_callback, &data, &zErrMsg);
- raw_printf(p->out, "ANALYZE sqlite_master;\n");
- }
- }else
-
- if( c=='h' && strncmp(azArg[0], "headers", n)==0 ){
- if( nArg==2 ){
- p->showHeader = booleanValue(azArg[1]);
- }else{
- raw_printf(stderr, "Usage: .headers on|off\n");
- rc = 1;
- }
- }else
-
- if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
- utf8_printf(p->out, "%s", zHelp);
- }else
-
- if( c=='i' && strncmp(azArg[0], "import", n)==0 ){
- char *zTable; /* Insert data into this table */
- char *zFile; /* Name of file to extra content from */
- sqlite3_stmt *pStmt = NULL; /* A statement */
- int nCol; /* Number of columns in the table */
- int nByte; /* Number of bytes in an SQL string */
- int i, j; /* Loop counters */
- int needCommit; /* True to COMMIT or ROLLBACK at end */
- int nSep; /* Number of bytes in p->colSeparator[] */
- char *zSql; /* An SQL statement */
- ImportCtx sCtx; /* Reader context */
- char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
- int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close file */
-
- if( nArg!=3 ){
- raw_printf(stderr, "Usage: .import FILE TABLE\n");
- goto meta_command_exit;
- }
- zFile = azArg[1];
- zTable = azArg[2];
- seenInterrupt = 0;
- memset(&sCtx, 0, sizeof(sCtx));
- open_db(p, 0);
- nSep = strlen30(p->colSeparator);
- if( nSep==0 ){
- raw_printf(stderr,
- "Error: non-null column separator required for import\n");
- return 1;
- }
- if( nSep>1 ){
- raw_printf(stderr, "Error: multi-character column separators not allowed"
- " for import\n");
- return 1;
- }
- nSep = strlen30(p->rowSeparator);
- if( nSep==0 ){
- raw_printf(stderr, "Error: non-null row separator required for import\n");
- return 1;
- }
- if( nSep==2 && p->mode==MODE_Csv && strcmp(p->rowSeparator, SEP_CrLf)==0 ){
- /* When importing CSV (only), if the row separator is set to the
- ** default output row separator, change it to the default input
- ** row separator. This avoids having to maintain different input
- ** and output row separators. */
- sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
- nSep = strlen30(p->rowSeparator);
- }
- if( nSep>1 ){
- raw_printf(stderr, "Error: multi-character row separators not allowed"
- " for import\n");
- return 1;
- }
- sCtx.zFile = zFile;
- sCtx.nLine = 1;
- if( sCtx.zFile[0]=='|' ){
-#ifdef SQLITE_OMIT_POPEN
- raw_printf(stderr, "Error: pipes are not supported in this OS\n");
- return 1;
-#else
- sCtx.in = popen(sCtx.zFile+1, "r");
- sCtx.zFile = "<pipe>";
- xCloser = pclose;
-#endif
- }else{
- sCtx.in = fopen(sCtx.zFile, "rb");
- xCloser = fclose;
- }
- if( p->mode==MODE_Ascii ){
- xRead = ascii_read_one_field;
- }else{
- xRead = csv_read_one_field;
- }
- if( sCtx.in==0 ){
- utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
- return 1;
- }
- sCtx.cColSep = p->colSeparator[0];
- sCtx.cRowSep = p->rowSeparator[0];
- zSql = sqlite3_mprintf("SELECT * FROM %s", zTable);
- if( zSql==0 ){
- raw_printf(stderr, "Error: out of memory\n");
- xCloser(sCtx.in);
- return 1;
- }
- nByte = strlen30(zSql);
- rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
- import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
- if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
- char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable);
- char cSep = '(';
- while( xRead(&sCtx) ){
- zCreate = sqlite3_mprintf("%z%c\n \"%w\" TEXT", zCreate, cSep, sCtx.z);
- cSep = ',';
- if( sCtx.cTerm!=sCtx.cColSep ) break;
- }
- if( cSep=='(' ){
- sqlite3_free(zCreate);
- sqlite3_free(sCtx.z);
- xCloser(sCtx.in);
- utf8_printf(stderr,"%s: empty file\n", sCtx.zFile);
- return 1;
- }
- zCreate = sqlite3_mprintf("%z\n)", zCreate);
- rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
- sqlite3_free(zCreate);
- if( rc ){
- utf8_printf(stderr, "CREATE TABLE %s(...) failed: %s\n", zTable,
- sqlite3_errmsg(p->db));
- sqlite3_free(sCtx.z);
- xCloser(sCtx.in);
- return 1;
- }
- rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
- }
- sqlite3_free(zSql);
- if( rc ){
- if (pStmt) sqlite3_finalize(pStmt);
- utf8_printf(stderr,"Error: %s\n", sqlite3_errmsg(p->db));
- xCloser(sCtx.in);
- return 1;
- }
- nCol = sqlite3_column_count(pStmt);
- sqlite3_finalize(pStmt);
- pStmt = 0;
- if( nCol==0 ) return 0; /* no columns, no error */
- zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 );
- if( zSql==0 ){
- raw_printf(stderr, "Error: out of memory\n");
- xCloser(sCtx.in);
- return 1;
- }
- sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);
- j = strlen30(zSql);
- for(i=1; i<nCol; i++){
- zSql[j++] = ',';
- zSql[j++] = '?';
- }
- zSql[j++] = ')';
- zSql[j] = 0;
- rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
- sqlite3_free(zSql);
- if( rc ){
- utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
- if (pStmt) sqlite3_finalize(pStmt);
- xCloser(sCtx.in);
- return 1;
- }
- needCommit = sqlite3_get_autocommit(p->db);
- if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
- do{
- int startLine = sCtx.nLine;
- for(i=0; i<nCol; i++){
- char *z = xRead(&sCtx);
- /*
- ** Did we reach end-of-file before finding any columns?
- ** If so, stop instead of NULL filling the remaining columns.
- */
- if( z==0 && i==0 ) break;
- /*
- ** Did we reach end-of-file OR end-of-line before finding any
- ** columns in ASCII mode? If so, stop instead of NULL filling
- ** the remaining columns.
- */
- if( p->mode==MODE_Ascii && (z==0 || z[0]==0) && i==0 ) break;
- sqlite3_bind_text(pStmt, i+1, z, -1, SQLITE_TRANSIENT);
- if( i<nCol-1 && sCtx.cTerm!=sCtx.cColSep ){
- utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
- "filling the rest with NULL\n",
- sCtx.zFile, startLine, nCol, i+1);
- i += 2;
- while( i<=nCol ){ sqlite3_bind_null(pStmt, i); i++; }
- }
- }
- if( sCtx.cTerm==sCtx.cColSep ){
- do{
- xRead(&sCtx);
- i++;
- }while( sCtx.cTerm==sCtx.cColSep );
- utf8_printf(stderr, "%s:%d: expected %d columns but found %d - "
- "extras ignored\n",
- sCtx.zFile, startLine, nCol, i);
- }
- if( i>=nCol ){
- sqlite3_step(pStmt);
- rc = sqlite3_reset(pStmt);
- if( rc!=SQLITE_OK ){
- utf8_printf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile,
- startLine, sqlite3_errmsg(p->db));
- }
- }
- }while( sCtx.cTerm!=EOF );
-
- xCloser(sCtx.in);
- sqlite3_free(sCtx.z);
- sqlite3_finalize(pStmt);
- if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
- }else
-
-#ifndef SQLITE_UNTESTABLE
- if( c=='i' && strncmp(azArg[0], "imposter", n)==0 ){
- char *zSql;
- char *zCollist = 0;
- sqlite3_stmt *pStmt;
- int tnum = 0;
- int i;
- if( nArg!=3 ){
- utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n");
- rc = 1;
- goto meta_command_exit;
- }
- open_db(p, 0);
- zSql = sqlite3_mprintf("SELECT rootpage FROM sqlite_master"
- " WHERE name='%q' AND type='index'", azArg[1]);
- sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
- sqlite3_free(zSql);
- if( sqlite3_step(pStmt)==SQLITE_ROW ){
- tnum = sqlite3_column_int(pStmt, 0);
- }
- sqlite3_finalize(pStmt);
- if( tnum==0 ){
- utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]);
- rc = 1;
- goto meta_command_exit;
- }
- zSql = sqlite3_mprintf("PRAGMA index_xinfo='%q'", azArg[1]);
- rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
- sqlite3_free(zSql);
- i = 0;
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- char zLabel[20];
- const char *zCol = (const char*)sqlite3_column_text(pStmt,2);
- i++;
- if( zCol==0 ){
- if( sqlite3_column_int(pStmt,1)==-1 ){
- zCol = "_ROWID_";
- }else{
- sqlite3_snprintf(sizeof(zLabel),zLabel,"expr%d",i);
- zCol = zLabel;
- }
- }
- if( zCollist==0 ){
- zCollist = sqlite3_mprintf("\"%w\"", zCol);
- }else{
- zCollist = sqlite3_mprintf("%z,\"%w\"", zCollist, zCol);
- }
- }
- sqlite3_finalize(pStmt);
- zSql = sqlite3_mprintf(
- "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%s))WITHOUT ROWID",
- azArg[2], zCollist, zCollist);
- sqlite3_free(zCollist);
- rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum);
- if( rc==SQLITE_OK ){
- rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
- sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0);
- if( rc ){
- utf8_printf(stderr, "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db));
- }else{
- utf8_printf(stdout, "%s;\n", zSql);
- raw_printf(stdout,
- "WARNING: writing to an imposter table will corrupt the index!\n"
- );
- }
- }else{
- raw_printf(stderr, "SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc);
- rc = 1;
- }
- sqlite3_free(zSql);
- }else
-#endif /* !defined(SQLITE_OMIT_TEST_CONTROL) */
-
-#ifdef SQLITE_ENABLE_IOTRACE
- if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){
- SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...);
- if( iotrace && iotrace!=stdout ) fclose(iotrace);
- iotrace = 0;
- if( nArg<2 ){
- sqlite3IoTrace = 0;
- }else if( strcmp(azArg[1], "-")==0 ){
- sqlite3IoTrace = iotracePrintf;
- iotrace = stdout;
- }else{
- iotrace = fopen(azArg[1], "w");
- if( iotrace==0 ){
- utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
- sqlite3IoTrace = 0;
- rc = 1;
- }else{
- sqlite3IoTrace = iotracePrintf;
- }
- }
- }else
-#endif
-
- if( c=='l' && n>=5 && strncmp(azArg[0], "limits", n)==0 ){
- static const struct {
- const char *zLimitName; /* Name of a limit */
- int limitCode; /* Integer code for that limit */
- } aLimit[] = {
- { "length", SQLITE_LIMIT_LENGTH },
- { "sql_length", SQLITE_LIMIT_SQL_LENGTH },
- { "column", SQLITE_LIMIT_COLUMN },
- { "expr_depth", SQLITE_LIMIT_EXPR_DEPTH },
- { "compound_select", SQLITE_LIMIT_COMPOUND_SELECT },
- { "vdbe_op", SQLITE_LIMIT_VDBE_OP },
- { "function_arg", SQLITE_LIMIT_FUNCTION_ARG },
- { "attached", SQLITE_LIMIT_ATTACHED },
- { "like_pattern_length", SQLITE_LIMIT_LIKE_PATTERN_LENGTH },
- { "variable_number", SQLITE_LIMIT_VARIABLE_NUMBER },
- { "trigger_depth", SQLITE_LIMIT_TRIGGER_DEPTH },
- { "worker_threads", SQLITE_LIMIT_WORKER_THREADS },
- };
- int i, n2;
- open_db(p, 0);
- if( nArg==1 ){
- for(i=0; i<ArraySize(aLimit); i++){
- printf("%20s %d\n", aLimit[i].zLimitName,
- sqlite3_limit(p->db, aLimit[i].limitCode, -1));
- }
- }else if( nArg>3 ){
- raw_printf(stderr, "Usage: .limit NAME ?NEW-VALUE?\n");
- rc = 1;
- goto meta_command_exit;
- }else{
- int iLimit = -1;
- n2 = strlen30(azArg[1]);
- for(i=0; i<ArraySize(aLimit); i++){
- if( sqlite3_strnicmp(aLimit[i].zLimitName, azArg[1], n2)==0 ){
- if( iLimit<0 ){
- iLimit = i;
- }else{
- utf8_printf(stderr, "ambiguous limit: \"%s\"\n", azArg[1]);
- rc = 1;
- goto meta_command_exit;
- }
- }
- }
- if( iLimit<0 ){
- utf8_printf(stderr, "unknown limit: \"%s\"\n"
- "enter \".limits\" with no arguments for a list.\n",
- azArg[1]);
- rc = 1;
- goto meta_command_exit;
- }
- if( nArg==3 ){
- sqlite3_limit(p->db, aLimit[iLimit].limitCode,
- (int)integerValue(azArg[2]));
- }
- printf("%20s %d\n", aLimit[iLimit].zLimitName,
- sqlite3_limit(p->db, aLimit[iLimit].limitCode, -1));
- }
- }else
-
- if( c=='l' && n>2 && strncmp(azArg[0], "lint", n)==0 ){
- open_db(p, 0);
- lintDotCommand(p, azArg, nArg);
- }else
-
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
- if( c=='l' && strncmp(azArg[0], "load", n)==0 ){
- const char *zFile, *zProc;
- char *zErrMsg = 0;
- if( nArg<2 ){
- raw_printf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n");
- rc = 1;
- goto meta_command_exit;
- }
- zFile = azArg[1];
- zProc = nArg>=3 ? azArg[2] : 0;
- open_db(p, 0);
- rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg);
- if( rc!=SQLITE_OK ){
- utf8_printf(stderr, "Error: %s\n", zErrMsg);
- sqlite3_free(zErrMsg);
- rc = 1;
- }
- }else
-#endif
-
- if( c=='l' && strncmp(azArg[0], "log", n)==0 ){
- if( nArg!=2 ){
- raw_printf(stderr, "Usage: .log FILENAME\n");
- rc = 1;
- }else{
- const char *zFile = azArg[1];
- output_file_close(p->pLog);
- p->pLog = output_file_open(zFile);
- }
- }else
-
- if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){
- const char *zMode = nArg>=2 ? azArg[1] : "";
- int n2 = (int)strlen(zMode);
- int c2 = zMode[0];
- if( c2=='l' && n2>2 && strncmp(azArg[1],"lines",n2)==0 ){
- p->mode = MODE_Line;
- sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
- }else if( c2=='c' && strncmp(azArg[1],"columns",n2)==0 ){
- p->mode = MODE_Column;
- sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
- }else if( c2=='l' && n2>2 && strncmp(azArg[1],"list",n2)==0 ){
- p->mode = MODE_List;
- sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Column);
- sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
- }else if( c2=='h' && strncmp(azArg[1],"html",n2)==0 ){
- p->mode = MODE_Html;
- }else if( c2=='t' && strncmp(azArg[1],"tcl",n2)==0 ){
- p->mode = MODE_Tcl;
- sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Space);
- sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
- }else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){
- p->mode = MODE_Csv;
- sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
- sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
- }else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){
- p->mode = MODE_List;
- sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab);
- }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){
- p->mode = MODE_Insert;
- set_table_name(p, nArg>=3 ? azArg[2] : "table");
- }else if( c2=='q' && strncmp(azArg[1],"quote",n2)==0 ){
- p->mode = MODE_Quote;
- }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){
- p->mode = MODE_Ascii;
- sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit);
- sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
- }else if( nArg==1 ){
- raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]);
- }else{
- raw_printf(stderr, "Error: mode should be one of: "
- "ascii column csv html insert line list quote tabs tcl\n");
- rc = 1;
- }
- p->cMode = p->mode;
- }else
-
- if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){
- if( nArg==2 ){
- sqlite3_snprintf(sizeof(p->nullValue), p->nullValue,
- "%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]);
- }else{
- raw_printf(stderr, "Usage: .nullvalue STRING\n");
- rc = 1;
- }
- }else
-
- if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
- char *zNewFilename; /* Name of the database file to open */
- int iName = 1; /* Index in azArg[] of the filename */
- int newFlag = 0; /* True to delete file before opening */
- /* Close the existing database */
- session_close_all(p);
- sqlite3_close(p->db);
- p->db = 0;
- p->zDbFilename = 0;
- sqlite3_free(p->zFreeOnClose);
- p->zFreeOnClose = 0;
- /* Check for command-line arguments */
- for(iName=1; iName<nArg && azArg[iName][0]=='-'; iName++){
- const char *z = azArg[iName];
- if( optionMatch(z,"new") ){
- newFlag = 1;
- }else if( z[0]=='-' ){
- utf8_printf(stderr, "unknown option: %s\n", z);
- rc = 1;
- goto meta_command_exit;
- }
- }
- /* If a filename is specified, try to open it first */
- zNewFilename = nArg>iName ? sqlite3_mprintf("%s", azArg[iName]) : 0;
- if( zNewFilename ){
- if( newFlag ) shellDeleteFile(zNewFilename);
- p->zDbFilename = zNewFilename;
- open_db(p, 1);
- if( p->db==0 ){
- utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename);
- sqlite3_free(zNewFilename);
- }else{
- p->zFreeOnClose = zNewFilename;
- }
- }
- if( p->db==0 ){
- /* As a fall-back open a TEMP database */
- p->zDbFilename = 0;
- open_db(p, 0);
- }
- }else
-
- if( c=='o'
- && (strncmp(azArg[0], "output", n)==0 || strncmp(azArg[0], "once", n)==0)
- ){
- const char *zFile = nArg>=2 ? azArg[1] : "stdout";
- if( nArg>2 ){
- utf8_printf(stderr, "Usage: .%s FILE\n", azArg[0]);
- rc = 1;
- goto meta_command_exit;
- }
- if( n>1 && strncmp(azArg[0], "once", n)==0 ){
- if( nArg<2 ){
- raw_printf(stderr, "Usage: .once FILE\n");
- rc = 1;
- goto meta_command_exit;
- }
- p->outCount = 2;
- }else{
- p->outCount = 0;
- }
- output_reset(p);
- if( zFile[0]=='|' ){
-#ifdef SQLITE_OMIT_POPEN
- raw_printf(stderr, "Error: pipes are not supported in this OS\n");
- rc = 1;
- p->out = stdout;
-#else
- p->out = popen(zFile + 1, "w");
- if( p->out==0 ){
- utf8_printf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1);
- p->out = stdout;
- rc = 1;
- }else{
- sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
- }
-#endif
- }else{
- p->out = output_file_open(zFile);
- if( p->out==0 ){
- if( strcmp(zFile,"off")!=0 ){
- utf8_printf(stderr,"Error: cannot write to \"%s\"\n", zFile);
- }
- p->out = stdout;
- rc = 1;
- } else {
- sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
- }
- }
- }else
-
- if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){
- int i;
- for(i=1; i<nArg; i++){
- if( i>1 ) raw_printf(p->out, " ");
- utf8_printf(p->out, "%s", azArg[i]);
- }
- raw_printf(p->out, "\n");
- }else
-
- if( c=='p' && strncmp(azArg[0], "prompt", n)==0 ){
- if( nArg >= 2) {
- strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
- }
- if( nArg >= 3) {
- strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1);
- }
- }else
-
- if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){
- rc = 2;
- }else
-
- if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){
- FILE *alt;
- if( nArg!=2 ){
- raw_printf(stderr, "Usage: .read FILE\n");
- rc = 1;
- goto meta_command_exit;
- }
- alt = fopen(azArg[1], "rb");
- if( alt==0 ){
- utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
- rc = 1;
- }else{
- rc = process_input(p, alt);
- fclose(alt);
- }
- }else
-
- if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 ){
- const char *zSrcFile;
- const char *zDb;
- sqlite3 *pSrc;
- sqlite3_backup *pBackup;
- int nTimeout = 0;
-
- if( nArg==2 ){
- zSrcFile = azArg[1];
- zDb = "main";
- }else if( nArg==3 ){
- zSrcFile = azArg[2];
- zDb = azArg[1];
- }else{
- raw_printf(stderr, "Usage: .restore ?DB? FILE\n");
- rc = 1;
- goto meta_command_exit;
- }
- rc = sqlite3_open(zSrcFile, &pSrc);
- if( rc!=SQLITE_OK ){
- utf8_printf(stderr, "Error: cannot open \"%s\"\n", zSrcFile);
- sqlite3_close(pSrc);
- return 1;
- }
- open_db(p, 0);
- pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main");
- if( pBackup==0 ){
- utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
- sqlite3_close(pSrc);
- return 1;
- }
- while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK
- || rc==SQLITE_BUSY ){
- if( rc==SQLITE_BUSY ){
- if( nTimeout++ >= 3 ) break;
- sqlite3_sleep(100);
- }
- }
- sqlite3_backup_finish(pBackup);
- if( rc==SQLITE_DONE ){
- rc = 0;
- }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){
- raw_printf(stderr, "Error: source database is busy\n");
- rc = 1;
- }else{
- utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
- rc = 1;
- }
- sqlite3_close(pSrc);
- }else
-
-
- if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){
- if( nArg==2 ){
- p->scanstatsOn = booleanValue(azArg[1]);
-#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
- raw_printf(stderr, "Warning: .scanstats not available in this build.\n");
-#endif
- }else{
- raw_printf(stderr, "Usage: .scanstats on|off\n");
- rc = 1;
- }
- }else
-
- if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
- ShellText sSelect;
- ShellState data;
- char *zErrMsg = 0;
- const char *zDiv = 0;
- int iSchema = 0;
-
- open_db(p, 0);
- memcpy(&data, p, sizeof(data));
- data.showHeader = 0;
- data.cMode = data.mode = MODE_Semi;
- initText(&sSelect);
- if( nArg>=2 && optionMatch(azArg[1], "indent") ){
- data.cMode = data.mode = MODE_Pretty;
- nArg--;
- if( nArg==2 ) azArg[1] = azArg[2];
- }
- if( nArg==2 && azArg[1][0]!='-' ){
- int i;
- for(i=0; azArg[1][i]; i++) azArg[1][i] = ToLower(azArg[1][i]);
- if( strcmp(azArg[1],"sqlite_master")==0 ){
- char *new_argv[2], *new_colv[2];
- new_argv[0] = "CREATE TABLE sqlite_master (\n"
- " type text,\n"
- " name text,\n"
- " tbl_name text,\n"
- " rootpage integer,\n"
- " sql text\n"
- ")";
- new_argv[1] = 0;
- new_colv[0] = "sql";
- new_colv[1] = 0;
- callback(&data, 1, new_argv, new_colv);
- rc = SQLITE_OK;
- }else if( strcmp(azArg[1],"sqlite_temp_master")==0 ){
- char *new_argv[2], *new_colv[2];
- new_argv[0] = "CREATE TEMP TABLE sqlite_temp_master (\n"
- " type text,\n"
- " name text,\n"
- " tbl_name text,\n"
- " rootpage integer,\n"
- " sql text\n"
- ")";
- new_argv[1] = 0;
- new_colv[0] = "sql";
- new_colv[1] = 0;
- callback(&data, 1, new_argv, new_colv);
- rc = SQLITE_OK;
- }else{
- zDiv = "(";
- }
- }else if( nArg==1 ){
- zDiv = "(";
- }else{
- raw_printf(stderr, "Usage: .schema ?--indent? ?LIKE-PATTERN?\n");
- rc = 1;
- goto meta_command_exit;
- }
- if( zDiv ){
- sqlite3_stmt *pStmt = 0;
- rc = sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list",
- -1, &pStmt, 0);
- if( rc ){
- utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
- sqlite3_finalize(pStmt);
- rc = 1;
- goto meta_command_exit;
- }
- appendText(&sSelect, "SELECT sql FROM", 0);
- iSchema = 0;
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- const char *zDb = (const char*)sqlite3_column_text(pStmt, 0);
- char zScNum[30];
- sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema);
- appendText(&sSelect, zDiv, 0);
- zDiv = " UNION ALL ";
- if( strcmp(zDb, "main")!=0 ){
- appendText(&sSelect, "SELECT shell_add_schema(sql,", 0);
- appendText(&sSelect, zDb, '"');
- appendText(&sSelect, ") AS sql, type, tbl_name, name, rowid,", 0);
- appendText(&sSelect, zScNum, 0);
- appendText(&sSelect, " AS snum, ", 0);
- appendText(&sSelect, zDb, '\'');
- appendText(&sSelect, " AS sname FROM ", 0);
- appendText(&sSelect, zDb, '"');
- appendText(&sSelect, ".sqlite_master", 0);
- }else{
- appendText(&sSelect, "SELECT sql, type, tbl_name, name, rowid, ", 0);
- appendText(&sSelect, zScNum, 0);
- appendText(&sSelect, " AS snum, 'main' AS sname FROM sqlite_master",0);
- }
- }
- sqlite3_finalize(pStmt);
- appendText(&sSelect, ") WHERE ", 0);
- if( nArg>1 ){
- char *zQarg = sqlite3_mprintf("%Q", azArg[1]);
- if( strchr(azArg[1], '.') ){
- appendText(&sSelect, "lower(printf('%s.%s',sname,tbl_name))", 0);
- }else{
- appendText(&sSelect, "lower(tbl_name)", 0);
- }
- appendText(&sSelect, strchr(azArg[1], '*') ? " GLOB " : " LIKE ", 0);
- appendText(&sSelect, zQarg, 0);
- appendText(&sSelect, " AND ", 0);
- sqlite3_free(zQarg);
- }
- appendText(&sSelect, "type!='meta' AND sql IS NOT NULL"
- " ORDER BY snum, rowid", 0);
- rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg);
- freeText(&sSelect);
- }
- if( zErrMsg ){
- utf8_printf(stderr,"Error: %s\n", zErrMsg);
- sqlite3_free(zErrMsg);
- rc = 1;
- }else if( rc != SQLITE_OK ){
- raw_printf(stderr,"Error: querying schema information\n");
- rc = 1;
- }else{
- rc = 0;
- }
- }else
-
-#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
- if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){
- sqlite3SelectTrace = (int)integerValue(azArg[1]);
- }else
-#endif
-
-#if defined(SQLITE_ENABLE_SESSION)
- if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){
- OpenSession *pSession = &p->aSession[0];
- char **azCmd = &azArg[1];
- int iSes = 0;
- int nCmd = nArg - 1;
- int i;
- if( nArg<=1 ) goto session_syntax_error;
- open_db(p, 0);
- if( nArg>=3 ){
- for(iSes=0; iSes<p->nSession; iSes++){
- if( strcmp(p->aSession[iSes].zName, azArg[1])==0 ) break;
- }
- if( iSes<p->nSession ){
- pSession = &p->aSession[iSes];
- azCmd++;
- nCmd--;
- }else{
- pSession = &p->aSession[0];
- iSes = 0;
- }
- }
-
- /* .session attach TABLE
- ** Invoke the sqlite3session_attach() interface to attach a particular
- ** table so that it is never filtered.
- */
- if( strcmp(azCmd[0],"attach")==0 ){
- if( nCmd!=2 ) goto session_syntax_error;
- if( pSession->p==0 ){
- session_not_open:
- raw_printf(stderr, "ERROR: No sessions are open\n");
- }else{
- rc = sqlite3session_attach(pSession->p, azCmd[1]);
- if( rc ){
- raw_printf(stderr, "ERROR: sqlite3session_attach() returns %d\n", rc);
- rc = 0;
- }
- }
- }else
-
- /* .session changeset FILE
- ** .session patchset FILE
- ** Write a changeset or patchset into a file. The file is overwritten.
- */
- if( strcmp(azCmd[0],"changeset")==0 || strcmp(azCmd[0],"patchset")==0 ){
- FILE *out = 0;
- if( nCmd!=2 ) goto session_syntax_error;
- if( pSession->p==0 ) goto session_not_open;
- out = fopen(azCmd[1], "wb");
- if( out==0 ){
- utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n", azCmd[1]);
- }else{
- int szChng;
- void *pChng;
- if( azCmd[0][0]=='c' ){
- rc = sqlite3session_changeset(pSession->p, &szChng, &pChng);
- }else{
- rc = sqlite3session_patchset(pSession->p, &szChng, &pChng);
- }
- if( rc ){
- printf("Error: error code %d\n", rc);
- rc = 0;
- }
- if( pChng
- && fwrite(pChng, szChng, 1, out)!=1 ){
- raw_printf(stderr, "ERROR: Failed to write entire %d-byte output\n",
- szChng);
- }
- sqlite3_free(pChng);
- fclose(out);
- }
- }else
-
- /* .session close
- ** Close the identified session
- */
- if( strcmp(azCmd[0], "close")==0 ){
- if( nCmd!=1 ) goto session_syntax_error;
- if( p->nSession ){
- session_close(pSession);
- p->aSession[iSes] = p->aSession[--p->nSession];
- }
- }else
-
- /* .session enable ?BOOLEAN?
- ** Query or set the enable flag
- */
- if( strcmp(azCmd[0], "enable")==0 ){
- int ii;
- if( nCmd>2 ) goto session_syntax_error;
- ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
- if( p->nSession ){
- ii = sqlite3session_enable(pSession->p, ii);
- utf8_printf(p->out, "session %s enable flag = %d\n",
- pSession->zName, ii);
- }
- }else
-
- /* .session filter GLOB ....
- ** Set a list of GLOB patterns of table names to be excluded.
- */
- if( strcmp(azCmd[0], "filter")==0 ){
- int ii, nByte;
- if( nCmd<2 ) goto session_syntax_error;
- if( p->nSession ){
- for(ii=0; ii<pSession->nFilter; ii++){
- sqlite3_free(pSession->azFilter[ii]);
- }
- sqlite3_free(pSession->azFilter);
- nByte = sizeof(pSession->azFilter[0])*(nCmd-1);
- pSession->azFilter = sqlite3_malloc( nByte );
- if( pSession->azFilter==0 ){
- raw_printf(stderr, "Error: out or memory\n");
- exit(1);
- }
- for(ii=1; ii<nCmd; ii++){
- pSession->azFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]);
- }
- pSession->nFilter = ii-1;
- }
- }else
-
- /* .session indirect ?BOOLEAN?
- ** Query or set the indirect flag
- */
- if( strcmp(azCmd[0], "indirect")==0 ){
- int ii;
- if( nCmd>2 ) goto session_syntax_error;
- ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
- if( p->nSession ){
- ii = sqlite3session_indirect(pSession->p, ii);
- utf8_printf(p->out, "session %s indirect flag = %d\n",
- pSession->zName, ii);
- }
- }else
-
- /* .session isempty
- ** Determine if the session is empty
- */
- if( strcmp(azCmd[0], "isempty")==0 ){
- int ii;
- if( nCmd!=1 ) goto session_syntax_error;
- if( p->nSession ){
- ii = sqlite3session_isempty(pSession->p);
- utf8_printf(p->out, "session %s isempty flag = %d\n",
- pSession->zName, ii);
- }
- }else
-
- /* .session list
- ** List all currently open sessions
- */
- if( strcmp(azCmd[0],"list")==0 ){
- for(i=0; i<p->nSession; i++){
- utf8_printf(p->out, "%d %s\n", i, p->aSession[i].zName);
- }
- }else
-
- /* .session open DB NAME
- ** Open a new session called NAME on the attached database DB.
- ** DB is normally "main".
- */
- if( strcmp(azCmd[0],"open")==0 ){
- char *zName;
- if( nCmd!=3 ) goto session_syntax_error;
- zName = azCmd[2];
- if( zName[0]==0 ) goto session_syntax_error;
- for(i=0; i<p->nSession; i++){
- if( strcmp(p->aSession[i].zName,zName)==0 ){
- utf8_printf(stderr, "Session \"%s\" already exists\n", zName);
- goto meta_command_exit;
- }
- }
- if( p->nSession>=ArraySize(p->aSession) ){
- raw_printf(stderr, "Maximum of %d sessions\n", ArraySize(p->aSession));
- goto meta_command_exit;
- }
- pSession = &p->aSession[p->nSession];
- rc = sqlite3session_create(p->db, azCmd[1], &pSession->p);
- if( rc ){
- raw_printf(stderr, "Cannot open session: error code=%d\n", rc);
- rc = 0;
- goto meta_command_exit;
- }
- pSession->nFilter = 0;
- sqlite3session_table_filter(pSession->p, session_filter, pSession);
- p->nSession++;
- pSession->zName = sqlite3_mprintf("%s", zName);
- }else
- /* If no command name matches, show a syntax error */
- session_syntax_error:
- session_help(p);
- }else
-#endif
-
-#ifdef SQLITE_DEBUG
- /* Undocumented commands for internal testing. Subject to change
- ** without notice. */
- if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){
- if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){
- int i, v;
- for(i=1; i<nArg; i++){
- v = booleanValue(azArg[i]);
- utf8_printf(p->out, "%s: %d 0x%x\n", azArg[i], v, v);
- }
- }
- if( strncmp(azArg[0]+9, "integer", n-9)==0 ){
- int i; sqlite3_int64 v;
- for(i=1; i<nArg; i++){
- char zBuf[200];
- v = integerValue(azArg[i]);
- sqlite3_snprintf(sizeof(zBuf),zBuf,"%s: %lld 0x%llx\n", azArg[i],v,v);
- utf8_printf(p->out, "%s", zBuf);
- }
- }
- }else
-#endif
-
- if( c=='s' && n>=4 && strncmp(azArg[0],"selftest",n)==0 ){
- int bIsInit = 0; /* True to initialize the SELFTEST table */
- int bVerbose = 0; /* Verbose output */
- int bSelftestExists; /* True if SELFTEST already exists */
- int i, k; /* Loop counters */
- int nTest = 0; /* Number of tests runs */
- int nErr = 0; /* Number of errors seen */
- ShellText str; /* Answer for a query */
- sqlite3_stmt *pStmt = 0; /* Query against the SELFTEST table */
-
- open_db(p,0);
- for(i=1; i<nArg; i++){
- const char *z = azArg[i];
- if( z[0]=='-' && z[1]=='-' ) z++;
- if( strcmp(z,"-init")==0 ){
- bIsInit = 1;
- }else
- if( strcmp(z,"-v")==0 ){
- bVerbose++;
- }else
- {
- utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
- azArg[i], azArg[0]);
- raw_printf(stderr, "Should be one of: --init -v\n");
- rc = 1;
- goto meta_command_exit;
- }
- }
- if( sqlite3_table_column_metadata(p->db,"main","selftest",0,0,0,0,0,0)
- != SQLITE_OK ){
- bSelftestExists = 0;
- }else{
- bSelftestExists = 1;
- }
- if( bIsInit ){
- createSelftestTable(p);
- bSelftestExists = 1;
- }
- initText(&str);
- appendText(&str, "x", 0);
- for(k=bSelftestExists; k>=0; k--){
- if( k==1 ){
- rc = sqlite3_prepare_v2(p->db,
- "SELECT tno,op,cmd,ans FROM selftest ORDER BY tno",
- -1, &pStmt, 0);
- }else{
- rc = sqlite3_prepare_v2(p->db,
- "VALUES(0,'memo','Missing SELFTEST table - default checks only',''),"
- " (1,'run','PRAGMA integrity_check','ok')",
- -1, &pStmt, 0);
- }
- if( rc ){
- raw_printf(stderr, "Error querying the selftest table\n");
- rc = 1;
- sqlite3_finalize(pStmt);
- goto meta_command_exit;
- }
- for(i=1; sqlite3_step(pStmt)==SQLITE_ROW; i++){
- int tno = sqlite3_column_int(pStmt, 0);
- const char *zOp = (const char*)sqlite3_column_text(pStmt, 1);
- const char *zSql = (const char*)sqlite3_column_text(pStmt, 2);
- const char *zAns = (const char*)sqlite3_column_text(pStmt, 3);
-
- k = 0;
- if( bVerbose>0 ){
- char *zQuote = sqlite3_mprintf("%q", zSql);
- printf("%d: %s %s\n", tno, zOp, zSql);
- sqlite3_free(zQuote);
- }
- if( strcmp(zOp,"memo")==0 ){
- utf8_printf(p->out, "%s\n", zSql);
- }else
- if( strcmp(zOp,"run")==0 ){
- char *zErrMsg = 0;
- str.n = 0;
- str.z[0] = 0;
- rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg);
- nTest++;
- if( bVerbose ){
- utf8_printf(p->out, "Result: %s\n", str.z);
- }
- if( rc || zErrMsg ){
- nErr++;
- rc = 1;
- utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg);
- sqlite3_free(zErrMsg);
- }else if( strcmp(zAns,str.z)!=0 ){
- nErr++;
- rc = 1;
- utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns);
- utf8_printf(p->out, "%d: Got: [%s]\n", tno, str.z);
- }
- }else
- {
- utf8_printf(stderr,
- "Unknown operation \"%s\" on selftest line %d\n", zOp, tno);
- rc = 1;
- break;
- }
- } /* End loop over rows of content from SELFTEST */
- sqlite3_finalize(pStmt);
- } /* End loop over k */
- freeText(&str);
- utf8_printf(p->out, "%d errors out of %d tests\n", nErr, nTest);
- }else
-
- if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){
- if( nArg<2 || nArg>3 ){
- raw_printf(stderr, "Usage: .separator COL ?ROW?\n");
- rc = 1;
- }
- if( nArg>=2 ){
- sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator,
- "%.*s", (int)ArraySize(p->colSeparator)-1, azArg[1]);
- }
- if( nArg>=3 ){
- sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator,
- "%.*s", (int)ArraySize(p->rowSeparator)-1, azArg[2]);
- }
- }else
-
- if( c=='s' && n>=4 && strncmp(azArg[0],"sha3sum",n)==0 ){
- const char *zLike = 0; /* Which table to checksum. 0 means everything */
- int i; /* Loop counter */
- int bSchema = 0; /* Also hash the schema */
- int bSeparate = 0; /* Hash each table separately */
- int iSize = 224; /* Hash algorithm to use */
- int bDebug = 0; /* Only show the query that would have run */
- sqlite3_stmt *pStmt; /* For querying tables names */
- char *zSql; /* SQL to be run */
- char *zSep; /* Separator */
- ShellText sSql; /* Complete SQL for the query to run the hash */
- ShellText sQuery; /* Set of queries used to read all content */
- open_db(p, 0);
- for(i=1; i<nArg; i++){
- const char *z = azArg[i];
- if( z[0]=='-' ){
- z++;
- if( z[0]=='-' ) z++;
- if( strcmp(z,"schema")==0 ){
- bSchema = 1;
- }else
- if( strcmp(z,"sha3-224")==0 || strcmp(z,"sha3-256")==0
- || strcmp(z,"sha3-384")==0 || strcmp(z,"sha3-512")==0
- ){
- iSize = atoi(&z[5]);
- }else
- if( strcmp(z,"debug")==0 ){
- bDebug = 1;
- }else
- {
- utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
- azArg[i], azArg[0]);
- raw_printf(stderr, "Should be one of: --schema"
- " --sha3-224 --sha3-255 --sha3-384 --sha3-512\n");
- rc = 1;
- goto meta_command_exit;
- }
- }else if( zLike ){
- raw_printf(stderr, "Usage: .sha3sum ?OPTIONS? ?LIKE-PATTERN?\n");
- rc = 1;
- goto meta_command_exit;
- }else{
- zLike = z;
- bSeparate = 1;
- if( sqlite3_strlike("sqlite_%", zLike, 0)==0 ) bSchema = 1;
- }
- }
- if( bSchema ){
- zSql = "SELECT lower(name) FROM sqlite_master"
- " WHERE type='table' AND coalesce(rootpage,0)>1"
- " UNION ALL SELECT 'sqlite_master'"
- " ORDER BY 1 collate nocase";
- }else{
- zSql = "SELECT lower(name) FROM sqlite_master"
- " WHERE type='table' AND coalesce(rootpage,0)>1"
- " AND name NOT LIKE 'sqlite_%'"
- " ORDER BY 1 collate nocase";
- }
- sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
- initText(&sQuery);
- initText(&sSql);
- appendText(&sSql, "WITH [sha3sum$query](a,b) AS(",0);
- zSep = "VALUES(";
- while( SQLITE_ROW==sqlite3_step(pStmt) ){
- const char *zTab = (const char*)sqlite3_column_text(pStmt,0);
- if( zLike && sqlite3_strlike(zLike, zTab, 0)!=0 ) continue;
- if( strncmp(zTab, "sqlite_",7)!=0 ){
- appendText(&sQuery,"SELECT * FROM ", 0);
- appendText(&sQuery,zTab,'"');
- appendText(&sQuery," NOT INDEXED;", 0);
- }else if( strcmp(zTab, "sqlite_master")==0 ){
- appendText(&sQuery,"SELECT type,name,tbl_name,sql FROM sqlite_master"
- " ORDER BY name;", 0);
- }else if( strcmp(zTab, "sqlite_sequence")==0 ){
- appendText(&sQuery,"SELECT name,seq FROM sqlite_sequence"
- " ORDER BY name;", 0);
- }else if( strcmp(zTab, "sqlite_stat1")==0 ){
- appendText(&sQuery,"SELECT tbl,idx,stat FROM sqlite_stat1"
- " ORDER BY tbl,idx;", 0);
- }else if( strcmp(zTab, "sqlite_stat3")==0
- || strcmp(zTab, "sqlite_stat4")==0 ){
- appendText(&sQuery, "SELECT * FROM ", 0);
- appendText(&sQuery, zTab, 0);
- appendText(&sQuery, " ORDER BY tbl, idx, rowid;\n", 0);
- }
- appendText(&sSql, zSep, 0);
- appendText(&sSql, sQuery.z, '\'');
- sQuery.n = 0;
- appendText(&sSql, ",", 0);
- appendText(&sSql, zTab, '\'');
- zSep = "),(";
- }
- sqlite3_finalize(pStmt);
- if( bSeparate ){
- zSql = sqlite3_mprintf(
- "%s))"
- " SELECT lower(hex(sha3_query(a,%d))) AS hash, b AS label"
- " FROM [sha3sum$query]",
- sSql.z, iSize);
- }else{
- zSql = sqlite3_mprintf(
- "%s))"
- " SELECT lower(hex(sha3_query(group_concat(a,''),%d))) AS hash"
- " FROM [sha3sum$query]",
- sSql.z, iSize);
- }
- freeText(&sQuery);
- freeText(&sSql);
- if( bDebug ){
- utf8_printf(p->out, "%s\n", zSql);
- }else{
- shell_exec(p->db, zSql, shell_callback, p, 0);
- }
- sqlite3_free(zSql);
- }else
-
- if( c=='s'
- && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
- ){
- char *zCmd;
- int i, x;
- if( nArg<2 ){
- raw_printf(stderr, "Usage: .system COMMAND\n");
- rc = 1;
- goto meta_command_exit;
- }
- zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
- for(i=2; i<nArg; i++){
- zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
- zCmd, azArg[i]);
- }
- x = system(zCmd);
- sqlite3_free(zCmd);
- if( x ) raw_printf(stderr, "System command returns %d\n", x);
- }else
-
- if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
- static const char *azBool[] = { "off", "on", "full", "unk" };
- int i;
- if( nArg!=1 ){
- raw_printf(stderr, "Usage: .show\n");
- rc = 1;
- goto meta_command_exit;
- }
- utf8_printf(p->out, "%12.12s: %s\n","echo",
- azBool[ShellHasFlag(p, SHFLG_Echo)]);
- utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]);
- utf8_printf(p->out, "%12.12s: %s\n","explain",
- p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off");
- utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]);
- utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]);
- utf8_printf(p->out, "%12.12s: ", "nullvalue");
- output_c_string(p->out, p->nullValue);
- raw_printf(p->out, "\n");
- utf8_printf(p->out,"%12.12s: %s\n","output",
- strlen30(p->outfile) ? p->outfile : "stdout");
- utf8_printf(p->out,"%12.12s: ", "colseparator");
- output_c_string(p->out, p->colSeparator);
- raw_printf(p->out, "\n");
- utf8_printf(p->out,"%12.12s: ", "rowseparator");
- output_c_string(p->out, p->rowSeparator);
- raw_printf(p->out, "\n");
- utf8_printf(p->out, "%12.12s: %s\n","stats", azBool[p->statsOn!=0]);
- utf8_printf(p->out, "%12.12s: ", "width");
- for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) {
- raw_printf(p->out, "%d ", p->colWidth[i]);
- }
- raw_printf(p->out, "\n");
- utf8_printf(p->out, "%12.12s: %s\n", "filename",
- p->zDbFilename ? p->zDbFilename : "");
- }else
-
- if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){
- if( nArg==2 ){
- p->statsOn = booleanValue(azArg[1]);
- }else if( nArg==1 ){
- display_stats(p->db, p, 0);
- }else{
- raw_printf(stderr, "Usage: .stats ?on|off?\n");
- rc = 1;
- }
- }else
-
- if( (c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0)
- || (c=='i' && (strncmp(azArg[0], "indices", n)==0
- || strncmp(azArg[0], "indexes", n)==0) )
- ){
- sqlite3_stmt *pStmt;
- char **azResult;
- int nRow, nAlloc;
- int ii;
- ShellText s;
- initText(&s);
- open_db(p, 0);
- rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
- if( rc ) return shellDatabaseError(p->db);
-
- if( nArg>2 && c=='i' ){
- /* It is an historical accident that the .indexes command shows an error
- ** when called with the wrong number of arguments whereas the .tables
- ** command does not. */
- raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");
- rc = 1;
- goto meta_command_exit;
- }
- for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){
- const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1);
- if( zDbName==0 ) continue;
- if( s.z && s.z[0] ) appendText(&s, " UNION ALL ", 0);
- if( sqlite3_stricmp(zDbName, "main")==0 ){
- appendText(&s, "SELECT name FROM ", 0);
- }else{
- appendText(&s, "SELECT ", 0);
- appendText(&s, zDbName, '\'');
- appendText(&s, "||'.'||name FROM ", 0);
- }
- appendText(&s, zDbName, '"');
- appendText(&s, ".sqlite_master ", 0);
- if( c=='t' ){
- appendText(&s," WHERE type IN ('table','view')"
- " AND name NOT LIKE 'sqlite_%'"
- " AND name LIKE ?1", 0);
- }else{
- appendText(&s," WHERE type='index'"
- " AND tbl_name LIKE ?1", 0);
- }
- }
- rc = sqlite3_finalize(pStmt);
- appendText(&s, " ORDER BY 1", 0);
- rc = sqlite3_prepare_v2(p->db, s.z, -1, &pStmt, 0);
- freeText(&s);
- if( rc ) return shellDatabaseError(p->db);
-
- /* Run the SQL statement prepared by the above block. Store the results
- ** as an array of nul-terminated strings in azResult[]. */
- nRow = nAlloc = 0;
- azResult = 0;
- if( nArg>1 ){
- sqlite3_bind_text(pStmt, 1, azArg[1], -1, SQLITE_TRANSIENT);
- }else{
- sqlite3_bind_text(pStmt, 1, "%", -1, SQLITE_STATIC);
- }
- while( sqlite3_step(pStmt)==SQLITE_ROW ){
- if( nRow>=nAlloc ){
- char **azNew;
- int n2 = nAlloc*2 + 10;
- azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2);
- if( azNew==0 ){
- rc = shellNomemError();
- break;
- }
- nAlloc = n2;
- azResult = azNew;
- }
- azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
- if( 0==azResult[nRow] ){
- rc = shellNomemError();
- break;
- }
- nRow++;
- }
- if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
- rc = shellDatabaseError(p->db);
- }
-
- /* Pretty-print the contents of array azResult[] to the output */
- if( rc==0 && nRow>0 ){
- int len, maxlen = 0;
- int i, j;
- int nPrintCol, nPrintRow;
- for(i=0; i<nRow; i++){
- len = strlen30(azResult[i]);
- if( len>maxlen ) maxlen = len;
- }
- nPrintCol = 80/(maxlen+2);
- if( nPrintCol<1 ) nPrintCol = 1;
- nPrintRow = (nRow + nPrintCol - 1)/nPrintCol;
- for(i=0; i<nPrintRow; i++){
- for(j=i; j<nRow; j+=nPrintRow){
- char *zSp = j<nPrintRow ? "" : " ";
- utf8_printf(p->out, "%s%-*s", zSp, maxlen,
- azResult[j] ? azResult[j]:"");
- }
- raw_printf(p->out, "\n");
- }
- }
-
- for(ii=0; ii<nRow; ii++) sqlite3_free(azResult[ii]);
- sqlite3_free(azResult);
- }else
-
- /* Begin redirecting output to the file "testcase-out.txt" */
- if( c=='t' && strcmp(azArg[0],"testcase")==0 ){
- output_reset(p);
- p->out = output_file_open("testcase-out.txt");
- if( p->out==0 ){
- raw_printf(stderr, "Error: cannot open 'testcase-out.txt'\n");
- }
- if( nArg>=2 ){
- sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]);
- }else{
- sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?");
- }
- }else
-
-#ifndef SQLITE_UNTESTABLE
- if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 && nArg>=2 ){
- static const struct {
- const char *zCtrlName; /* Name of a test-control option */
- int ctrlCode; /* Integer code for that option */
- } aCtrl[] = {
- { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE },
- { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE },
- { "prng_reset", SQLITE_TESTCTRL_PRNG_RESET },
- { "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST },
- { "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL },
- { "benign_malloc_hooks", SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS },
- { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE },
- { "assert", SQLITE_TESTCTRL_ASSERT },
- { "always", SQLITE_TESTCTRL_ALWAYS },
- { "reserve", SQLITE_TESTCTRL_RESERVE },
- { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS },
- { "iskeyword", SQLITE_TESTCTRL_ISKEYWORD },
- { "scratchmalloc", SQLITE_TESTCTRL_SCRATCHMALLOC },
- { "byteorder", SQLITE_TESTCTRL_BYTEORDER },
- { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT },
- { "imposter", SQLITE_TESTCTRL_IMPOSTER },
- };
- int testctrl = -1;
- int rc2 = 0;
- int i, n2;
- open_db(p, 0);
-
- /* convert testctrl text option to value. allow any unique prefix
- ** of the option name, or a numerical value. */
- n2 = strlen30(azArg[1]);
- for(i=0; i<ArraySize(aCtrl); i++){
- if( strncmp(azArg[1], aCtrl[i].zCtrlName, n2)==0 ){
- if( testctrl<0 ){
- testctrl = aCtrl[i].ctrlCode;
- }else{
- utf8_printf(stderr, "ambiguous option name: \"%s\"\n", azArg[1]);
- testctrl = -1;
- break;
- }
- }
- }
- if( testctrl<0 ) testctrl = (int)integerValue(azArg[1]);
- if( (testctrl<SQLITE_TESTCTRL_FIRST) || (testctrl>SQLITE_TESTCTRL_LAST) ){
- utf8_printf(stderr,"Error: invalid testctrl option: %s\n", azArg[1]);
- }else{
- switch(testctrl){
-
- /* sqlite3_test_control(int, db, int) */
- case SQLITE_TESTCTRL_OPTIMIZATIONS:
- case SQLITE_TESTCTRL_RESERVE:
- if( nArg==3 ){
- int opt = (int)strtol(azArg[2], 0, 0);
- rc2 = sqlite3_test_control(testctrl, p->db, opt);
- raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2);
- } else {
- utf8_printf(stderr,"Error: testctrl %s takes a single int option\n",
- azArg[1]);
- }
- break;
-
- /* sqlite3_test_control(int) */
- case SQLITE_TESTCTRL_PRNG_SAVE:
- case SQLITE_TESTCTRL_PRNG_RESTORE:
- case SQLITE_TESTCTRL_PRNG_RESET:
- case SQLITE_TESTCTRL_BYTEORDER:
- if( nArg==2 ){
- rc2 = sqlite3_test_control(testctrl);
- raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2);
- } else {
- utf8_printf(stderr,"Error: testctrl %s takes no options\n",
- azArg[1]);
- }
- break;
-
- /* sqlite3_test_control(int, uint) */
- case SQLITE_TESTCTRL_PENDING_BYTE:
- if( nArg==3 ){
- unsigned int opt = (unsigned int)integerValue(azArg[2]);
- rc2 = sqlite3_test_control(testctrl, opt);
- raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2);
- } else {
- utf8_printf(stderr,"Error: testctrl %s takes a single unsigned"
- " int option\n", azArg[1]);
- }
- break;
-
- /* sqlite3_test_control(int, int) */
- case SQLITE_TESTCTRL_ASSERT:
- case SQLITE_TESTCTRL_ALWAYS:
- case SQLITE_TESTCTRL_NEVER_CORRUPT:
- if( nArg==3 ){
- int opt = booleanValue(azArg[2]);
- rc2 = sqlite3_test_control(testctrl, opt);
- raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2);
- } else {
- utf8_printf(stderr,"Error: testctrl %s takes a single int option\n",
- azArg[1]);
- }
- break;
-
- /* sqlite3_test_control(int, char *) */
-#ifdef SQLITE_N_KEYWORD
- case SQLITE_TESTCTRL_ISKEYWORD:
- if( nArg==3 ){
- const char *opt = azArg[2];
- rc2 = sqlite3_test_control(testctrl, opt);
- raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2);
- } else {
- utf8_printf(stderr,
- "Error: testctrl %s takes a single char * option\n",
- azArg[1]);
- }
- break;
-#endif
-
- case SQLITE_TESTCTRL_IMPOSTER:
- if( nArg==5 ){
- rc2 = sqlite3_test_control(testctrl, p->db,
- azArg[2],
- integerValue(azArg[3]),
- integerValue(azArg[4]));
- raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2);
- }else{
- raw_printf(stderr,"Usage: .testctrl imposter dbName onoff tnum\n");
- }
- break;
-
- case SQLITE_TESTCTRL_BITVEC_TEST:
- case SQLITE_TESTCTRL_FAULT_INSTALL:
- case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS:
- case SQLITE_TESTCTRL_SCRATCHMALLOC:
- default:
- utf8_printf(stderr,
- "Error: CLI support for testctrl %s not implemented\n",
- azArg[1]);
- break;
- }
- }
- }else
-#endif /* !defined(SQLITE_UNTESTABLE) */
-
- if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){
- open_db(p, 0);
- sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0);
- }else
-
- if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 ){
- if( nArg==2 ){
- enableTimer = booleanValue(azArg[1]);
- if( enableTimer && !HAS_TIMER ){
- raw_printf(stderr, "Error: timer not available on this system.\n");
- enableTimer = 0;
- }
- }else{
- raw_printf(stderr, "Usage: .timer on|off\n");
- rc = 1;
- }
- }else
-
- if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){
- open_db(p, 0);
- if( nArg!=2 ){
- raw_printf(stderr, "Usage: .trace FILE|off\n");
- rc = 1;
- goto meta_command_exit;
- }
- output_file_close(p->traceOut);
- p->traceOut = output_file_open(azArg[1]);
-#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT)
- if( p->traceOut==0 ){
- sqlite3_trace_v2(p->db, 0, 0, 0);
- }else{
- sqlite3_trace_v2(p->db, SQLITE_TRACE_STMT, sql_trace_callback,p->traceOut);
- }
-#endif
- }else
-
-#if SQLITE_USER_AUTHENTICATION
- if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
- if( nArg<2 ){
- raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n");
- rc = 1;
- goto meta_command_exit;
- }
- open_db(p, 0);
- if( strcmp(azArg[1],"login")==0 ){
- if( nArg!=4 ){
- raw_printf(stderr, "Usage: .user login USER PASSWORD\n");
- rc = 1;
- goto meta_command_exit;
- }
- rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3],
- (int)strlen(azArg[3]));
- if( rc ){
- utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]);
- rc = 1;
- }
- }else if( strcmp(azArg[1],"add")==0 ){
- if( nArg!=5 ){
- raw_printf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n");
- rc = 1;
- goto meta_command_exit;
- }
- rc = sqlite3_user_add(p->db, azArg[2],
- azArg[3], (int)strlen(azArg[3]),
- booleanValue(azArg[4]));
- if( rc ){
- raw_printf(stderr, "User-Add failed: %d\n", rc);
- rc = 1;
- }
- }else if( strcmp(azArg[1],"edit")==0 ){
- if( nArg!=5 ){
- raw_printf(stderr, "Usage: .user edit USER PASSWORD ISADMIN\n");
- rc = 1;
- goto meta_command_exit;
- }
- rc = sqlite3_user_change(p->db, azArg[2],
- azArg[3], (int)strlen(azArg[3]),
- booleanValue(azArg[4]));
- if( rc ){
- raw_printf(stderr, "User-Edit failed: %d\n", rc);
- rc = 1;
- }
- }else if( strcmp(azArg[1],"delete")==0 ){
- if( nArg!=3 ){
- raw_printf(stderr, "Usage: .user delete USER\n");
- rc = 1;
- goto meta_command_exit;
- }
- rc = sqlite3_user_delete(p->db, azArg[2]);
- if( rc ){
- raw_printf(stderr, "User-Delete failed: %d\n", rc);
- rc = 1;
- }
- }else{
- raw_printf(stderr, "Usage: .user login|add|edit|delete ...\n");
- rc = 1;
- goto meta_command_exit;
- }
- }else
-#endif /* SQLITE_USER_AUTHENTICATION */
-
- if( c=='v' && strncmp(azArg[0], "version", n)==0 ){
- utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
- sqlite3_libversion(), sqlite3_sourceid());
- }else
-
- if( c=='v' && strncmp(azArg[0], "vfsinfo", n)==0 ){
- const char *zDbName = nArg==2 ? azArg[1] : "main";
- sqlite3_vfs *pVfs = 0;
- if( p->db ){
- sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs);
- if( pVfs ){
- utf8_printf(p->out, "vfs.zName = \"%s\"\n", pVfs->zName);
- raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion);
- raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile);
- raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
- }
- }
- }else
-
- if( c=='v' && strncmp(azArg[0], "vfslist", n)==0 ){
- sqlite3_vfs *pVfs;
- sqlite3_vfs *pCurrent = 0;
- if( p->db ){
- sqlite3_file_control(p->db, "main", SQLITE_FCNTL_VFS_POINTER, &pCurrent);
- }
- for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){
- utf8_printf(p->out, "vfs.zName = \"%s\"%s\n", pVfs->zName,
- pVfs==pCurrent ? " <--- CURRENT" : "");
- raw_printf(p->out, "vfs.iVersion = %d\n", pVfs->iVersion);
- raw_printf(p->out, "vfs.szOsFile = %d\n", pVfs->szOsFile);
- raw_printf(p->out, "vfs.mxPathname = %d\n", pVfs->mxPathname);
- if( pVfs->pNext ){
- raw_printf(p->out, "-----------------------------------\n");
- }
- }
- }else
-
- if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){
- const char *zDbName = nArg==2 ? azArg[1] : "main";
- char *zVfsName = 0;
- if( p->db ){
- sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName);
- if( zVfsName ){
- utf8_printf(p->out, "%s\n", zVfsName);
- sqlite3_free(zVfsName);
- }
- }
- }else
-
-#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
- if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){
- sqlite3WhereTrace = nArg>=2 ? booleanValue(azArg[1]) : 0xff;
- }else
-#endif
-
- if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
- int j;
- assert( nArg<=ArraySize(azArg) );
- for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){
- p->colWidth[j-1] = (int)integerValue(azArg[j]);
- }
- }else
-
- {
- utf8_printf(stderr, "Error: unknown command or invalid arguments: "
- " \"%s\". Enter \".help\" for help\n", azArg[0]);
- rc = 1;
- }
-
-meta_command_exit:
- if( p->outCount ){
- p->outCount--;
- if( p->outCount==0 ) output_reset(p);
- }
- return rc;
-}
-
-/*
-** Return TRUE if a semicolon occurs anywhere in the first N characters
-** of string z[].
-*/
-static int line_contains_semicolon(const char *z, int N){
- int i;
- for(i=0; i<N; i++){ if( z[i]==';' ) return 1; }
- return 0;
-}
-
-/*
-** Test to see if a line consists entirely of whitespace.
-*/
-static int _all_whitespace(const char *z){
- for(; *z; z++){
- if( IsSpace(z[0]) ) continue;
- if( *z=='/' && z[1]=='*' ){
- z += 2;
- while( *z && (*z!='*' || z[1]!='/') ){ z++; }
- if( *z==0 ) return 0;
- z++;
- continue;
- }
- if( *z=='-' && z[1]=='-' ){
- z += 2;
- while( *z && *z!='\n' ){ z++; }
- if( *z==0 ) return 1;
- continue;
- }
- return 0;
- }
- return 1;
-}
-
-/*
-** Return TRUE if the line typed in is an SQL command terminator other
-** than a semi-colon. The SQL Server style "go" command is understood
-** as is the Oracle "/".
-*/
-static int line_is_command_terminator(const char *zLine){
- while( IsSpace(zLine[0]) ){ zLine++; };
- if( zLine[0]=='/' && _all_whitespace(&zLine[1]) ){
- return 1; /* Oracle */
- }
- if( ToLower(zLine[0])=='g' && ToLower(zLine[1])=='o'
- && _all_whitespace(&zLine[2]) ){
- return 1; /* SQL Server */
- }
- return 0;
-}
-
-/*
-** Return true if zSql is a complete SQL statement. Return false if it
-** ends in the middle of a string literal or C-style comment.
-*/
-static int line_is_complete(char *zSql, int nSql){
- int rc;
- if( zSql==0 ) return 1;
- zSql[nSql] = ';';
- zSql[nSql+1] = 0;
- rc = sqlite3_complete(zSql);
- zSql[nSql] = 0;
- return rc;
-}
-
-/*
-** Run a single line of SQL
-*/
-static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
- int rc;
- char *zErrMsg = 0;
-
- open_db(p, 0);
- if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql);
- BEGIN_TIMER;
- rc = shell_exec(p->db, zSql, shell_callback, p, &zErrMsg);
- END_TIMER;
- if( rc || zErrMsg ){
- char zPrefix[100];
- if( in!=0 || !stdin_is_interactive ){
- sqlite3_snprintf(sizeof(zPrefix), zPrefix,
- "Error: near line %d:", startline);
- }else{
- sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error:");
- }
- if( zErrMsg!=0 ){
- utf8_printf(stderr, "%s %s\n", zPrefix, zErrMsg);
- sqlite3_free(zErrMsg);
- zErrMsg = 0;
- }else{
- utf8_printf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db));
- }
- return 1;
- }else if( ShellHasFlag(p, SHFLG_CountChanges) ){
- raw_printf(p->out, "changes: %3d total_changes: %d\n",
- sqlite3_changes(p->db), sqlite3_total_changes(p->db));
- }
- return 0;
-}
-
-
-/*
-** Read input from *in and process it. If *in==0 then input
-** is interactive - the user is typing it it. Otherwise, input
-** is coming from a file or device. A prompt is issued and history
-** is saved only if input is interactive. An interrupt signal will
-** cause this routine to exit immediately, unless input is interactive.
-**
-** Return the number of errors.
-*/
-static int process_input(ShellState *p, FILE *in){
- char *zLine = 0; /* A single input line */
- char *zSql = 0; /* Accumulated SQL text */
- int nLine; /* Length of current line */
- int nSql = 0; /* Bytes of zSql[] used */
- int nAlloc = 0; /* Allocated zSql[] space */
- int nSqlPrior = 0; /* Bytes of zSql[] used by prior line */
- int rc; /* Error code */
- int errCnt = 0; /* Number of errors seen */
- int lineno = 0; /* Current line number */
- int startline = 0; /* Line number for start of current input */
-
- while( errCnt==0 || !bail_on_error || (in==0 && stdin_is_interactive) ){
- fflush(p->out);
- zLine = one_input_line(in, zLine, nSql>0);
- if( zLine==0 ){
- /* End of input */
- if( in==0 && stdin_is_interactive ) printf("\n");
- break;
- }
- if( seenInterrupt ){
- if( in!=0 ) break;
- seenInterrupt = 0;
- }
- lineno++;
- if( nSql==0 && _all_whitespace(zLine) ){
- if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine);
- continue;
- }
- if( zLine && zLine[0]=='.' && nSql==0 ){
- if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine);
- rc = do_meta_command(zLine, p);
- if( rc==2 ){ /* exit requested */
- break;
- }else if( rc ){
- errCnt++;
- }
- continue;
- }
- if( line_is_command_terminator(zLine) && line_is_complete(zSql, nSql) ){
- memcpy(zLine,";",2);
- }
- nLine = strlen30(zLine);
- if( nSql+nLine+2>=nAlloc ){
- nAlloc = nSql+nLine+100;
- zSql = realloc(zSql, nAlloc);
- if( zSql==0 ){
- raw_printf(stderr, "Error: out of memory\n");
- exit(1);
- }
- }
- nSqlPrior = nSql;
- if( nSql==0 ){
- int i;
- for(i=0; zLine[i] && IsSpace(zLine[i]); i++){}
- assert( nAlloc>0 && zSql!=0 );
- memcpy(zSql, zLine+i, nLine+1-i);
- startline = lineno;
- nSql = nLine-i;
- }else{
- zSql[nSql++] = '\n';
- memcpy(zSql+nSql, zLine, nLine+1);
- nSql += nLine;
- }
- if( nSql && line_contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior)
- && sqlite3_complete(zSql) ){
- errCnt += runOneSqlLine(p, zSql, in, startline);
- nSql = 0;
- if( p->outCount ){
- output_reset(p);
- p->outCount = 0;
- }
- }else if( nSql && _all_whitespace(zSql) ){
- if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zSql);
- nSql = 0;
- }
- }
- if( nSql && !_all_whitespace(zSql) ){
- runOneSqlLine(p, zSql, in, startline);
- }
- free(zSql);
- free(zLine);
- return errCnt>0;
-}
-
-/*
-** Return a pathname which is the user's home directory. A
-** 0 return indicates an error of some kind.
-*/
-static char *find_home_dir(int clearFlag){
- static char *home_dir = NULL;
- if( clearFlag ){
- free(home_dir);
- home_dir = 0;
- return 0;
- }
- if( home_dir ) return home_dir;
-
-#if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) \
- && !defined(__RTP__) && !defined(_WRS_KERNEL)
- {
- struct passwd *pwent;
- uid_t uid = getuid();
- if( (pwent=getpwuid(uid)) != NULL) {
- home_dir = pwent->pw_dir;
- }
- }
-#endif
-
-#if defined(_WIN32_WCE)
- /* Windows CE (arm-wince-mingw32ce-gcc) does not provide getenv()
- */
- home_dir = "/";
-#else
-
-#if defined(_WIN32) || defined(WIN32)
- if (!home_dir) {
- home_dir = getenv("USERPROFILE");
- }
-#endif
-
- if (!home_dir) {
- home_dir = getenv("HOME");
- }
-
-#if defined(_WIN32) || defined(WIN32)
- if (!home_dir) {
- char *zDrive, *zPath;
- int n;
- zDrive = getenv("HOMEDRIVE");
- zPath = getenv("HOMEPATH");
- if( zDrive && zPath ){
- n = strlen30(zDrive) + strlen30(zPath) + 1;
- home_dir = malloc( n );
- if( home_dir==0 ) return 0;
- sqlite3_snprintf(n, home_dir, "%s%s", zDrive, zPath);
- return home_dir;
- }
- home_dir = "c:\\";
- }
-#endif
-
-#endif /* !_WIN32_WCE */
-
- if( home_dir ){
- int n = strlen30(home_dir) + 1;
- char *z = malloc( n );
- if( z ) memcpy(z, home_dir, n);
- home_dir = z;
- }
-
- return home_dir;
-}
-
-/*
-** Read input from the file given by sqliterc_override. Or if that
-** parameter is NULL, take input from ~/.sqliterc
-**
-** Returns the number of errors.
-*/
-static void process_sqliterc(
- ShellState *p, /* Configuration data */
- const char *sqliterc_override /* Name of config file. NULL to use default */
-){
- char *home_dir = NULL;
- const char *sqliterc = sqliterc_override;
- char *zBuf = 0;
- FILE *in = NULL;
-
- if (sqliterc == NULL) {
- home_dir = find_home_dir(0);
- if( home_dir==0 ){
- raw_printf(stderr, "-- warning: cannot find home directory;"
- " cannot read ~/.sqliterc\n");
- return;
- }
- sqlite3_initialize();
- zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
- sqliterc = zBuf;
- }
- in = fopen(sqliterc,"rb");
- if( in ){
- if( stdin_is_interactive ){
- utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc);
- }
- process_input(p,in);
- fclose(in);
- }
- sqlite3_free(zBuf);
-}
-
-/*
-** Show available command line options
-*/
-static const char zOptions[] =
- " -ascii set output mode to 'ascii'\n"
- " -bail stop after hitting an error\n"
- " -batch force batch I/O\n"
- " -column set output mode to 'column'\n"
- " -cmd COMMAND run \"COMMAND\" before reading stdin\n"
- " -csv set output mode to 'csv'\n"
- " -echo print commands before execution\n"
- " -init FILENAME read/process named file\n"
- " -[no]header turn headers on or off\n"
-#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
- " -heap SIZE Size of heap for memsys3 or memsys5\n"
-#endif
- " -help show this message\n"
- " -html set output mode to HTML\n"
- " -interactive force interactive I/O\n"
- " -line set output mode to 'line'\n"
- " -list set output mode to 'list'\n"
- " -lookaside SIZE N use N entries of SZ bytes for lookaside memory\n"
- " -mmap N default mmap size set to N\n"
-#ifdef SQLITE_ENABLE_MULTIPLEX
- " -multiplex enable the multiplexor VFS\n"
-#endif
- " -newline SEP set output row separator. Default: '\\n'\n"
- " -nullvalue TEXT set text string for NULL values. Default ''\n"
- " -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n"
- " -quote set output mode to 'quote'\n"
- " -scratch SIZE N use N slots of SZ bytes each for scratch memory\n"
- " -separator SEP set output column separator. Default: '|'\n"
- " -stats print memory stats before each finalize\n"
- " -version show SQLite version\n"
- " -vfs NAME use NAME as the default VFS\n"
-#ifdef SQLITE_ENABLE_VFSTRACE
- " -vfstrace enable tracing of all VFS calls\n"
-#endif
-;
-static void usage(int showDetail){
- utf8_printf(stderr,
- "Usage: %s [OPTIONS] FILENAME [SQL]\n"
- "FILENAME is the name of an SQLite database. A new database is created\n"
- "if the file does not previously exist.\n", Argv0);
- if( showDetail ){
- utf8_printf(stderr, "OPTIONS include:\n%s", zOptions);
- }else{
- raw_printf(stderr, "Use the -help option for additional information\n");
- }
- exit(1);
-}
-
-/*
-** Initialize the state information in data
-*/
-static void main_init(ShellState *data) {
- memset(data, 0, sizeof(*data));
- data->normalMode = data->cMode = data->mode = MODE_List;
- data->autoExplain = 1;
- memcpy(data->colSeparator,SEP_Column, 2);
- memcpy(data->rowSeparator,SEP_Row, 2);
- data->showHeader = 0;
- data->shellFlgs = SHFLG_Lookaside;
- sqlite3_config(SQLITE_CONFIG_URI, 1);
- sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
- sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
- sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
- sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> ");
-}
-
-/*
-** Output text to the console in a font that attracts extra attention.
-*/
-#ifdef _WIN32
-static void printBold(const char *zText){
- HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
- CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo;
- GetConsoleScreenBufferInfo(out, &defaultScreenInfo);
- SetConsoleTextAttribute(out,
- FOREGROUND_RED|FOREGROUND_INTENSITY
- );
- printf("%s", zText);
- SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes);
-}
-#else
-static void printBold(const char *zText){
- printf("\033[1m%s\033[0m", zText);
-}
-#endif
-
-/*
-** Get the argument to an --option. Throw an error and die if no argument
-** is available.
-*/
-static char *cmdline_option_value(int argc, char **argv, int i){
- if( i==argc ){
- utf8_printf(stderr, "%s: Error: missing argument to %s\n",
- argv[0], argv[argc-1]);
- exit(1);
- }
- return argv[i];
-}
-
-#ifndef SQLITE_SHELL_IS_UTF8
-# if (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
-# define SQLITE_SHELL_IS_UTF8 (0)
-# else
-# define SQLITE_SHELL_IS_UTF8 (1)
-# endif
-#endif
-
-#if SQLITE_SHELL_IS_UTF8
-int SQLITE_CDECL main(int argc, char **argv){
-#else
-int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
- char **argv;
-#endif
- char *zErrMsg = 0;
- ShellState data;
- const char *zInitFile = 0;
- int i;
- int rc = 0;
- int warnInmemoryDb = 0;
- int readStdin = 1;
- int nCmd = 0;
- char **azCmd = 0;
-
- setBinaryMode(stdin, 0);
- setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
- stdin_is_interactive = isatty(0);
- stdout_is_console = isatty(1);
-
-#if USE_SYSTEM_SQLITE+0!=1
- if( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)!=0 ){
- utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
- sqlite3_sourceid(), SQLITE_SOURCE_ID);
- exit(1);
- }
-#endif
- main_init(&data);
-#if !SQLITE_SHELL_IS_UTF8
- sqlite3_initialize();
- argv = sqlite3_malloc64(sizeof(argv[0])*argc);
- if( argv==0 ){
- raw_printf(stderr, "out of memory\n");
- exit(1);
- }
- for(i=0; i<argc; i++){
- argv[i] = sqlite3_win32_unicode_to_utf8(wargv[i]);
- if( argv[i]==0 ){
- raw_printf(stderr, "out of memory\n");
- exit(1);
- }
- }
-#endif
- assert( argc>=1 && argv && argv[0] );
- Argv0 = argv[0];
-
- /* Make sure we have a valid signal handler early, before anything
- ** else is done.
- */
-#ifdef SIGINT
- signal(SIGINT, interrupt_handler);
-#endif
-
-#ifdef SQLITE_SHELL_DBNAME_PROC
- {
- /* If the SQLITE_SHELL_DBNAME_PROC macro is defined, then it is the name
- ** of a C-function that will provide the name of the database file. Use
- ** this compile-time option to embed this shell program in larger
- ** applications. */
- extern void SQLITE_SHELL_DBNAME_PROC(const char**);
- SQLITE_SHELL_DBNAME_PROC(&data.zDbFilename);
- warnInmemoryDb = 0;
- }
-#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,
- ** and the first command to execute.
- */
- for(i=1; i<argc; i++){
- char *z;
- z = argv[i];
- if( z[0]!='-' ){
- if( data.zDbFilename==0 ){
- data.zDbFilename = z;
- }else{
- /* Excesss arguments are interpreted as SQL (or dot-commands) and
- ** mean that nothing is read from stdin */
- readStdin = 0;
- nCmd++;
- azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd);
- if( azCmd==0 ){
- raw_printf(stderr, "out of memory\n");
- exit(1);
- }
- azCmd[nCmd-1] = z;
- }
- }
- if( z[1]=='-' ) z++;
- if( strcmp(z,"-separator")==0
- || strcmp(z,"-nullvalue")==0
- || strcmp(z,"-newline")==0
- || strcmp(z,"-cmd")==0
- ){
- (void)cmdline_option_value(argc, argv, ++i);
- }else if( strcmp(z,"-init")==0 ){
- zInitFile = cmdline_option_value(argc, argv, ++i);
- }else if( strcmp(z,"-batch")==0 ){
- /* Need to check for batch mode here to so we can avoid printing
- ** informational messages (like from process_sqliterc) before
- ** we do the actual processing of arguments later in a second pass.
- */
- stdin_is_interactive = 0;
- }else if( strcmp(z,"-heap")==0 ){
-#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
- const char *zSize;
- sqlite3_int64 szHeap;
-
- zSize = cmdline_option_value(argc, argv, ++i);
- szHeap = integerValue(zSize);
- if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000;
- sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64);
-#else
- (void)cmdline_option_value(argc, argv, ++i);
-#endif
- }else if( strcmp(z,"-scratch")==0 ){
- int n, sz;
- sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
- if( sz>400000 ) sz = 400000;
- if( sz<2500 ) sz = 2500;
- n = (int)integerValue(cmdline_option_value(argc,argv,++i));
- if( n>10 ) n = 10;
- if( n<1 ) n = 1;
- sqlite3_config(SQLITE_CONFIG_SCRATCH, malloc(n*sz+1), sz, n);
- data.shellFlgs |= SHFLG_Scratch;
- }else if( strcmp(z,"-pagecache")==0 ){
- int n, sz;
- sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
- if( sz>70000 ) sz = 70000;
- if( sz<0 ) sz = 0;
- n = (int)integerValue(cmdline_option_value(argc,argv,++i));
- sqlite3_config(SQLITE_CONFIG_PAGECACHE,
- (n>0 && sz>0) ? malloc(n*sz) : 0, sz, n);
- data.shellFlgs |= SHFLG_Pagecache;
- }else if( strcmp(z,"-lookaside")==0 ){
- int n, sz;
- sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
- if( sz<0 ) sz = 0;
- n = (int)integerValue(cmdline_option_value(argc,argv,++i));
- if( n<0 ) n = 0;
- sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, n);
- if( sz*n==0 ) data.shellFlgs &= ~SHFLG_Lookaside;
-#ifdef SQLITE_ENABLE_VFSTRACE
- }else if( strcmp(z,"-vfstrace")==0 ){
- extern int vfstrace_register(
- const char *zTraceName,
- const char *zOldVfsName,
- int (*xOut)(const char*,void*),
- void *pOutArg,
- int makeDefault
- );
- vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1);
-#endif
-#ifdef SQLITE_ENABLE_MULTIPLEX
- }else if( strcmp(z,"-multiplex")==0 ){
- extern int sqlite3_multiple_initialize(const char*,int);
- sqlite3_multiplex_initialize(0, 1);
-#endif
- }else if( strcmp(z,"-mmap")==0 ){
- sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
- sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, sz, sz);
- }else if( strcmp(z,"-vfs")==0 ){
- sqlite3_vfs *pVfs = sqlite3_vfs_find(cmdline_option_value(argc,argv,++i));
- if( pVfs ){
- sqlite3_vfs_register(pVfs, 1);
- }else{
- utf8_printf(stderr, "no such VFS: \"%s\"\n", argv[i]);
- exit(1);
- }
- }
- }
- if( data.zDbFilename==0 ){
-#ifndef SQLITE_OMIT_MEMORYDB
- data.zDbFilename = ":memory:";
- warnInmemoryDb = argc==1;
-#else
- utf8_printf(stderr,"%s: Error: no database filename specified\n", Argv0);
- return 1;
-#endif
- }
- data.out = stdout;
-
- /* Go ahead and open the database file if it already exists. If the
- ** file does not exist, delay opening it. This prevents empty database
- ** files from being created if a user mistypes the database name argument
- ** to the sqlite command-line tool.
- */
- if( access(data.zDbFilename, 0)==0 ){
- open_db(&data, 0);
- }
-
- /* Process the initialization file if there is one. If no -init option
- ** is given on the command line, look for a file named ~/.sqliterc and
- ** try to process it.
- */
- process_sqliterc(&data,zInitFile);
-
- /* Make a second pass through the command-line argument and set
- ** options. This second pass is delayed until after the initialization
- ** file is processed so that the command-line arguments will override
- ** settings in the initialization file.
- */
- for(i=1; i<argc; i++){
- char *z = argv[i];
- if( z[0]!='-' ) continue;
- if( z[1]=='-' ){ z++; }
- if( strcmp(z,"-init")==0 ){
- i++;
- }else if( strcmp(z,"-html")==0 ){
- data.mode = MODE_Html;
- }else if( strcmp(z,"-list")==0 ){
- data.mode = MODE_List;
- }else if( strcmp(z,"-quote")==0 ){
- data.mode = MODE_Quote;
- }else if( strcmp(z,"-line")==0 ){
- data.mode = MODE_Line;
- }else if( strcmp(z,"-column")==0 ){
- data.mode = MODE_Column;
- }else if( strcmp(z,"-csv")==0 ){
- data.mode = MODE_Csv;
- memcpy(data.colSeparator,",",2);
- }else if( strcmp(z,"-ascii")==0 ){
- data.mode = MODE_Ascii;
- sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
- SEP_Unit);
- sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
- SEP_Record);
- }else if( strcmp(z,"-separator")==0 ){
- sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
- "%s",cmdline_option_value(argc,argv,++i));
- }else if( strcmp(z,"-newline")==0 ){
- sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
- "%s",cmdline_option_value(argc,argv,++i));
- }else if( strcmp(z,"-nullvalue")==0 ){
- sqlite3_snprintf(sizeof(data.nullValue), data.nullValue,
- "%s",cmdline_option_value(argc,argv,++i));
- }else if( strcmp(z,"-header")==0 ){
- data.showHeader = 1;
- }else if( strcmp(z,"-noheader")==0 ){
- data.showHeader = 0;
- }else if( strcmp(z,"-echo")==0 ){
- ShellSetFlag(&data, SHFLG_Echo);
- }else if( strcmp(z,"-eqp")==0 ){
- data.autoEQP = 1;
- }else if( strcmp(z,"-eqpfull")==0 ){
- data.autoEQP = 2;
- }else if( strcmp(z,"-stats")==0 ){
- data.statsOn = 1;
- }else if( strcmp(z,"-scanstats")==0 ){
- data.scanstatsOn = 1;
- }else if( strcmp(z,"-backslash")==0 ){
- /* Undocumented command-line option: -backslash
- ** Causes C-style backslash escapes to be evaluated in SQL statements
- ** prior to sending the SQL into SQLite. Useful for injecting
- ** crazy bytes in the middle of SQL statements for testing and debugging.
- */
- ShellSetFlag(&data, SHFLG_Backslash);
- }else if( strcmp(z,"-bail")==0 ){
- bail_on_error = 1;
- }else if( strcmp(z,"-version")==0 ){
- printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid());
- return 0;
- }else if( strcmp(z,"-interactive")==0 ){
- stdin_is_interactive = 1;
- }else if( strcmp(z,"-batch")==0 ){
- stdin_is_interactive = 0;
- }else if( strcmp(z,"-heap")==0 ){
- i++;
- }else if( strcmp(z,"-scratch")==0 ){
- i+=2;
- }else if( strcmp(z,"-pagecache")==0 ){
- i+=2;
- }else if( strcmp(z,"-lookaside")==0 ){
- i+=2;
- }else if( strcmp(z,"-mmap")==0 ){
- i++;
- }else if( strcmp(z,"-vfs")==0 ){
- i++;
-#ifdef SQLITE_ENABLE_VFSTRACE
- }else if( strcmp(z,"-vfstrace")==0 ){
- i++;
-#endif
-#ifdef SQLITE_ENABLE_MULTIPLEX
- }else if( strcmp(z,"-multiplex")==0 ){
- i++;
-#endif
- }else if( strcmp(z,"-help")==0 ){
- usage(1);
- }else if( strcmp(z,"-cmd")==0 ){
- /* Run commands that follow -cmd first and separately from commands
- ** that simply appear on the command-line. This seems goofy. It would
- ** be better if all commands ran in the order that they appear. But
- ** we retain the goofy behavior for historical compatibility. */
- if( i==argc-1 ) break;
- z = cmdline_option_value(argc,argv,++i);
- if( z[0]=='.' ){
- rc = do_meta_command(z, &data);
- if( rc && bail_on_error ) return rc==2 ? 0 : rc;
- }else{
- open_db(&data, 0);
- rc = shell_exec(data.db, z, shell_callback, &data, &zErrMsg);
- if( zErrMsg!=0 ){
- utf8_printf(stderr,"Error: %s\n", zErrMsg);
- if( bail_on_error ) return rc!=0 ? rc : 1;
- }else if( rc!=0 ){
- utf8_printf(stderr,"Error: unable to process SQL \"%s\"\n", z);
- if( bail_on_error ) return rc;
- }
- }
- }else{
- utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
- raw_printf(stderr,"Use -help for a list of options.\n");
- return 1;
- }
- data.cMode = data.mode;
- }
-
- if( !readStdin ){
- /* Run all arguments that do not begin with '-' as if they were separate
- ** command-line inputs, except for the argToSkip argument which contains
- ** the database filename.
- */
- for(i=0; i<nCmd; i++){
- if( azCmd[i][0]=='.' ){
- rc = do_meta_command(azCmd[i], &data);
- if( rc ) return rc==2 ? 0 : rc;
- }else{
- open_db(&data, 0);
- rc = shell_exec(data.db, azCmd[i], shell_callback, &data, &zErrMsg);
- if( zErrMsg!=0 ){
- utf8_printf(stderr,"Error: %s\n", zErrMsg);
- return rc!=0 ? rc : 1;
- }else if( rc!=0 ){
- utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]);
- return rc;
- }
- }
- }
- free(azCmd);
- }else{
- /* Run commands received from standard input
- */
- if( stdin_is_interactive ){
- char *zHome;
- char *zHistory = 0;
- int nHistory;
- printf(
- "SQLite version %s %.19s\n" /*extra-version-info*/
- "Enter \".help\" for usage hints.\n",
- sqlite3_libversion(), sqlite3_sourceid()
- );
- if( warnInmemoryDb ){
- printf("Connected to a ");
- printBold("transient in-memory database");
- printf(".\nUse \".open FILENAME\" to reopen on a "
- "persistent database.\n");
- }
- zHome = find_home_dir(0);
- if( zHome ){
- nHistory = strlen30(zHome) + 20;
- if( (zHistory = malloc(nHistory))!=0 ){
- sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome);
- }
- }
- if( zHistory ){ shell_read_history(zHistory); }
-#if HAVE_READLINE || HAVE_EDITLINE
- rl_attempted_completion_function = readline_completion;
-#elif HAVE_LINENOISE
- linenoiseSetCompletionCallback(linenoise_completion);
-#endif
- rc = process_input(&data, 0);
- if( zHistory ){
- shell_stifle_history(2000);
- shell_write_history(zHistory);
- free(zHistory);
- }
- }else{
- rc = process_input(&data, stdin);
- }
- }
- set_table_name(&data, 0);
- if( data.db ){
- session_close_all(&data);
- sqlite3_close(data.db);
- }
- sqlite3_free(data.zFreeOnClose);
- find_home_dir(1);
-#if !SQLITE_SHELL_IS_UTF8
- for(i=0; i<argc; i++) sqlite3_free(argv[i]);
- sqlite3_free(argv);
-#endif
- return rc;
-}
diff --git a/chromium/third_party/sqlite/src/src/shell.c.in b/chromium/third_party/sqlite/src/src/shell.c.in
index 4dac4a62d5f..a500a19ca7d 100644
--- a/chromium/third_party/sqlite/src/src/shell.c.in
+++ b/chromium/third_party/sqlite/src/src/shell.c.in
@@ -871,14 +871,13 @@ struct ShellState {
/*
** These are the allowed shellFlgs values
*/
-#define SHFLG_Scratch 0x00000001 /* The --scratch option is used */
-#define SHFLG_Pagecache 0x00000002 /* The --pagecache option is used */
-#define SHFLG_Lookaside 0x00000004 /* Lookaside memory is used */
-#define SHFLG_Backslash 0x00000008 /* The --backslash option is used */
-#define SHFLG_PreserveRowid 0x00000010 /* .dump preserves rowid values */
-#define SHFLG_Newlines 0x00000020 /* .dump --newline flag */
-#define SHFLG_CountChanges 0x00000040 /* .changes setting */
-#define SHFLG_Echo 0x00000080 /* .echo or --echo setting */
+#define SHFLG_Pagecache 0x00000001 /* The --pagecache option is used */
+#define SHFLG_Lookaside 0x00000002 /* Lookaside memory is used */
+#define SHFLG_Backslash 0x00000004 /* The --backslash option is used */
+#define SHFLG_PreserveRowid 0x00000008 /* .dump preserves rowid values */
+#define SHFLG_Newlines 0x00000010 /* .dump --newline flag */
+#define SHFLG_CountChanges 0x00000020 /* .changes setting */
+#define SHFLG_Echo 0x00000040 /* .echo or --echo setting */
/*
** Macros for testing and setting shellFlgs
@@ -1299,6 +1298,7 @@ static int shell_callback(
int i;
ShellState *p = (ShellState*)pArg;
+ if( azArg==0 ) return 0;
switch( p->cMode ){
case MODE_Line: {
int w = 5;
@@ -1413,6 +1413,7 @@ static int shell_callback(
for(i=0; IsSpace(z[i]); i++){}
for(; (c = z[i])!=0; i++){
if( IsSpace(c) ){
+ if( z[j-1]=='\r' ) z[j-1] = '\n';
if( IsSpace(z[j-1]) || z[j-1]=='(' ) continue;
}else if( (c=='(' || c==')') && j>0 && IsSpace(z[j-1]) ){
j--;
@@ -1649,6 +1650,7 @@ static int captureOutputCallback(void *pArg, int nArg, char **azArg, char **az){
ShellText *p = (ShellText*)pArg;
int i;
UNUSED_PARAMETER(az);
+ if( azArg==0 ) return 0;
if( p->n ) appendText(p, "|", 0);
for(i=0; i<nArg; i++){
if( i ) appendText(p, ",", 0);
@@ -1713,7 +1715,7 @@ static void createSelftestTable(ShellState *p){
*/
static void set_table_name(ShellState *p, const char *zName){
int i, n;
- int cQuote;
+ char cQuote;
char *z;
if( p->zDestTable ){
@@ -1895,18 +1897,10 @@ static int display_stats(
}
displayStatLine(pArg, "Number of Pcache Overflow Bytes:",
"%lld (max %lld) bytes", SQLITE_STATUS_PAGECACHE_OVERFLOW, bReset);
- if( pArg->shellFlgs & SHFLG_Scratch ){
- displayStatLine(pArg, "Number of Scratch Allocations Used:",
- "%lld (max %lld)", SQLITE_STATUS_SCRATCH_USED, bReset);
- }
- displayStatLine(pArg, "Number of Scratch Overflow Bytes:",
- "%lld (max %lld) bytes", SQLITE_STATUS_SCRATCH_OVERFLOW, bReset);
displayStatLine(pArg, "Largest Allocation:",
"%lld bytes", SQLITE_STATUS_MALLOC_SIZE, bReset);
displayStatLine(pArg, "Largest Pcache Allocation:",
"%lld bytes", SQLITE_STATUS_PAGECACHE_SIZE, bReset);
- displayStatLine(pArg, "Largest Scratch Allocation:",
- "%lld bytes", SQLITE_STATUS_SCRATCH_SIZE, bReset);
#ifdef YYTRACKMAXSTACKDEPTH
displayStatLine(pArg, "Deepest Parser Stack:",
"%lld (max %lld)", SQLITE_STATUS_PARSER_STACK, bReset);
@@ -2447,6 +2441,7 @@ static char **tableColumnList(ShellState *p, const char *zTab){
}
}
sqlite3_finalize(pStmt);
+ if( azCol==0 ) return 0;
azCol[0] = 0;
azCol[nCol+1] = 0;
@@ -2530,7 +2525,7 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
ShellState *p = (ShellState *)pArg;
UNUSED_PARAMETER(azNotUsed);
- if( nArg!=3 ) return 1;
+ if( nArg!=3 || azArg==0 ) return 0;
zTable = azArg[0];
zType = azArg[1];
zSql = azArg[2];
@@ -3616,20 +3611,24 @@ static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
{ "schema size:",
"SELECT total(length(sql)) FROM %s" },
};
- sqlite3_file *pFile = 0;
int i;
char *zSchemaTab;
char *zDb = nArg>=2 ? azArg[1] : "main";
+ sqlite3_stmt *pStmt = 0;
unsigned char aHdr[100];
open_db(p, 0);
if( p->db==0 ) return 1;
- sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_FILE_POINTER, &pFile);
- if( pFile==0 || pFile->pMethods==0 || pFile->pMethods->xRead==0 ){
- return 1;
- }
- i = pFile->pMethods->xRead(pFile, aHdr, 100, 0);
- if( i!=SQLITE_OK ){
+ sqlite3_prepare_v2(p->db,"SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
+ -1, &pStmt, 0);
+ sqlite3_bind_text(pStmt, 1, zDb, -1, SQLITE_STATIC);
+ if( sqlite3_step(pStmt)==SQLITE_ROW
+ && sqlite3_column_bytes(pStmt,0)>100
+ ){
+ memcpy(aHdr, sqlite3_column_blob(pStmt,0), 100);
+ sqlite3_finalize(pStmt);
+ }else{
raw_printf(stderr, "unable to read database header\n");
+ sqlite3_finalize(pStmt);
return 1;
}
i = get2byteInt(aHdr+16);
@@ -4249,7 +4248,7 @@ static int do_meta_command(char *zLine, ShellState *p){
utf8_printf(stderr,
"testcase-%s FAILED\n Expected: [%s]\n Got: [%s]\n",
p->zTestcase, azArg[1], zRes);
- rc = 2;
+ rc = 1;
}else{
utf8_printf(stdout, "testcase-%s ok\n", p->zTestcase);
p->nCheck++;
@@ -5927,7 +5926,6 @@ static int do_meta_command(char *zLine, ShellState *p){
{ "reserve", SQLITE_TESTCTRL_RESERVE },
{ "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS },
{ "iskeyword", SQLITE_TESTCTRL_ISKEYWORD },
- { "scratchmalloc", SQLITE_TESTCTRL_SCRATCHMALLOC },
{ "byteorder", SQLITE_TESTCTRL_BYTEORDER },
{ "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT },
{ "imposter", SQLITE_TESTCTRL_IMPOSTER },
@@ -6040,7 +6038,6 @@ static int do_meta_command(char *zLine, ShellState *p){
case SQLITE_TESTCTRL_BITVEC_TEST:
case SQLITE_TESTCTRL_FAULT_INSTALL:
case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS:
- case SQLITE_TESTCTRL_SCRATCHMALLOC:
default:
utf8_printf(stderr,
"Error: CLI support for testctrl %s not implemented\n",
@@ -6560,7 +6557,6 @@ static const char zOptions[] =
" -nullvalue TEXT set text string for NULL values. Default ''\n"
" -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n"
" -quote set output mode to 'quote'\n"
- " -scratch SIZE N use N slots of SZ bytes each for scratch memory\n"
" -separator SEP set output column separator. Default: '|'\n"
" -stats print memory stats before each finalize\n"
" -version show SQLite version\n"
@@ -6663,7 +6659,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
stdout_is_console = isatty(1);
#if USE_SYSTEM_SQLITE+0!=1
- if( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)!=0 ){
+ if( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){
utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
sqlite3_sourceid(), SQLITE_SOURCE_ID);
exit(1);
@@ -6707,6 +6703,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,
@@ -6758,16 +6764,6 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
#else
(void)cmdline_option_value(argc, argv, ++i);
#endif
- }else if( strcmp(z,"-scratch")==0 ){
- int n, sz;
- sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
- if( sz>400000 ) sz = 400000;
- if( sz<2500 ) sz = 2500;
- n = (int)integerValue(cmdline_option_value(argc,argv,++i));
- if( n>10 ) n = 10;
- if( n<1 ) n = 1;
- sqlite3_config(SQLITE_CONFIG_SCRATCH, malloc(n*sz+1), sz, n);
- data.shellFlgs |= SHFLG_Scratch;
}else if( strcmp(z,"-pagecache")==0 ){
int n, sz;
sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
@@ -6911,8 +6907,6 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
stdin_is_interactive = 0;
}else if( strcmp(z,"-heap")==0 ){
i++;
- }else if( strcmp(z,"-scratch")==0 ){
- i+=2;
}else if( strcmp(z,"-pagecache")==0 ){
i+=2;
}else if( strcmp(z,"-lookaside")==0 ){
diff --git a/chromium/third_party/sqlite/src/src/sqlite.h.in b/chromium/third_party/sqlite/src/src/sqlite.h.in
index c65406abe59..877e79f74af 100644
--- a/chromium/third_party/sqlite/src/src/sqlite.h.in
+++ b/chromium/third_party/sqlite/src/src/sqlite.h.in
@@ -115,7 +115,9 @@ extern "C" {
** a string which identifies a particular check-in of SQLite
** within its configuration management system. ^The SQLITE_SOURCE_ID
** string contains the date and time of the check-in (UTC) and a SHA1
-** or SHA3-256 hash of the entire source tree.
+** or SHA3-256 hash of the entire source tree. If the source code has
+** been edited in any way since it was last checked in, then the last
+** four hexadecimal digits of the hash may be modified.
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
@@ -139,7 +141,7 @@ extern "C" {
**
** <blockquote><pre>
** assert( sqlite3_libversion_number()==SQLITE_VERSION_NUMBER );
-** assert( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)==0 );
+** assert( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,80)==0 );
** assert( strcmp(sqlite3_libversion(),SQLITE_VERSION)==0 );
** </pre></blockquote>)^
**
@@ -149,9 +151,11 @@ extern "C" {
** function is provided for use in DLLs since DLL users usually do not have
** direct access to string constants within the DLL. ^The
** sqlite3_libversion_number() function returns an integer equal to
-** [SQLITE_VERSION_NUMBER]. ^The sqlite3_sourceid() function returns
+** [SQLITE_VERSION_NUMBER]. ^(The sqlite3_sourceid() function returns
** a pointer to a string constant whose value is the same as the
-** [SQLITE_SOURCE_ID] C preprocessor macro.
+** [SQLITE_SOURCE_ID] C preprocessor macro. Except if SQLite is built
+** using an edited copy of [the amalgamation], then the last four characters
+** of the hash might be different from [SQLITE_SOURCE_ID].)^
**
** See also: [sqlite_version()] and [sqlite_source_id()].
*/
@@ -432,7 +436,7 @@ int sqlite3_exec(
#define SQLITE_FULL 13 /* Insertion failed because database is full */
#define SQLITE_CANTOPEN 14 /* Unable to open the database file */
#define SQLITE_PROTOCOL 15 /* Database lock protocol error */
-#define SQLITE_EMPTY 16 /* Not used */
+#define SQLITE_EMPTY 16 /* Internal use only */
#define SQLITE_SCHEMA 17 /* The database schema changed */
#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */
#define SQLITE_CONSTRAINT 19 /* Abort due to constraint violation */
@@ -494,6 +498,9 @@ int sqlite3_exec(
#define SQLITE_IOERR_CONVPATH (SQLITE_IOERR | (26<<8))
#define SQLITE_IOERR_VNODE (SQLITE_IOERR | (27<<8))
#define SQLITE_IOERR_AUTH (SQLITE_IOERR | (28<<8))
+#define SQLITE_IOERR_BEGIN_ATOMIC (SQLITE_IOERR | (29<<8))
+#define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8))
+#define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8))
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
#define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8))
@@ -580,6 +587,11 @@ int sqlite3_exec(
** SQLITE_IOCAP_IMMUTABLE flag indicates that the file is on
** read-only media and cannot be changed even by processes with
** elevated privileges.
+**
+** The SQLITE_IOCAP_BATCH_ATOMIC property means that the underlying
+** filesystem supports doing multiple write operations atomically when those
+** write operations are bracketed by [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] and
+** [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE].
*/
#define SQLITE_IOCAP_ATOMIC 0x00000001
#define SQLITE_IOCAP_ATOMIC512 0x00000002
@@ -595,6 +607,7 @@ int sqlite3_exec(
#define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800
#define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000
#define SQLITE_IOCAP_IMMUTABLE 0x00002000
+#define SQLITE_IOCAP_BATCH_ATOMIC 0x00004000
/*
** CAPI3REF: File Locking Levels
@@ -729,6 +742,7 @@ struct sqlite3_file {
** <li> [SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN]
** <li> [SQLITE_IOCAP_POWERSAFE_OVERWRITE]
** <li> [SQLITE_IOCAP_IMMUTABLE]
+** <li> [SQLITE_IOCAP_BATCH_ATOMIC]
** </ul>
**
** The SQLITE_IOCAP_ATOMIC property means that all writes of
@@ -1012,6 +1026,40 @@ struct sqlite3_io_methods {
** The [SQLITE_FCNTL_RBU] opcode is implemented by the special VFS used by
** the RBU extension only. All other VFS should return SQLITE_NOTFOUND for
** this opcode.
+**
+** <li>[[SQLITE_FCNTL_BEGIN_ATOMIC_WRITE]]
+** If the [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] opcode returns SQLITE_OK, then
+** the file descriptor is placed in "batch write mode", which
+** means all subsequent write operations will be deferred and done
+** atomically at the next [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE]. Systems
+** that do not support batch atomic writes will return SQLITE_NOTFOUND.
+** ^Following a successful SQLITE_FCNTL_BEGIN_ATOMIC_WRITE and prior to
+** the closing [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE] or
+** [SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE], SQLite will make
+** no VFS interface calls on the same [sqlite3_file] file descriptor
+** except for calls to the xWrite method and the xFileControl method
+** with [SQLITE_FCNTL_SIZE_HINT].
+**
+** <li>[[SQLITE_FCNTL_COMMIT_ATOMIC_WRITE]]
+** The [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE] opcode causes all write
+** operations since the previous successful call to
+** [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] to be performed atomically.
+** This file control returns [SQLITE_OK] if and only if the writes were
+** all performed successfully and have been committed to persistent storage.
+** ^Regardless of whether or not it is successful, this file control takes
+** the file descriptor out of batch write mode so that all subsequent
+** write operations are independent.
+** ^SQLite will never invoke SQLITE_FCNTL_COMMIT_ATOMIC_WRITE without
+** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE].
+**
+** <li>[[SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE]]
+** The [SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE] opcode causes all write
+** operations since the previous successful call to
+** [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] to be rolled back.
+** ^This file control takes the file descriptor out of batch write mode
+** so that all subsequent write operations are independent.
+** ^SQLite will never invoke SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE without
+** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE].
** </ul>
*/
#define SQLITE_FCNTL_LOCKSTATE 1
@@ -1043,6 +1091,9 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_JOURNAL_POINTER 28
#define SQLITE_FCNTL_WIN32_GET_HANDLE 29
#define SQLITE_FCNTL_PDB 30
+#define SQLITE_FCNTL_BEGIN_ATOMIC_WRITE 31
+#define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE 32
+#define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33
/* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
@@ -1613,6 +1664,16 @@ struct sqlite3_mem_methods {
** routines with a wrapper that simulations memory allocation failure or
** tracks memory usage, for example. </dd>
**
+** [[SQLITE_CONFIG_SMALL_MALLOC]] <dt>SQLITE_CONFIG_SMALL_MALLOC</dt>
+** <dd> ^The SQLITE_CONFIG_SMALL_MALLOC option takes single argument of
+** type int, interpreted as a boolean, which if true provides a hint to
+** SQLite that it should avoid large memory allocations if possible.
+** SQLite will run faster if it is free to make large memory allocations,
+** but some application might prefer to run slower in exchange for
+** guarantees about memory fragmentation that are possible if large
+** allocations are avoided. This hint is normally off.
+** </dd>
+**
** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt>
** <dd> ^The SQLITE_CONFIG_MEMSTATUS option takes single argument of type int,
** interpreted as a boolean, which enables or disables the collection of
@@ -1630,25 +1691,7 @@ struct sqlite3_mem_methods {
** </dd>
**
** [[SQLITE_CONFIG_SCRATCH]] <dt>SQLITE_CONFIG_SCRATCH</dt>
-** <dd> ^The SQLITE_CONFIG_SCRATCH option specifies a static memory buffer
-** that SQLite can use for scratch memory. ^(There are three arguments
-** to SQLITE_CONFIG_SCRATCH: A pointer an 8-byte
-** aligned memory buffer from which the scratch allocations will be
-** drawn, the size of each scratch allocation (sz),
-** and the maximum number of scratch allocations (N).)^
-** The first argument must be a pointer to an 8-byte aligned buffer
-** of at least sz*N bytes of memory.
-** ^SQLite will not use more than one scratch buffers per thread.
-** ^SQLite will never request a scratch buffer that is more than 6
-** times the database page size.
-** ^If SQLite needs needs additional
-** scratch memory beyond what is provided by this configuration option, then
-** [sqlite3_malloc()] will be used to obtain the memory needed.<p>
-** ^When the application provides any amount of scratch memory using
-** SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary large
-** [sqlite3_malloc|heap allocations].
-** This can help [Robson proof|prevent memory allocation failures] due to heap
-** fragmentation in low-memory embedded systems.
+** <dd> The SQLITE_CONFIG_SCRATCH option is no longer used.
** </dd>
**
** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt>
@@ -1684,8 +1727,7 @@ struct sqlite3_mem_methods {
** [[SQLITE_CONFIG_HEAP]] <dt>SQLITE_CONFIG_HEAP</dt>
** <dd> ^The SQLITE_CONFIG_HEAP option specifies a static memory buffer
** that SQLite will use for all of its dynamic memory allocation needs
-** beyond those provided for by [SQLITE_CONFIG_SCRATCH] and
-** [SQLITE_CONFIG_PAGECACHE].
+** beyond those provided for by [SQLITE_CONFIG_PAGECACHE].
** ^The SQLITE_CONFIG_HEAP option is only available if SQLite is compiled
** with either [SQLITE_ENABLE_MEMSYS3] or [SQLITE_ENABLE_MEMSYS5] and returns
** [SQLITE_ERROR] if invoked otherwise.
@@ -1878,7 +1920,7 @@ struct sqlite3_mem_methods {
#define SQLITE_CONFIG_SERIALIZED 3 /* nil */
#define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */
#define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */
-#define SQLITE_CONFIG_SCRATCH 6 /* void*, int sz, int N */
+#define SQLITE_CONFIG_SCRATCH 6 /* No longer used */
#define SQLITE_CONFIG_PAGECACHE 7 /* void*, int sz, int N */
#define SQLITE_CONFIG_HEAP 8 /* void*, int nByte, int min */
#define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */
@@ -1899,6 +1941,7 @@ struct sqlite3_mem_methods {
#define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */
#define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */
#define SQLITE_CONFIG_STMTJRNL_SPILL 26 /* int nByte */
+#define SQLITE_CONFIG_SMALL_MALLOC 27 /* boolean */
/*
** CAPI3REF: Database Connection Configuration Options
@@ -3099,10 +3142,10 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** ^If [URI filename] interpretation is enabled, and the filename argument
** begins with "file:", then the filename is interpreted as a URI. ^URI
** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is
-** set in the fourth argument to sqlite3_open_v2(), or if it has
+** set in the third argument to sqlite3_open_v2(), or if it has
** been enabled globally using the [SQLITE_CONFIG_URI] option with the
** [sqlite3_config()] method or by the [SQLITE_USE_URI] compile-time option.
-** As of SQLite version 3.7.7, URI filename interpretation is turned off
+** URI filename interpretation is turned off
** by default, but future releases of SQLite might enable URI filename
** interpretation by default. See "[URI filenames]" for additional
** information.
@@ -3776,8 +3819,9 @@ int sqlite3_stmt_busy(sqlite3_stmt*);
** implementation of [application-defined SQL functions] are protected.
** ^The sqlite3_value object returned by
** [sqlite3_column_value()] is unprotected.
-** Unprotected sqlite3_value objects may only be used with
-** [sqlite3_result_value()] and [sqlite3_bind_value()].
+** Unprotected sqlite3_value objects may only be used as arguments
+** to [sqlite3_result_value()], [sqlite3_bind_value()], and
+** [sqlite3_value_dup()].
** The [sqlite3_value_blob | sqlite3_value_type()] family of
** interfaces require protected sqlite3_value objects.
*/
@@ -4199,7 +4243,7 @@ const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
** other than [SQLITE_ROW] before any subsequent invocation of
** sqlite3_step(). Failure to reset the prepared statement using
** [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from
-** sqlite3_step(). But after [version 3.6.23.1] ([dateof:3.6.23.1]),
+** sqlite3_step(). But after [version 3.6.23.1] ([dateof:3.6.23.1],
** sqlite3_step() began
** calling [sqlite3_reset()] automatically in this circumstance rather
** than returning [SQLITE_MISUSE]. This is not considered a compatibility
@@ -6203,15 +6247,20 @@ struct sqlite3_index_info {
** an operator that is part of a constraint term in the wHERE clause of
** a query that uses a [virtual table].
*/
-#define SQLITE_INDEX_CONSTRAINT_EQ 2
-#define SQLITE_INDEX_CONSTRAINT_GT 4
-#define SQLITE_INDEX_CONSTRAINT_LE 8
-#define SQLITE_INDEX_CONSTRAINT_LT 16
-#define SQLITE_INDEX_CONSTRAINT_GE 32
-#define SQLITE_INDEX_CONSTRAINT_MATCH 64
-#define SQLITE_INDEX_CONSTRAINT_LIKE 65
-#define SQLITE_INDEX_CONSTRAINT_GLOB 66
-#define SQLITE_INDEX_CONSTRAINT_REGEXP 67
+#define SQLITE_INDEX_CONSTRAINT_EQ 2
+#define SQLITE_INDEX_CONSTRAINT_GT 4
+#define SQLITE_INDEX_CONSTRAINT_LE 8
+#define SQLITE_INDEX_CONSTRAINT_LT 16
+#define SQLITE_INDEX_CONSTRAINT_GE 32
+#define SQLITE_INDEX_CONSTRAINT_MATCH 64
+#define SQLITE_INDEX_CONSTRAINT_LIKE 65
+#define SQLITE_INDEX_CONSTRAINT_GLOB 66
+#define SQLITE_INDEX_CONSTRAINT_REGEXP 67
+#define SQLITE_INDEX_CONSTRAINT_NE 68
+#define SQLITE_INDEX_CONSTRAINT_ISNOT 69
+#define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70
+#define SQLITE_INDEX_CONSTRAINT_ISNULL 71
+#define SQLITE_INDEX_CONSTRAINT_IS 72
/*
** CAPI3REF: Register A Virtual Table Implementation
@@ -6963,7 +7012,7 @@ int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_RESERVE 14
#define SQLITE_TESTCTRL_OPTIMIZATIONS 15
#define SQLITE_TESTCTRL_ISKEYWORD 16
-#define SQLITE_TESTCTRL_SCRATCHMALLOC 17
+#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */
#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
#define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */
#define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19
@@ -7022,8 +7071,7 @@ int sqlite3_status64(
** <dd>This parameter is the current amount of memory checked out
** using [sqlite3_malloc()], either directly or indirectly. The
** figure includes calls made to [sqlite3_malloc()] by the application
-** and internal memory usage by the SQLite library. Scratch memory
-** controlled by [SQLITE_CONFIG_SCRATCH] and auxiliary page-cache
+** and internal memory usage by the SQLite library. Auxiliary page-cache
** memory controlled by [SQLITE_CONFIG_PAGECACHE] is not included in
** this parameter. The amount returned is the sum of the allocation
** sizes as reported by the xSize method in [sqlite3_mem_methods].</dd>)^
@@ -7061,29 +7109,14 @@ int sqlite3_status64(
** *pHighwater parameter to [sqlite3_status()] is of interest.
** The value written into the *pCurrent parameter is undefined.</dd>)^
**
-** [[SQLITE_STATUS_SCRATCH_USED]] ^(<dt>SQLITE_STATUS_SCRATCH_USED</dt>
-** <dd>This parameter returns the number of allocations used out of the
-** [scratch memory allocator] configured using
-** [SQLITE_CONFIG_SCRATCH]. The value returned is in allocations, not
-** in bytes. Since a single thread may only have one scratch allocation
-** outstanding at time, this parameter also reports the number of threads
-** using scratch memory at the same time.</dd>)^
+** [[SQLITE_STATUS_SCRATCH_USED]] <dt>SQLITE_STATUS_SCRATCH_USED</dt>
+** <dd>No longer used.</dd>
**
** [[SQLITE_STATUS_SCRATCH_OVERFLOW]] ^(<dt>SQLITE_STATUS_SCRATCH_OVERFLOW</dt>
-** <dd>This parameter returns the number of bytes of scratch memory
-** allocation which could not be satisfied by the [SQLITE_CONFIG_SCRATCH]
-** buffer and where forced to overflow to [sqlite3_malloc()]. The values
-** returned include overflows because the requested allocation was too
-** larger (that is, because the requested allocation was larger than the
-** "sz" parameter to [SQLITE_CONFIG_SCRATCH]) and because no scratch buffer
-** slots were available.
-** </dd>)^
-**
-** [[SQLITE_STATUS_SCRATCH_SIZE]] ^(<dt>SQLITE_STATUS_SCRATCH_SIZE</dt>
-** <dd>This parameter records the largest memory allocation request
-** handed to [scratch memory allocator]. Only the value returned in the
-** *pHighwater parameter to [sqlite3_status()] is of interest.
-** The value written into the *pCurrent parameter is undefined.</dd>)^
+** <dd>No longer used.</dd>
+**
+** [[SQLITE_STATUS_SCRATCH_SIZE]] <dt>SQLITE_STATUS_SCRATCH_SIZE</dt>
+** <dd>No longer used.</dd>
**
** [[SQLITE_STATUS_PARSER_STACK]] ^(<dt>SQLITE_STATUS_PARSER_STACK</dt>
** <dd>The *pHighwater parameter records the deepest parser stack.
@@ -7096,12 +7129,12 @@ int sqlite3_status64(
#define SQLITE_STATUS_MEMORY_USED 0
#define SQLITE_STATUS_PAGECACHE_USED 1
#define SQLITE_STATUS_PAGECACHE_OVERFLOW 2
-#define SQLITE_STATUS_SCRATCH_USED 3
-#define SQLITE_STATUS_SCRATCH_OVERFLOW 4
+#define SQLITE_STATUS_SCRATCH_USED 3 /* NOT USED */
+#define SQLITE_STATUS_SCRATCH_OVERFLOW 4 /* NOT USED */
#define SQLITE_STATUS_MALLOC_SIZE 5
#define SQLITE_STATUS_PARSER_STACK 6
#define SQLITE_STATUS_PAGECACHE_SIZE 7
-#define SQLITE_STATUS_SCRATCH_SIZE 8
+#define SQLITE_STATUS_SCRATCH_SIZE 8 /* NOT USED */
#define SQLITE_STATUS_MALLOC_COUNT 9
/*
diff --git a/chromium/third_party/sqlite/src/src/sqlite3ext.h b/chromium/third_party/sqlite/src/src/sqlite3ext.h
index d24fe484ef8..d279ab223f3 100644
--- a/chromium/third_party/sqlite/src/src/sqlite3ext.h
+++ b/chromium/third_party/sqlite/src/src/sqlite3ext.h
@@ -134,7 +134,7 @@ struct sqlite3_api_routines {
int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,
const char*,const char*),void*);
void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*));
- char * (*snprintf)(int,char*,const char*,...);
+ char * (*xsnprintf)(int,char*,const char*,...);
int (*step)(sqlite3_stmt*);
int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,
char const**,char const**,int*,int*,int*);
@@ -246,7 +246,7 @@ struct sqlite3_api_routines {
int (*uri_boolean)(const char*,const char*,int);
sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64);
const char *(*uri_parameter)(const char*,const char*);
- char *(*vsnprintf)(int,char*,const char*,va_list);
+ char *(*xvsnprintf)(int,char*,const char*,va_list);
int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*);
/* Version 3.8.7 and later */
int (*auto_extension)(void(*)(void));
@@ -418,7 +418,7 @@ typedef int (*sqlite3_loadext_entry)(
#define sqlite3_rollback_hook sqlite3_api->rollback_hook
#define sqlite3_set_authorizer sqlite3_api->set_authorizer
#define sqlite3_set_auxdata sqlite3_api->set_auxdata
-#define sqlite3_snprintf sqlite3_api->snprintf
+#define sqlite3_snprintf sqlite3_api->xsnprintf
#define sqlite3_step sqlite3_api->step
#define sqlite3_table_column_metadata sqlite3_api->table_column_metadata
#define sqlite3_thread_cleanup sqlite3_api->thread_cleanup
@@ -442,7 +442,7 @@ typedef int (*sqlite3_loadext_entry)(
#define sqlite3_value_text16le sqlite3_api->value_text16le
#define sqlite3_value_type sqlite3_api->value_type
#define sqlite3_vmprintf sqlite3_api->vmprintf
-#define sqlite3_vsnprintf sqlite3_api->vsnprintf
+#define sqlite3_vsnprintf sqlite3_api->xvsnprintf
#define sqlite3_overload_function sqlite3_api->overload_function
#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
@@ -518,7 +518,7 @@ typedef int (*sqlite3_loadext_entry)(
#define sqlite3_uri_boolean sqlite3_api->uri_boolean
#define sqlite3_uri_int64 sqlite3_api->uri_int64
#define sqlite3_uri_parameter sqlite3_api->uri_parameter
-#define sqlite3_uri_vsnprintf sqlite3_api->vsnprintf
+#define sqlite3_uri_vsnprintf sqlite3_api->xvsnprintf
#define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2
/* Version 3.8.7 and later */
#define sqlite3_auto_extension sqlite3_api->auto_extension
diff --git a/chromium/third_party/sqlite/src/src/sqliteInt.h b/chromium/third_party/sqlite/src/src/sqliteInt.h
index f341b695800..d12148d4209 100644
--- a/chromium/third_party/sqlite/src/src/sqliteInt.h
+++ b/chromium/third_party/sqlite/src/src/sqliteInt.h
@@ -51,17 +51,6 @@
#endif
/*
-** Make sure that rand_s() is available on Windows systems with MSVC 2005
-** or higher.
-*/
-#if defined(_MSC_VER) && _MSC_VER>=1400
-/* TODO(shess): Already defined by build/config/win/BUILD.gn */
-#ifndef _CRT_RAND_S
-# define _CRT_RAND_S
-#endif
-#endif
-
-/*
** Include the header file used to customize the compiler options for MSVC.
** This should be done first so that it can successfully prevent spurious
** compiler warnings due to subsequent content in this file and other files
@@ -458,6 +447,21 @@
#endif
/*
+** Some conditionals are optimizations only. In other words, if the
+** conditionals are replaced with a constant 1 (true) or 0 (false) then
+** the correct answer is still obtained, though perhaps not as quickly.
+**
+** The following macros mark these optimizations conditionals.
+*/
+#if defined(SQLITE_MUTATION_TEST)
+# define OK_IF_ALWAYS_TRUE(X) (1)
+# define OK_IF_ALWAYS_FALSE(X) (0)
+#else
+# define OK_IF_ALWAYS_TRUE(X) (X)
+# define OK_IF_ALWAYS_FALSE(X) (X)
+#endif
+
+/*
** Some malloc failures are only possible if SQLITE_TEST_REALLOC_STRESS is
** defined. We need to defend against those failures when testing with
** SQLITE_TEST_REALLOC_STRESS, but we don't want the unreachable branches
@@ -634,6 +638,15 @@
#endif
/*
+** The compile-time options SQLITE_MMAP_READWRITE and
+** SQLITE_ENABLE_BATCH_ATOMIC_WRITE are not compatible with one another.
+** You must choose one or the other (or neither) but not both.
+*/
+#if defined(SQLITE_MMAP_READWRITE) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
+#error Cannot use both SQLITE_MMAP_READWRITE and SQLITE_ENABLE_BATCH_ATOMIC_WRITE
+#endif
+
+/*
** GCC does not define the offsetof() macro so we'll have to do it
** ourselves.
*/
@@ -931,7 +944,7 @@ typedef INT16_TYPE LogEst;
** SELECTTRACE_ENABLED will be either 1 or 0 depending on whether or not
** the Select query generator tracing logic is turned on.
*/
-#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_SELECTTRACE)
+#if defined(SQLITE_ENABLE_SELECTTRACE)
# define SELECTTRACE_ENABLED 1
#else
# define SELECTTRACE_ENABLED 0
@@ -1207,6 +1220,7 @@ struct Schema {
#define DB_SchemaLoaded 0x0001 /* The schema has been loaded */
#define DB_UnresetViews 0x0002 /* Some views have defined column names */
#define DB_Empty 0x0004 /* The file is empty (length 0 bytes) */
+#define DB_ResetWanted 0x0008 /* Reset the schema when nSchemaLock==0 */
/*
** The number of different kinds of things that can be limited
@@ -1238,9 +1252,9 @@ struct Lookaside {
u32 bDisable; /* Only operate the lookaside when zero */
u16 sz; /* Size of each buffer in bytes */
u8 bMalloced; /* True if pStart obtained from sqlite3_malloc() */
- int nOut; /* Number of buffers currently checked out */
- int mxOut; /* Highwater mark for nOut */
- int anStat[3]; /* 0: hits. 1: size misses. 2: full misses */
+ u32 nSlot; /* Number of lookaside slots allocated */
+ u32 anStat[3]; /* 0: hits. 1: size misses. 2: full misses */
+ LookasideSlot *pInit; /* List of buffers not previously used */
LookasideSlot *pFree; /* List of available buffers */
void *pStart; /* First byte of available memory space */
void *pEnd; /* First byte past end of available space */
@@ -1319,9 +1333,11 @@ struct sqlite3 {
sqlite3_mutex *mutex; /* Connection mutex */
Db *aDb; /* All backends */
int nDb; /* Number of backends currently in use */
- int flags; /* Miscellaneous flags. See below */
+ u32 mDbFlags; /* flags recording internal state */
+ u32 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 */
unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */
int errCode; /* Most recent error code (SQLITE_*) */
int errMask; /* & result codes with this before returning */
@@ -1473,18 +1489,13 @@ struct sqlite3 {
#define SQLITE_ForeignKeys 0x00004000 /* Enforce foreign key constraints */
#define SQLITE_AutoIndex 0x00008000 /* Enable automatic indexes */
#define SQLITE_LoadExtension 0x00010000 /* Enable load_extension */
-#define SQLITE_EnableTrigger 0x00020000 /* True to enable triggers */
-#define SQLITE_DeferFKs 0x00040000 /* Defer all FK constraints */
-#define SQLITE_QueryOnly 0x00080000 /* Disable database changes */
-#define SQLITE_CellSizeCk 0x00100000 /* Check btree cell sizes on load */
-#define SQLITE_Fts3Tokenizer 0x00200000 /* Enable fts3_tokenizer(2) */
-#define SQLITE_EnableQPSG 0x00400000 /* Query Planner Stability Guarantee */
-/* The next four values are not used by PRAGMAs or by sqlite3_dbconfig() and
-** could be factored out into a separate bit vector of the sqlite3 object. */
-#define SQLITE_InternChanges 0x00800000 /* Uncommitted Hash table changes */
-#define SQLITE_LoadExtFunc 0x01000000 /* Enable load_extension() SQL func */
-#define SQLITE_PreferBuiltin 0x02000000 /* Preference to built-in funcs */
-#define SQLITE_Vacuum 0x04000000 /* Currently in a VACUUM */
+#define SQLITE_LoadExtFunc 0x00020000 /* Enable load_extension() SQL func */
+#define SQLITE_EnableTrigger 0x00040000 /* True to enable triggers */
+#define SQLITE_DeferFKs 0x00080000 /* Defer all FK constraints */
+#define SQLITE_QueryOnly 0x00100000 /* Disable database changes */
+#define SQLITE_CellSizeCk 0x00200000 /* Check btree cell sizes on load */
+#define SQLITE_Fts3Tokenizer 0x00400000 /* Enable fts3_tokenizer(2) */
+#define SQLITE_EnableQPSG 0x00800000 /* Query Planner Stability Guarantee */
/* Flags used only if debugging */
#ifdef SQLITE_DEBUG
#define SQLITE_SqlTrace 0x08000000 /* Debug print SQL as it executes */
@@ -1494,6 +1505,12 @@ struct sqlite3 {
#define SQLITE_VdbeEQP 0x80000000 /* Debug EXPLAIN QUERY PLAN */
#endif
+/*
+** Allowed values for sqlite3.mDbFlags
+*/
+#define DBFLAG_SchemaChange 0x0001 /* Uncommitted Hash table changes */
+#define DBFLAG_PreferBuiltin 0x0002 /* Preference to built-in funcs */
+#define DBFLAG_Vacuum 0x0004 /* Currently in a VACUUM */
/*
** Bits of the sqlite3.dbOptFlags field that are used by the
@@ -1504,16 +1521,15 @@ struct sqlite3 {
#define SQLITE_ColumnCache 0x0002 /* Column cache */
#define SQLITE_GroupByOrder 0x0004 /* GROUPBY cover of ORDERBY */
#define SQLITE_FactorOutConst 0x0008 /* Constant factoring */
-/* not used 0x0010 // Was: SQLITE_IdxRealAsInt */
-#define SQLITE_DistinctOpt 0x0020 /* DISTINCT using indexes */
-#define SQLITE_CoverIdxScan 0x0040 /* Covering index scans */
-#define SQLITE_OrderByIdxJoin 0x0080 /* ORDER BY of joins via index */
-#define SQLITE_SubqCoroutine 0x0100 /* Evaluate subqueries as coroutines */
-#define SQLITE_Transitive 0x0200 /* Transitive constraints */
-#define SQLITE_OmitNoopJoin 0x0400 /* Omit unused tables in joins */
+#define SQLITE_DistinctOpt 0x0010 /* DISTINCT using indexes */
+#define SQLITE_CoverIdxScan 0x0020 /* Covering index scans */
+#define SQLITE_OrderByIdxJoin 0x0040 /* ORDER BY of joins via index */
+#define SQLITE_Transitive 0x0080 /* Transitive constraints */
+#define SQLITE_OmitNoopJoin 0x0100 /* Omit unused tables in joins */
+#define SQLITE_CountOfView 0x0200 /* The count-of-view optimization */
+#define SQLITE_CursorHints 0x0400 /* Add OP_CursorHint opcodes */
#define SQLITE_Stat34 0x0800 /* Use STAT3 or STAT4 data */
-#define SQLITE_CountOfView 0x1000 /* The count-of-view optimization */
-#define SQLITE_CursorHints 0x2000 /* Add OP_CursorHint opcodes */
+ /* TH3 expects the Stat34 ^^^^^^ value to be 0x0800. Don't change it */
#define SQLITE_AllOpts 0xffff /* All optimizations */
/*
@@ -2044,8 +2060,8 @@ struct FKey {
struct KeyInfo {
u32 nRef; /* Number of references to this KeyInfo object */
u8 enc; /* Text encoding - one of the SQLITE_UTF* values */
- u16 nField; /* Number of key columns in the index */
- u16 nXField; /* Number of columns beyond the key columns */
+ u16 nKeyField; /* Number of key columns in the index */
+ u16 nAllField; /* Total columns, including key plus others */
sqlite3 *db; /* The database connection */
u8 *aSortOrder; /* Sort order for each column. */
CollSeq *aColl[1]; /* Collating sequence for each term of the key */
@@ -2092,8 +2108,8 @@ struct UnpackedRecord {
u16 nField; /* Number of entries in apMem[] */
i8 default_rc; /* Comparison result if keys are equal */
u8 errCode; /* Error detected by xRecordCompare (CORRUPT or NOMEM) */
- i8 r1; /* Value to return if (lhs > rhs) */
- i8 r2; /* Value to return if (rhs < lhs) */
+ i8 r1; /* Value to return if (lhs < rhs) */
+ i8 r2; /* Value to return if (lhs > rhs) */
u8 eqSeen; /* True if an equality comparison has been seen */
};
@@ -2377,7 +2393,8 @@ 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. */
+ Table *pTab; /* Table for TK_COLUMN expressions. Can be NULL
+ ** for a column of an index on an expression */
};
/*
@@ -2465,7 +2482,6 @@ struct Expr {
*/
struct ExprList {
int nExpr; /* Number of expressions on the list */
- int nAlloc; /* Number of a[] slots allocated */
struct ExprList_item { /* For each expression in the list */
Expr *pExpr; /* The parse tree for this expression */
char *zName; /* Token associated with this expression */
@@ -2990,7 +3006,7 @@ struct Parse {
AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */
Parse *pToplevel; /* Parse structure for main program (or NULL) */
Table *pTriggerTab; /* Table triggers are being coded for */
- int addrCrTab; /* Address of OP_CreateTable opcode on CREATE TABLE */
+ int addrCrTab; /* Address of OP_CreateBtree opcode on CREATE TABLE */
u32 nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */
u32 oldmask; /* Mask of old.* columns referenced */
u32 newmask; /* Mask of new.* columns referenced */
@@ -3219,11 +3235,10 @@ struct DbFixer {
*/
struct StrAccum {
sqlite3 *db; /* Optional database for lookaside. Can be NULL */
- char *zBase; /* A base allocation. Not from malloc. */
char *zText; /* The string collected so far */
- u32 nChar; /* Length of the string so far */
u32 nAlloc; /* Amount of space allocated in zText */
u32 mxAlloc; /* Maximum allowed allocation. 0 for no malloc usage */
+ u32 nChar; /* Length of the string so far */
u8 accError; /* STRACCUM_NOMEM or STRACCUM_TOOBIG */
u8 printfFlags; /* SQLITE_PRINTF flags below */
};
@@ -3258,6 +3273,7 @@ struct Sqlite3Config {
int bFullMutex; /* True to enable full mutexing */
int bOpenUri; /* True to interpret filenames as URIs */
int bUseCis; /* Use covering indices for full-scans */
+ int bSmallMalloc; /* Avoid large memory allocations if true */
int mxStrlen; /* Maximum string length */
int neverCorrupt; /* Database is always well-formed */
int szLookaside; /* Default lookaside buffer size */
@@ -3271,9 +3287,6 @@ struct Sqlite3Config {
int mnReq, mxReq; /* Min and max heap requests sizes */
sqlite3_int64 szMmap; /* mmap() space per open file */
sqlite3_int64 mxMmap; /* Maximum value for szMmap */
- void *pScratch; /* Scratch memory */
- int szScratch; /* Size of each scratch buffer */
- int nScratch; /* Number of scratch buffers */
void *pPage; /* Page cache memory */
int szPage; /* Size of each page in pPage[] */
int nPage; /* Number of pages in pPage[] */
@@ -3360,6 +3373,7 @@ int sqlite3WalkSelectExpr(Walker*, Select*);
int sqlite3WalkSelectFrom(Walker*, Select*);
int sqlite3ExprWalkNoop(Walker*, Expr*);
int sqlite3SelectWalkNoop(Walker*, Select*);
+int sqlite3SelectWalkFail(Walker*, Select*);
#ifdef SQLITE_DEBUG
void sqlite3SelectWalkAssert2(Walker*, Select*);
#endif
@@ -3512,8 +3526,6 @@ void sqlite3DbFree(sqlite3*, void*);
void sqlite3DbFreeNN(sqlite3*, void*);
int sqlite3MallocSize(void*);
int sqlite3DbMallocSize(sqlite3*, void*);
-void *sqlite3ScratchMalloc(int);
-void sqlite3ScratchFree(void*);
void *sqlite3PageMalloc(int);
void sqlite3PageFree(void*);
void sqlite3MemSetDefault(void);
@@ -3569,6 +3581,7 @@ sqlite3_int64 sqlite3StatusValue(int);
void sqlite3StatusUp(int, int);
void sqlite3StatusDown(int, int);
void sqlite3StatusHighwater(int, int);
+int sqlite3LookasideUsed(sqlite3*,int*);
/* Access to mutexes used by sqlite3_status() */
sqlite3_mutex *sqlite3Pcache1Mutex(void);
@@ -4005,6 +4018,8 @@ int sqlite3ReadSchema(Parse *pParse);
CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
+CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, Expr *pExpr);
+int sqlite3ExprCollSeqMatch(Parse*,Expr*,Expr*);
Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int);
Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
Expr *sqlite3ExprSkipCollate(Expr*);
@@ -4288,7 +4303,8 @@ int sqlite3FindInIndex(Parse *, Expr *, u32, int*, int*);
int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int);
int sqlite3JournalSize(sqlite3_vfs *);
-#ifdef SQLITE_ENABLE_ATOMIC_WRITE
+#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \
+ || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
int sqlite3JournalCreate(sqlite3_file *);
#endif
@@ -4374,8 +4390,7 @@ SQLITE_API SQLITE_EXTERN void (SQLITE_CDECL *sqlite3IoTrace)(const char*,...);
#endif
#define MEMTYPE_HEAP 0x01 /* General heap allocations */
#define MEMTYPE_LOOKASIDE 0x02 /* Heap that might have been lookaside */
-#define MEMTYPE_SCRATCH 0x04 /* Scratch allocations */
-#define MEMTYPE_PCACHE 0x08 /* Page cache allocations */
+#define MEMTYPE_PCACHE 0x04 /* Page cache allocations */
/*
** Threading interface
@@ -4385,6 +4400,9 @@ int sqlite3ThreadCreate(SQLiteThread**,void*(*)(void*),void*);
int sqlite3ThreadJoin(SQLiteThread*, void**);
#endif
+#if defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)
+int sqlite3DbpageRegister(sqlite3*);
+#endif
#if defined(SQLITE_ENABLE_DBSTAT_VTAB) || defined(SQLITE_TEST)
int sqlite3DbstatRegister(sqlite3*);
#endif
diff --git a/chromium/third_party/sqlite/src/src/status.c b/chromium/third_party/sqlite/src/src/status.c
index 74548b73b6f..f859dd4dd48 100644
--- a/chromium/third_party/sqlite/src/src/status.c
+++ b/chromium/third_party/sqlite/src/src/status.c
@@ -122,7 +122,6 @@ void sqlite3StatusHighwater(int op, int X){
: sqlite3MallocMutex()) );
assert( op==SQLITE_STATUS_MALLOC_SIZE
|| op==SQLITE_STATUS_PAGECACHE_SIZE
- || op==SQLITE_STATUS_SCRATCH_SIZE
|| op==SQLITE_STATUS_PARSER_STACK );
if( newValue>wsdStat.mxValue[op] ){
wsdStat.mxValue[op] = newValue;
@@ -172,6 +171,28 @@ int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
}
/*
+** Return the number of LookasideSlot elements on the linked list
+*/
+static u32 countLookasideSlots(LookasideSlot *p){
+ u32 cnt = 0;
+ while( p ){
+ p = p->pNext;
+ cnt++;
+ }
+ return cnt;
+}
+
+/*
+** Count the number of slots of lookaside memory that are outstanding
+*/
+int sqlite3LookasideUsed(sqlite3 *db, int *pHighwater){
+ u32 nInit = countLookasideSlots(db->lookaside.pInit);
+ u32 nFree = countLookasideSlots(db->lookaside.pFree);
+ if( pHighwater ) *pHighwater = db->lookaside.nSlot - nInit;
+ return db->lookaside.nSlot - (nInit+nFree);
+}
+
+/*
** Query status information for a single database connection
*/
int sqlite3_db_status(
@@ -190,10 +211,15 @@ int sqlite3_db_status(
sqlite3_mutex_enter(db->mutex);
switch( op ){
case SQLITE_DBSTATUS_LOOKASIDE_USED: {
- *pCurrent = db->lookaside.nOut;
- *pHighwater = db->lookaside.mxOut;
+ *pCurrent = sqlite3LookasideUsed(db, pHighwater);
if( resetFlag ){
- db->lookaside.mxOut = db->lookaside.nOut;
+ LookasideSlot *p = db->lookaside.pFree;
+ if( p ){
+ while( p->pNext ) p = p->pNext;
+ p->pNext = db->lookaside.pInit;
+ db->lookaside.pInit = db->lookaside.pFree;
+ db->lookaside.pFree = 0;
+ }
}
break;
}
diff --git a/chromium/third_party/sqlite/src/src/tclsqlite.c b/chromium/third_party/sqlite/src/src/tclsqlite.c
index 2507e300efb..99b18087565 100644
--- a/chromium/third_party/sqlite/src/src/tclsqlite.c
+++ b/chromium/third_party/sqlite/src/src/tclsqlite.c
@@ -14,17 +14,19 @@
**
** Compile-time options:
**
-** -DTCLSH=1 Add a "main()" routine that works as a tclsh.
+** -DTCLSH Add a "main()" routine that works as a tclsh.
**
-** -DSQLITE_TCLMD5 When used in conjuction with -DTCLSH=1, add
-** four new commands to the TCL interpreter for
-** generating MD5 checksums: md5, md5file,
-** md5-10x8, and md5file-10x8.
+** -DTCLSH_INIT_PROC=name
**
-** -DSQLITE_TEST When used in conjuction with -DTCLSH=1, add
-** hundreds of new commands used for testing
-** SQLite. This option implies -DSQLITE_TCLMD5.
-*/
+** Invoke name(interp) to initialize the Tcl interpreter.
+** If name(interp) returns a non-NULL string, then run
+** that string as a Tcl script to launch the application.
+** If name(interp) returns NULL, then run the regular
+** tclsh-emulator code.
+*/
+#ifdef TCLSH_INIT_PROC
+# define TCLSH 1
+#endif
/*
** If requested, include the SQLite compiler options file for MSVC.
@@ -3286,7 +3288,42 @@ static int SQLITE_TCLAPI DbObjCmd(
** Return the version string for this database.
*/
case DB_VERSION: {
- Tcl_SetResult(interp, (char *)sqlite3_libversion(), TCL_STATIC);
+ int i;
+ for(i=2; i<objc; i++){
+ const char *zArg = Tcl_GetString(objv[i]);
+ /* Optional arguments to $db version are used for testing purpose */
+#ifdef SQLITE_TEST
+ /* $db version -use-legacy-prepare BOOLEAN
+ **
+ ** Turn the use of legacy sqlite3_prepare() on or off.
+ */
+ if( strcmp(zArg, "-use-legacy-prepare")==0 && i+1<objc ){
+ i++;
+ if( Tcl_GetBooleanFromObj(interp, objv[i], &pDb->bLegacyPrepare) ){
+ return TCL_ERROR;
+ }
+ }else
+
+ /* $db version -last-stmt-ptr
+ **
+ ** Return a string which is a hex encoding of the pointer to the
+ ** most recent sqlite3_stmt in the statement cache.
+ */
+ if( strcmp(zArg, "-last-stmt-ptr")==0 ){
+ char zBuf[100];
+ sqlite3_snprintf(sizeof(zBuf), zBuf, "%p",
+ pDb->stmtList ? pDb->stmtList->pStmt: 0);
+ Tcl_SetResult(interp, zBuf, TCL_VOLATILE);
+ }else
+#endif /* SQLITE_TEST */
+ {
+ Tcl_AppendResult(interp, "unknown argument: ", zArg, (char*)0);
+ return TCL_ERROR;
+ }
+ }
+ if( i==2 ){
+ Tcl_SetResult(interp, (char *)sqlite3_libversion(), TCL_STATIC);
+ }
break;
}
@@ -3546,710 +3583,56 @@ int Sqlite_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }
int Tclsqlite_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }
#endif
-#ifdef TCLSH
-/*****************************************************************************
-** All of the code that follows is used to build standalone TCL interpreters
-** that are statically linked with SQLite. Enable these by compiling
-** with -DTCLSH=n where n can be 1 or 2. An n of 1 generates a standard
-** tclsh but with SQLite built in. An n of 2 generates the SQLite space
-** analysis program.
-*/
-
-#if defined(SQLITE_TEST) || defined(SQLITE_TCLMD5)
/*
- * This code implements the MD5 message-digest algorithm.
- * The algorithm is due to Ron Rivest. This code was
- * written by Colin Plumb in 1993, no copyright is claimed.
- * This code is in the public domain; do with it what you wish.
- *
- * Equivalent code is available from RSA Data Security, Inc.
- * This code has been tested against that, and is equivalent,
- * except that you don't need to include two pages of legalese
- * with every copy.
- *
- * To compute the message digest of a chunk of bytes, declare an
- * MD5Context structure, pass it to MD5Init, call MD5Update as
- * needed on buffers full of bytes, and then call MD5Final, which
- * will fill a supplied 16-byte array with the digest.
- */
-
-/*
- * If compiled on a machine that doesn't have a 32-bit integer,
- * you just set "uint32" to the appropriate datatype for an
- * unsigned 32-bit integer. For example:
- *
- * cc -Duint32='unsigned long' md5.c
- *
- */
-#ifndef uint32
-# define uint32 unsigned int
-#endif
-
-struct MD5Context {
- int isInit;
- uint32 buf[4];
- uint32 bits[2];
- unsigned char in[64];
-};
-typedef struct MD5Context MD5Context;
-
-/*
- * Note: this code is harmless on little-endian machines.
- */
-static void byteReverse (unsigned char *buf, unsigned longs){
- uint32 t;
- do {
- t = (uint32)((unsigned)buf[3]<<8 | buf[2]) << 16 |
- ((unsigned)buf[1]<<8 | buf[0]);
- *(uint32 *)buf = t;
- buf += 4;
- } while (--longs);
-}
-/* The four core functions - F1 is optimized somewhat */
-
-/* #define F1(x, y, z) (x & y | ~x & z) */
-#define F1(x, y, z) (z ^ (x & (y ^ z)))
-#define F2(x, y, z) F1(z, x, y)
-#define F3(x, y, z) (x ^ y ^ z)
-#define F4(x, y, z) (y ^ (x | ~z))
-
-/* This is the central step in the MD5 algorithm. */
-#define MD5STEP(f, w, x, y, z, data, s) \
- ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
-
-/*
- * The core of the MD5 algorithm, this alters an existing MD5 hash to
- * reflect the addition of 16 longwords of new data. MD5Update blocks
- * the data and converts bytes into longwords for this routine.
- */
-static void MD5Transform(uint32 buf[4], const uint32 in[16]){
- register uint32 a, b, c, d;
-
- a = buf[0];
- b = buf[1];
- c = buf[2];
- d = buf[3];
-
- MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7);
- MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
- MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
- MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
- MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7);
- MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
- MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
- MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
- MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7);
- MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
- MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
- MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
- MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7);
- MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
- MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
- MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
-
- MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5);
- MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9);
- MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
- MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
- MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5);
- MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9);
- MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
- MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
- MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5);
- MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9);
- MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
- MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
- MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5);
- MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9);
- MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
- MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
-
- MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4);
- MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
- MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
- MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
- MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4);
- MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
- MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
- MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
- MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4);
- MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
- MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
- MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
- MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4);
- MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
- MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
- MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
-
- MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6);
- MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
- MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
- MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
- MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6);
- MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
- MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
- MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
- MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6);
- MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
- MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
- MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
- MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6);
- MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
- MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
- MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
-
- buf[0] += a;
- buf[1] += b;
- buf[2] += c;
- buf[3] += d;
-}
-
-/*
- * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
- * initialization constants.
- */
-static void MD5Init(MD5Context *ctx){
- ctx->isInit = 1;
- ctx->buf[0] = 0x67452301;
- ctx->buf[1] = 0xefcdab89;
- ctx->buf[2] = 0x98badcfe;
- ctx->buf[3] = 0x10325476;
- ctx->bits[0] = 0;
- ctx->bits[1] = 0;
-}
-
-/*
- * Update context to reflect the concatenation of another buffer full
- * of bytes.
- */
-static
-void MD5Update(MD5Context *ctx, const unsigned char *buf, unsigned int len){
- uint32 t;
-
- /* Update bitcount */
-
- t = ctx->bits[0];
- if ((ctx->bits[0] = t + ((uint32)len << 3)) < t)
- ctx->bits[1]++; /* Carry from low to high */
- ctx->bits[1] += len >> 29;
-
- t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
-
- /* Handle any leading odd-sized chunks */
-
- if ( t ) {
- unsigned char *p = (unsigned char *)ctx->in + t;
-
- t = 64-t;
- if (len < t) {
- memcpy(p, buf, len);
- return;
- }
- memcpy(p, buf, t);
- byteReverse(ctx->in, 16);
- MD5Transform(ctx->buf, (uint32 *)ctx->in);
- buf += t;
- len -= t;
- }
-
- /* Process data in 64-byte chunks */
-
- while (len >= 64) {
- memcpy(ctx->in, buf, 64);
- byteReverse(ctx->in, 16);
- MD5Transform(ctx->buf, (uint32 *)ctx->in);
- buf += 64;
- len -= 64;
- }
-
- /* Handle any remaining bytes of data. */
-
- memcpy(ctx->in, buf, len);
-}
-
-/*
- * Final wrapup - pad to 64-byte boundary with the bit pattern
- * 1 0* (64-bit count of bits processed, MSB-first)
- */
-static void MD5Final(unsigned char digest[16], MD5Context *ctx){
- unsigned count;
- unsigned char *p;
-
- /* Compute number of bytes mod 64 */
- count = (ctx->bits[0] >> 3) & 0x3F;
-
- /* Set the first char of padding to 0x80. This is safe since there is
- always at least one byte free */
- p = ctx->in + count;
- *p++ = 0x80;
-
- /* Bytes of padding needed to make 64 bytes */
- count = 64 - 1 - count;
-
- /* Pad out to 56 mod 64 */
- if (count < 8) {
- /* Two lots of padding: Pad the first block to 64 bytes */
- memset(p, 0, count);
- byteReverse(ctx->in, 16);
- MD5Transform(ctx->buf, (uint32 *)ctx->in);
-
- /* Now fill the next block with 56 bytes */
- memset(ctx->in, 0, 56);
- } else {
- /* Pad block to 56 bytes */
- memset(p, 0, count-8);
- }
- byteReverse(ctx->in, 14);
-
- /* Append length in bits and transform */
- memcpy(ctx->in + 14*4, ctx->bits, 8);
-
- MD5Transform(ctx->buf, (uint32 *)ctx->in);
- byteReverse((unsigned char *)ctx->buf, 4);
- memcpy(digest, ctx->buf, 16);
-}
-
-/*
-** Convert a 128-bit MD5 digest into a 32-digit base-16 number.
-*/
-static void MD5DigestToBase16(unsigned char *digest, char *zBuf){
- static char const zEncode[] = "0123456789abcdef";
- int i, j;
-
- for(j=i=0; i<16; i++){
- int a = digest[i];
- zBuf[j++] = zEncode[(a>>4)&0xf];
- zBuf[j++] = zEncode[a & 0xf];
- }
- zBuf[j] = 0;
-}
-
-
-/*
-** Convert a 128-bit MD5 digest into sequency of eight 5-digit integers
-** each representing 16 bits of the digest and separated from each
-** other by a "-" character.
-*/
-static void MD5DigestToBase10x8(unsigned char digest[16], char zDigest[50]){
- int i, j;
- unsigned int x;
- for(i=j=0; i<16; i+=2){
- x = digest[i]*256 + digest[i+1];
- if( i>0 ) zDigest[j++] = '-';
- sqlite3_snprintf(50-j, &zDigest[j], "%05u", x);
- j += 5;
- }
- zDigest[j] = 0;
-}
-
-/*
-** A TCL command for md5. The argument is the text to be hashed. The
-** Result is the hash in base64.
-*/
-static int SQLITE_TCLAPI md5_cmd(
- void*cd,
- Tcl_Interp *interp,
- int argc,
- const char **argv
-){
- MD5Context ctx;
- unsigned char digest[16];
- char zBuf[50];
- void (*converter)(unsigned char*, char*);
-
- if( argc!=2 ){
- Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
- " TEXT\"", (char*)0);
- return TCL_ERROR;
- }
- MD5Init(&ctx);
- MD5Update(&ctx, (unsigned char*)argv[1], (unsigned)strlen(argv[1]));
- MD5Final(digest, &ctx);
- converter = (void(*)(unsigned char*,char*))cd;
- converter(digest, zBuf);
- Tcl_AppendResult(interp, zBuf, (char*)0);
- return TCL_OK;
-}
-
-/*
-** A TCL command to take the md5 hash of a file. The argument is the
-** name of the file.
-*/
-static int SQLITE_TCLAPI md5file_cmd(
- void*cd,
- Tcl_Interp *interp,
- int argc,
- const char **argv
-){
- FILE *in;
- MD5Context ctx;
- void (*converter)(unsigned char*, char*);
- unsigned char digest[16];
- char zBuf[10240];
-
- if( argc!=2 ){
- Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
- " FILENAME\"", (char*)0);
- return TCL_ERROR;
- }
- in = fopen(argv[1],"rb");
- if( in==0 ){
- Tcl_AppendResult(interp,"unable to open file \"", argv[1],
- "\" for reading", (char*)0);
- return TCL_ERROR;
- }
- MD5Init(&ctx);
- for(;;){
- int n;
- n = (int)fread(zBuf, 1, sizeof(zBuf), in);
- if( n<=0 ) break;
- MD5Update(&ctx, (unsigned char*)zBuf, (unsigned)n);
- }
- fclose(in);
- MD5Final(digest, &ctx);
- converter = (void(*)(unsigned char*,char*))cd;
- converter(digest, zBuf);
- Tcl_AppendResult(interp, zBuf, (char*)0);
- return TCL_OK;
-}
-
-/*
-** Register the four new TCL commands for generating MD5 checksums
-** with the TCL interpreter.
+** If the TCLSH macro is defined, add code to make a stand-alone program.
*/
-int Md5_Init(Tcl_Interp *interp){
- Tcl_CreateCommand(interp, "md5", (Tcl_CmdProc*)md5_cmd,
- MD5DigestToBase16, 0);
- Tcl_CreateCommand(interp, "md5-10x8", (Tcl_CmdProc*)md5_cmd,
- MD5DigestToBase10x8, 0);
- Tcl_CreateCommand(interp, "md5file", (Tcl_CmdProc*)md5file_cmd,
- MD5DigestToBase16, 0);
- Tcl_CreateCommand(interp, "md5file-10x8", (Tcl_CmdProc*)md5file_cmd,
- MD5DigestToBase10x8, 0);
- return TCL_OK;
-}
-#endif /* defined(SQLITE_TEST) || defined(SQLITE_TCLMD5) */
+#if defined(TCLSH)
-#if defined(SQLITE_TEST)
-/*
-** During testing, the special md5sum() aggregate function is available.
-** inside SQLite. The following routines implement that function.
+/* This is the main routine for an ordinary TCL shell. If there are
+** are arguments, run the first argument as a script. Otherwise,
+** read TCL commands from standard input
*/
-static void md5step(sqlite3_context *context, int argc, sqlite3_value **argv){
- MD5Context *p;
- int i;
- if( argc<1 ) return;
- p = sqlite3_aggregate_context(context, sizeof(*p));
- if( p==0 ) return;
- if( !p->isInit ){
- MD5Init(p);
- }
- for(i=0; i<argc; i++){
- const char *zData = (char*)sqlite3_value_text(argv[i]);
- if( zData ){
- MD5Update(p, (unsigned char*)zData, (int)strlen(zData));
- }
- }
-}
-static void md5finalize(sqlite3_context *context){
- MD5Context *p;
- unsigned char digest[16];
- char zBuf[33];
- p = sqlite3_aggregate_context(context, sizeof(*p));
- MD5Final(digest,p);
- MD5DigestToBase16(digest, zBuf);
- sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
-}
-int Md5_Register(
- sqlite3 *db,
- char **pzErrMsg,
- const sqlite3_api_routines *pThunk
-){
- int rc = sqlite3_create_function(db, "md5sum", -1, SQLITE_UTF8, 0, 0,
- md5step, md5finalize);
- sqlite3_overload_function(db, "md5sum", -1); /* To exercise this API */
- return rc;
-}
-#endif /* defined(SQLITE_TEST) */
-
-
-/*
-** If the macro TCLSH is one, then put in code this for the
-** "main" routine that will initialize Tcl and take input from
-** standard input, or if a file is named on the command line
-** the TCL interpreter reads and evaluates that file.
-*/
-#if TCLSH==1
static const char *tclsh_main_loop(void){
static const char zMainloop[] =
- "set line {}\n"
- "while {![eof stdin]} {\n"
- "if {$line!=\"\"} {\n"
- "puts -nonewline \"> \"\n"
- "} else {\n"
- "puts -nonewline \"% \"\n"
- "}\n"
- "flush stdout\n"
- "append line [gets stdin]\n"
- "if {[info complete $line]} {\n"
- "if {[catch {uplevel #0 $line} result]} {\n"
- "puts stderr \"Error: $result\"\n"
- "} elseif {$result!=\"\"} {\n"
- "puts $result\n"
+ "if {[llength $argv]>=1} {\n"
+ "set argv0 [lindex $argv 0]\n"
+ "set argv [lrange $argv 1 end]\n"
+ "source $argv0\n"
+ "} else {\n"
+ "set line {}\n"
+ "while {![eof stdin]} {\n"
+ "if {$line!=\"\"} {\n"
+ "puts -nonewline \"> \"\n"
+ "} else {\n"
+ "puts -nonewline \"% \"\n"
+ "}\n"
+ "flush stdout\n"
+ "append line [gets stdin]\n"
+ "if {[info complete $line]} {\n"
+ "if {[catch {uplevel #0 $line} result]} {\n"
+ "puts stderr \"Error: $result\"\n"
+ "} elseif {$result!=\"\"} {\n"
+ "puts $result\n"
+ "}\n"
+ "set line {}\n"
+ "} else {\n"
+ "append line \\n\n"
"}\n"
- "set line {}\n"
- "} else {\n"
- "append line \\n\n"
"}\n"
"}\n"
;
return zMainloop;
}
-#endif
-#if TCLSH==2
-static const char *tclsh_main_loop(void);
-#endif
-
-#ifdef SQLITE_TEST
-static void init_all(Tcl_Interp *);
-static int SQLITE_TCLAPI init_all_cmd(
- ClientData cd,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
-
- Tcl_Interp *slave;
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "SLAVE");
- return TCL_ERROR;
- }
-
- slave = Tcl_GetSlave(interp, Tcl_GetString(objv[1]));
- if( !slave ){
- return TCL_ERROR;
- }
-
- init_all(slave);
- return TCL_OK;
-}
-
-/*
-** Tclcmd: db_use_legacy_prepare DB BOOLEAN
-**
-** The first argument to this command must be a database command created by
-** [sqlite3]. If the second argument is true, then the handle is configured
-** to use the sqlite3_prepare_v2() function to prepare statements. If it
-** is false, sqlite3_prepare().
-*/
-static int SQLITE_TCLAPI db_use_legacy_prepare_cmd(
- ClientData cd,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- Tcl_CmdInfo cmdInfo;
- SqliteDb *pDb;
- int bPrepare;
-
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB BOOLEAN");
- return TCL_ERROR;
- }
-
- if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){
- Tcl_AppendResult(interp, "no such db: ", Tcl_GetString(objv[1]), (char*)0);
- return TCL_ERROR;
- }
- pDb = (SqliteDb*)cmdInfo.objClientData;
- if( Tcl_GetBooleanFromObj(interp, objv[2], &bPrepare) ){
- return TCL_ERROR;
- }
-
- pDb->bLegacyPrepare = bPrepare;
-
- Tcl_ResetResult(interp);
- return TCL_OK;
-}
-
-/*
-** Tclcmd: db_last_stmt_ptr DB
-**
-** If the statement cache associated with database DB is not empty,
-** return the text representation of the most recently used statement
-** handle.
-*/
-static int SQLITE_TCLAPI db_last_stmt_ptr(
- ClientData cd,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- extern int sqlite3TestMakePointerStr(Tcl_Interp*, char*, void*);
- Tcl_CmdInfo cmdInfo;
- SqliteDb *pDb;
- sqlite3_stmt *pStmt = 0;
- char zBuf[100];
-
- if( objc!=2 ){
- Tcl_WrongNumArgs(interp, 1, objv, "DB");
- return TCL_ERROR;
- }
-
- if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){
- Tcl_AppendResult(interp, "no such db: ", Tcl_GetString(objv[1]), (char*)0);
- return TCL_ERROR;
- }
- pDb = (SqliteDb*)cmdInfo.objClientData;
-
- if( pDb->stmtList ) pStmt = pDb->stmtList->pStmt;
- if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ){
- return TCL_ERROR;
- }
- Tcl_SetResult(interp, zBuf, TCL_VOLATILE);
-
- return TCL_OK;
-}
-#endif /* SQLITE_TEST */
-
-/*
-** Configure the interpreter passed as the first argument to have access
-** to the commands and linked variables that make up:
-**
-** * the [sqlite3] extension itself,
-**
-** * If SQLITE_TCLMD5 or SQLITE_TEST is defined, the Md5 commands, and
-**
-** * If SQLITE_TEST is set, the various test interfaces used by the Tcl
-** test suite.
-*/
-static void init_all(Tcl_Interp *interp){
- Sqlite3_Init(interp);
-
-#if defined(SQLITE_TEST) || defined(SQLITE_TCLMD5)
- Md5_Init(interp);
-#endif
-
-#ifdef SQLITE_TEST
- {
- extern int Sqliteconfig_Init(Tcl_Interp*);
- extern int Sqlitetest1_Init(Tcl_Interp*);
- extern int Sqlitetest2_Init(Tcl_Interp*);
- extern int Sqlitetest3_Init(Tcl_Interp*);
- extern int Sqlitetest4_Init(Tcl_Interp*);
- extern int Sqlitetest5_Init(Tcl_Interp*);
- extern int Sqlitetest6_Init(Tcl_Interp*);
- extern int Sqlitetest7_Init(Tcl_Interp*);
- extern int Sqlitetest8_Init(Tcl_Interp*);
- extern int Sqlitetest9_Init(Tcl_Interp*);
- extern int Sqlitetestasync_Init(Tcl_Interp*);
- extern int Sqlitetest_autoext_Init(Tcl_Interp*);
- extern int Sqlitetest_blob_Init(Tcl_Interp*);
- extern int Sqlitetest_demovfs_Init(Tcl_Interp *);
- extern int Sqlitetest_func_Init(Tcl_Interp*);
- extern int Sqlitetest_hexio_Init(Tcl_Interp*);
- extern int Sqlitetest_init_Init(Tcl_Interp*);
- extern int Sqlitetest_malloc_Init(Tcl_Interp*);
- extern int Sqlitetest_mutex_Init(Tcl_Interp*);
- extern int Sqlitetestschema_Init(Tcl_Interp*);
- extern int Sqlitetestsse_Init(Tcl_Interp*);
- extern int Sqlitetesttclvar_Init(Tcl_Interp*);
- extern int Sqlitetestfs_Init(Tcl_Interp*);
- extern int SqlitetestThread_Init(Tcl_Interp*);
- extern int SqlitetestOnefile_Init();
- extern int SqlitetestOsinst_Init(Tcl_Interp*);
- extern int Sqlitetestbackup_Init(Tcl_Interp*);
- extern int Sqlitetestintarray_Init(Tcl_Interp*);
- extern int Sqlitetestvfs_Init(Tcl_Interp *);
- extern int Sqlitetestrtree_Init(Tcl_Interp*);
- extern int Sqlitequota_Init(Tcl_Interp*);
- extern int Sqlitemultiplex_Init(Tcl_Interp*);
- extern int SqliteSuperlock_Init(Tcl_Interp*);
- extern int SqlitetestSyscall_Init(Tcl_Interp*);
-#if defined(SQLITE_ENABLE_SESSION) && defined(SQLITE_ENABLE_PREUPDATE_HOOK)
- extern int TestSession_Init(Tcl_Interp*);
-#endif
- extern int Fts5tcl_Init(Tcl_Interp *);
- extern int SqliteRbu_Init(Tcl_Interp*);
- extern int Sqlitetesttcl_Init(Tcl_Interp*);
-#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
- extern int Sqlitetestfts3_Init(Tcl_Interp *interp);
-#endif
-
-#ifdef SQLITE_ENABLE_ZIPVFS
- extern int Zipvfs_Init(Tcl_Interp*);
- Zipvfs_Init(interp);
-#endif
-
- Sqliteconfig_Init(interp);
- Sqlitetest1_Init(interp);
- Sqlitetest2_Init(interp);
- Sqlitetest3_Init(interp);
- Sqlitetest4_Init(interp);
- Sqlitetest5_Init(interp);
- Sqlitetest6_Init(interp);
- Sqlitetest7_Init(interp);
- Sqlitetest8_Init(interp);
- Sqlitetest9_Init(interp);
- Sqlitetestasync_Init(interp);
- Sqlitetest_autoext_Init(interp);
- Sqlitetest_blob_Init(interp);
- Sqlitetest_demovfs_Init(interp);
- Sqlitetest_func_Init(interp);
- Sqlitetest_hexio_Init(interp);
- Sqlitetest_init_Init(interp);
- Sqlitetest_malloc_Init(interp);
- Sqlitetest_mutex_Init(interp);
- Sqlitetestschema_Init(interp);
- Sqlitetesttclvar_Init(interp);
- Sqlitetestfs_Init(interp);
- SqlitetestThread_Init(interp);
- SqlitetestOnefile_Init();
- SqlitetestOsinst_Init(interp);
- Sqlitetestbackup_Init(interp);
- Sqlitetestintarray_Init(interp);
- Sqlitetestvfs_Init(interp);
- Sqlitetestrtree_Init(interp);
- Sqlitequota_Init(interp);
- Sqlitemultiplex_Init(interp);
- SqliteSuperlock_Init(interp);
- SqlitetestSyscall_Init(interp);
-#if defined(SQLITE_ENABLE_SESSION) && defined(SQLITE_ENABLE_PREUPDATE_HOOK)
- TestSession_Init(interp);
-#endif
- Fts5tcl_Init(interp);
- SqliteRbu_Init(interp);
- Sqlitetesttcl_Init(interp);
-
-#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
- Sqlitetestfts3_Init(interp);
-#endif
-
- Tcl_CreateObjCommand(
- interp, "load_testfixture_extensions", init_all_cmd, 0, 0
- );
- Tcl_CreateObjCommand(
- interp, "db_use_legacy_prepare", db_use_legacy_prepare_cmd, 0, 0
- );
- Tcl_CreateObjCommand(
- interp, "db_last_stmt_ptr", db_last_stmt_ptr, 0, 0
- );
-
-#ifdef SQLITE_SSE
- Sqlitetestsse_Init(interp);
-#endif
- }
-#endif
-}
-
-/* Needed for the setrlimit() system call on unix */
-#if defined(unix)
-#include <sys/resource.h>
-#endif
#define TCLSH_MAIN main /* Needed to fake out mktclapp */
int SQLITE_CDECL TCLSH_MAIN(int argc, char **argv){
Tcl_Interp *interp;
+ int i;
+ const char *zScript = 0;
+ char zArgc[32];
+#if defined(TCLSH_INIT_PROC)
+ extern const char *TCLSH_INIT_PROC(Tcl_Interp*);
+#endif
#if !defined(_WIN32_WCE)
if( getenv("BREAK") ){
@@ -4260,17 +3643,6 @@ int SQLITE_CDECL TCLSH_MAIN(int argc, char **argv){
}
#endif
- /* Since the primary use case for this binary is testing of SQLite,
- ** be sure to generate core files if we crash */
-#if defined(SQLITE_TEST) && defined(unix)
- { struct rlimit x;
- getrlimit(RLIMIT_CORE, &x);
- x.rlim_cur = x.rlim_max;
- setrlimit(RLIMIT_CORE, &x);
- }
-#endif /* SQLITE_TEST && unix */
-
-
/* Call sqlite3_shutdown() once before doing anything else. This is to
** test that sqlite3_shutdown() can be safely called by a process before
** sqlite3_initialize() is. */
@@ -4279,32 +3651,27 @@ int SQLITE_CDECL TCLSH_MAIN(int argc, char **argv){
Tcl_FindExecutable(argv[0]);
Tcl_SetSystemEncoding(NULL, "utf-8");
interp = Tcl_CreateInterp();
+ Sqlite3_Init(interp);
-#if TCLSH==2
- sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);
+ sqlite3_snprintf(sizeof(zArgc), zArgc, "%d", argc-1);
+ Tcl_SetVar(interp,"argc", zArgc, TCL_GLOBAL_ONLY);
+ Tcl_SetVar(interp,"argv0",argv[0],TCL_GLOBAL_ONLY);
+ Tcl_SetVar(interp,"argv", "", TCL_GLOBAL_ONLY);
+ for(i=1; i<argc; i++){
+ Tcl_SetVar(interp, "argv", argv[i],
+ TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT | TCL_APPEND_VALUE);
+ }
+#if defined(TCLSH_INIT_PROC)
+ zScript = TCLSH_INIT_PROC(interp);
#endif
-
- init_all(interp);
- if( argc>=2 ){
- int i;
- char zArgc[32];
- sqlite3_snprintf(sizeof(zArgc), zArgc, "%d", argc-(3-TCLSH));
- Tcl_SetVar(interp,"argc", zArgc, TCL_GLOBAL_ONLY);
- Tcl_SetVar(interp,"argv0",argv[1],TCL_GLOBAL_ONLY);
- Tcl_SetVar(interp,"argv", "", TCL_GLOBAL_ONLY);
- for(i=3-TCLSH; i<argc; i++){
- Tcl_SetVar(interp, "argv", argv[i],
- TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT | TCL_APPEND_VALUE);
- }
- if( TCLSH==1 && Tcl_EvalFile(interp, argv[1])!=TCL_OK ){
- const char *zInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
- if( zInfo==0 ) zInfo = Tcl_GetStringResult(interp);
- fprintf(stderr,"%s: %s\n", *argv, zInfo);
- return 1;
- }
+ if( zScript==0 ){
+ zScript = tclsh_main_loop();
}
- if( TCLSH==2 || argc<=1 ){
- Tcl_GlobalEval(interp, tclsh_main_loop());
+ if( Tcl_GlobalEval(interp, zScript)!=TCL_OK ){
+ const char *zInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);
+ if( zInfo==0 ) zInfo = Tcl_GetStringResult(interp);
+ fprintf(stderr,"%s: %s\n", *argv, zInfo);
+ return 1;
}
return 0;
}
diff --git a/chromium/third_party/sqlite/src/src/test1.c b/chromium/third_party/sqlite/src/src/test1.c
index 4122651cbe3..66778262732 100644
--- a/chromium/third_party/sqlite/src/src/test1.c
+++ b/chromium/third_party/sqlite/src/src/test1.c
@@ -2554,6 +2554,46 @@ static int SQLITE_TCLAPI test_delete_database(
}
/*
+** Usage: atomic_batch_write PATH
+*/
+static int SQLITE_TCLAPI test_atomic_batch_write(
+ void * clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+ char *zFile = 0; /* Path to file to test */
+ sqlite3 *db = 0; /* Database handle */
+ sqlite3_file *pFd = 0; /* SQLite fd open on zFile */
+ int bRes = 0; /* Integer result of this command */
+ int dc = 0; /* Device-characteristics mask */
+ int rc; /* sqlite3_open() return code */
+
+ if( objc!=2 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "PATH");
+ return TCL_ERROR;
+ }
+ zFile = Tcl_GetString(objv[1]);
+
+ rc = sqlite3_open(zFile, &db);
+ if( rc!=SQLITE_OK ){
+ Tcl_AppendResult(interp, sqlite3_errmsg(db), 0);
+ sqlite3_close(db);
+ return TCL_ERROR;
+ }
+
+ rc = sqlite3_file_control(db, "main", SQLITE_FCNTL_FILE_POINTER, (void*)&pFd);
+ dc = pFd->pMethods->xDeviceCharacteristics(pFd);
+ if( dc & SQLITE_IOCAP_BATCH_ATOMIC ){
+ bRes = 1;
+ }
+
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(bRes));
+ sqlite3_close(db);
+ return TCL_OK;
+}
+
+/*
** Usage: sqlite3_next_stmt DB STMT
**
** Return the next statment in sequence after STMT.
@@ -6861,7 +6901,6 @@ static int SQLITE_TCLAPI optimization_control(
{ "cover-idx-scan", SQLITE_CoverIdxScan },
{ "order-by-idx-join", SQLITE_OrderByIdxJoin },
{ "transitive", SQLITE_Transitive },
- { "subquery-coroutine", SQLITE_SubqCoroutine },
{ "omit-noop-join", SQLITE_OmitNoopJoin },
{ "stat3", SQLITE_Stat34 },
{ "stat4", SQLITE_Stat34 },
@@ -7376,6 +7415,35 @@ static int SQLITE_TCLAPI test_dbconfig_maindbname_icecube(
}
/*
+** Usage: sqlite3_mmap_warm DB DBNAME
+*/
+static int SQLITE_TCLAPI test_mmap_warm(
+ void * clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+ extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
+ extern int sqlite3_mmap_warm(sqlite3 *db, const char *);
+
+ if( objc!=2 && objc!=3 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "DB ?DBNAME?");
+ return TCL_ERROR;
+ }else{
+ int rc;
+ sqlite3 *db;
+ const char *zDb = 0;
+ if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
+ if( objc==3 ){
+ zDb = Tcl_GetString(objv[2]);
+ }
+ rc = sqlite3_mmap_warm(db, zDb);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
+ return TCL_OK;
+ }
+}
+
+/*
** Register commands with the TCL interpreter.
*/
int Sqlitetest1_Init(Tcl_Interp *interp){
@@ -7644,7 +7712,9 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "sqlite3_snapshot_open_blob", test_snapshot_open_blob, 0 },
{ "sqlite3_snapshot_cmp_blob", test_snapshot_cmp_blob, 0 },
#endif
- { "sqlite3_delete_database", test_delete_database, 0 },
+ { "sqlite3_delete_database", test_delete_database, 0 },
+ { "atomic_batch_write", test_atomic_batch_write, 0 },
+ { "sqlite3_mmap_warm", test_mmap_warm, 0 },
};
static int bitmask_size = sizeof(Bitmask)*8;
static int longdouble_size = sizeof(LONGDOUBLE_TYPE);
diff --git a/chromium/third_party/sqlite/src/src/test6.c b/chromium/third_party/sqlite/src/src/test6.c
index 682185005b7..191fe05860d 100644
--- a/chromium/third_party/sqlite/src/src/test6.c
+++ b/chromium/third_party/sqlite/src/src/test6.c
@@ -736,6 +736,7 @@ static int processDevSymArgs(
{ "sequential", SQLITE_IOCAP_SEQUENTIAL },
{ "safe_append", SQLITE_IOCAP_SAFE_APPEND },
{ "powersafe_overwrite", SQLITE_IOCAP_POWERSAFE_OVERWRITE },
+ { "batch-atomic", SQLITE_IOCAP_BATCH_ATOMIC },
{ 0, 0 }
};
@@ -976,7 +977,30 @@ static int SQLITE_TCLAPI devSymObjCmd(
devsym_register(iDc, iSectorSize);
return TCL_OK;
+}
+/*
+** tclcmd: sqlite3_crash_on_write N
+*/
+static int SQLITE_TCLAPI writeCrashObjCmd(
+ void * clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+ void devsym_crash_on_write(int);
+ int nWrite = 0;
+
+ if( objc!=2 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "NWRITE");
+ return TCL_ERROR;
+ }
+ if( Tcl_GetIntFromObj(interp, objv[1], &nWrite) ){
+ return TCL_ERROR;
+ }
+
+ devsym_crash_on_write(nWrite);
+ return TCL_OK;
}
/*
@@ -1068,6 +1092,7 @@ int Sqlitetest6_Init(Tcl_Interp *interp){
Tcl_CreateObjCommand(interp, "sqlite3_crashparams", crashParamsObjCmd, 0, 0);
Tcl_CreateObjCommand(interp, "sqlite3_crash_now", crashNowCmd, 0, 0);
Tcl_CreateObjCommand(interp, "sqlite3_simulate_device", devSymObjCmd, 0, 0);
+ Tcl_CreateObjCommand(interp, "sqlite3_crash_on_write", writeCrashObjCmd,0,0);
Tcl_CreateObjCommand(interp, "unregister_devsim", dsUnregisterObjCmd, 0, 0);
Tcl_CreateObjCommand(interp, "register_jt_vfs", jtObjCmd, 0, 0);
Tcl_CreateObjCommand(interp, "unregister_jt_vfs", jtUnregisterObjCmd, 0, 0);
diff --git a/chromium/third_party/sqlite/src/src/test8.c b/chromium/third_party/sqlite/src/src/test8.c
index 1a89e475b08..b54759f8e4b 100644
--- a/chromium/third_party/sqlite/src/src/test8.c
+++ b/chromium/third_party/sqlite/src/src/test8.c
@@ -897,17 +897,18 @@ static int echoBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
case SQLITE_INDEX_CONSTRAINT_REGEXP:
zOp = "regexp"; break;
}
- if( zOp[0]=='L' ){
- zNew = sqlite3_mprintf(" %s %s LIKE (SELECT '%%'||?||'%%')",
- zSep, zNewCol);
- } else {
- zNew = sqlite3_mprintf(" %s %s %s ?", zSep, zNewCol, zOp);
+ if( zOp ){
+ if( zOp[0]=='L' ){
+ zNew = sqlite3_mprintf(" %s %s LIKE (SELECT '%%'||?||'%%')",
+ zSep, zNewCol);
+ } else {
+ zNew = sqlite3_mprintf(" %s %s %s ?", zSep, zNewCol, zOp);
+ }
+ string_concat(&zQuery, zNew, 1, &rc);
+ zSep = "AND";
+ pUsage->argvIndex = ++nArg;
+ pUsage->omit = 1;
}
- string_concat(&zQuery, zNew, 1, &rc);
-
- zSep = "AND";
- pUsage->argvIndex = ++nArg;
- pUsage->omit = 1;
}
}
diff --git a/chromium/third_party/sqlite/src/src/test_bestindex.c b/chromium/third_party/sqlite/src/src/test_bestindex.c
index f0cef49489b..581f5b1a76d 100644
--- a/chromium/third_party/sqlite/src/src/test_bestindex.c
+++ b/chromium/third_party/sqlite/src/src/test_bestindex.c
@@ -414,6 +414,16 @@ static int tclBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
zOp = "glob"; break;
case SQLITE_INDEX_CONSTRAINT_REGEXP:
zOp = "regexp"; break;
+ case SQLITE_INDEX_CONSTRAINT_NE:
+ zOp = "ne"; break;
+ case SQLITE_INDEX_CONSTRAINT_ISNOT:
+ zOp = "isnot"; break;
+ case SQLITE_INDEX_CONSTRAINT_ISNOTNULL:
+ zOp = "isnotnull"; break;
+ case SQLITE_INDEX_CONSTRAINT_ISNULL:
+ zOp = "isnull"; break;
+ case SQLITE_INDEX_CONSTRAINT_IS:
+ zOp = "is"; break;
}
Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj("op", -1));
diff --git a/chromium/third_party/sqlite/src/src/test_config.c b/chromium/third_party/sqlite/src/src/test_config.c
index b794f6c90c9..95392925f3f 100644
--- a/chromium/third_party/sqlite/src/src/test_config.c
+++ b/chromium/third_party/sqlite/src/src/test_config.c
@@ -214,6 +214,12 @@ static void set_options(Tcl_Interp *interp){
Tcl_SetVar2(interp, "sqlite_options", "json1", "0", TCL_GLOBAL_ONLY);
#endif
+#ifdef SQLITE_HAS_CODEC
+ Tcl_SetVar2(interp, "sqlite_options", "has_codec", "1", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "has_codec", "0", TCL_GLOBAL_ONLY);
+#endif
+
#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
Tcl_SetVar2(interp, "sqlite_options", "like_match_blobs", "0", TCL_GLOBAL_ONLY);
#else
diff --git a/chromium/third_party/sqlite/src/src/test_devsym.c b/chromium/third_party/sqlite/src/src/test_devsym.c
index a436bb5ac39..22542b7a47f 100644
--- a/chromium/third_party/sqlite/src/src/test_devsym.c
+++ b/chromium/third_party/sqlite/src/src/test_devsym.c
@@ -28,6 +28,7 @@
** Name used to identify this VFS.
*/
#define DEVSYM_VFS_NAME "devsym"
+#define WRITECRASH_NAME "writecrash"
typedef struct devsym_file devsym_file;
struct devsym_file {
@@ -72,61 +73,13 @@ static int devsymRandomness(sqlite3_vfs*, int nByte, char *zOut);
static int devsymSleep(sqlite3_vfs*, int microseconds);
static int devsymCurrentTime(sqlite3_vfs*, double*);
-static sqlite3_vfs devsym_vfs = {
- 2, /* iVersion */
- sizeof(devsym_file), /* szOsFile */
- DEVSYM_MAX_PATHNAME, /* mxPathname */
- 0, /* pNext */
- DEVSYM_VFS_NAME, /* zName */
- 0, /* pAppData */
- devsymOpen, /* xOpen */
- devsymDelete, /* xDelete */
- devsymAccess, /* xAccess */
- devsymFullPathname, /* xFullPathname */
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
- devsymDlOpen, /* xDlOpen */
- devsymDlError, /* xDlError */
- devsymDlSym, /* xDlSym */
- devsymDlClose, /* xDlClose */
-#else
- 0, /* xDlOpen */
- 0, /* xDlError */
- 0, /* xDlSym */
- 0, /* xDlClose */
-#endif /* SQLITE_OMIT_LOAD_EXTENSION */
- devsymRandomness, /* xRandomness */
- devsymSleep, /* xSleep */
- devsymCurrentTime, /* xCurrentTime */
- 0, /* xGetLastError */
- 0 /* xCurrentTimeInt64 */
-};
-
-static sqlite3_io_methods devsym_io_methods = {
- 2, /* iVersion */
- devsymClose, /* xClose */
- devsymRead, /* xRead */
- devsymWrite, /* xWrite */
- devsymTruncate, /* xTruncate */
- devsymSync, /* xSync */
- devsymFileSize, /* xFileSize */
- devsymLock, /* xLock */
- devsymUnlock, /* xUnlock */
- devsymCheckReservedLock, /* xCheckReservedLock */
- devsymFileControl, /* xFileControl */
- devsymSectorSize, /* xSectorSize */
- devsymDeviceCharacteristics, /* xDeviceCharacteristics */
- devsymShmMap, /* xShmMap */
- devsymShmLock, /* xShmLock */
- devsymShmBarrier, /* xShmBarrier */
- devsymShmUnmap /* xShmUnmap */
-};
-
struct DevsymGlobal {
sqlite3_vfs *pVfs;
int iDeviceChar;
int iSectorSize;
+ int nWriteCrash;
};
-struct DevsymGlobal g = {0, 0, 512};
+struct DevsymGlobal g = {0, 0, 512, 0};
/*
** Close an devsym-file.
@@ -271,6 +224,26 @@ static int devsymOpen(
int flags,
int *pOutFlags
){
+static sqlite3_io_methods devsym_io_methods = {
+ 2, /* iVersion */
+ devsymClose, /* xClose */
+ devsymRead, /* xRead */
+ devsymWrite, /* xWrite */
+ devsymTruncate, /* xTruncate */
+ devsymSync, /* xSync */
+ devsymFileSize, /* xFileSize */
+ devsymLock, /* xLock */
+ devsymUnlock, /* xUnlock */
+ devsymCheckReservedLock, /* xCheckReservedLock */
+ devsymFileControl, /* xFileControl */
+ devsymSectorSize, /* xSectorSize */
+ devsymDeviceCharacteristics, /* xDeviceCharacteristics */
+ devsymShmMap, /* xShmMap */
+ devsymShmLock, /* xShmLock */
+ devsymShmBarrier, /* xShmBarrier */
+ devsymShmUnmap /* xShmUnmap */
+};
+
int rc;
devsym_file *p = (devsym_file *)pFile;
p->pReal = (sqlite3_file *)&p[1];
@@ -372,6 +345,137 @@ static int devsymCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
return g.pVfs->xCurrentTime(g.pVfs, pTimeOut);
}
+/*
+** Return the sector-size in bytes for an writecrash-file.
+*/
+static int writecrashSectorSize(sqlite3_file *pFile){
+ devsym_file *p = (devsym_file *)pFile;
+ return sqlite3OsSectorSize(p->pReal);
+}
+
+/*
+** Return the device characteristic flags supported by an writecrash-file.
+*/
+static int writecrashDeviceCharacteristics(sqlite3_file *pFile){
+ devsym_file *p = (devsym_file *)pFile;
+ return sqlite3OsDeviceCharacteristics(p->pReal);
+}
+
+/*
+** Write data to an writecrash-file.
+*/
+static int writecrashWrite(
+ sqlite3_file *pFile,
+ const void *zBuf,
+ int iAmt,
+ sqlite_int64 iOfst
+){
+ devsym_file *p = (devsym_file *)pFile;
+ if( g.nWriteCrash>0 ){
+ g.nWriteCrash--;
+ if( g.nWriteCrash==0 ) abort();
+ }
+ return sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst);
+}
+
+/*
+** Open an writecrash file handle.
+*/
+static int writecrashOpen(
+ sqlite3_vfs *pVfs,
+ const char *zName,
+ sqlite3_file *pFile,
+ int flags,
+ int *pOutFlags
+){
+static sqlite3_io_methods writecrash_io_methods = {
+ 2, /* iVersion */
+ devsymClose, /* xClose */
+ devsymRead, /* xRead */
+ writecrashWrite, /* xWrite */
+ devsymTruncate, /* xTruncate */
+ devsymSync, /* xSync */
+ devsymFileSize, /* xFileSize */
+ devsymLock, /* xLock */
+ devsymUnlock, /* xUnlock */
+ devsymCheckReservedLock, /* xCheckReservedLock */
+ devsymFileControl, /* xFileControl */
+ writecrashSectorSize, /* xSectorSize */
+ writecrashDeviceCharacteristics, /* xDeviceCharacteristics */
+ devsymShmMap, /* xShmMap */
+ devsymShmLock, /* xShmLock */
+ devsymShmBarrier, /* xShmBarrier */
+ devsymShmUnmap /* xShmUnmap */
+};
+
+ int rc;
+ devsym_file *p = (devsym_file *)pFile;
+ p->pReal = (sqlite3_file *)&p[1];
+ rc = sqlite3OsOpen(g.pVfs, zName, p->pReal, flags, pOutFlags);
+ if( p->pReal->pMethods ){
+ pFile->pMethods = &writecrash_io_methods;
+ }
+ return rc;
+}
+
+static sqlite3_vfs devsym_vfs = {
+ 2, /* iVersion */
+ sizeof(devsym_file), /* szOsFile */
+ DEVSYM_MAX_PATHNAME, /* mxPathname */
+ 0, /* pNext */
+ DEVSYM_VFS_NAME, /* zName */
+ 0, /* pAppData */
+ devsymOpen, /* xOpen */
+ devsymDelete, /* xDelete */
+ devsymAccess, /* xAccess */
+ devsymFullPathname, /* xFullPathname */
+#ifndef SQLITE_OMIT_LOAD_EXTENSION
+ devsymDlOpen, /* xDlOpen */
+ devsymDlError, /* xDlError */
+ devsymDlSym, /* xDlSym */
+ devsymDlClose, /* xDlClose */
+#else
+ 0, /* xDlOpen */
+ 0, /* xDlError */
+ 0, /* xDlSym */
+ 0, /* xDlClose */
+#endif /* SQLITE_OMIT_LOAD_EXTENSION */
+ devsymRandomness, /* xRandomness */
+ devsymSleep, /* xSleep */
+ devsymCurrentTime, /* xCurrentTime */
+ 0, /* xGetLastError */
+ 0 /* xCurrentTimeInt64 */
+};
+
+static sqlite3_vfs writecrash_vfs = {
+ 2, /* iVersion */
+ sizeof(devsym_file), /* szOsFile */
+ DEVSYM_MAX_PATHNAME, /* mxPathname */
+ 0, /* pNext */
+ WRITECRASH_NAME, /* zName */
+ 0, /* pAppData */
+ writecrashOpen, /* xOpen */
+ devsymDelete, /* xDelete */
+ devsymAccess, /* xAccess */
+ devsymFullPathname, /* xFullPathname */
+#ifndef SQLITE_OMIT_LOAD_EXTENSION
+ devsymDlOpen, /* xDlOpen */
+ devsymDlError, /* xDlError */
+ devsymDlSym, /* xDlSym */
+ devsymDlClose, /* xDlClose */
+#else
+ 0, /* xDlOpen */
+ 0, /* xDlError */
+ 0, /* xDlSym */
+ 0, /* xDlClose */
+#endif /* SQLITE_OMIT_LOAD_EXTENSION */
+ devsymRandomness, /* xRandomness */
+ devsymSleep, /* xSleep */
+ devsymCurrentTime, /* xCurrentTime */
+ 0, /* xGetLastError */
+ 0 /* xCurrentTimeInt64 */
+};
+
/*
** This procedure registers the devsym vfs with SQLite. If the argument is
@@ -379,10 +483,13 @@ static int devsymCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
** available function in this file.
*/
void devsym_register(int iDeviceChar, int iSectorSize){
+
if( g.pVfs==0 ){
g.pVfs = sqlite3_vfs_find(0);
devsym_vfs.szOsFile += g.pVfs->szOsFile;
+ writecrash_vfs.szOsFile += g.pVfs->szOsFile;
sqlite3_vfs_register(&devsym_vfs, 0);
+ sqlite3_vfs_register(&writecrash_vfs, 0);
}
if( iDeviceChar>=0 ){
g.iDeviceChar = iDeviceChar;
@@ -403,4 +510,15 @@ void devsym_unregister(){
g.iSectorSize = 0;
}
+void devsym_crash_on_write(int nWrite){
+ if( g.pVfs==0 ){
+ g.pVfs = sqlite3_vfs_find(0);
+ devsym_vfs.szOsFile += g.pVfs->szOsFile;
+ writecrash_vfs.szOsFile += g.pVfs->szOsFile;
+ sqlite3_vfs_register(&devsym_vfs, 0);
+ sqlite3_vfs_register(&writecrash_vfs, 0);
+ }
+ g.nWriteCrash = nWrite;
+}
+
#endif
diff --git a/chromium/third_party/sqlite/src/src/test_func.c b/chromium/third_party/sqlite/src/src/test_func.c
index c8d287341d0..30f4a326a5b 100644
--- a/chromium/third_party/sqlite/src/src/test_func.c
+++ b/chromium/third_party/sqlite/src/src/test_func.c
@@ -792,6 +792,123 @@ abuse_err:
/*
+** SQLite user defined function to use with matchinfo() to calculate the
+** relevancy of an FTS match. The value returned is the relevancy score
+** (a real value greater than or equal to zero). A larger value indicates
+** a more relevant document.
+**
+** The overall relevancy returned is the sum of the relevancies of each
+** column value in the FTS table. The relevancy of a column value is the
+** sum of the following for each reportable phrase in the FTS query:
+**
+** (<hit count> / <global hit count>) * <column weight>
+**
+** where <hit count> is the number of instances of the phrase in the
+** column value of the current row and <global hit count> is the number
+** of instances of the phrase in the same column of all rows in the FTS
+** table. The <column weight> is a weighting factor assigned to each
+** column by the caller (see below).
+**
+** The first argument to this function must be the return value of the FTS
+** matchinfo() function. Following this must be one argument for each column
+** of the FTS table containing a numeric weight factor for the corresponding
+** column. Example:
+**
+** CREATE VIRTUAL TABLE documents USING fts3(title, content)
+**
+** The following query returns the docids of documents that match the full-text
+** query <query> sorted from most to least relevant. When calculating
+** relevance, query term instances in the 'title' column are given twice the
+** weighting of those in the 'content' column.
+**
+** SELECT docid FROM documents
+** WHERE documents MATCH <query>
+** ORDER BY rank(matchinfo(documents), 1.0, 0.5) DESC
+*/
+static void rankfunc(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){
+ int *aMatchinfo; /* Return value of matchinfo() */
+ int nMatchinfo; /* Number of elements in aMatchinfo[] */
+ int nCol = 0; /* Number of columns in the table */
+ int nPhrase = 0; /* Number of phrases in the query */
+ int iPhrase; /* Current phrase */
+ double score = 0.0; /* Value to return */
+
+ assert( sizeof(int)==4 );
+
+ /* Check that the number of arguments passed to this function is correct.
+ ** If not, jump to wrong_number_args. Set aMatchinfo to point to the array
+ ** of unsigned integer values returned by FTS function matchinfo. Set
+ ** nPhrase to contain the number of reportable phrases in the users full-text
+ ** query, and nCol to the number of columns in the table. Then check that the
+ ** size of the matchinfo blob is as expected. Return an error if it is not.
+ */
+ if( nVal<1 ) goto wrong_number_args;
+ aMatchinfo = (int*)sqlite3_value_blob(apVal[0]);
+ nMatchinfo = sqlite3_value_bytes(apVal[0]) / sizeof(int);
+ if( nMatchinfo>=2 ){
+ nPhrase = aMatchinfo[0];
+ nCol = aMatchinfo[1];
+ }
+ if( nMatchinfo!=(2+3*nCol*nPhrase) ){
+ sqlite3_result_error(pCtx,
+ "invalid matchinfo blob passed to function rank()", -1);
+ return;
+ }
+ if( nVal!=(1+nCol) ) goto wrong_number_args;
+
+ /* Iterate through each phrase in the users query. */
+ for(iPhrase=0; iPhrase<nPhrase; iPhrase++){
+ int iCol; /* Current column */
+
+ /* Now iterate through each column in the users query. For each column,
+ ** increment the relevancy score by:
+ **
+ ** (<hit count> / <global hit count>) * <column weight>
+ **
+ ** aPhraseinfo[] points to the start of the data for phrase iPhrase. So
+ ** the hit count and global hit counts for each column are found in
+ ** aPhraseinfo[iCol*3] and aPhraseinfo[iCol*3+1], respectively.
+ */
+ int *aPhraseinfo = &aMatchinfo[2 + iPhrase*nCol*3];
+ for(iCol=0; iCol<nCol; iCol++){
+ int nHitCount = aPhraseinfo[3*iCol];
+ int nGlobalHitCount = aPhraseinfo[3*iCol+1];
+ double weight = sqlite3_value_double(apVal[iCol+1]);
+ if( nHitCount>0 ){
+ score += ((double)nHitCount / (double)nGlobalHitCount) * weight;
+ }
+ }
+ }
+
+ sqlite3_result_double(pCtx, score);
+ return;
+
+ /* Jump here if the wrong number of arguments are passed to this function */
+wrong_number_args:
+ sqlite3_result_error(pCtx, "wrong number of arguments to function rank()", -1);
+}
+
+static int SQLITE_TCLAPI install_fts3_rank_function(
+ void * clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+ extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
+ sqlite3 *db;
+
+ if( objc!=2 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "DB");
+ return TCL_ERROR;
+ }
+
+ if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
+ sqlite3_create_function(db, "rank", -1, SQLITE_UTF8, 0, rankfunc, 0, 0);
+ return TCL_OK;
+}
+
+
+/*
** Register commands with the TCL interpreter.
*/
int Sqlitetest_func_Init(Tcl_Interp *interp){
@@ -801,6 +918,7 @@ int Sqlitetest_func_Init(Tcl_Interp *interp){
} aObjCmd[] = {
{ "autoinstall_test_functions", autoinstall_test_funcs },
{ "abuse_create_function", abuse_create_function },
+ { "install_fts3_rank_function", install_fts3_rank_function },
};
int i;
extern int Md5_Register(sqlite3 *, char **, const sqlite3_api_routines *);
diff --git a/chromium/third_party/sqlite/src/src/test_malloc.c b/chromium/third_party/sqlite/src/src/test_malloc.c
index 9283b9a68ff..54a61dfea08 100644
--- a/chromium/third_party/sqlite/src/src/test_malloc.c
+++ b/chromium/third_party/sqlite/src/src/test_malloc.c
@@ -888,46 +888,6 @@ static int SQLITE_TCLAPI test_memdebug_log(
}
/*
-** Usage: sqlite3_config_scratch SIZE N
-**
-** Set the scratch memory buffer using SQLITE_CONFIG_SCRATCH.
-** The buffer is static and is of limited size. N might be
-** adjusted downward as needed to accommodate the requested size.
-** The revised value of N is returned.
-**
-** A negative SIZE causes the buffer pointer to be NULL.
-*/
-static int SQLITE_TCLAPI test_config_scratch(
- void * clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *CONST objv[]
-){
- int sz, N, rc;
- Tcl_Obj *pResult;
- static char *buf = 0;
- if( objc!=3 ){
- Tcl_WrongNumArgs(interp, 1, objv, "SIZE N");
- return TCL_ERROR;
- }
- if( Tcl_GetIntFromObj(interp, objv[1], &sz) ) return TCL_ERROR;
- if( Tcl_GetIntFromObj(interp, objv[2], &N) ) return TCL_ERROR;
- free(buf);
- if( sz<0 ){
- buf = 0;
- rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, (void*)0, 0, 0);
- }else{
- buf = malloc( sz*N + 1 );
- rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, buf, sz, N);
- }
- pResult = Tcl_NewObj();
- Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc));
- Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(N));
- Tcl_SetObjResult(interp, pResult);
- return TCL_OK;
-}
-
-/*
** Usage: sqlite3_config_pagecache SIZE N
**
** Set the page-cache memory buffer using SQLITE_CONFIG_PAGECACHE.
@@ -1538,7 +1498,6 @@ int Sqlitetest_malloc_Init(Tcl_Interp *interp){
{ "sqlite3_memdebug_settitle", test_memdebug_settitle ,0 },
{ "sqlite3_memdebug_malloc_count", test_memdebug_malloc_count ,0 },
{ "sqlite3_memdebug_log", test_memdebug_log ,0 },
- { "sqlite3_config_scratch", test_config_scratch ,0 },
{ "sqlite3_config_pagecache", test_config_pagecache ,0 },
{ "sqlite3_config_alt_pcache", test_alt_pcache ,0 },
{ "sqlite3_status", test_status ,0 },
diff --git a/chromium/third_party/sqlite/src/src/test_md5.c b/chromium/third_party/sqlite/src/src/test_md5.c
new file mode 100644
index 00000000000..b670026861a
--- /dev/null
+++ b/chromium/third_party/sqlite/src/src/test_md5.c
@@ -0,0 +1,450 @@
+/*
+** 2017-10-13
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file contains code to implement an MD5 extension to TCL.
+*/
+#include "sqlite3.h"
+#include <stdlib.h>
+#include <string.h>
+#include "sqlite3.h"
+#if defined(INCLUDE_SQLITE_TCL_H)
+# include "sqlite_tcl.h"
+#else
+# include "tcl.h"
+# ifndef SQLITE_TCLAPI
+# define SQLITE_TCLAPI
+# endif
+#endif
+
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest. This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ */
+
+/*
+ * If compiled on a machine that doesn't have a 32-bit integer,
+ * you just set "uint32" to the appropriate datatype for an
+ * unsigned 32-bit integer. For example:
+ *
+ * cc -Duint32='unsigned long' md5.c
+ *
+ */
+#ifndef uint32
+# define uint32 unsigned int
+#endif
+
+struct MD5Context {
+ int isInit;
+ uint32 buf[4];
+ uint32 bits[2];
+ unsigned char in[64];
+};
+typedef struct MD5Context MD5Context;
+
+/*
+ * Note: this code is harmless on little-endian machines.
+ */
+static void byteReverse (unsigned char *buf, unsigned longs){
+ uint32 t;
+ do {
+ t = (uint32)((unsigned)buf[3]<<8 | buf[2]) << 16 |
+ ((unsigned)buf[1]<<8 | buf[0]);
+ *(uint32 *)buf = t;
+ buf += 4;
+ } while (--longs);
+}
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f, w, x, y, z, data, s) \
+ ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data. MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+static void MD5Transform(uint32 buf[4], const uint32 in[16]){
+ register uint32 a, b, c, d;
+
+ a = buf[0];
+ b = buf[1];
+ c = buf[2];
+ d = buf[3];
+
+ MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
+
+ MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
+
+ MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
+
+ MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+}
+
+/*
+ * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+static void MD5Init(MD5Context *ctx){
+ ctx->isInit = 1;
+ ctx->buf[0] = 0x67452301;
+ ctx->buf[1] = 0xefcdab89;
+ ctx->buf[2] = 0x98badcfe;
+ ctx->buf[3] = 0x10325476;
+ ctx->bits[0] = 0;
+ ctx->bits[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+static
+void MD5Update(MD5Context *ctx, const unsigned char *buf, unsigned int len){
+ uint32 t;
+
+ /* Update bitcount */
+
+ t = ctx->bits[0];
+ if ((ctx->bits[0] = t + ((uint32)len << 3)) < t)
+ ctx->bits[1]++; /* Carry from low to high */
+ ctx->bits[1] += len >> 29;
+
+ t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
+
+ /* Handle any leading odd-sized chunks */
+
+ if ( t ) {
+ unsigned char *p = (unsigned char *)ctx->in + t;
+
+ t = 64-t;
+ if (len < t) {
+ memcpy(p, buf, len);
+ return;
+ }
+ memcpy(p, buf, t);
+ byteReverse(ctx->in, 16);
+ MD5Transform(ctx->buf, (uint32 *)ctx->in);
+ buf += t;
+ len -= t;
+ }
+
+ /* Process data in 64-byte chunks */
+
+ while (len >= 64) {
+ memcpy(ctx->in, buf, 64);
+ byteReverse(ctx->in, 16);
+ MD5Transform(ctx->buf, (uint32 *)ctx->in);
+ buf += 64;
+ len -= 64;
+ }
+
+ /* Handle any remaining bytes of data. */
+
+ memcpy(ctx->in, buf, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+static void MD5Final(unsigned char digest[16], MD5Context *ctx){
+ unsigned count;
+ unsigned char *p;
+
+ /* Compute number of bytes mod 64 */
+ count = (ctx->bits[0] >> 3) & 0x3F;
+
+ /* Set the first char of padding to 0x80. This is safe since there is
+ always at least one byte free */
+ p = ctx->in + count;
+ *p++ = 0x80;
+
+ /* Bytes of padding needed to make 64 bytes */
+ count = 64 - 1 - count;
+
+ /* Pad out to 56 mod 64 */
+ if (count < 8) {
+ /* Two lots of padding: Pad the first block to 64 bytes */
+ memset(p, 0, count);
+ byteReverse(ctx->in, 16);
+ MD5Transform(ctx->buf, (uint32 *)ctx->in);
+
+ /* Now fill the next block with 56 bytes */
+ memset(ctx->in, 0, 56);
+ } else {
+ /* Pad block to 56 bytes */
+ memset(p, 0, count-8);
+ }
+ byteReverse(ctx->in, 14);
+
+ /* Append length in bits and transform */
+ memcpy(ctx->in + 14*4, ctx->bits, 8);
+
+ MD5Transform(ctx->buf, (uint32 *)ctx->in);
+ byteReverse((unsigned char *)ctx->buf, 4);
+ memcpy(digest, ctx->buf, 16);
+}
+
+/*
+** Convert a 128-bit MD5 digest into a 32-digit base-16 number.
+*/
+static void MD5DigestToBase16(unsigned char *digest, char *zBuf){
+ static char const zEncode[] = "0123456789abcdef";
+ int i, j;
+
+ for(j=i=0; i<16; i++){
+ int a = digest[i];
+ zBuf[j++] = zEncode[(a>>4)&0xf];
+ zBuf[j++] = zEncode[a & 0xf];
+ }
+ zBuf[j] = 0;
+}
+
+
+/*
+** Convert a 128-bit MD5 digest into sequency of eight 5-digit integers
+** each representing 16 bits of the digest and separated from each
+** other by a "-" character.
+*/
+static void MD5DigestToBase10x8(unsigned char digest[16], char zDigest[50]){
+ int i, j;
+ unsigned int x;
+ for(i=j=0; i<16; i+=2){
+ x = digest[i]*256 + digest[i+1];
+ if( i>0 ) zDigest[j++] = '-';
+ sqlite3_snprintf(50-j, &zDigest[j], "%05u", x);
+ j += 5;
+ }
+ zDigest[j] = 0;
+}
+
+/*
+** A TCL command for md5. The argument is the text to be hashed. The
+** Result is the hash in base64.
+*/
+static int SQLITE_TCLAPI md5_cmd(
+ void*cd,
+ Tcl_Interp *interp,
+ int argc,
+ const char **argv
+){
+ MD5Context ctx;
+ unsigned char digest[16];
+ char zBuf[50];
+ void (*converter)(unsigned char*, char*);
+
+ if( argc!=2 ){
+ Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
+ " TEXT\"", (char*)0);
+ return TCL_ERROR;
+ }
+ MD5Init(&ctx);
+ MD5Update(&ctx, (unsigned char*)argv[1], (unsigned)strlen(argv[1]));
+ MD5Final(digest, &ctx);
+ converter = (void(*)(unsigned char*,char*))cd;
+ converter(digest, zBuf);
+ Tcl_AppendResult(interp, zBuf, (char*)0);
+ return TCL_OK;
+}
+
+/*
+** A TCL command to take the md5 hash of a file. The argument is the
+** name of the file.
+*/
+static int SQLITE_TCLAPI md5file_cmd(
+ void*cd,
+ Tcl_Interp *interp,
+ int argc,
+ const char **argv
+){
+ FILE *in;
+ int ofst;
+ int amt;
+ MD5Context ctx;
+ void (*converter)(unsigned char*, char*);
+ unsigned char digest[16];
+ char zBuf[10240];
+
+ if( argc!=2 && argc!=4 ){
+ Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
+ " FILENAME [OFFSET AMT]\"", (char*)0);
+ return TCL_ERROR;
+ }
+ if( argc==4 ){
+ ofst = atoi(argv[2]);
+ amt = atoi(argv[3]);
+ }else{
+ ofst = 0;
+ amt = 2147483647;
+ }
+ in = fopen(argv[1],"rb");
+ if( in==0 ){
+ Tcl_AppendResult(interp,"unable to open file \"", argv[1],
+ "\" for reading", (char*)0);
+ return TCL_ERROR;
+ }
+ fseek(in, ofst, SEEK_SET);
+ MD5Init(&ctx);
+ while( amt>0 ){
+ int n;
+ n = (int)fread(zBuf, 1, sizeof(zBuf)<=amt ? sizeof(zBuf) : amt, in);
+ if( n<=0 ) break;
+ MD5Update(&ctx, (unsigned char*)zBuf, (unsigned)n);
+ amt -= n;
+ }
+ fclose(in);
+ MD5Final(digest, &ctx);
+ converter = (void(*)(unsigned char*,char*))cd;
+ converter(digest, zBuf);
+ Tcl_AppendResult(interp, zBuf, (char*)0);
+ return TCL_OK;
+}
+
+/*
+** Register the four new TCL commands for generating MD5 checksums
+** with the TCL interpreter.
+*/
+int Md5_Init(Tcl_Interp *interp){
+ Tcl_CreateCommand(interp, "md5", (Tcl_CmdProc*)md5_cmd,
+ MD5DigestToBase16, 0);
+ Tcl_CreateCommand(interp, "md5-10x8", (Tcl_CmdProc*)md5_cmd,
+ MD5DigestToBase10x8, 0);
+ Tcl_CreateCommand(interp, "md5file", (Tcl_CmdProc*)md5file_cmd,
+ MD5DigestToBase16, 0);
+ Tcl_CreateCommand(interp, "md5file-10x8", (Tcl_CmdProc*)md5file_cmd,
+ MD5DigestToBase10x8, 0);
+ return TCL_OK;
+}
+
+/*
+** During testing, the special md5sum() aggregate function is available.
+** inside SQLite. The following routines implement that function.
+*/
+static void md5step(sqlite3_context *context, int argc, sqlite3_value **argv){
+ MD5Context *p;
+ int i;
+ if( argc<1 ) return;
+ p = sqlite3_aggregate_context(context, sizeof(*p));
+ if( p==0 ) return;
+ if( !p->isInit ){
+ MD5Init(p);
+ }
+ for(i=0; i<argc; i++){
+ const char *zData = (char*)sqlite3_value_text(argv[i]);
+ if( zData ){
+ MD5Update(p, (unsigned char*)zData, (int)strlen(zData));
+ }
+ }
+}
+static void md5finalize(sqlite3_context *context){
+ MD5Context *p;
+ unsigned char digest[16];
+ char zBuf[33];
+ p = sqlite3_aggregate_context(context, sizeof(*p));
+ MD5Final(digest,p);
+ MD5DigestToBase16(digest, zBuf);
+ sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
+}
+int Md5_Register(
+ sqlite3 *db,
+ char **pzErrMsg,
+ const sqlite3_api_routines *pThunk
+){
+ int rc = sqlite3_create_function(db, "md5sum", -1, SQLITE_UTF8, 0, 0,
+ md5step, md5finalize);
+ sqlite3_overload_function(db, "md5sum", -1); /* To exercise this API */
+ return rc;
+}
diff --git a/chromium/third_party/sqlite/src/src/test_tclsh.c b/chromium/third_party/sqlite/src/src/test_tclsh.c
new file mode 100644
index 00000000000..976f7cb248c
--- /dev/null
+++ b/chromium/third_party/sqlite/src/src/test_tclsh.c
@@ -0,0 +1,198 @@
+/*
+** 2017-10-13
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file contains extensions to the the "tclsqlite.c" module used for
+** testing. Basically, all of the other "test_*.c" modules are linked
+** into the enhanced tclsh used for testing (and named "testfixture" or
+** "testfixture.exe") using logic encoded by this file.
+**
+** The code in this file used to be found in tclsqlite3.c, contained within
+** #if SQLITE_TEST ... #endif. It is factored out into this separate module
+** in an effort to keep the tclsqlite.c file pure.
+*/
+#include "sqlite3.h"
+#if defined(INCLUDE_SQLITE_TCL_H)
+# include "sqlite_tcl.h"
+#else
+# include "tcl.h"
+# ifndef SQLITE_TCLAPI
+# define SQLITE_TCLAPI
+# endif
+#endif
+
+/* Needed for the setrlimit() system call on unix */
+#if defined(unix)
+#include <sys/resource.h>
+#endif
+
+/* Forward declaration */
+static int SQLITE_TCLAPI load_testfixture_extensions(
+ ClientData cd,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+);
+
+/*
+** This routine is the primary export of this file.
+**
+** Configure the interpreter passed as the first argument to have access
+** to the commands and linked variables that make up:
+**
+** * the [sqlite3] extension itself,
+**
+** * If SQLITE_TCLMD5 or SQLITE_TEST is defined, the Md5 commands, and
+**
+** * If SQLITE_TEST is set, the various test interfaces used by the Tcl
+** test suite.
+*/
+const char *sqlite3TestInit(Tcl_Interp *interp){
+ extern int Sqlite3_Init(Tcl_Interp*);
+ extern int Sqliteconfig_Init(Tcl_Interp*);
+ extern int Sqlitetest1_Init(Tcl_Interp*);
+ extern int Sqlitetest2_Init(Tcl_Interp*);
+ extern int Sqlitetest3_Init(Tcl_Interp*);
+ extern int Sqlitetest4_Init(Tcl_Interp*);
+ extern int Sqlitetest5_Init(Tcl_Interp*);
+ extern int Sqlitetest6_Init(Tcl_Interp*);
+ extern int Sqlitetest7_Init(Tcl_Interp*);
+ extern int Sqlitetest8_Init(Tcl_Interp*);
+ extern int Sqlitetest9_Init(Tcl_Interp*);
+ extern int Sqlitetestasync_Init(Tcl_Interp*);
+ extern int Sqlitetest_autoext_Init(Tcl_Interp*);
+ extern int Sqlitetest_blob_Init(Tcl_Interp*);
+ extern int Sqlitetest_demovfs_Init(Tcl_Interp *);
+ extern int Sqlitetest_func_Init(Tcl_Interp*);
+ extern int Sqlitetest_hexio_Init(Tcl_Interp*);
+ extern int Sqlitetest_init_Init(Tcl_Interp*);
+ extern int Sqlitetest_malloc_Init(Tcl_Interp*);
+ extern int Sqlitetest_mutex_Init(Tcl_Interp*);
+ extern int Sqlitetestschema_Init(Tcl_Interp*);
+ extern int Sqlitetestsse_Init(Tcl_Interp*);
+ extern int Sqlitetesttclvar_Init(Tcl_Interp*);
+ extern int Sqlitetestfs_Init(Tcl_Interp*);
+ extern int SqlitetestThread_Init(Tcl_Interp*);
+ extern int SqlitetestOnefile_Init();
+ extern int SqlitetestOsinst_Init(Tcl_Interp*);
+ extern int Sqlitetestbackup_Init(Tcl_Interp*);
+ extern int Sqlitetestintarray_Init(Tcl_Interp*);
+ extern int Sqlitetestvfs_Init(Tcl_Interp *);
+ extern int Sqlitetestrtree_Init(Tcl_Interp*);
+ extern int Sqlitequota_Init(Tcl_Interp*);
+ extern int Sqlitemultiplex_Init(Tcl_Interp*);
+ extern int SqliteSuperlock_Init(Tcl_Interp*);
+ extern int SqlitetestSyscall_Init(Tcl_Interp*);
+#if defined(SQLITE_ENABLE_SESSION) && defined(SQLITE_ENABLE_PREUPDATE_HOOK)
+ extern int TestSession_Init(Tcl_Interp*);
+#endif
+ extern int Md5_Init(Tcl_Interp*);
+ extern int Fts5tcl_Init(Tcl_Interp *);
+ extern int SqliteRbu_Init(Tcl_Interp*);
+ extern int Sqlitetesttcl_Init(Tcl_Interp*);
+#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
+ extern int Sqlitetestfts3_Init(Tcl_Interp *interp);
+#endif
+#ifdef SQLITE_ENABLE_ZIPVFS
+ extern int Zipvfs_Init(Tcl_Interp*);
+#endif
+ Tcl_CmdInfo cmdInfo;
+
+ /* Since the primary use case for this binary is testing of SQLite,
+ ** be sure to generate core files if we crash */
+#if defined(unix)
+ { struct rlimit x;
+ getrlimit(RLIMIT_CORE, &x);
+ x.rlim_cur = x.rlim_max;
+ setrlimit(RLIMIT_CORE, &x);
+ }
+#endif /* unix */
+
+ if( Tcl_GetCommandInfo(interp, "sqlite3", &cmdInfo)==0 ){
+ Sqlite3_Init(interp);
+ }
+#ifdef SQLITE_ENABLE_ZIPVFS
+ Zipvfs_Init(interp);
+#endif
+ Md5_Init(interp);
+ Sqliteconfig_Init(interp);
+ Sqlitetest1_Init(interp);
+ Sqlitetest2_Init(interp);
+ Sqlitetest3_Init(interp);
+ Sqlitetest4_Init(interp);
+ Sqlitetest5_Init(interp);
+ Sqlitetest6_Init(interp);
+ Sqlitetest7_Init(interp);
+ Sqlitetest8_Init(interp);
+ Sqlitetest9_Init(interp);
+ Sqlitetestasync_Init(interp);
+ Sqlitetest_autoext_Init(interp);
+ Sqlitetest_blob_Init(interp);
+ Sqlitetest_demovfs_Init(interp);
+ Sqlitetest_func_Init(interp);
+ Sqlitetest_hexio_Init(interp);
+ Sqlitetest_init_Init(interp);
+ Sqlitetest_malloc_Init(interp);
+ Sqlitetest_mutex_Init(interp);
+ Sqlitetestschema_Init(interp);
+ Sqlitetesttclvar_Init(interp);
+ Sqlitetestfs_Init(interp);
+ SqlitetestThread_Init(interp);
+ SqlitetestOnefile_Init();
+ SqlitetestOsinst_Init(interp);
+ Sqlitetestbackup_Init(interp);
+ Sqlitetestintarray_Init(interp);
+ Sqlitetestvfs_Init(interp);
+ Sqlitetestrtree_Init(interp);
+ Sqlitequota_Init(interp);
+ Sqlitemultiplex_Init(interp);
+ SqliteSuperlock_Init(interp);
+ SqlitetestSyscall_Init(interp);
+#if defined(SQLITE_ENABLE_SESSION) && defined(SQLITE_ENABLE_PREUPDATE_HOOK)
+ TestSession_Init(interp);
+#endif
+ Fts5tcl_Init(interp);
+ SqliteRbu_Init(interp);
+ Sqlitetesttcl_Init(interp);
+
+#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4)
+ Sqlitetestfts3_Init(interp);
+#endif
+
+ Tcl_CreateObjCommand(
+ interp, "load_testfixture_extensions", load_testfixture_extensions,0,0
+ );
+ return 0;
+}
+
+/* tclcmd: load_testfixture_extensions
+*/
+static int SQLITE_TCLAPI load_testfixture_extensions(
+ ClientData cd,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *CONST objv[]
+){
+
+ Tcl_Interp *slave;
+ if( objc!=2 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "SLAVE");
+ return TCL_ERROR;
+ }
+
+ slave = Tcl_GetSlave(interp, Tcl_GetString(objv[1]));
+ if( !slave ){
+ return TCL_ERROR;
+ }
+
+ (void)sqlite3TestInit(slave);
+ return TCL_OK;
+}
diff --git a/chromium/third_party/sqlite/src/src/test_tclvar.c b/chromium/third_party/sqlite/src/src/test_tclvar.c
index bef8ca94d6a..c656c57724b 100644
--- a/chromium/third_party/sqlite/src/src/test_tclvar.c
+++ b/chromium/third_party/sqlite/src/src/test_tclvar.c
@@ -15,6 +15,25 @@
**
** The emphasis of this file is a virtual table that provides
** access to TCL variables.
+**
+** The TCLVAR eponymous virtual table has a schema like this:
+**
+** CREATE TABLE tclvar(
+** name TEXT, -- base name of the variable: "x" in "$x(y)"
+** arrayname TEXT, -- array index name: "y" in "$x(y)"
+** value TEXT, -- the value of the variable
+** fullname TEXT, -- the full name of the variable
+** PRIMARY KEY(fullname)
+** ) WITHOUT ROWID;
+**
+** DELETE, INSERT, and UPDATE operations use the "fullname" field to
+** determine the variable to be modified. Changing "value" to NULL
+** deletes the variable.
+**
+** For SELECT operations, the "name" and "arrayname" fields will always
+** match the "fullname" field. For DELETE, INSERT, and UPDATE, the
+** "name" and "arrayname" fields are ignored and the variable is modified
+** according to "fullname" and "value" only.
*/
#include "sqliteInt.h"
#if defined(INCLUDE_SQLITE_TCL_H)
@@ -67,7 +86,12 @@ static int tclvarConnect(
){
tclvar_vtab *pVtab;
static const char zSchema[] =
- "CREATE TABLE whatever(name TEXT, arrayname TEXT, value TEXT)";
+ "CREATE TABLE x("
+ " name TEXT," /* Base name */
+ " arrayname TEXT," /* Array index */
+ " value TEXT," /* Value */
+ " fullname TEXT PRIMARY KEY" /* base(index) name */
+ ") WITHOUT ROWID";
pVtab = sqlite3MallocZero( sizeof(*pVtab) );
if( pVtab==0 ) return SQLITE_NOMEM;
*ppVtab = &pVtab->base;
@@ -251,6 +275,16 @@ static int tclvarColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
sqlite3_result_text(ctx, Tcl_GetString(pVal), -1, SQLITE_TRANSIENT);
break;
}
+ case 3: {
+ char *z3;
+ if( p2 ){
+ z3 = sqlite3_mprintf("%s(%s)", z1, z2);
+ sqlite3_result_text(ctx, z3, -1, sqlite3_free);
+ }else{
+ sqlite3_result_text(ctx, z1, -1, SQLITE_TRANSIENT);
+ }
+ break;
+ }
}
return SQLITE_OK;
}
@@ -377,6 +411,58 @@ static int tclvarBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
}
/*
+** Invoked for any UPDATE, INSERT, or DELETE against a tclvar table
+*/
+static int tclvarUpdate(
+ sqlite3_vtab *tab,
+ int argc,
+ sqlite3_value **argv,
+ sqlite_int64 *pRowid
+){
+ tclvar_vtab *pTab = (tclvar_vtab*)tab;
+ if( argc==1 ){
+ /* A DELETE operation. The variable to be deleted is stored in argv[0] */
+ const char *zVar = (const char*)sqlite3_value_text(argv[0]);
+ Tcl_UnsetVar(pTab->interp, zVar, TCL_GLOBAL_ONLY);
+ return SQLITE_OK;
+ }
+ if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
+ /* An INSERT operation */
+ const char *zValue = (const char*)sqlite3_value_text(argv[4]);
+ const char *zName;
+ if( sqlite3_value_type(argv[5])!=SQLITE_TEXT ){
+ tab->zErrMsg = sqlite3_mprintf("the 'fullname' column must be TEXT");
+ return SQLITE_ERROR;
+ }
+ zName = (const char*)sqlite3_value_text(argv[5]);
+ if( zValue ){
+ Tcl_SetVar(pTab->interp, zName, zValue, TCL_GLOBAL_ONLY);
+ }else{
+ Tcl_UnsetVar(pTab->interp, zName, TCL_GLOBAL_ONLY);
+ }
+ return SQLITE_OK;
+ }
+ if( sqlite3_value_type(argv[0])==SQLITE_TEXT
+ && sqlite3_value_type(argv[1])==SQLITE_TEXT
+ ){
+ /* An UPDATE operation */
+ const char *zOldName = (const char*)sqlite3_value_text(argv[0]);
+ const char *zNewName = (const char*)sqlite3_value_text(argv[1]);
+ const char *zValue = (const char*)sqlite3_value_text(argv[4]);
+
+ if( strcmp(zOldName, zNewName)!=0 || zValue==0 ){
+ Tcl_UnsetVar(pTab->interp, zOldName, TCL_GLOBAL_ONLY);
+ }
+ if( zValue!=0 ){
+ Tcl_SetVar(pTab->interp, zNewName, zValue, TCL_GLOBAL_ONLY);
+ }
+ return SQLITE_OK;
+ }
+ tab->zErrMsg = sqlite3_mprintf("prohibited TCL variable change");
+ return SQLITE_ERROR;
+}
+
+/*
** A virtual table module that provides read-only access to a
** Tcl global variable namespace.
*/
@@ -394,7 +480,7 @@ static sqlite3_module tclvarModule = {
tclvarEof, /* xEof - check for end of scan */
tclvarColumn, /* xColumn - read data */
tclvarRowid, /* xRowid - read data */
- 0, /* xUpdate */
+ tclvarUpdate, /* xUpdate */
0, /* xBegin */
0, /* xSync */
0, /* xCommit */
diff --git a/chromium/third_party/sqlite/src/src/trigger.c b/chromium/third_party/sqlite/src/src/trigger.c
index fed63049b7e..57fbc8edabb 100644
--- a/chromium/third_party/sqlite/src/src/trigger.c
+++ b/chromium/third_party/sqlite/src/src/trigger.c
@@ -585,7 +585,7 @@ void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){
*pp = (*pp)->pNext;
}
sqlite3DeleteTrigger(db, pTrigger);
- db->flags |= SQLITE_InternChanges;
+ db->mDbFlags |= DBFLAG_SchemaChange;
}
}
diff --git a/chromium/third_party/sqlite/src/src/update.c b/chromium/third_party/sqlite/src/src/update.c
index 0d3225d9f61..ec8cbb5b98d 100644
--- a/chromium/third_party/sqlite/src/src/update.c
+++ b/chromium/third_party/sqlite/src/src/update.c
@@ -803,12 +803,6 @@ static void updateVirtualTable(
if( pWInfo==0 ) return;
/* Populate the argument registers. */
- sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg);
- if( pRowid ){
- sqlite3ExprCode(pParse, pRowid, regArg+1);
- }else{
- sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg+1);
- }
for(i=0; i<pTab->nCol; i++){
if( aXRef[i]>=0 ){
sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i);
@@ -816,6 +810,23 @@ static void updateVirtualTable(
sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, i, regArg+2+i);
}
}
+ if( HasRowid(pTab) ){
+ sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg);
+ if( pRowid ){
+ sqlite3ExprCode(pParse, pRowid, regArg+1);
+ }else{
+ sqlite3VdbeAddOp2(v, OP_Rowid, iCsr, regArg+1);
+ }
+ }else{
+ Index *pPk; /* PRIMARY KEY index */
+ i16 iPk; /* PRIMARY KEY column */
+ pPk = sqlite3PrimaryKeyIndex(pTab);
+ assert( pPk!=0 );
+ assert( pPk->nKeyCol==1 );
+ iPk = pPk->aiColumn[0];
+ sqlite3VdbeAddOp3(v, OP_VColumn, iCsr, iPk, regArg);
+ sqlite3VdbeAddOp2(v, OP_SCopy, regArg+2+iPk, regArg+1);
+ }
bOnePass = sqlite3WhereOkOnePass(pWInfo, aDummy);
diff --git a/chromium/third_party/sqlite/src/src/util.c b/chromium/third_party/sqlite/src/src/util.c
index 941d26e1453..da4a772d58c 100644
--- a/chromium/third_party/sqlite/src/src/util.c
+++ b/chromium/third_party/sqlite/src/src/util.c
@@ -491,7 +491,11 @@ do_atof_calc:
if( esign<0 ){
result = 0.0*s;
}else{
+#ifdef INFINITY
+ result = INFINITY*s;
+#else
result = 1e308*1e308*s; /* Infinity */
+#endif
}
}
}else{
@@ -553,16 +557,12 @@ static int compare2pow63(const char *zNum, int incr){
** Convert zNum to a 64-bit signed integer. zNum must be decimal. This
** routine does *not* accept hexadecimal notation.
**
-** If the zNum value is representable as a 64-bit twos-complement
-** integer, then write that value into *pNum and return 0.
-**
-** If zNum is exactly 9223372036854775808, return 2. This special
-** case is broken out because while 9223372036854775808 cannot be a
-** signed 64-bit integer, its negative -9223372036854775808 can be.
+** Returns:
**
-** If zNum is too big for a 64-bit integer and is not
-** 9223372036854775808 or if zNum contains any non-numeric text,
-** then return 1.
+** 0 Successful transformation. Fits in a 64-bit signed integer.
+** 1 Excess text after the integer value
+** 2 Integer too large for a 64-bit signed integer or is malformed
+** 3 Special case of 9223372036854775808
**
** length is the number of bytes in the string (bytes, not characters).
** The string is not necessarily zero-terminated. The encoding is
@@ -575,6 +575,7 @@ int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
int i;
int c = 0;
int nonNum = 0; /* True if input contains UTF16 with high byte non-zero */
+ int rc; /* Baseline return code */
const char *zStart;
const char *zEnd = zNum + length;
assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
@@ -614,31 +615,35 @@ int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
testcase( i==20 );
if( &zNum[i]<zEnd /* Extra bytes at the end */
|| (i==0 && zStart==zNum) /* No digits */
- || i>19*incr /* Too many digits */
|| nonNum /* UTF16 with high-order bytes non-zero */
){
+ rc = 1;
+ }else{
+ rc = 0;
+ }
+ if( i>19*incr ){ /* Too many digits */
/* zNum is empty or contains non-numeric text or is longer
** than 19 digits (thus guaranteeing that it is too large) */
- return 1;
+ return 2;
}else if( i<19*incr ){
/* Less than 19 digits, so we know that it fits in 64 bits */
assert( u<=LARGEST_INT64 );
- return 0;
+ return rc;
}else{
/* zNum is a 19-digit numbers. Compare it against 9223372036854775808. */
c = compare2pow63(zNum, incr);
if( c<0 ){
/* zNum is less than 9223372036854775808 so it fits */
assert( u<=LARGEST_INT64 );
- return 0;
+ return rc;
}else if( c>0 ){
/* zNum is greater than 9223372036854775808 so it overflows */
- return 1;
+ return 2;
}else{
/* zNum is exactly 9223372036854775808. Fits if negative. The
** special case 2 overflow if positive */
assert( u-1==LARGEST_INT64 );
- return neg ? 0 : 2;
+ return neg ? rc : 3;
}
}
}
@@ -651,8 +656,9 @@ int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
** Returns:
**
** 0 Successful transformation. Fits in a 64-bit signed integer.
-** 1 Integer too large for a 64-bit signed integer or is malformed
-** 2 Special case of 9223372036854775808
+** 1 Excess text after the integer value
+** 2 Integer too large for a 64-bit signed integer or is malformed
+** 3 Special case of 9223372036854775808
*/
int sqlite3DecOrHexToI64(const char *z, i64 *pOut){
#ifndef SQLITE_OMIT_HEX_INTEGER
@@ -666,7 +672,7 @@ int sqlite3DecOrHexToI64(const char *z, i64 *pOut){
u = u*16 + sqlite3HexToInt(z[k]);
}
memcpy(pOut, &u, 8);
- return (z[k]==0 && k-i<=16) ? 0 : 1;
+ return (z[k]==0 && k-i<=16) ? 0 : 2;
}else
#endif /* SQLITE_OMIT_HEX_INTEGER */
{
@@ -1276,7 +1282,7 @@ int sqlite3SafetyCheckSickOrOk(sqlite3 *db){
** overflow, leave *pA unchanged and return 1.
*/
int sqlite3AddInt64(i64 *pA, i64 iB){
-#if GCC_VERSION>=5004000
+#if GCC_VERSION>=5004000 && !defined(__INTEL_COMPILER)
return __builtin_add_overflow(*pA, iB, pA);
#else
i64 iA = *pA;
@@ -1296,7 +1302,7 @@ int sqlite3AddInt64(i64 *pA, i64 iB){
#endif
}
int sqlite3SubInt64(i64 *pA, i64 iB){
-#if GCC_VERSION>=5004000
+#if GCC_VERSION>=5004000 && !defined(__INTEL_COMPILER)
return __builtin_sub_overflow(*pA, iB, pA);
#else
testcase( iB==SMALLEST_INT64+1 );
@@ -1311,7 +1317,7 @@ int sqlite3SubInt64(i64 *pA, i64 iB){
#endif
}
int sqlite3MulInt64(i64 *pA, i64 iB){
-#if GCC_VERSION>=5004000
+#if GCC_VERSION>=5004000 && !defined(__INTEL_COMPILER)
return __builtin_mul_overflow(*pA, iB, pA);
#else
i64 iA = *pA;
@@ -1413,8 +1419,14 @@ LogEst sqlite3LogEst(u64 x){
if( x<2 ) return 0;
while( x<8 ){ y -= 10; x <<= 1; }
}else{
+#if GCC_VERSION>=5004000
+ int i = 60 - __builtin_clzll(x);
+ y += i*10;
+ x >>= i;
+#else
while( x>255 ){ y += 40; x >>= 4; } /*OPTIMIZATION-IF-TRUE*/
while( x>15 ){ y += 10; x >>= 1; }
+#endif
}
return a[x&7] + y - 10;
}
diff --git a/chromium/third_party/sqlite/src/src/vacuum.c b/chromium/third_party/sqlite/src/src/vacuum.c
index 2480a6de7b9..42e247f4f5e 100644
--- a/chromium/third_party/sqlite/src/src/vacuum.c
+++ b/chromium/third_party/sqlite/src/src/vacuum.c
@@ -130,7 +130,8 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
int rc = SQLITE_OK; /* Return code from service routines */
Btree *pMain; /* The database being vacuumed */
Btree *pTemp; /* The temporary database we vacuum into */
- int saved_flags; /* Saved value of the db->flags */
+ u16 saved_mDbFlags; /* Saved value of db->mDbFlags */
+ u32 saved_flags; /* Saved value of db->flags */
int saved_nChange; /* Saved value of db->nChange */
int saved_nTotalChange; /* Saved value of db->nTotalChange */
u8 saved_mTrace; /* Saved trace settings */
@@ -153,11 +154,12 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
** restored before returning. Then set the writable-schema flag, and
** disable CHECK and foreign key constraints. */
saved_flags = db->flags;
+ saved_mDbFlags = db->mDbFlags;
saved_nChange = db->nChange;
saved_nTotalChange = db->nTotalChange;
saved_mTrace = db->mTrace;
- db->flags |= (SQLITE_WriteSchema | SQLITE_IgnoreChecks
- | SQLITE_PreferBuiltin | SQLITE_Vacuum);
+ db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks;
+ db->mDbFlags |= DBFLAG_PreferBuiltin | DBFLAG_Vacuum;
db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder | SQLITE_CountRows);
db->mTrace = 0;
@@ -268,8 +270,8 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
"WHERE type='table'AND coalesce(rootpage,1)>0",
zDbMain
);
- assert( (db->flags & SQLITE_Vacuum)!=0 );
- db->flags &= ~SQLITE_Vacuum;
+ assert( (db->mDbFlags & DBFLAG_Vacuum)!=0 );
+ db->mDbFlags &= ~DBFLAG_Vacuum;
if( rc!=SQLITE_OK ) goto end_of_vacuum;
/* Copy the triggers, views, and virtual tables from the main database
@@ -337,6 +339,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
end_of_vacuum:
/* Restore the original value of db->flags */
db->init.iDb = 0;
+ db->mDbFlags = saved_mDbFlags;
db->flags = saved_flags;
db->nChange = saved_nChange;
db->nTotalChange = saved_nTotalChange;
diff --git a/chromium/third_party/sqlite/src/src/vdbe.c b/chromium/third_party/sqlite/src/src/vdbe.c
index c79018d3f77..72f35c2a538 100644
--- a/chromium/third_party/sqlite/src/src/vdbe.c
+++ b/chromium/third_party/sqlite/src/src/vdbe.c
@@ -354,7 +354,7 @@ static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){
if( sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc)==0 ){
return 0;
}
- if( sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc)==SQLITE_OK ){
+ if( sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc)==0 ){
return MEM_Int;
}
return MEM_Real;
@@ -1955,13 +1955,23 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
}
compare_op:
- switch( pOp->opcode ){
- case OP_Eq: res2 = res==0; break;
- case OP_Ne: res2 = res; break;
- case OP_Lt: res2 = res<0; break;
- case OP_Le: res2 = res<=0; break;
- case OP_Gt: res2 = res>0; break;
- default: res2 = res>=0; break;
+ /* At this point, res is negative, zero, or positive if reg[P1] is
+ ** less than, equal to, or greater than reg[P3], respectively. Compute
+ ** the answer to this operator in res2, depending on what the comparison
+ ** operator actually is. The next block of code depends on the fact
+ ** that the 6 comparison operators are consecutive integers in this
+ ** order: NE, EQ, GT, LE, LT, GE */
+ assert( OP_Eq==OP_Ne+1 ); assert( OP_Gt==OP_Ne+2 ); assert( OP_Le==OP_Ne+3 );
+ assert( OP_Lt==OP_Ne+4 ); assert( OP_Ge==OP_Ne+5 );
+ if( res<0 ){ /* ne, eq, gt, le, lt, ge */
+ static const unsigned char aLTb[] = { 1, 0, 0, 1, 1, 0 };
+ res2 = aLTb[pOp->opcode - OP_Ne];
+ }else if( res==0 ){
+ static const unsigned char aEQb[] = { 0, 1, 0, 1, 0, 1 };
+ res2 = aEQb[pOp->opcode - OP_Ne];
+ }else{
+ static const unsigned char aGTb[] = { 1, 0, 1, 0, 0, 1 };
+ res2 = aGTb[pOp->opcode - OP_Ne];
}
/* Undo any changes made by applyAffinity() to the input registers. */
@@ -1973,7 +1983,6 @@ compare_op:
if( pOp->p5 & SQLITE_STOREP2 ){
pOut = &aMem[pOp->p2];
iCompare = res;
- res2 = res2!=0; /* For this path res2 must be exactly 0 or 1 */
if( (pOp->p5 & SQLITE_KEEPNULL)!=0 ){
/* The KEEPNULL flag prevents OP_Eq from overwriting a NULL with 1
** and prevents OP_Ne from overwriting NULL with 0. This flag
@@ -2104,7 +2113,7 @@ case OP_Compare: {
assert( memIsValid(&aMem[p2+idx]) );
REGISTER_TRACE(p1+idx, &aMem[p1+idx]);
REGISTER_TRACE(p2+idx, &aMem[p2+idx]);
- assert( i<pKeyInfo->nField );
+ assert( i<pKeyInfo->nKeyField );
pColl = pKeyInfo->aColl[i];
bRev = pKeyInfo->aSortOrder[i];
iCompare = sqlite3MemCompare(&aMem[p1+idx], &aMem[p2+idx], pColl);
@@ -2377,9 +2386,7 @@ case OP_Column: {
const u8 *zData; /* Part of the record being decoded */
const u8 *zHdr; /* Next unparsed byte of the header */
const u8 *zEndHdr; /* Pointer to first byte after the header */
- u32 offset; /* Offset into the data */
u64 offset64; /* 64-bit offset */
- u32 avail; /* Number of bytes of available data */
u32 t; /* A type code from the record header */
Mem *pReg; /* PseudoTable input register */
@@ -2406,11 +2413,13 @@ case OP_Column: {
if( pC->cacheStatus!=p->cacheCtr ){ /*OPTIMIZATION-IF-FALSE*/
if( pC->nullRow ){
if( pC->eCurType==CURTYPE_PSEUDO ){
- assert( pC->uc.pseudoTableReg>0 );
- pReg = &aMem[pC->uc.pseudoTableReg];
+ /* For the special case of as pseudo-cursor, the seekResult field
+ ** identifies the register that holds the record */
+ assert( pC->seekResult>0 );
+ pReg = &aMem[pC->seekResult];
assert( pReg->flags & MEM_Blob );
assert( memIsValid(pReg) );
- pC->payloadSize = pC->szRow = avail = pReg->n;
+ pC->payloadSize = pC->szRow = pReg->n;
pC->aRow = (u8*)pReg->z;
}else{
sqlite3VdbeMemSetNull(pDest);
@@ -2422,23 +2431,19 @@ case OP_Column: {
assert( pCrsr );
assert( sqlite3BtreeCursorIsValid(pCrsr) );
pC->payloadSize = sqlite3BtreePayloadSize(pCrsr);
- pC->aRow = sqlite3BtreePayloadFetch(pCrsr, &avail);
- assert( avail<=65536 ); /* Maximum page size is 64KiB */
- if( pC->payloadSize <= (u32)avail ){
- pC->szRow = pC->payloadSize;
- }else if( pC->payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
+ pC->aRow = sqlite3BtreePayloadFetch(pCrsr, &pC->szRow);
+ assert( pC->szRow<=pC->payloadSize );
+ assert( pC->szRow<=65536 ); /* Maximum page size is 64KiB */
+ if( pC->payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
- }else{
- pC->szRow = avail;
}
}
pC->cacheStatus = p->cacheCtr;
- pC->iHdrOffset = getVarint32(pC->aRow, offset);
+ pC->iHdrOffset = getVarint32(pC->aRow, aOffset[0]);
pC->nHdrParsed = 0;
- aOffset[0] = offset;
- if( avail<offset ){ /*OPTIMIZATION-IF-FALSE*/
+ if( pC->szRow<aOffset[0] ){ /*OPTIMIZATION-IF-FALSE*/
/* pC->aRow does not have to hold the entire row, but it does at least
** need to cover the header of the record. If pC->aRow does not contain
** the complete header, then set it to zero, forcing the header to be
@@ -2455,17 +2460,26 @@ case OP_Column: {
** 3-byte type for each of the maximum of 32768 columns plus three
** extra bytes for the header length itself. 32768*3 + 3 = 98307.
*/
- if( offset > 98307 || offset > pC->payloadSize ){
- rc = SQLITE_CORRUPT_BKPT;
- goto abort_due_to_error;
+ if( aOffset[0] > 98307 || aOffset[0] > pC->payloadSize ){
+ goto op_column_corrupt;
}
- }else if( offset>0 ){ /*OPTIMIZATION-IF-TRUE*/
- /* The following goto is an optimization. It can be omitted and
- ** everything will still work. But OP_Column is measurably faster
- ** by skipping the subsequent conditional, which is always true.
+ }else{
+ /* This is an optimization. By skipping over the first few tests
+ ** (ex: pC->nHdrParsed<=p2) in the next section, we achieve a
+ ** measurable performance gain.
+ **
+ ** This branch is taken even if aOffset[0]==0. Such a record is never
+ ** generated by SQLite, and could be considered corruption, but we
+ ** accept it for historical reasons. When aOffset[0]==0, the code this
+ ** branch jumps to reads past the end of the record, but never more
+ ** than a few bytes. Even if the record occurs at the end of the page
+ ** content area, the "page header" comes after the page content and so
+ ** this overread is harmless. Similar overreads can occur for a corrupt
+ ** database file.
*/
zData = pC->aRow;
assert( pC->nHdrParsed<=p2 ); /* Conditional skipped */
+ testcase( aOffset[0]==0 );
goto op_column_read_header;
}
}
@@ -2494,6 +2508,7 @@ case OP_Column: {
offset64 = aOffset[i];
zHdr = zData + pC->iHdrOffset;
zEndHdr = zData + aOffset[0];
+ testcase( zHdr>=zEndHdr );
do{
if( (t = zHdr[0])<0x80 ){
zHdr++;
@@ -2514,9 +2529,13 @@ case OP_Column: {
if( (zHdr>=zEndHdr && (zHdr>zEndHdr || offset64!=pC->payloadSize))
|| (offset64 > pC->payloadSize)
){
- if( pC->aRow==0 ) sqlite3VdbeMemRelease(&sMem);
- rc = SQLITE_CORRUPT_BKPT;
- goto abort_due_to_error;
+ if( aOffset[0]==0 ){
+ i = 0;
+ zHdr = zEndHdr;
+ }else{
+ if( pC->aRow==0 ) sqlite3VdbeMemRelease(&sMem);
+ goto op_column_corrupt;
+ }
}
pC->nHdrParsed = i;
@@ -2610,6 +2629,15 @@ op_column_out:
UPDATE_MAX_BLOBSIZE(pDest);
REGISTER_TRACE(pOp->p3, pDest);
break;
+
+op_column_corrupt:
+ if( aOp[0].p3>0 ){
+ pOp = &aOp[aOp[0].p3-1];
+ break;
+ }else{
+ rc = SQLITE_CORRUPT_BKPT;
+ goto abort_due_to_error;
+ }
}
/* Opcode: Affinity P1 P2 * P4 *
@@ -2950,7 +2978,7 @@ case OP_Savepoint: {
int isSchemaChange;
iSavepoint = db->nSavepoint - iSavepoint - 1;
if( p1==SAVEPOINT_ROLLBACK ){
- isSchemaChange = (db->flags & SQLITE_InternChanges)!=0;
+ isSchemaChange = (db->mDbFlags & DBFLAG_SchemaChange)!=0;
for(ii=0; ii<db->nDb; ii++){
rc = sqlite3BtreeTripAllCursors(db->aDb[ii].pBt,
SQLITE_ABORT_ROLLBACK,
@@ -2969,7 +2997,7 @@ case OP_Savepoint: {
if( isSchemaChange ){
sqlite3ExpirePreparedStatements(db);
sqlite3ResetAllSchemasOfConnection(db);
- db->flags = (db->flags | SQLITE_InternChanges);
+ db->mDbFlags |= DBFLAG_SchemaChange;
}
}
@@ -3249,7 +3277,7 @@ case OP_SetCookie: {
if( pOp->p2==BTREE_SCHEMA_VERSION ){
/* When the schema cookie changes, record the new cookie internally */
pDb->pSchema->schema_cookie = pOp->p3;
- db->flags |= SQLITE_InternChanges;
+ db->mDbFlags |= DBFLAG_SchemaChange;
}else if( pOp->p2==BTREE_FILE_FORMAT ){
/* Record changes in the file format */
pDb->pSchema->file_format = pOp->p3;
@@ -3388,7 +3416,7 @@ case OP_OpenWrite:
assert( (pIn2->flags & MEM_Int)!=0 );
sqlite3VdbeMemIntegerify(pIn2);
p2 = (int)pIn2->u.i;
- /* The p2 value always comes from a prior OP_CreateTable opcode and
+ /* The p2 value always comes from a prior OP_CreateBtree opcode and
** that opcode will always set the p2 value to 2 or more or else fail.
** If there were a failure, the prepared statement would have halted
** before reaching this instruction. */
@@ -3398,7 +3426,7 @@ case OP_OpenWrite:
pKeyInfo = pOp->p4.pKeyInfo;
assert( pKeyInfo->enc==ENC(db) );
assert( pKeyInfo->db==db );
- nField = pKeyInfo->nField+pKeyInfo->nXField;
+ nField = pKeyInfo->nAllField;
}else if( pOp->p4type==P4_INT32 ){
nField = pOp->p4.i;
}
@@ -3609,8 +3637,13 @@ case OP_OpenPseudo: {
pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, CURTYPE_PSEUDO);
if( pCx==0 ) goto no_mem;
pCx->nullRow = 1;
- pCx->uc.pseudoTableReg = pOp->p2;
+ pCx->seekResult = pOp->p2;
pCx->isTable = 1;
+ /* Give this pseudo-cursor a fake BtCursor pointer so that pCx
+ ** can be safely passed to sqlite3VdbeCursorMoveto(). This avoids a test
+ ** for pCx->eCurType==CURTYPE_BTREE inside of sqlite3VdbeCursorMoveto()
+ ** which is a performance optimization */
+ pCx->uc.pCursor = sqlite3BtreeFakeValidCursor();
assert( pOp->p5==0 );
break;
}
@@ -4402,14 +4435,9 @@ case OP_InsertInt: {
if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = x.nKey;
- if( pData->flags & MEM_Null ){
- x.pData = 0;
- x.nData = 0;
- }else{
- assert( pData->flags & (MEM_Blob|MEM_Str) );
- x.pData = pData->z;
- x.nData = pData->n;
- }
+ assert( pData->flags & (MEM_Blob|MEM_Str) );
+ x.pData = pData->z;
+ x.nData = pData->n;
seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0);
if( pData->flags & MEM_Zero ){
x.nZero = pData->u.nZero;
@@ -4776,7 +4804,17 @@ case OP_NullRow: {
break;
}
-/* Opcode: Last P1 P2 P3 * *
+/* Opcode: SeekEnd P1 * * * *
+**
+** Position cursor P1 at the end of the btree for the purpose of
+** appending a new entry onto the btree.
+**
+** It is assumed that the cursor is used only for appending and so
+** if the cursor is valid, then the cursor must already be pointing
+** at the end of the btree and so no changes are made to
+** the cursor.
+*/
+/* Opcode: Last P1 P2 * * *
**
** The next use of the Rowid or Column or Prev instruction for P1
** will refer to the last entry in the database table or index.
@@ -4787,14 +4825,8 @@ case OP_NullRow: {
** This opcode leaves the cursor configured to move in reverse order,
** from the end toward the beginning. In other words, the cursor is
** configured to use Prev, not Next.
-**
-** If P3 is -1, then the cursor is positioned at the end of the btree
-** for the purpose of appending a new entry onto the btree. In that
-** case P2 must be 0. It is assumed that the cursor is used only for
-** appending and so if the cursor is valid, then the cursor must already
-** be pointing at the end of the btree and so no changes are made to
-** the cursor.
*/
+case OP_SeekEnd:
case OP_Last: { /* jump */
VdbeCursor *pC;
BtCursor *pCrsr;
@@ -4807,22 +4839,24 @@ case OP_Last: { /* jump */
pCrsr = pC->uc.pCursor;
res = 0;
assert( pCrsr!=0 );
- pC->seekResult = pOp->p3;
#ifdef SQLITE_DEBUG
- pC->seekOp = OP_Last;
+ pC->seekOp = pOp->opcode;
#endif
- if( pOp->p3==0 || !sqlite3BtreeCursorIsValidNN(pCrsr) ){
- rc = sqlite3BtreeLast(pCrsr, &res);
- pC->nullRow = (u8)res;
- pC->deferredMoveto = 0;
- pC->cacheStatus = CACHE_STALE;
- if( rc ) goto abort_due_to_error;
- if( pOp->p2>0 ){
- VdbeBranchTaken(res!=0,2);
- if( res ) goto jump_to_p2;
- }
- }else{
+ if( pOp->opcode==OP_SeekEnd ){
assert( pOp->p2==0 );
+ pC->seekResult = -1;
+ if( sqlite3BtreeCursorIsValidNN(pCrsr) ){
+ break;
+ }
+ }
+ rc = sqlite3BtreeLast(pCrsr, &res);
+ pC->nullRow = (u8)res;
+ pC->deferredMoveto = 0;
+ pC->cacheStatus = CACHE_STALE;
+ if( rc ) goto abort_due_to_error;
+ if( pOp->p2>0 ){
+ VdbeBranchTaken(res!=0,2);
+ if( res ) goto jump_to_p2;
}
break;
}
@@ -5451,50 +5485,28 @@ case OP_ResetSorter: {
break;
}
-/* Opcode: CreateTable P1 P2 * * *
-** Synopsis: r[P2]=root iDb=P1
-**
-** Allocate a new table in the main database file if P1==0 or in the
-** auxiliary database file if P1==1 or in an attached database if
-** P1>1. Write the root page number of the new table into
-** register P2
-**
-** The difference between a table and an index is this: A table must
-** have a 4-byte integer key and can have arbitrary data. An index
-** has an arbitrary key but no data.
-**
-** See also: CreateIndex
-*/
-/* Opcode: CreateIndex P1 P2 * * *
-** Synopsis: r[P2]=root iDb=P1
-**
-** Allocate a new index in the main database file if P1==0 or in the
-** auxiliary database file if P1==1 or in an attached database if
-** P1>1. Write the root page number of the new table into
-** register P2.
+/* Opcode: CreateBtree P1 P2 P3 * *
+** Synopsis: r[P2]=root iDb=P1 flags=P3
**
-** See documentation on OP_CreateTable for additional information.
+** Allocate a new b-tree in the main database file if P1==0 or in the
+** TEMP database file if P1==1 or in an attached database if
+** P1>1. The P3 argument must be 1 (BTREE_INTKEY) for a rowid table
+** it must be 2 (BTREE_BLOBKEY) for a index or WITHOUT ROWID table.
+** The root page number of the new b-tree is stored in register P2.
*/
-case OP_CreateIndex: /* out2 */
-case OP_CreateTable: { /* out2 */
+case OP_CreateBtree: { /* out2 */
int pgno;
- int flags;
Db *pDb;
pOut = out2Prerelease(p, pOp);
pgno = 0;
+ assert( pOp->p3==BTREE_INTKEY || pOp->p3==BTREE_BLOBKEY );
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( DbMaskTest(p->btreeMask, pOp->p1) );
assert( p->readOnly==0 );
pDb = &db->aDb[pOp->p1];
assert( pDb->pBt!=0 );
- if( pOp->opcode==OP_CreateTable ){
- /* flags = BTREE_INTKEY; */
- flags = BTREE_INTKEY;
- }else{
- flags = BTREE_BLOBKEY;
- }
- rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, flags);
+ rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, pOp->p3);
if( rc ) goto abort_due_to_error;
pOut->u.i = pgno;
break;
@@ -7005,7 +7017,7 @@ case OP_Function: {
}
-/* Opcode: Init P1 P2 * P4 *
+/* Opcode: Init P1 P2 P3 P4 *
** Synopsis: Start at P2
**
** Programs contain a single instance of this opcode as the very first
@@ -7019,6 +7031,9 @@ case OP_Function: {
**
** Increment the value of P1 so that OP_Once opcodes will jump the
** first time they are evaluated for this run.
+**
+** If P3 is not zero, then it is an address to jump to if an SQLITE_CORRUPT
+** error is encountered.
*/
case OP_Init: { /* jump */
char *zTrace;
diff --git a/chromium/third_party/sqlite/src/src/vdbeInt.h b/chromium/third_party/sqlite/src/src/vdbeInt.h
index 7ce13072953..c48eb930d92 100644
--- a/chromium/third_party/sqlite/src/src/vdbeInt.h
+++ b/chromium/third_party/sqlite/src/src/vdbeInt.h
@@ -96,18 +96,18 @@ struct VdbeCursor {
u32 cacheStatus; /* Cache is valid if this matches Vdbe.cacheCtr */
int seekResult; /* Result of previous sqlite3BtreeMoveto() or 0
** if there have been no prior seeks on the cursor. */
- /* NB: seekResult does not distinguish between "no seeks have ever occurred
- ** on this cursor" and "the most recent seek was an exact match". */
+ /* seekResult does not distinguish between "no seeks have ever occurred
+ ** on this cursor" and "the most recent seek was an exact match".
+ ** For CURTYPE_PSEUDO, seekResult is the register holding the record */
/* When a new VdbeCursor is allocated, only the fields above are zeroed.
** The fields that follow are uninitialized, and must be individually
** initialized prior to first use. */
VdbeCursor *pAltCursor; /* Associated index cursor from which to read */
union {
- BtCursor *pCursor; /* CURTYPE_BTREE. Btree cursor */
- sqlite3_vtab_cursor *pVCur; /* CURTYPE_VTAB. Vtab cursor */
- int pseudoTableReg; /* CURTYPE_PSEUDO. Reg holding content. */
- VdbeSorter *pSorter; /* CURTYPE_SORTER. Sorter object */
+ BtCursor *pCursor; /* CURTYPE_BTREE or _PSEUDO. Btree cursor */
+ sqlite3_vtab_cursor *pVCur; /* CURTYPE_VTAB. Vtab cursor */
+ VdbeSorter *pSorter; /* CURTYPE_SORTER. Sorter object */
} uc;
KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */
u32 iHdrOffset; /* Offset to next unparsed byte of the header */
diff --git a/chromium/third_party/sqlite/src/src/vdbeapi.c b/chromium/third_party/sqlite/src/src/vdbeapi.c
index e6ddc8ebe54..01adbd7c8be 100644
--- a/chromium/third_party/sqlite/src/src/vdbeapi.c
+++ b/chromium/third_party/sqlite/src/src/vdbeapi.c
@@ -524,7 +524,7 @@ static int doWalCallbacks(sqlite3 *db){
sqlite3BtreeEnter(pBt);
nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt));
sqlite3BtreeLeave(pBt);
- if( db->xWalCallback && nEntry>0 && rc==SQLITE_OK ){
+ if( nEntry>0 && db->xWalCallback && rc==SQLITE_OK ){
rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zDbSName, nEntry);
}
}
@@ -634,7 +634,7 @@ static int sqlite3Step(Vdbe *p){
if( rc!=SQLITE_ROW ) checkProfileCallback(db, p);
#endif
- if( rc==SQLITE_DONE ){
+ if( rc==SQLITE_DONE && db->autoCommit ){
assert( p->rc==SQLITE_OK );
p->rc = doWalCallbacks(db);
if( p->rc!=SQLITE_OK ){
@@ -678,7 +678,6 @@ end_of_step:
*/
int sqlite3_step(sqlite3_stmt *pStmt){
int rc = SQLITE_OK; /* Result from sqlite3Step() */
- int rc2 = SQLITE_OK; /* Result from sqlite3Reprepare() */
Vdbe *v = (Vdbe*)pStmt; /* the prepared statement */
int cnt = 0; /* Counter to prevent infinite loop of reprepares */
sqlite3 *db; /* The database connection */
@@ -692,32 +691,31 @@ int sqlite3_step(sqlite3_stmt *pStmt){
while( (rc = sqlite3Step(v))==SQLITE_SCHEMA
&& cnt++ < SQLITE_MAX_SCHEMA_RETRY ){
int savedPc = v->pc;
- rc2 = rc = sqlite3Reprepare(v);
- if( rc!=SQLITE_OK) break;
+ rc = sqlite3Reprepare(v);
+ if( rc!=SQLITE_OK ){
+ /* This case occurs after failing to recompile an sql statement.
+ ** The error message from the SQL compiler has already been loaded
+ ** into the database handle. This block copies the error message
+ ** from the database handle into the statement and sets the statement
+ ** program counter to 0 to ensure that when the statement is
+ ** finalized or reset the parser error message is available via
+ ** sqlite3_errmsg() and sqlite3_errcode().
+ */
+ const char *zErr = (const char *)sqlite3_value_text(db->pErr);
+ sqlite3DbFree(db, v->zErrMsg);
+ if( !db->mallocFailed ){
+ v->zErrMsg = sqlite3DbStrDup(db, zErr);
+ v->rc = rc = sqlite3ApiExit(db, rc);
+ } else {
+ v->zErrMsg = 0;
+ v->rc = rc = SQLITE_NOMEM_BKPT;
+ }
+ break;
+ }
sqlite3_reset(pStmt);
if( savedPc>=0 ) v->doingRerun = 1;
assert( v->expired==0 );
}
- if( rc2!=SQLITE_OK ){
- /* This case occurs after failing to recompile an sql statement.
- ** The error message from the SQL compiler has already been loaded
- ** into the database handle. This block copies the error message
- ** from the database handle into the statement and sets the statement
- ** program counter to 0 to ensure that when the statement is
- ** finalized or reset the parser error message is available via
- ** sqlite3_errmsg() and sqlite3_errcode().
- */
- const char *zErr = (const char *)sqlite3_value_text(db->pErr);
- sqlite3DbFree(db, v->zErrMsg);
- if( !db->mallocFailed ){
- v->zErrMsg = sqlite3DbStrDup(db, zErr);
- v->rc = rc2;
- } else {
- v->zErrMsg = 0;
- v->rc = rc = SQLITE_NOMEM_BKPT;
- }
- }
- rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
return rc;
}
@@ -1723,7 +1721,7 @@ static UnpackedRecord *vdbeUnpackRecord(
pRet = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
if( pRet ){
- memset(pRet->aMem, 0, sizeof(Mem)*(pKeyInfo->nField+1));
+ memset(pRet->aMem, 0, sizeof(Mem)*(pKeyInfo->nKeyField+1));
sqlite3VdbeRecordUnpack(pKeyInfo, nKey, pKey, pRet);
}
return pRet;
@@ -1796,7 +1794,7 @@ int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
*/
int sqlite3_preupdate_count(sqlite3 *db){
PreUpdate *p = db->pPreUpdate;
- return (p ? p->keyinfo.nField : 0);
+ return (p ? p->keyinfo.nKeyField : 0);
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
diff --git a/chromium/third_party/sqlite/src/src/vdbeaux.c b/chromium/third_party/sqlite/src/src/vdbeaux.c
index f4dc8614f5d..fa5668316f4 100644
--- a/chromium/third_party/sqlite/src/src/vdbeaux.c
+++ b/chromium/third_party/sqlite/src/src/vdbeaux.c
@@ -33,10 +33,12 @@ Vdbe *sqlite3VdbeCreate(Parse *pParse){
db->pVdbe = p;
p->magic = VDBE_MAGIC_INIT;
p->pParse = pParse;
+ pParse->pVdbe = p;
assert( pParse->aLabel==0 );
assert( pParse->nLabel==0 );
assert( pParse->nOpAlloc==0 );
assert( pParse->szOpAlloc==0 );
+ sqlite3VdbeAddOp2(p, OP_Init, 0, 1);
return p;
}
@@ -490,7 +492,8 @@ static Op *opIterNext(VdbeOpIter *p){
** * OP_VUpdate
** * OP_VRename
** * OP_FkCounter with P2==0 (immediate foreign key constraint)
-** * OP_CreateTable and OP_InitCoroutine (for CREATE TABLE AS SELECT ...)
+** * OP_CreateBtree/BTREE_INTKEY and OP_InitCoroutine
+** (for CREATE TABLE AS SELECT ...)
**
** Then check that the value of Parse.mayAbort is true if an
** ABORT may be thrown, or false otherwise. Return true if it does
@@ -518,7 +521,7 @@ int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
hasAbort = 1;
break;
}
- if( opcode==OP_CreateTable ) hasCreateTable = 1;
+ if( opcode==OP_CreateBtree && pOp->p3==BTREE_INTKEY ) hasCreateTable = 1;
if( opcode==OP_InitCoroutine ) hasInitCoroutine = 1;
#ifndef SQLITE_OMIT_FOREIGN_KEY
if( opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1 ){
@@ -597,6 +600,27 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
p->bIsReader = 1;
break;
}
+ case OP_Next:
+ case OP_NextIfOpen:
+ case OP_SorterNext: {
+ pOp->p4.xAdvance = sqlite3BtreeNext;
+ pOp->p4type = P4_ADVANCE;
+ /* The code generator never codes any of these opcodes as a jump
+ ** to a label. They are always coded as a jump backwards to a
+ ** known address */
+ assert( pOp->p2>=0 );
+ break;
+ }
+ case OP_Prev:
+ case OP_PrevIfOpen: {
+ pOp->p4.xAdvance = sqlite3BtreePrevious;
+ pOp->p4type = P4_ADVANCE;
+ /* The code generator never codes any of these opcodes as a jump
+ ** to a label. They are always coded as a jump backwards to a
+ ** known address */
+ assert( pOp->p2>=0 );
+ break;
+ }
#ifndef SQLITE_OMIT_VIRTUALTABLE
case OP_VUpdate: {
if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2;
@@ -608,27 +632,25 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
assert( pOp[-1].opcode==OP_Integer );
n = pOp[-1].p1;
if( n>nMaxArgs ) nMaxArgs = n;
- break;
+ /* Fall through into the default case */
}
#endif
- case OP_Next:
- case OP_NextIfOpen:
- case OP_SorterNext: {
- pOp->p4.xAdvance = sqlite3BtreeNext;
- pOp->p4type = P4_ADVANCE;
- break;
- }
- case OP_Prev:
- case OP_PrevIfOpen: {
- pOp->p4.xAdvance = sqlite3BtreePrevious;
- pOp->p4type = P4_ADVANCE;
+ default: {
+ if( pOp->p2<0 ){
+ /* The mkopcodeh.tcl script has so arranged things that the only
+ ** non-jump opcodes less than SQLITE_MX_JUMP_CODE are guaranteed to
+ ** have non-negative values for P2. */
+ assert( (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP)!=0 );
+ assert( ADDR(pOp->p2)<pParse->nLabel );
+ pOp->p2 = aLabel[ADDR(pOp->p2)];
+ }
break;
}
}
- if( (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP)!=0 && pOp->p2<0 ){
- assert( ADDR(pOp->p2)<pParse->nLabel );
- pOp->p2 = aLabel[ADDR(pOp->p2)];
- }
+ /* The mkopcodeh.tcl script has so arranged things that the only
+ ** non-jump opcodes less than SQLITE_MX_JUMP_CODE are guaranteed to
+ ** have non-negative values for P2. */
+ assert( (sqlite3OpcodeProperty[pOp->opcode]&OPFLG_JUMP)==0 || pOp->p2>=0);
}
if( pOp==p->aOp ) break;
pOp--;
@@ -1301,8 +1323,8 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
int j;
KeyInfo *pKeyInfo = pOp->p4.pKeyInfo;
assert( pKeyInfo->aSortOrder!=0 );
- sqlite3XPrintf(&x, "k(%d", pKeyInfo->nField);
- for(j=0; j<pKeyInfo->nField; j++){
+ sqlite3XPrintf(&x, "k(%d", pKeyInfo->nKeyField);
+ for(j=0; j<pKeyInfo->nKeyField; j++){
CollSeq *pColl = pKeyInfo->aColl[j];
const char *zColl = pColl ? pColl->zName : "";
if( strcmp(zColl, "BINARY")==0 ) zColl = "B";
@@ -2139,27 +2161,6 @@ static void closeAllCursors(Vdbe *p){
}
/*
-** Clean up the VM after a single run.
-*/
-static void Cleanup(Vdbe *p){
- sqlite3 *db = p->db;
-
-#ifdef SQLITE_DEBUG
- /* Execute assert() statements to ensure that the Vdbe.apCsr[] and
- ** Vdbe.aMem[] arrays have already been cleaned up. */
- int i;
- if( p->apCsr ) for(i=0; i<p->nCursor; i++) assert( p->apCsr[i]==0 );
- if( p->aMem ){
- for(i=0; i<p->nMem; i++) assert( p->aMem[i].flags==MEM_Undefined );
- }
-#endif
-
- sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = 0;
- p->pResultSet = 0;
-}
-
-/*
** Set the number of result columns that will be returned by this SQL
** statement. This is now set at compile time, rather than during
** execution of the vdbe program so that sqlite3_column_count() can
@@ -2867,6 +2868,10 @@ static void vdbeInvokeSqllog(Vdbe *v){
** VDBE_MAGIC_INIT.
*/
int sqlite3VdbeReset(Vdbe *p){
+#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
+ int i;
+#endif
+
sqlite3 *db;
db = p->db;
@@ -2884,8 +2889,6 @@ int sqlite3VdbeReset(Vdbe *p){
if( p->pc>=0 ){
vdbeInvokeSqllog(p);
sqlite3VdbeTransferError(p);
- sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = 0;
if( p->runOnlyOnce ) p->expired = 1;
}else if( p->rc && p->expired ){
/* The expired flag was set on the VDBE before the first call
@@ -2893,13 +2896,21 @@ int sqlite3VdbeReset(Vdbe *p){
** called), set the database error in this case as well.
*/
sqlite3ErrorWithMsg(db, p->rc, p->zErrMsg ? "%s" : 0, p->zErrMsg);
- sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = 0;
}
- /* Reclaim all memory used by the VDBE
+ /* Reset register contents and reclaim error message memory.
*/
- Cleanup(p);
+#ifdef SQLITE_DEBUG
+ /* Execute assert() statements to ensure that the Vdbe.apCsr[] and
+ ** Vdbe.aMem[] arrays have already been cleaned up. */
+ if( p->apCsr ) for(i=0; i<p->nCursor; i++) assert( p->apCsr[i]==0 );
+ if( p->aMem ){
+ for(i=0; i<p->nMem; i++) assert( p->aMem[i].flags==MEM_Undefined );
+ }
+#endif
+ sqlite3DbFree(db, p->zErrMsg);
+ p->zErrMsg = 0;
+ p->pResultSet = 0;
/* Save profiling information from this VDBE run.
*/
@@ -2907,7 +2918,6 @@ int sqlite3VdbeReset(Vdbe *p){
{
FILE *out = fopen("vdbe_profile.out", "a");
if( out ){
- int i;
fprintf(out, "---- ");
for(i=0; i<p->nOp; i++){
fprintf(out, "%02x", p->aOp[i].opcode);
@@ -3120,19 +3130,18 @@ int sqlite3VdbeCursorRestore(VdbeCursor *p){
*/
int sqlite3VdbeCursorMoveto(VdbeCursor **pp, int *piCol){
VdbeCursor *p = *pp;
- if( p->eCurType==CURTYPE_BTREE ){
- if( p->deferredMoveto ){
- int iMap;
- if( p->aAltMap && (iMap = p->aAltMap[1+*piCol])>0 ){
- *pp = p->pAltCursor;
- *piCol = iMap - 1;
- return SQLITE_OK;
- }
- return handleDeferredMoveto(p);
- }
- if( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ){
- return handleMovedCursor(p);
+ assert( p->eCurType==CURTYPE_BTREE || p->eCurType==CURTYPE_PSEUDO );
+ if( p->deferredMoveto ){
+ int iMap;
+ if( p->aAltMap && (iMap = p->aAltMap[1+*piCol])>0 ){
+ *pp = p->pAltCursor;
+ *piCol = iMap - 1;
+ return SQLITE_OK;
}
+ return handleDeferredMoveto(p);
+ }
+ if( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ){
+ return handleMovedCursor(p);
}
return SQLITE_OK;
}
@@ -3528,13 +3537,13 @@ UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(
){
UnpackedRecord *p; /* Unpacked record to return */
int nByte; /* Number of bytes required for *p */
- nByte = ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nField+1);
+ nByte = ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nKeyField+1);
p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte);
if( !p ) return 0;
p->aMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))];
assert( pKeyInfo->aSortOrder!=0 );
p->pKeyInfo = pKeyInfo;
- p->nField = pKeyInfo->nField + 1;
+ p->nField = pKeyInfo->nKeyField + 1;
return p;
}
@@ -3574,7 +3583,7 @@ void sqlite3VdbeRecordUnpack(
pMem++;
if( (++u)>=p->nField ) break;
}
- assert( u<=pKeyInfo->nField + 1 );
+ assert( u<=pKeyInfo->nKeyField + 1 );
p->nField = u;
}
@@ -3623,9 +3632,9 @@ static int vdbeRecordCompareDebug(
idx1 = getVarint32(aKey1, szHdr1);
if( szHdr1>98307 ) return SQLITE_CORRUPT;
d1 = szHdr1;
- assert( pKeyInfo->nField+pKeyInfo->nXField>=pPKey2->nField || CORRUPT_DB );
+ assert( pKeyInfo->nAllField>=pPKey2->nField || CORRUPT_DB );
assert( pKeyInfo->aSortOrder!=0 );
- assert( pKeyInfo->nField>0 );
+ assert( pKeyInfo->nKeyField>0 );
assert( idx1<=szHdr1 || CORRUPT_DB );
do{
u32 serial_type1;
@@ -3687,12 +3696,12 @@ debugCompareEnd:
/*
** Count the number of fields (a.k.a. columns) in the record given by
** pKey,nKey. The verify that this count is less than or equal to the
-** limit given by pKeyInfo->nField + pKeyInfo->nXField.
+** limit given by pKeyInfo->nAllField.
**
** If this constraint is not satisfied, it means that the high-speed
** vdbeRecordCompareInt() and vdbeRecordCompareString() routines will
** not work correctly. If this assert() ever fires, it probably means
-** that the KeyInfo.nField or KeyInfo.nXField values were computed
+** that the KeyInfo.nKeyField or KeyInfo.nAllField values were computed
** incorrectly.
*/
static void vdbeAssertFieldCountWithinLimits(
@@ -3713,7 +3722,7 @@ static void vdbeAssertFieldCountWithinLimits(
idx += getVarint32(aKey+idx, notUsed);
nField++;
}
- assert( nField <= pKeyInfo->nField+pKeyInfo->nXField );
+ assert( nField <= pKeyInfo->nAllField );
}
#else
# define vdbeAssertFieldCountWithinLimits(A,B,C)
@@ -4018,10 +4027,10 @@ int sqlite3VdbeRecordCompareWithSkip(
}
VVA_ONLY( mem1.szMalloc = 0; ) /* Only needed by assert() statements */
- assert( pPKey2->pKeyInfo->nField+pPKey2->pKeyInfo->nXField>=pPKey2->nField
+ assert( pPKey2->pKeyInfo->nAllField>=pPKey2->nField
|| CORRUPT_DB );
assert( pPKey2->pKeyInfo->aSortOrder!=0 );
- assert( pPKey2->pKeyInfo->nField>0 );
+ assert( pPKey2->pKeyInfo->nKeyField>0 );
assert( idx1<=szHdr1 || CORRUPT_DB );
do{
u32 serial_type;
@@ -4354,7 +4363,7 @@ RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){
** The easiest way to enforce this limit is to consider only records with
** 13 fields or less. If the first field is an integer, the maximum legal
** header size is (12*5 + 1 + 1) bytes. */
- if( (p->pKeyInfo->nField + p->pKeyInfo->nXField)<=13 ){
+ if( p->pKeyInfo->nAllField<=13 ){
int flags = p->aMem[0].flags;
if( p->pKeyInfo->aSortOrder[0] ){
p->r1 = 1;
@@ -4689,7 +4698,7 @@ void sqlite3VdbePreUpdateHook(
preupdate.iNewReg = iReg;
preupdate.keyinfo.db = db;
preupdate.keyinfo.enc = ENC(db);
- preupdate.keyinfo.nField = pTab->nCol;
+ preupdate.keyinfo.nKeyField = pTab->nCol;
preupdate.keyinfo.aSortOrder = (u8*)&fakeSortOrder;
preupdate.iKey1 = iKey1;
preupdate.iKey2 = iKey2;
@@ -4699,8 +4708,8 @@ void sqlite3VdbePreUpdateHook(
db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2);
db->pPreUpdate = 0;
sqlite3DbFree(db, preupdate.aRecord);
- vdbeFreeUnpacked(db, preupdate.keyinfo.nField+1, preupdate.pUnpacked);
- vdbeFreeUnpacked(db, preupdate.keyinfo.nField+1, preupdate.pNewUnpacked);
+ vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pUnpacked);
+ vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pNewUnpacked);
if( preupdate.aNew ){
int i;
for(i=0; i<pCsr->nField; i++){
diff --git a/chromium/third_party/sqlite/src/src/vdbeblob.c b/chromium/third_party/sqlite/src/src/vdbeblob.c
index 96a98649bfc..785efdc84bb 100644
--- a/chromium/third_party/sqlite/src/src/vdbeblob.c
+++ b/chromium/third_party/sqlite/src/src/vdbeblob.c
@@ -63,11 +63,12 @@ static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){
v->aMem[1].u.i = iRow;
/* If the statement has been run before (and is paused at the OP_ResultRow)
- ** then back it up to the point where it does the OP_SeekRowid. This could
+ ** then back it up to the point where it does the OP_NotExists. This could
** have been down with an extra OP_Goto, but simply setting the program
** counter is faster. */
- if( v->pc>3 ){
- v->pc = 3;
+ if( v->pc>4 ){
+ v->pc = 4;
+ assert( v->aOp[v->pc].opcode==OP_NotExists );
rc = sqlite3VdbeExec(v);
}else{
rc = sqlite3_step(p->pStmt);
@@ -129,8 +130,8 @@ int sqlite3_blob_open(
int rc = SQLITE_OK;
char *zErr = 0;
Table *pTab;
- Parse *pParse = 0;
Incrblob *pBlob = 0;
+ Parse sParse;
#ifdef SQLITE_ENABLE_API_ARMOR
if( ppBlob==0 ){
@@ -148,37 +149,34 @@ int sqlite3_blob_open(
sqlite3_mutex_enter(db->mutex);
pBlob = (Incrblob *)sqlite3DbMallocZero(db, sizeof(Incrblob));
- if( !pBlob ) goto blob_open_out;
- pParse = sqlite3StackAllocRaw(db, sizeof(*pParse));
- if( !pParse ) goto blob_open_out;
-
do {
- memset(pParse, 0, sizeof(Parse));
- pParse->db = db;
+ memset(&sParse, 0, sizeof(Parse));
+ if( !pBlob ) goto blob_open_out;
+ sParse.db = db;
sqlite3DbFree(db, zErr);
zErr = 0;
sqlite3BtreeEnterAll(db);
- pTab = sqlite3LocateTable(pParse, 0, zTable, zDb);
+ pTab = sqlite3LocateTable(&sParse, 0, zTable, zDb);
if( pTab && IsVirtual(pTab) ){
pTab = 0;
- sqlite3ErrorMsg(pParse, "cannot open virtual table: %s", zTable);
+ sqlite3ErrorMsg(&sParse, "cannot open virtual table: %s", zTable);
}
if( pTab && !HasRowid(pTab) ){
pTab = 0;
- sqlite3ErrorMsg(pParse, "cannot open table without rowid: %s", zTable);
+ sqlite3ErrorMsg(&sParse, "cannot open table without rowid: %s", zTable);
}
#ifndef SQLITE_OMIT_VIEW
if( pTab && pTab->pSelect ){
pTab = 0;
- sqlite3ErrorMsg(pParse, "cannot open view: %s", zTable);
+ sqlite3ErrorMsg(&sParse, "cannot open view: %s", zTable);
}
#endif
if( !pTab ){
- if( pParse->zErrMsg ){
+ if( sParse.zErrMsg ){
sqlite3DbFree(db, zErr);
- zErr = pParse->zErrMsg;
- pParse->zErrMsg = 0;
+ zErr = sParse.zErrMsg;
+ sParse.zErrMsg = 0;
}
rc = SQLITE_ERROR;
sqlite3BtreeLeaveAll(db);
@@ -242,7 +240,7 @@ int sqlite3_blob_open(
}
}
- pBlob->pStmt = (sqlite3_stmt *)sqlite3VdbeCreate(pParse);
+ pBlob->pStmt = (sqlite3_stmt *)sqlite3VdbeCreate(&sParse);
assert( pBlob->pStmt || db->mallocFailed );
if( pBlob->pStmt ){
@@ -279,6 +277,7 @@ int sqlite3_blob_open(
pTab->pSchema->schema_cookie,
pTab->pSchema->iGeneration);
sqlite3VdbeChangeP5(v, 1);
+ assert( sqlite3VdbeCurrentAddr(v)==2 || db->mallocFailed );
aOp = sqlite3VdbeAddOpList(v, ArraySize(openBlob), openBlob, iLn);
/* Make sure a mutex is held on the table to be accessed */
@@ -293,7 +292,7 @@ int sqlite3_blob_open(
aOp[0].p1 = iDb;
aOp[0].p2 = pTab->tnum;
aOp[0].p3 = wrFlag;
- sqlite3VdbeChangeP4(v, 1, pTab->zName, P4_TRANSIENT);
+ sqlite3VdbeChangeP4(v, 2, pTab->zName, P4_TRANSIENT);
}
if( db->mallocFailed==0 ){
#endif
@@ -315,10 +314,10 @@ int sqlite3_blob_open(
aOp[1].p4.i = pTab->nCol+1;
aOp[3].p2 = pTab->nCol;
- pParse->nVar = 0;
- pParse->nMem = 1;
- pParse->nTab = 1;
- sqlite3VdbeMakeReady(v, pParse);
+ sParse.nVar = 0;
+ sParse.nMem = 1;
+ sParse.nTab = 1;
+ sqlite3VdbeMakeReady(v, &sParse);
}
}
@@ -340,8 +339,7 @@ blob_open_out:
}
sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr);
sqlite3DbFree(db, zErr);
- sqlite3ParserReset(pParse);
- sqlite3StackFree(db, pParse);
+ sqlite3ParserReset(&sParse);
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
return rc;
diff --git a/chromium/third_party/sqlite/src/src/vdbemem.c b/chromium/third_party/sqlite/src/src/vdbemem.c
index f8c7166d962..64aca98147e 100644
--- a/chromium/third_party/sqlite/src/src/vdbemem.c
+++ b/chromium/third_party/sqlite/src/src/vdbemem.c
@@ -155,7 +155,7 @@ SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
assert( pMem->szMalloc==0
|| pMem->szMalloc==sqlite3DbMallocSize(pMem->db, pMem->zMalloc) );
if( n<32 ) n = 32;
- if( bPreserve && pMem->szMalloc>0 && pMem->z==pMem->zMalloc ){
+ if( pMem->szMalloc>0 && bPreserve && pMem->z==pMem->zMalloc ){
pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
bPreserve = 0;
}else{
@@ -171,7 +171,8 @@ SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc);
}
- if( bPreserve && pMem->z && ALWAYS(pMem->z!=pMem->zMalloc) ){
+ if( bPreserve && pMem->z ){
+ assert( pMem->z!=pMem->zMalloc );
memcpy(pMem->zMalloc, pMem->z, pMem->n);
}
if( (pMem->flags&MEM_Dyn)!=0 ){
@@ -210,6 +211,20 @@ int sqlite3VdbeMemClearAndResize(Mem *pMem, int szNew){
}
/*
+** It is already known that pMem contains an unterminated string.
+** Add the zero terminator.
+*/
+static SQLITE_NOINLINE int vdbeMemAddTerminator(Mem *pMem){
+ if( sqlite3VdbeMemGrow(pMem, pMem->n+2, 1) ){
+ return SQLITE_NOMEM_BKPT;
+ }
+ pMem->z[pMem->n] = 0;
+ pMem->z[pMem->n+1] = 0;
+ pMem->flags |= MEM_Term;
+ return SQLITE_OK;
+}
+
+/*
** Change pMem so that its MEM_Str or MEM_Blob value is stored in
** MEM.zMalloc, where it can be safely written.
**
@@ -221,12 +236,8 @@ int sqlite3VdbeMemMakeWriteable(Mem *pMem){
if( (pMem->flags & (MEM_Str|MEM_Blob))!=0 ){
if( ExpandBlob(pMem) ) return SQLITE_NOMEM;
if( pMem->szMalloc==0 || pMem->z!=pMem->zMalloc ){
- if( sqlite3VdbeMemGrow(pMem, pMem->n + 2, 1) ){
- return SQLITE_NOMEM_BKPT;
- }
- pMem->z[pMem->n] = 0;
- pMem->z[pMem->n+1] = 0;
- pMem->flags |= MEM_Term;
+ int rc = vdbeMemAddTerminator(pMem);
+ if( rc ) return rc;
}
}
pMem->flags &= ~MEM_Ephem;
@@ -266,20 +277,6 @@ int sqlite3VdbeMemExpandBlob(Mem *pMem){
#endif
/*
-** It is already known that pMem contains an unterminated string.
-** Add the zero terminator.
-*/
-static SQLITE_NOINLINE int vdbeMemAddTerminator(Mem *pMem){
- if( sqlite3VdbeMemGrow(pMem, pMem->n+2, 1) ){
- return SQLITE_NOMEM_BKPT;
- }
- pMem->z[pMem->n] = 0;
- pMem->z[pMem->n+1] = 0;
- pMem->flags |= MEM_Term;
- return SQLITE_OK;
-}
-
-/*
** Make sure the given Mem is \u0000 terminated.
*/
int sqlite3VdbeMemNulTerminate(Mem *pMem){
@@ -597,14 +594,21 @@ int sqlite3VdbeMemRealify(Mem *pMem){
*/
int sqlite3VdbeMemNumerify(Mem *pMem){
if( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 ){
+ int rc;
assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
- if( 0==sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc) ){
+ rc = sqlite3Atoi64(pMem->z, &pMem->u.i, pMem->n, pMem->enc);
+ if( rc==0 ){
MemSetTypeFlag(pMem, MEM_Int);
}else{
- pMem->u.r = sqlite3VdbeRealValue(pMem);
- MemSetTypeFlag(pMem, MEM_Real);
- sqlite3VdbeIntegerAffinity(pMem);
+ i64 i = pMem->u.i;
+ sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc);
+ if( rc==1 && pMem->u.r==(double)i ){
+ pMem->u.i = i;
+ MemSetTypeFlag(pMem, MEM_Int);
+ }else{
+ MemSetTypeFlag(pMem, MEM_Real);
+ }
}
}
assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))!=0 );
@@ -931,7 +935,7 @@ int sqlite3VdbeMemSetStr(
if( nByte<0 ){
assert( enc!=0 );
if( enc==SQLITE_UTF8 ){
- nByte = sqlite3Strlen30(z);
+ nByte = 0x7fffffff & (int)strlen(z);
if( nByte>iLimit ) nByte = iLimit+1;
}else{
for(nByte=0; nByte<=iLimit && (z[nByte] | z[nByte+1]); nByte+=2){}
@@ -1009,12 +1013,11 @@ static SQLITE_NOINLINE int vdbeMemFromBtreeResize(
){
int rc;
pMem->flags = MEM_Null;
- if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt+2)) ){
+ if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt+1)) ){
rc = sqlite3BtreePayload(pCur, offset, amt, pMem->z);
if( rc==SQLITE_OK ){
- pMem->z[amt] = 0;
- pMem->z[amt+1] = 0;
- pMem->flags = MEM_Blob|MEM_Term;
+ pMem->z[amt] = 0; /* Overrun area used when reading malformed records */
+ pMem->flags = MEM_Blob;
pMem->n = (int)amt;
}else{
sqlite3VdbeMemRelease(pMem);
@@ -1163,7 +1166,7 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
if( pRec ){
pRec->pKeyInfo = sqlite3KeyInfoOfIndex(p->pParse, pIdx);
if( pRec->pKeyInfo ){
- assert( pRec->pKeyInfo->nField+pRec->pKeyInfo->nXField==nCol );
+ assert( pRec->pKeyInfo->nAllField==nCol );
assert( pRec->pKeyInfo->enc==ENC(db) );
pRec->aMem = (Mem *)((u8*)pRec + ROUND8(sizeof(UnpackedRecord)));
for(i=0; i<nCol; i++){
@@ -1699,7 +1702,7 @@ int sqlite3Stat4Column(
void sqlite3Stat4ProbeFree(UnpackedRecord *pRec){
if( pRec ){
int i;
- int nCol = pRec->pKeyInfo->nField+pRec->pKeyInfo->nXField;
+ int nCol = pRec->pKeyInfo->nAllField;
Mem *aMem = pRec->aMem;
sqlite3 *db = aMem[0].db;
for(i=0; i<nCol; i++){
diff --git a/chromium/third_party/sqlite/src/src/vdbesort.c b/chromium/third_party/sqlite/src/src/vdbesort.c
index 30be45a43e9..9fd430321a1 100644
--- a/chromium/third_party/sqlite/src/src/vdbesort.c
+++ b/chromium/third_party/sqlite/src/src/vdbesort.c
@@ -823,7 +823,7 @@ static int vdbeSorterCompareText(
}
if( res==0 ){
- if( pTask->pSorter->pKeyInfo->nField>1 ){
+ if( pTask->pSorter->pKeyInfo->nKeyField>1 ){
res = vdbeSorterCompareTail(
pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2
);
@@ -892,7 +892,7 @@ static int vdbeSorterCompareInt(
}
if( res==0 ){
- if( pTask->pSorter->pKeyInfo->nField>1 ){
+ if( pTask->pSorter->pKeyInfo->nKeyField>1 ){
res = vdbeSorterCompareTail(
pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2
);
@@ -907,7 +907,7 @@ static int vdbeSorterCompareInt(
/*
** Initialize the temporary index cursor just opened as a sorter cursor.
**
-** Usually, the sorter module uses the value of (pCsr->pKeyInfo->nField)
+** Usually, the sorter module uses the value of (pCsr->pKeyInfo->nKeyField)
** to determine the number of fields that should be compared from the
** records being sorted. However, if the value passed as argument nField
** is non-zero and the sorter is able to guarantee a stable sort, nField
@@ -960,7 +960,7 @@ int sqlite3VdbeSorterInit(
assert( pCsr->pKeyInfo && pCsr->pBtx==0 );
assert( pCsr->eCurType==CURTYPE_SORTER );
- szKeyInfo = sizeof(KeyInfo) + (pCsr->pKeyInfo->nField-1)*sizeof(CollSeq*);
+ szKeyInfo = sizeof(KeyInfo) + (pCsr->pKeyInfo->nKeyField-1)*sizeof(CollSeq*);
sz = sizeof(VdbeSorter) + nWorker * sizeof(SortSubtask);
pSorter = (VdbeSorter*)sqlite3DbMallocZero(db, sz + szKeyInfo);
@@ -972,8 +972,7 @@ int sqlite3VdbeSorterInit(
memcpy(pKeyInfo, pCsr->pKeyInfo, szKeyInfo);
pKeyInfo->db = 0;
if( nField && nWorker==0 ){
- pKeyInfo->nXField += (pKeyInfo->nField - nField);
- pKeyInfo->nField = nField;
+ pKeyInfo->nKeyField = nField;
}
pSorter->pgsz = pgsz = sqlite3BtreeGetPageSize(db->aDb[0].pBt);
pSorter->nTask = nWorker + 1;
@@ -1001,11 +1000,9 @@ int sqlite3VdbeSorterInit(
mxCache = MIN(mxCache, SQLITE_MAX_PMASZ);
pSorter->mxPmaSize = MAX(pSorter->mnPmaSize, (int)mxCache);
- /* EVIDENCE-OF: R-26747-61719 When the application provides any amount of
- ** scratch memory using SQLITE_CONFIG_SCRATCH, SQLite avoids unnecessary
- ** large heap allocations.
- */
- if( sqlite3GlobalConfig.pScratch==0 ){
+ /* Avoid large memory allocations if the application has requested
+ ** SQLITE_CONFIG_SMALL_MALLOC. */
+ if( sqlite3GlobalConfig.bSmallMalloc==0 ){
assert( pSorter->iMemory==0 );
pSorter->nMemory = pgsz;
pSorter->list.aMemory = (u8*)sqlite3Malloc(pgsz);
@@ -1013,7 +1010,7 @@ int sqlite3VdbeSorterInit(
}
}
- if( (pKeyInfo->nField+pKeyInfo->nXField)<13
+ if( pKeyInfo->nAllField<13
&& (pKeyInfo->aColl[0]==0 || pKeyInfo->aColl[0]==db->pDfltColl)
){
pSorter->typeMask = SORTER_TYPE_INTEGER | SORTER_TYPE_TEXT;
@@ -1328,7 +1325,7 @@ static int vdbeSortAllocUnpacked(SortSubtask *pTask){
if( pTask->pUnpacked==0 ){
pTask->pUnpacked = sqlite3VdbeAllocUnpackedRecord(pTask->pSorter->pKeyInfo);
if( pTask->pUnpacked==0 ) return SQLITE_NOMEM_BKPT;
- pTask->pUnpacked->nField = pTask->pSorter->pKeyInfo->nField;
+ pTask->pUnpacked->nField = pTask->pSorter->pKeyInfo->nKeyField;
pTask->pUnpacked->errCode = 0;
}
return SQLITE_OK;
diff --git a/chromium/third_party/sqlite/src/src/vdbetrace.c b/chromium/third_party/sqlite/src/src/vdbetrace.c
index b565c5c485e..da3036adfd1 100644
--- a/chromium/third_party/sqlite/src/src/vdbetrace.c
+++ b/chromium/third_party/sqlite/src/src/vdbetrace.c
@@ -82,7 +82,7 @@ char *sqlite3VdbeExpandSql(
Mem *pVar; /* Value of a host parameter */
StrAccum out; /* Accumulate the output here */
#ifndef SQLITE_OMIT_UTF16
- Mem utf8; /* Used to convert UTF16 parameters into UTF8 for display */
+ Mem utf8; /* Used to convert UTF16 into UTF8 for display */
#endif
char zBase[100]; /* Initial working space */
diff --git a/chromium/third_party/sqlite/src/src/vtab.c b/chromium/third_party/sqlite/src/src/vtab.c
index f2dc732fc90..bdf20f1af12 100644
--- a/chromium/third_party/sqlite/src/src/vtab.c
+++ b/chromium/third_party/sqlite/src/src/vtab.c
@@ -42,8 +42,10 @@ Module *sqlite3VtabCreateModule(
){
Module *pMod;
int nName = sqlite3Strlen30(zName);
- pMod = (Module *)sqlite3DbMallocRawNN(db, sizeof(Module) + nName + 1);
- if( pMod ){
+ pMod = (Module *)sqlite3Malloc(sizeof(Module) + nName + 1);
+ if( pMod==0 ){
+ sqlite3OomFault(db);
+ }else{
Module *pDel;
char *zCopy = (char *)(&pMod[1]);
memcpy(zCopy, zName, nName+1);
@@ -518,13 +520,14 @@ static int vtabCallConstructor(
}
}
- zModuleName = sqlite3MPrintf(db, "%s", pTab->zName);
+ zModuleName = sqlite3DbStrDup(db, pTab->zName);
if( !zModuleName ){
return SQLITE_NOMEM_BKPT;
}
- pVTable = sqlite3DbMallocZero(db, sizeof(VTable));
+ pVTable = sqlite3MallocZero(sizeof(VTable));
if( !pVTable ){
+ sqlite3OomFault(db);
sqlite3DbFree(db, zModuleName);
return SQLITE_NOMEM_BKPT;
}
@@ -644,6 +647,7 @@ int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){
rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xConnect, &zErr);
if( rc!=SQLITE_OK ){
sqlite3ErrorMsg(pParse, "%s", zErr);
+ pParse->rc = rc;
}
sqlite3DbFree(db, zErr);
}
@@ -733,10 +737,10 @@ int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){
*/
int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
VtabCtx *pCtx;
- Parse *pParse;
int rc = SQLITE_OK;
Table *pTab;
char *zErr = 0;
+ Parse sParse;
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) || zCreateTable==0 ){
@@ -753,55 +757,55 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
pTab = pCtx->pTab;
assert( IsVirtual(pTab) );
- pParse = sqlite3StackAllocZero(db, sizeof(*pParse));
- if( pParse==0 ){
- rc = SQLITE_NOMEM_BKPT;
- }else{
- pParse->declareVtab = 1;
- pParse->db = db;
- pParse->nQueryLoop = 1;
-
- if( SQLITE_OK==sqlite3RunParser(pParse, zCreateTable, &zErr)
- && pParse->pNewTable
- && !db->mallocFailed
- && !pParse->pNewTable->pSelect
- && !IsVirtual(pParse->pNewTable)
- ){
- if( !pTab->aCol ){
- Table *pNew = pParse->pNewTable;
- Index *pIdx;
- pTab->aCol = pNew->aCol;
- pTab->nCol = pNew->nCol;
- pTab->tabFlags |= pNew->tabFlags & (TF_WithoutRowid|TF_NoVisibleRowid);
- pNew->nCol = 0;
- pNew->aCol = 0;
- assert( pTab->pIndex==0 );
- if( !HasRowid(pNew) && pCtx->pVTable->pMod->pModule->xUpdate!=0 ){
- rc = SQLITE_ERROR;
- }
- pIdx = pNew->pIndex;
- if( pIdx ){
- assert( pIdx->pNext==0 );
- pTab->pIndex = pIdx;
- pNew->pIndex = 0;
- pIdx->pTable = pTab;
- }
+ memset(&sParse, 0, sizeof(sParse));
+ sParse.declareVtab = 1;
+ sParse.db = db;
+ sParse.nQueryLoop = 1;
+ if( SQLITE_OK==sqlite3RunParser(&sParse, zCreateTable, &zErr)
+ && sParse.pNewTable
+ && !db->mallocFailed
+ && !sParse.pNewTable->pSelect
+ && !IsVirtual(sParse.pNewTable)
+ ){
+ if( !pTab->aCol ){
+ Table *pNew = sParse.pNewTable;
+ Index *pIdx;
+ pTab->aCol = pNew->aCol;
+ pTab->nCol = pNew->nCol;
+ pTab->tabFlags |= pNew->tabFlags & (TF_WithoutRowid|TF_NoVisibleRowid);
+ pNew->nCol = 0;
+ pNew->aCol = 0;
+ assert( pTab->pIndex==0 );
+ assert( HasRowid(pNew) || sqlite3PrimaryKeyIndex(pNew)!=0 );
+ if( !HasRowid(pNew)
+ && pCtx->pVTable->pMod->pModule->xUpdate!=0
+ && sqlite3PrimaryKeyIndex(pNew)->nKeyCol!=1
+ ){
+ /* WITHOUT ROWID virtual tables must either be read-only (xUpdate==0)
+ ** or else must have a single-column PRIMARY KEY */
+ rc = SQLITE_ERROR;
+ }
+ pIdx = pNew->pIndex;
+ if( pIdx ){
+ assert( pIdx->pNext==0 );
+ pTab->pIndex = pIdx;
+ pNew->pIndex = 0;
+ pIdx->pTable = pTab;
}
- pCtx->bDeclared = 1;
- }else{
- sqlite3ErrorWithMsg(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr);
- sqlite3DbFree(db, zErr);
- rc = SQLITE_ERROR;
}
- pParse->declareVtab = 0;
+ pCtx->bDeclared = 1;
+ }else{
+ sqlite3ErrorWithMsg(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr);
+ sqlite3DbFree(db, zErr);
+ rc = SQLITE_ERROR;
+ }
+ sParse.declareVtab = 0;
- if( pParse->pVdbe ){
- sqlite3VdbeFinalize(pParse->pVdbe);
- }
- sqlite3DeleteTable(db, pParse->pNewTable);
- sqlite3ParserReset(pParse);
- sqlite3StackFree(db, pParse);
+ if( sParse.pVdbe ){
+ sqlite3VdbeFinalize(sParse.pVdbe);
}
+ sqlite3DeleteTable(db, sParse.pNewTable);
+ sqlite3ParserReset(&sParse);
assert( (rc&0xff)==rc );
rc = sqlite3ApiExit(db, rc);
diff --git a/chromium/third_party/sqlite/src/src/wal.c b/chromium/third_party/sqlite/src/src/wal.c
index 0a3bc37a4e0..a88be06faae 100644
--- a/chromium/third_party/sqlite/src/src/wal.c
+++ b/chromium/third_party/sqlite/src/src/wal.c
@@ -1798,9 +1798,7 @@ static int walCheckpoint(
pInfo->nBackfillAttempted = mxSafeFrame;
/* Sync the WAL to disk */
- if( sync_flags ){
- rc = sqlite3OsSync(pWal->pWalFd, sync_flags);
- }
+ rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags));
/* If the database may grow as a result of this checkpoint, hint
** about the eventual size of the db file to the VFS layer.
@@ -1841,8 +1839,8 @@ static int walCheckpoint(
i64 szDb = pWal->hdr.nPage*(i64)szPage;
testcase( IS_BIG_INT(szDb) );
rc = sqlite3OsTruncate(pWal->pDbFd, szDb);
- if( rc==SQLITE_OK && sync_flags ){
- rc = sqlite3OsSync(pWal->pDbFd, sync_flags);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3OsSync(pWal->pDbFd, CKPT_SYNC_FLAGS(sync_flags));
}
}
if( rc==SQLITE_OK ){
@@ -2948,8 +2946,8 @@ static int walWriteToLog(
iOffset += iFirstAmt;
iAmt -= iFirstAmt;
pContent = (void*)(iFirstAmt + (char*)pContent);
- assert( p->syncFlags & (SQLITE_SYNC_NORMAL|SQLITE_SYNC_FULL) );
- rc = sqlite3OsSync(p->pFd, p->syncFlags & SQLITE_SYNC_MASK);
+ assert( WAL_SYNC_FLAGS(p->syncFlags)!=0 );
+ rc = sqlite3OsSync(p->pFd, WAL_SYNC_FLAGS(p->syncFlags));
if( iAmt==0 || rc ) return rc;
}
rc = sqlite3OsWrite(p->pFd, pContent, iAmt, iOffset);
@@ -3119,10 +3117,10 @@ int sqlite3WalFrames(
** an out-of-order write following a WAL restart could result in
** database corruption. See the ticket:
**
- ** http://localhost:591/sqlite/info/ff5be73dee
+ ** https://sqlite.org/src/info/ff5be73dee
*/
- if( pWal->syncHeader && sync_flags ){
- rc = sqlite3OsSync(pWal->pWalFd, sync_flags & SQLITE_SYNC_MASK);
+ if( pWal->syncHeader ){
+ rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags));
if( rc ) return rc;
}
}
@@ -3197,7 +3195,7 @@ int sqlite3WalFrames(
** sector boundary is synced; the part of the last frame that extends
** past the sector boundary is written after the sync.
*/
- if( isCommit && (sync_flags & WAL_SYNC_TRANSACTIONS)!=0 ){
+ if( isCommit && WAL_SYNC_FLAGS(sync_flags)!=0 ){
int bSync = 1;
if( pWal->padToSectorBoundary ){
int sectorSize = sqlite3SectorSize(pWal->pWalFd);
@@ -3213,7 +3211,7 @@ int sqlite3WalFrames(
}
if( bSync ){
assert( rc==SQLITE_OK );
- rc = sqlite3OsSync(w.pFd, sync_flags & SQLITE_SYNC_MASK);
+ rc = sqlite3OsSync(w.pFd, WAL_SYNC_FLAGS(sync_flags));
}
}
diff --git a/chromium/third_party/sqlite/src/src/wal.h b/chromium/third_party/sqlite/src/src/wal.h
index df831b5349b..27b8272fb9e 100644
--- a/chromium/third_party/sqlite/src/src/wal.h
+++ b/chromium/third_party/sqlite/src/src/wal.h
@@ -19,11 +19,11 @@
#include "sqliteInt.h"
-/* Additional values that can be added to the sync_flags argument of
-** sqlite3WalFrames():
+/* Macros for extracting appropriate sync flags for either transaction
+** commits (WAL_SYNC_FLAGS(X)) or for checkpoint ops (CKPT_SYNC_FLAGS(X)):
*/
-#define WAL_SYNC_TRANSACTIONS 0x20 /* Sync at the end of each transaction */
-#define SQLITE_SYNC_MASK 0x13 /* Mask off the SQLITE_SYNC_* values */
+#define WAL_SYNC_FLAGS(X) ((X)&0x03)
+#define CKPT_SYNC_FLAGS(X) (((X)>>2)&0x03)
#ifdef SQLITE_OMIT_WAL
# define sqlite3WalOpen(x,y,z) 0
diff --git a/chromium/third_party/sqlite/src/src/walker.c b/chromium/third_party/sqlite/src/src/walker.c
index 99333d1fc6c..d21ac1a9754 100644
--- a/chromium/third_party/sqlite/src/src/walker.c
+++ b/chromium/third_party/sqlite/src/src/walker.c
@@ -40,18 +40,22 @@ static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){
int rc;
testcase( ExprHasProperty(pExpr, EP_TokenOnly) );
testcase( ExprHasProperty(pExpr, EP_Reduced) );
- rc = pWalker->xExprCallback(pWalker, pExpr);
- if( rc ) return rc & WRC_Abort;
- if( !ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){
- if( pExpr->pLeft && walkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
- assert( pExpr->x.pList==0 || pExpr->pRight==0 );
- if( pExpr->pRight ){
- if( walkExpr(pWalker, pExpr->pRight) ) return WRC_Abort;
- }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
- if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort;
- }else if( pExpr->x.pList ){
- if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
+ while(1){
+ rc = pWalker->xExprCallback(pWalker, pExpr);
+ if( rc ) return rc & WRC_Abort;
+ if( !ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){
+ if( pExpr->pLeft && walkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
+ assert( pExpr->x.pList==0 || pExpr->pRight==0 );
+ if( pExpr->pRight ){
+ pExpr = pExpr->pRight;
+ continue;
+ }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort;
+ }else if( pExpr->x.pList ){
+ if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
+ }
}
+ break;
}
return WRC_Continue;
}
diff --git a/chromium/third_party/sqlite/src/src/where.c b/chromium/third_party/sqlite/src/src/where.c
index 63f26b6025d..13f6100e1d7 100644
--- a/chromium/third_party/sqlite/src/src/where.c
+++ b/chromium/third_party/sqlite/src/src/where.c
@@ -403,8 +403,8 @@ static int findIndexCol(
&& p->iColumn==pIdx->aiColumn[iCol]
&& p->iTable==iBase
){
- CollSeq *pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr);
- if( pColl && 0==sqlite3StrICmp(pColl->zName, zColl) ){
+ CollSeq *pColl = sqlite3ExprNNCollSeq(pParse, pList->a[i].pExpr);
+ if( 0==sqlite3StrICmp(pColl->zName, zColl) ){
return i;
}
}
@@ -868,7 +868,7 @@ static sqlite3_index_info *allocateIndexInfo(
testcase( pTerm->eOperator & WO_ISNULL );
testcase( pTerm->eOperator & WO_IS );
testcase( pTerm->eOperator & WO_ALL );
- if( (pTerm->eOperator & ~(WO_ISNULL|WO_EQUIV|WO_IS))==0 ) continue;
+ if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue;
if( pTerm->wtFlags & TERM_VNULL ) continue;
assert( pTerm->u.leftColumn>=(-1) );
nTerm++;
@@ -916,7 +916,7 @@ static sqlite3_index_info *allocateIndexInfo(
pUsage;
for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
- u8 op;
+ u16 op;
if( pTerm->leftCursor != pSrc->iCursor ) continue;
if( pTerm->prereqRight & mUnusable ) continue;
assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
@@ -924,34 +924,40 @@ static sqlite3_index_info *allocateIndexInfo(
testcase( pTerm->eOperator & WO_IS );
testcase( pTerm->eOperator & WO_ISNULL );
testcase( pTerm->eOperator & WO_ALL );
- if( (pTerm->eOperator & ~(WO_ISNULL|WO_EQUIV|WO_IS))==0 ) continue;
+ if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue;
if( pTerm->wtFlags & TERM_VNULL ) continue;
assert( pTerm->u.leftColumn>=(-1) );
pIdxCons[j].iColumn = pTerm->u.leftColumn;
pIdxCons[j].iTermOffset = i;
- op = (u8)pTerm->eOperator & WO_ALL;
+ op = pTerm->eOperator & WO_ALL;
if( op==WO_IN ) op = WO_EQ;
- if( op==WO_MATCH ){
- op = pTerm->eMatchOp;
- }
- pIdxCons[j].op = op;
- /* The direct assignment in the previous line is possible only because
- ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
- ** following asserts verify this fact. */
- assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ );
- assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT );
- assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE );
- assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
- assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
- assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH );
- assert( pTerm->eOperator & (WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) );
-
- if( op & (WO_LT|WO_LE|WO_GT|WO_GE)
- && sqlite3ExprIsVector(pTerm->pExpr->pRight)
- ){
- if( i<16 ) mNoOmit |= (1 << i);
- if( op==WO_LT ) pIdxCons[j].op = WO_LE;
- if( op==WO_GT ) pIdxCons[j].op = WO_GE;
+ if( op==WO_AUX ){
+ pIdxCons[j].op = pTerm->eMatchOp;
+ }else if( op & (WO_ISNULL|WO_IS) ){
+ if( op==WO_ISNULL ){
+ pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_ISNULL;
+ }else{
+ pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_IS;
+ }
+ }else{
+ pIdxCons[j].op = (u8)op;
+ /* The direct assignment in the previous line is possible only because
+ ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
+ ** following asserts verify this fact. */
+ assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ );
+ assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT );
+ assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE );
+ assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
+ assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
+ assert( pTerm->eOperator&(WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_AUX) );
+
+ if( op & (WO_LT|WO_LE|WO_GT|WO_GE)
+ && sqlite3ExprIsVector(pTerm->pExpr->pRight)
+ ){
+ if( i<16 ) mNoOmit |= (1 << i);
+ if( op==WO_LT ) pIdxCons[j].op = WO_LE;
+ if( op==WO_GT ) pIdxCons[j].op = WO_GE;
+ }
}
j++;
@@ -1879,18 +1885,19 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
** Return TRUE if all of the following are true:
**
** (1) X has the same or lower cost that Y
-** (2) X is a proper subset of Y
-** (3) X skips at least as many columns as Y
-**
-** By "proper subset" we mean that X uses fewer WHERE clause terms
-** than Y and that every WHERE clause term used by X is also used
-** by Y.
+** (2) X uses fewer WHERE clause terms than Y
+** (3) Every WHERE clause term used by X is also used by Y
+** (4) X skips at least as many columns as Y
+** (5) If X is a covering index, than Y is too
**
+** Conditions (2) and (3) mean that X is a "proper subset" of Y.
** If X is a proper subset of Y then Y is a better choice and ought
** to have a lower cost. This routine returns TRUE when that cost
-** relationship is inverted and needs to be adjusted. The third rule
+** relationship is inverted and needs to be adjusted. Constraint (4)
** was added because if X uses skip-scan less than Y it still might
-** deserve a lower cost even if it is a proper subset of Y.
+** deserve a lower cost even if it is a proper subset of Y. Constraint (5)
+** was added because a covering index probably deserves to have a lower cost
+** than a non-covering index even if it is a proper subset.
*/
static int whereLoopCheaperProperSubset(
const WhereLoop *pX, /* First WhereLoop to compare */
@@ -1912,6 +1919,10 @@ static int whereLoopCheaperProperSubset(
}
if( j<0 ) return 0; /* X not a subset of Y since term X[i] not used by Y */
}
+ if( (pX->wsFlags&WHERE_IDX_ONLY)!=0
+ && (pY->wsFlags&WHERE_IDX_ONLY)==0 ){
+ return 0; /* Constraint (5) */
+ }
return 1; /* All conditions meet */
}
@@ -2663,7 +2674,7 @@ static int indexMightHelpWithOrderBy(
}else if( (aColExpr = pIndex->aColExpr)!=0 ){
for(jj=0; jj<pIndex->nKeyCol; jj++){
if( pIndex->aiColumn[jj]!=XN_EXPR ) continue;
- if( sqlite3ExprCompare(0, pExpr,aColExpr->a[jj].pExpr,iCursor)==0 ){
+ if( sqlite3ExprCompareSkip(pExpr,aColExpr->a[jj].pExpr,iCursor)==0 ){
return 1;
}
}
@@ -3573,14 +3584,10 @@ static i8 wherePathSatisfiesOrderBy(
if( j>=pLoop->nLTerm ) continue;
}
if( (pTerm->eOperator&(WO_EQ|WO_IS))!=0 && pOBExpr->iColumn>=0 ){
- const char *z1, *z2;
- pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr);
- if( !pColl ) pColl = db->pDfltColl;
- z1 = pColl->zName;
- pColl = sqlite3ExprCollSeq(pWInfo->pParse, pTerm->pExpr);
- if( !pColl ) pColl = db->pDfltColl;
- z2 = pColl->zName;
- if( sqlite3StrICmp(z1, z2)!=0 ) continue;
+ if( sqlite3ExprCollSeqMatch(pWInfo->pParse,
+ pOrderBy->a[i].pExpr, pTerm->pExpr)==0 ){
+ continue;
+ }
testcase( pTerm->pExpr->op==TK_IS );
}
obSat |= MASKBIT(i);
@@ -3652,7 +3659,7 @@ static i8 wherePathSatisfiesOrderBy(
if( pIndex ){
iColumn = pIndex->aiColumn[j];
revIdx = pIndex->aSortOrder[j];
- if( iColumn==pIndex->pTable->iPKey ) iColumn = -1;
+ if( iColumn==pIndex->pTable->iPKey ) iColumn = XN_ROWID;
}else{
iColumn = XN_ROWID;
revIdx = 0;
@@ -3679,19 +3686,18 @@ static i8 wherePathSatisfiesOrderBy(
testcase( wctrlFlags & WHERE_GROUPBY );
testcase( wctrlFlags & WHERE_DISTINCTBY );
if( (wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0 ) bOnce = 0;
- if( iColumn>=(-1) ){
+ if( iColumn>=XN_ROWID ){
if( pOBExpr->op!=TK_COLUMN ) continue;
if( pOBExpr->iTable!=iCur ) continue;
if( pOBExpr->iColumn!=iColumn ) continue;
}else{
- if( sqlite3ExprCompare(0,
- pOBExpr,pIndex->aColExpr->a[j].pExpr,iCur) ){
+ Expr *pIdxExpr = pIndex->aColExpr->a[j].pExpr;
+ if( sqlite3ExprCompareSkip(pOBExpr, pIdxExpr, iCur) ){
continue;
}
}
- if( iColumn>=0 ){
- pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr);
- if( !pColl ) pColl = db->pDfltColl;
+ if( iColumn!=XN_ROWID ){
+ pColl = sqlite3ExprNNCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr);
if( sqlite3StrICmp(pColl->zName, pIndex->azColl[j])!=0 ) continue;
}
pLoop->u.btree.nIdxCol = j+1;
@@ -4328,6 +4334,7 @@ static int exprIsDeterministic(Expr *p){
memset(&w, 0, sizeof(w));
w.eCode = 1;
w.xExprCallback = exprNodeIsDeterministic;
+ w.xSelectCallback = sqlite3SelectWalkFail;
sqlite3WalkExpr(&w, p);
return w.eCode;
}
@@ -4537,36 +4544,37 @@ WhereInfo *sqlite3WhereBegin(
if( wctrlFlags & WHERE_WANT_DISTINCT ){
pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
}
- }
-
- /* Assign a bit from the bitmask to every term in the FROM clause.
- **
- ** The N-th term of the FROM clause is assigned a bitmask of 1<<N.
- **
- ** The rule of the previous sentence ensures thta if X is the bitmask for
- ** a table T, then X-1 is the bitmask for all other tables to the left of T.
- ** Knowing the bitmask for all tables to the left of a left join is
- ** important. Ticket #3015.
- **
- ** Note that bitmasks are created for all pTabList->nSrc tables in
- ** pTabList, not just the first nTabList tables. nTabList is normally
- ** equal to pTabList->nSrc but might be shortened to 1 if the
- ** WHERE_OR_SUBCLAUSE flag is set.
- */
- for(ii=0; ii<pTabList->nSrc; ii++){
- createMask(pMaskSet, pTabList->a[ii].iCursor);
- sqlite3WhereTabFuncArgs(pParse, &pTabList->a[ii], &pWInfo->sWC);
- }
-#ifdef SQLITE_DEBUG
- {
- Bitmask mx = 0;
- for(ii=0; ii<pTabList->nSrc; ii++){
- Bitmask m = sqlite3WhereGetMask(pMaskSet, pTabList->a[ii].iCursor);
- assert( m>=mx );
- mx = m;
+ }else{
+ /* Assign a bit from the bitmask to every term in the FROM clause.
+ **
+ ** The N-th term of the FROM clause is assigned a bitmask of 1<<N.
+ **
+ ** The rule of the previous sentence ensures thta if X is the bitmask for
+ ** a table T, then X-1 is the bitmask for all other tables to the left of T.
+ ** Knowing the bitmask for all tables to the left of a left join is
+ ** important. Ticket #3015.
+ **
+ ** Note that bitmasks are created for all pTabList->nSrc tables in
+ ** pTabList, not just the first nTabList tables. nTabList is normally
+ ** equal to pTabList->nSrc but might be shortened to 1 if the
+ ** WHERE_OR_SUBCLAUSE flag is set.
+ */
+ ii = 0;
+ do{
+ createMask(pMaskSet, pTabList->a[ii].iCursor);
+ sqlite3WhereTabFuncArgs(pParse, &pTabList->a[ii], &pWInfo->sWC);
+ }while( (++ii)<pTabList->nSrc );
+ #ifdef SQLITE_DEBUG
+ {
+ Bitmask mx = 0;
+ for(ii=0; ii<pTabList->nSrc; ii++){
+ Bitmask m = sqlite3WhereGetMask(pMaskSet, pTabList->a[ii].iCursor);
+ assert( m>=mx );
+ mx = m;
+ }
}
+ #endif
}
-#endif
/* Analyze all of the subexpressions. */
sqlite3WhereExprAnalyze(pTabList, &pWInfo->sWC);
@@ -4790,7 +4798,7 @@ WhereInfo *sqlite3WhereBegin(
Index *pIx = pLoop->u.btree.pIndex;
int iIndexCur;
int op = OP_OpenRead;
- /* iAuxArg is always set if to a positive value if ONEPASS is possible */
+ /* iAuxArg is always set to a positive value if ONEPASS is possible */
assert( iAuxArg!=0 || (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 );
if( !HasRowid(pTab) && IsPrimaryKeyIndex(pIx)
&& (wctrlFlags & WHERE_OR_SUBCLAUSE)!=0
diff --git a/chromium/third_party/sqlite/src/src/whereInt.h b/chromium/third_party/sqlite/src/src/whereInt.h
index 909cbb04ee6..03b74bb3cd4 100644
--- a/chromium/third_party/sqlite/src/src/whereInt.h
+++ b/chromium/third_party/sqlite/src/src/whereInt.h
@@ -515,7 +515,6 @@ void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereClause*);
** WO_LE == SQLITE_INDEX_CONSTRAINT_LE
** WO_GT == SQLITE_INDEX_CONSTRAINT_GT
** WO_GE == SQLITE_INDEX_CONSTRAINT_GE
-** WO_MATCH == SQLITE_INDEX_CONSTRAINT_MATCH
*/
#define WO_IN 0x0001
#define WO_EQ 0x0002
@@ -523,7 +522,7 @@ void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereClause*);
#define WO_LE (WO_EQ<<(TK_LE-TK_EQ))
#define WO_GT (WO_EQ<<(TK_GT-TK_EQ))
#define WO_GE (WO_EQ<<(TK_GE-TK_EQ))
-#define WO_MATCH 0x0040
+#define WO_AUX 0x0040 /* Op useful to virtual tables only */
#define WO_IS 0x0080
#define WO_ISNULL 0x0100
#define WO_OR 0x0200 /* Two or more OR-connected terms */
diff --git a/chromium/third_party/sqlite/src/src/wherecode.c b/chromium/third_party/sqlite/src/src/wherecode.c
index 7c16d0d6f6a..edb0c25ac04 100644
--- a/chromium/third_party/sqlite/src/src/wherecode.c
+++ b/chromium/third_party/sqlite/src/src/wherecode.c
@@ -794,7 +794,7 @@ static int codeCursorHintIsOrFunction(Walker *pWalker, Expr *pExpr){
pWalker->eCode = 1;
}else if( pExpr->op==TK_FUNCTION ){
int d1;
- char d2[3];
+ char d2[4];
if( 0==sqlite3IsLikeFunction(pWalker->pParse->db, pExpr, &d1, d2) ){
pWalker->eCode = 1;
}
@@ -1017,7 +1017,7 @@ static void codeDeferredSeek(
*/
static void codeExprOrVector(Parse *pParse, Expr *p, int iReg, int nReg){
assert( nReg>0 );
- if( sqlite3ExprIsVector(p) ){
+ if( p && sqlite3ExprIsVector(p) ){
#ifndef SQLITE_OMIT_SUBQUERY
if( (p->flags & EP_xIsSelect) ){
Vdbe *v = pParse->pVdbe;
@@ -1070,9 +1070,9 @@ static int whereIndexExprTransNode(Walker *p, Expr *pExpr){
}
/*
-** For an indexes on expression X, locate every instance of expression X in pExpr
-** and change that subexpression into a reference to the appropriate column of
-** the index.
+** For an indexes on expression X, locate every instance of expression X
+** in pExpr and change that subexpression into a reference to the appropriate
+** column of the index.
*/
static void whereIndexExprTrans(
Index *pIdx, /* The Index */
diff --git a/chromium/third_party/sqlite/src/src/whereexpr.c b/chromium/third_party/sqlite/src/src/whereexpr.c
index 3d53959110f..fa71539eab9 100644
--- a/chromium/third_party/sqlite/src/src/whereexpr.c
+++ b/chromium/third_party/sqlite/src/src/whereexpr.c
@@ -194,12 +194,12 @@ static int isLikeOrGlob(
int *pisComplete, /* True if the only wildcard is % in the last character */
int *pnoCase /* True if uppercase is equivalent to lowercase */
){
- const char *z = 0; /* String on RHS of LIKE operator */
+ const u8 *z = 0; /* String on RHS of LIKE operator */
Expr *pRight, *pLeft; /* Right and left size of LIKE operator */
ExprList *pList; /* List of operands to the LIKE operator */
int c; /* One character in z[] */
int cnt; /* Number of non-wildcard prefix characters */
- char wc[3]; /* Wildcard characters */
+ char wc[4]; /* Wildcard characters */
sqlite3 *db = pParse->db; /* Database connection */
sqlite3_value *pVal = 0;
int op; /* Opcode of pRight */
@@ -221,12 +221,12 @@ static int isLikeOrGlob(
int iCol = pRight->iColumn;
pVal = sqlite3VdbeGetBoundValue(pReprepare, iCol, SQLITE_AFF_BLOB);
if( pVal && sqlite3_value_type(pVal)==SQLITE_TEXT ){
- z = (char *)sqlite3_value_text(pVal);
+ z = sqlite3_value_text(pVal);
}
sqlite3VdbeSetVarmask(pParse->pVdbe, iCol);
assert( pRight->op==TK_VARIABLE || pRight->op==TK_REGISTER );
}else if( op==TK_STRING ){
- z = pRight->u.zToken;
+ z = (u8*)pRight->u.zToken;
}
if( z ){
@@ -246,16 +246,42 @@ static int isLikeOrGlob(
return 0;
}
}
+
+ /* Count the number of prefix characters prior to the first wildcard */
cnt = 0;
while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){
cnt++;
+ if( c==wc[3] && z[cnt]!=0 ) cnt++;
}
+
+ /* The optimization is possible only if (1) the pattern does not begin
+ ** with a wildcard and if (2) the non-wildcard prefix does not end with
+ ** an (illegal 0xff) character. The second condition is necessary so
+ ** that we can increment the prefix key to find an upper bound for the
+ ** range search.
+ */
if( cnt!=0 && 255!=(u8)z[cnt-1] ){
Expr *pPrefix;
+
+ /* A "complete" match if the pattern ends with "*" or "%" */
*pisComplete = c==wc[0] && z[cnt+1]==0;
- pPrefix = sqlite3Expr(db, TK_STRING, z);
- if( pPrefix ) pPrefix->u.zToken[cnt] = 0;
+
+ /* Get the pattern prefix. Remove all escapes from the prefix. */
+ pPrefix = sqlite3Expr(db, TK_STRING, (char*)z);
+ if( pPrefix ){
+ int iFrom, iTo;
+ char *zNew = pPrefix->u.zToken;
+ zNew[cnt] = 0;
+ for(iFrom=iTo=0; iFrom<cnt; iFrom++){
+ if( zNew[iFrom]==wc[3] ) iFrom++;
+ zNew[iTo++] = zNew[iFrom];
+ }
+ zNew[iTo] = 0;
+ }
*ppPrefix = pPrefix;
+
+ /* If the RHS pattern is a bound parameter, make arrangements to
+ ** reprepare the statement when that parameter is rebound */
if( op==TK_VARIABLE ){
Vdbe *v = pParse->pVdbe;
sqlite3VdbeSetVarmask(v, pRight->iColumn);
@@ -286,48 +312,84 @@ static int isLikeOrGlob(
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
-** Check to see if the given expression is of the form
+** Check to see if the pExpr expression is a form that needs to be passed
+** to the xBestIndex method of virtual tables. Forms of interest include:
**
-** column OP expr
+** Expression Virtual Table Operator
+** ----------------------- ---------------------------------
+** 1. column MATCH expr SQLITE_INDEX_CONSTRAINT_MATCH
+** 2. column GLOB expr SQLITE_INDEX_CONSTRAINT_GLOB
+** 3. column LIKE expr SQLITE_INDEX_CONSTRAINT_LIKE
+** 4. column REGEXP expr SQLITE_INDEX_CONSTRAINT_REGEXP
+** 5. column != expr SQLITE_INDEX_CONSTRAINT_NE
+** 6. expr != column SQLITE_INDEX_CONSTRAINT_NE
+** 7. column IS NOT expr SQLITE_INDEX_CONSTRAINT_ISNOT
+** 8. expr IS NOT column SQLITE_INDEX_CONSTRAINT_ISNOT
+** 9. column IS NOT NULL SQLITE_INDEX_CONSTRAINT_ISNOTNULL
**
-** where OP is one of MATCH, GLOB, LIKE or REGEXP and "column" is a
-** column of a virtual table.
+** In every case, "column" must be a column of a virtual table. If there
+** is a match, set *ppLeft to the "column" expression, set *ppRight to the
+** "expr" expression (even though in forms (6) and (8) the column is on the
+** right and the expression is on the left). Also set *peOp2 to the
+** appropriate virtual table operator. The return value is 1 or 2 if there
+** is a match. The usual return is 1, but if the RHS is also a column
+** of virtual table in forms (5) or (7) then return 2.
**
-** If it is then return TRUE. If not, return FALSE.
+** If the expression matches none of the patterns above, return 0.
*/
-static int isMatchOfColumn(
+static int isAuxiliaryVtabOperator(
Expr *pExpr, /* Test this expression */
- unsigned char *peOp2 /* OUT: 0 for MATCH, or else an op2 value */
+ unsigned char *peOp2, /* OUT: 0 for MATCH, or else an op2 value */
+ Expr **ppLeft, /* Column expression to left of MATCH/op2 */
+ Expr **ppRight /* Expression to left of MATCH/op2 */
){
- static const struct Op2 {
- const char *zOp;
- unsigned char eOp2;
- } aOp[] = {
- { "match", SQLITE_INDEX_CONSTRAINT_MATCH },
- { "glob", SQLITE_INDEX_CONSTRAINT_GLOB },
- { "like", SQLITE_INDEX_CONSTRAINT_LIKE },
- { "regexp", SQLITE_INDEX_CONSTRAINT_REGEXP }
- };
- ExprList *pList;
- Expr *pCol; /* Column reference */
- int i;
+ if( pExpr->op==TK_FUNCTION ){
+ static const struct Op2 {
+ const char *zOp;
+ unsigned char eOp2;
+ } aOp[] = {
+ { "match", SQLITE_INDEX_CONSTRAINT_MATCH },
+ { "glob", SQLITE_INDEX_CONSTRAINT_GLOB },
+ { "like", SQLITE_INDEX_CONSTRAINT_LIKE },
+ { "regexp", SQLITE_INDEX_CONSTRAINT_REGEXP }
+ };
+ ExprList *pList;
+ Expr *pCol; /* Column reference */
+ int i;
- if( pExpr->op!=TK_FUNCTION ){
- return 0;
- }
- pList = pExpr->x.pList;
- if( pList==0 || pList->nExpr!=2 ){
- return 0;
- }
- pCol = pList->a[1].pExpr;
- if( pCol->op!=TK_COLUMN || !IsVirtual(pCol->pTab) ){
- return 0;
- }
- for(i=0; i<ArraySize(aOp); i++){
- if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){
- *peOp2 = aOp[i].eOp2;
- return 1;
+ pList = pExpr->x.pList;
+ if( pList==0 || pList->nExpr!=2 ){
+ return 0;
+ }
+ pCol = pList->a[1].pExpr;
+ if( pCol->op!=TK_COLUMN || !IsVirtual(pCol->pTab) ){
+ return 0;
+ }
+ for(i=0; i<ArraySize(aOp); i++){
+ if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){
+ *peOp2 = aOp[i].eOp2;
+ *ppRight = pList->a[0].pExpr;
+ *ppLeft = pCol;
+ return 1;
+ }
}
+ }else if( pExpr->op==TK_NE || pExpr->op==TK_ISNOT || pExpr->op==TK_NOTNULL ){
+ int res = 0;
+ Expr *pLeft = pExpr->pLeft;
+ Expr *pRight = pExpr->pRight;
+ if( pLeft->op==TK_COLUMN && IsVirtual(pLeft->pTab) ){
+ res++;
+ }
+ if( pRight && pRight->op==TK_COLUMN && IsVirtual(pRight->pTab) ){
+ res++;
+ SWAP(Expr*, pLeft, pRight);
+ }
+ *ppLeft = pLeft;
+ *ppRight = pRight;
+ if( pExpr->op==TK_NE ) *peOp2 = SQLITE_INDEX_CONSTRAINT_NE;
+ if( pExpr->op==TK_ISNOT ) *peOp2 = SQLITE_INDEX_CONSTRAINT_ISNOT;
+ if( pExpr->op==TK_NOTNULL ) *peOp2 = SQLITE_INDEX_CONSTRAINT_ISNOTNULL;
+ return res;
}
return 0;
}
@@ -578,7 +640,7 @@ static void exprAnalyzeOrTerm(
for(j=0, pAndTerm=pAndWC->a; j<pAndWC->nTerm; j++, pAndTerm++){
assert( pAndTerm->pExpr );
if( allowedOp(pAndTerm->pExpr->op)
- || pAndTerm->eOperator==WO_MATCH
+ || pAndTerm->eOperator==WO_AUX
){
b |= sqlite3WhereGetMask(&pWInfo->sMaskSet, pAndTerm->leftCursor);
}
@@ -780,7 +842,6 @@ static void exprAnalyzeOrTerm(
static int termIsEquivalence(Parse *pParse, Expr *pExpr){
char aff1, aff2;
CollSeq *pColl;
- const char *zColl1, *zColl2;
if( !OptimizationEnabled(pParse->db, SQLITE_Transitive) ) return 0;
if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0;
if( ExprHasProperty(pExpr, EP_FromJoin) ) return 0;
@@ -793,11 +854,7 @@ static int termIsEquivalence(Parse *pParse, Expr *pExpr){
}
pColl = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pRight);
if( pColl==0 || sqlite3StrICmp(pColl->zName, "BINARY")==0 ) return 1;
- pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
- zColl1 = pColl ? pColl->zName : 0;
- pColl = sqlite3ExprCollSeq(pParse, pExpr->pRight);
- zColl2 = pColl ? pColl->zName : 0;
- return sqlite3_stricmp(zColl1, zColl2)==0;
+ return sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight);
}
/*
@@ -1160,41 +1217,46 @@ static void exprAnalyze(
#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */
#ifndef SQLITE_OMIT_VIRTUALTABLE
- /* Add a WO_MATCH auxiliary term to the constraint set if the
- ** current expression is of the form: column MATCH expr.
+ /* Add a WO_AUX auxiliary term to the constraint set if the
+ ** current expression is of the form "column OP expr" where OP
+ ** is an operator that gets passed into virtual tables but which is
+ ** not normally optimized for ordinary tables. In other words, OP
+ ** is one of MATCH, LIKE, GLOB, REGEXP, !=, IS, IS NOT, or NOT NULL.
** This information is used by the xBestIndex methods of
** virtual tables. The native query optimizer does not attempt
** to do anything with MATCH functions.
*/
- if( pWC->op==TK_AND && isMatchOfColumn(pExpr, &eOp2) ){
- int idxNew;
+ if( pWC->op==TK_AND ){
Expr *pRight, *pLeft;
- WhereTerm *pNewTerm;
- Bitmask prereqColumn, prereqExpr;
-
- pRight = pExpr->x.pList->a[0].pExpr;
- pLeft = pExpr->x.pList->a[1].pExpr;
- prereqExpr = sqlite3WhereExprUsage(pMaskSet, pRight);
- prereqColumn = sqlite3WhereExprUsage(pMaskSet, pLeft);
- if( (prereqExpr & prereqColumn)==0 ){
- Expr *pNewExpr;
- pNewExpr = sqlite3PExpr(pParse, TK_MATCH,
- 0, sqlite3ExprDup(db, pRight, 0));
- if( ExprHasProperty(pExpr, EP_FromJoin) && pNewExpr ){
- ExprSetProperty(pNewExpr, EP_FromJoin);
+ int res = isAuxiliaryVtabOperator(pExpr, &eOp2, &pLeft, &pRight);
+ while( res-- > 0 ){
+ int idxNew;
+ WhereTerm *pNewTerm;
+ Bitmask prereqColumn, prereqExpr;
+
+ prereqExpr = sqlite3WhereExprUsage(pMaskSet, pRight);
+ prereqColumn = sqlite3WhereExprUsage(pMaskSet, pLeft);
+ if( (prereqExpr & prereqColumn)==0 ){
+ Expr *pNewExpr;
+ pNewExpr = sqlite3PExpr(pParse, TK_MATCH,
+ 0, sqlite3ExprDup(db, pRight, 0));
+ if( ExprHasProperty(pExpr, EP_FromJoin) && pNewExpr ){
+ ExprSetProperty(pNewExpr, EP_FromJoin);
+ }
+ idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
+ testcase( idxNew==0 );
+ pNewTerm = &pWC->a[idxNew];
+ pNewTerm->prereqRight = prereqExpr;
+ pNewTerm->leftCursor = pLeft->iTable;
+ pNewTerm->u.leftColumn = pLeft->iColumn;
+ pNewTerm->eOperator = WO_AUX;
+ pNewTerm->eMatchOp = eOp2;
+ markTermAsChild(pWC, idxNew, idxTerm);
+ pTerm = &pWC->a[idxTerm];
+ pTerm->wtFlags |= TERM_COPIED;
+ pNewTerm->prereqAll = pTerm->prereqAll;
}
- idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
- testcase( idxNew==0 );
- pNewTerm = &pWC->a[idxNew];
- pNewTerm->prereqRight = prereqExpr;
- pNewTerm->leftCursor = pLeft->iTable;
- pNewTerm->u.leftColumn = pLeft->iColumn;
- pNewTerm->eOperator = WO_MATCH;
- pNewTerm->eMatchOp = eOp2;
- markTermAsChild(pWC, idxNew, idxTerm);
- pTerm = &pWC->a[idxTerm];
- pTerm->wtFlags |= TERM_COPIED;
- pNewTerm->prereqAll = pTerm->prereqAll;
+ SWAP(Expr*, pLeft, pRight);
}
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
diff --git a/chromium/third_party/sqlite/src/tool/addopcodes.tcl b/chromium/third_party/sqlite/src/tool/addopcodes.tcl
index 2c204c6b7b0..80ba5c8f5bb 100644
--- a/chromium/third_party/sqlite/src/tool/addopcodes.tcl
+++ b/chromium/third_party/sqlite/src/tool/addopcodes.tcl
@@ -22,14 +22,7 @@ close $in
# ILLEGAL *must* be the last two token codes and they must be in that order.
#
set extras {
- TO_TEXT
- TO_BLOB
- TO_NUMERIC
- TO_INT
- TO_REAL
ISNOT
- END_OF_FILE
- UNCLOSED_STRING
FUNCTION
COLUMN
AGG_FUNCTION
@@ -42,6 +35,8 @@ set extras {
IF_NULL_ROW
ASTERISK
SPAN
+ END_OF_FILE
+ UNCLOSED_STRING
SPACE
ILLEGAL
}
diff --git a/chromium/third_party/sqlite/src/tool/lemon.c b/chromium/third_party/sqlite/src/tool/lemon.c
index fe0fb4c6155..acc5450c993 100644
--- a/chromium/third_party/sqlite/src/tool/lemon.c
+++ b/chromium/third_party/sqlite/src/tool/lemon.c
@@ -2155,7 +2155,8 @@ enum e_state {
WAITING_FOR_FALLBACK_ID,
WAITING_FOR_WILDCARD_ID,
WAITING_FOR_CLASS_ID,
- WAITING_FOR_CLASS_TOKEN
+ WAITING_FOR_CLASS_TOKEN,
+ WAITING_FOR_TOKEN_NAME
};
struct pstate {
char *filename; /* Name of the input file */
@@ -2470,6 +2471,8 @@ to follow the previous rule.");
}else if( strcmp(x,"fallback")==0 ){
psp->fallback = 0;
psp->state = WAITING_FOR_FALLBACK_ID;
+ }else if( strcmp(x,"token")==0 ){
+ psp->state = WAITING_FOR_TOKEN_NAME;
}else if( strcmp(x,"wildcard")==0 ){
psp->state = WAITING_FOR_WILDCARD_ID;
}else if( strcmp(x,"token_class")==0 ){
@@ -2624,6 +2627,26 @@ to follow the previous rule.");
}
}
break;
+ case WAITING_FOR_TOKEN_NAME:
+ /* Tokens do not have to be declared before use. But they can be
+ ** in order to control their assigned integer number. The number for
+ ** each token is assigned when it is first seen. So by including
+ **
+ ** %token ONE TWO THREE
+ **
+ ** early in the grammar file, that assigns small consecutive values
+ ** to each of the tokens ONE TWO and THREE.
+ */
+ if( x[0]=='.' ){
+ psp->state = WAITING_FOR_DECL_OR_RULE;
+ }else if( !ISUPPER(x[0]) ){
+ ErrorMsg(psp->filename, psp->tokenlineno,
+ "%%token argument \"%s\" should be a token", x);
+ psp->errorcnt++;
+ }else{
+ (void)Symbol_new(x);
+ }
+ break;
case WAITING_FOR_WILDCARD_ID:
if( x[0]=='.' ){
psp->state = WAITING_FOR_DECL_OR_RULE;
diff --git a/chromium/third_party/sqlite/src/tool/lempar.c b/chromium/third_party/sqlite/src/tool/lempar.c
index 866d9eecc33..f24684f6fa0 100644
--- a/chromium/third_party/sqlite/src/tool/lempar.c
+++ b/chromium/third_party/sqlite/src/tool/lempar.c
@@ -75,7 +75,8 @@
** YY_MAX_SHIFT Maximum value for shift actions
** YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions
** YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions
-** YY_MIN_REDUCE Maximum value for reduce actions
+** YY_MIN_REDUCE Minimum value for reduce actions
+** YY_MAX_REDUCE Maximum value for reduce actions
** YY_ERROR_ACTION The yy_action[] code for syntax error
** YY_ACCEPT_ACTION The yy_action[] code for accept
** YY_NO_ACTION The yy_action[] code for no-op
diff --git a/chromium/third_party/sqlite/src/tool/mkautoconfamal.sh b/chromium/third_party/sqlite/src/tool/mkautoconfamal.sh
index d7cea6840dc..363c6046d6c 100644
--- a/chromium/third_party/sqlite/src/tool/mkautoconfamal.sh
+++ b/chromium/third_party/sqlite/src/tool/mkautoconfamal.sh
@@ -51,7 +51,7 @@ cp sqlite3.h $TMPSPACE
cp sqlite3ext.h $TMPSPACE
cp $TOP/sqlite3.1 $TMPSPACE
cp $TOP/sqlite3.pc.in $TMPSPACE
-cp $TOP/src/shell.c $TMPSPACE
+cp shell.c $TMPSPACE
cp $TOP/src/sqlite3.rc $TMPSPACE
cp $TOP/tool/Replace.cs $TMPSPACE
diff --git a/chromium/third_party/sqlite/src/tool/mkccode.tcl b/chromium/third_party/sqlite/src/tool/mkccode.tcl
new file mode 100755
index 00000000000..41b09f1e810
--- /dev/null
+++ b/chromium/third_party/sqlite/src/tool/mkccode.tcl
@@ -0,0 +1,93 @@
+#!/usr/bin/tclsh
+#
+# Use this script to build C-language source code for a program that uses
+# tclsqlite.c together with custom TCL scripts and/or C extensions for
+# either SQLite or TCL.
+#
+# Usage example:
+#
+# tclsh mktclsqliteprog.tcl demoapp.c.in >demoapp.c
+#
+# The demoapp.c.in file contains a mixture of C code, TCL script, and
+# processing directives used by mktclsqliteprog.tcl to build the final C-code
+# output file. Most lines of demoapp.c.in are copied straight through into
+# the output. The following control directives are recognized:
+#
+# BEGIN_STRING
+#
+# This marks the beginning of large string literal - usually a TCL
+# script of some kind. Subsequent lines of text through the first
+# line that begins with END_STRING are converted into a C-language
+# string literal.
+#
+# INCLUDE path
+#
+# The path argument is the name of a file to be inserted in place of
+# the INCLUDE line. The path can begin with $ROOT to signify the
+# root of the SQLite source tree, or $HOME to signify the directory
+# that contains the demoapp.c.in input script itself. If the path does
+# not begin with either $ROOT or $HOME, then it is interpreted relative
+# to the current working directory.
+#
+# If the INCLUDE occurs in the middle of BEGIN_STRING...END_STRING
+# then all of the text in the input file is converted into C-language
+# string literals.
+#
+# None of the control directives described above will nest. Only the
+# top-level input file ("demoapp.c.in" in the example) is interpreted.
+# referenced files are copied verbatim.
+#
+if {[llength $argv]!=1} {
+ puts stderr "Usage: $argv0 TEMPLATE >OUTPUT"
+ exit 1
+}
+set infile [lindex $argv 0]
+set ROOT [file normalize [file dir $argv0]/..]
+set HOME [file normalize [file dir $infile]]
+set in [open $infile rb]
+puts [subst {/* DO NOT EDIT
+**
+** This file was generated by \"$argv0 $infile\".
+** To make changes, edit $infile then rerun the generator
+** command.
+*/}]
+set instr 0
+while {1} {
+ set line [gets $in]
+ if {[eof $in]} break
+ if {[regexp {^INCLUDE (.*)} $line all path]} {
+ regsub {^\$ROOT\y} $path $ROOT path
+ regsub {^\$HOME\y} $path $HOME path
+ set in2 [open $path rb]
+ puts "/* INCLUDE $path */"
+ if {$instr} {
+ while {1} {
+ set line [gets $in2]
+ if {[eof $in2]} break
+ set x [string map "\\\\ \\\\\\\\ \\\" \\\\\"" $line]
+ puts "\"$x\\n\""
+ }
+ } else {
+ puts [read $in2]
+ }
+ puts "/* END $path */"
+ close $in2
+ continue
+ }
+ if {[regexp {^BEGIN_STRING} $line]} {
+ set instr 1
+ puts "/* BEGIN_STRING */"
+ continue
+ }
+ if {[regexp {^END_STRING} $line]} {
+ set instr 0
+ puts "/* END_STRING */"
+ continue
+ }
+ if {$instr} {
+ set x [string map "\\\\ \\\\\\\\ \\\" \\\\\"" $line]
+ puts "\"$x\\n\""
+ } else {
+ puts $line
+ }
+}
diff --git a/chromium/third_party/sqlite/src/tool/mkopcodeh.tcl b/chromium/third_party/sqlite/src/tool/mkopcodeh.tcl
index e15c5fa703f..969d5d5fce3 100644
--- a/chromium/third_party/sqlite/src/tool/mkopcodeh.tcl
+++ b/chromium/third_party/sqlite/src/tool/mkopcodeh.tcl
@@ -202,19 +202,17 @@ for {set i 0} {$i<=$max} {incr i} {
set name $def($i)
puts -nonewline [format {#define %-16s %3d} $name $i]
set com {}
+ if {$jump($name)} {
+ lappend com "jump"
+ }
if {[info exists sameas($i)]} {
- set com "same as $sameas($i)"
+ lappend com "same as $sameas($i)"
}
if {[info exists synopsis($name)]} {
- set x $synopsis($name)
- if {$com==""} {
- set com "synopsis: $x"
- } else {
- append com ", synopsis: $x"
- }
+ lappend com "synopsis: $synopsis($name)"
}
- if {$com!=""} {
- puts -nonewline [format " /* %-42s */" $com]
+ if {[llength $com]} {
+ puts -nonewline [format " /* %-42s */" [join $com {, }]]
}
puts ""
}
diff --git a/chromium/third_party/sqlite/src/tool/mkshellc.tcl b/chromium/third_party/sqlite/src/tool/mkshellc.tcl
index 66f09e8beea..6974adeb3ca 100644
--- a/chromium/third_party/sqlite/src/tool/mkshellc.tcl
+++ b/chromium/third_party/sqlite/src/tool/mkshellc.tcl
@@ -1,11 +1,16 @@
#!/usr/bin/tclsh
#
-# Run this script to generate the "src/shell.c" source file from
+# Run this script to generate the "shell.c" source file from
# constituent parts.
#
+# No arguments are required. This script determines the location
+# of its input files relative to the location of the script itself.
+# This script should be tool/mkshellc.tcl. If the directory holding
+# the script is $DIR, then the component parts are located in $DIR/../src
+# and $DIR/../ext/misc.
+#
set topdir [file dir [file dir [file normal $argv0]]]
-puts "Overwriting $topdir/src/shell.c with new shell source code..."
-set out [open $topdir/src/shell.c wb]
+set out stdout
puts $out {/* DO NOT EDIT!
** This file is automatically generated by the script in the canonical
** SQLite source tree at tool/mkshellc.tcl. That script combines source
@@ -25,8 +30,9 @@ puts $out {/* DO NOT EDIT!
** by "src/shell.c.in", then rerun the tool/mkshellc.tcl script.
*/}
set in [open $topdir/src/shell.c.in rb]
-while {![eof $in]} {
+while {1} {
set lx [gets $in]
+ if {[eof $in]} break;
if {[regexp {^INCLUDE } $lx]} {
set cfile [lindex $lx 1]
puts $out "/************************* Begin $cfile ******************/"
@@ -34,6 +40,7 @@ while {![eof $in]} {
while {![eof $in2]} {
set lx [gets $in2]
if {[regexp {^#include "sqlite} $lx]} continue
+ set lx [string map [list __declspec(dllexport) {}] $lx]
puts $out $lx
}
close $in2
diff --git a/chromium/third_party/sqlite/src/tool/mksourceid.c b/chromium/third_party/sqlite/src/tool/mksourceid.c
new file mode 100644
index 00000000000..3f4c2133f22
--- /dev/null
+++ b/chromium/third_party/sqlite/src/tool/mksourceid.c
@@ -0,0 +1,853 @@
+/*
+** Run this program with a single argument which is the name of the
+** Fossil "manifest" file for a project, and this program will emit on
+** standard output the "source id" for for the program.
+**
+** (1) The "source id" is the date of check-in together with the
+** SHA3 hash of the manifest file.
+**
+** (2) All individual file hashes in the manifest are verified. If any
+** source file has changed, the SHA3 hash ends with "modified".
+**
+*/
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <ctype.h>
+
+/* Portable 64-bit unsigned integers */
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+ typedef unsigned __int64 u64;
+#else
+ typedef unsigned long long int u64;
+#endif
+
+
+/*
+** Macros to determine whether the machine is big or little endian,
+** and whether or not that determination is run-time or compile-time.
+**
+** For best performance, an attempt is made to guess at the byte-order
+** using C-preprocessor macros. If that is unsuccessful, or if
+** -DBYTEORDER=0 is set, then byte-order is determined
+** at run-time.
+*/
+#ifndef BYTEORDER
+# if defined(i386) || defined(__i386__) || defined(_M_IX86) || \
+ defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
+ defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \
+ defined(__arm__)
+# define BYTEORDER 1234
+# elif defined(sparc) || defined(__ppc__)
+# define BYTEORDER 4321
+# else
+# define BYTEORDER 0
+# endif
+#endif
+
+
+
+/*
+** State structure for a SHA3 hash in progress
+*/
+typedef struct SHA3Context SHA3Context;
+struct SHA3Context {
+ union {
+ u64 s[25]; /* Keccak state. 5x5 lines of 64 bits each */
+ unsigned char x[1600]; /* ... or 1600 bytes */
+ } u;
+ unsigned nRate; /* Bytes of input accepted per Keccak iteration */
+ unsigned nLoaded; /* Input bytes loaded into u.x[] so far this cycle */
+ unsigned ixMask; /* Insert next input into u.x[nLoaded^ixMask]. */
+};
+
+/*
+** A single step of the Keccak mixing function for a 1600-bit state
+*/
+static void KeccakF1600Step(SHA3Context *p){
+ int i;
+ u64 B0, B1, B2, B3, B4;
+ u64 C0, C1, C2, C3, C4;
+ u64 D0, D1, D2, D3, D4;
+ static const u64 RC[] = {
+ 0x0000000000000001ULL, 0x0000000000008082ULL,
+ 0x800000000000808aULL, 0x8000000080008000ULL,
+ 0x000000000000808bULL, 0x0000000080000001ULL,
+ 0x8000000080008081ULL, 0x8000000000008009ULL,
+ 0x000000000000008aULL, 0x0000000000000088ULL,
+ 0x0000000080008009ULL, 0x000000008000000aULL,
+ 0x000000008000808bULL, 0x800000000000008bULL,
+ 0x8000000000008089ULL, 0x8000000000008003ULL,
+ 0x8000000000008002ULL, 0x8000000000000080ULL,
+ 0x000000000000800aULL, 0x800000008000000aULL,
+ 0x8000000080008081ULL, 0x8000000000008080ULL,
+ 0x0000000080000001ULL, 0x8000000080008008ULL
+ };
+# define A00 (p->u.s[0])
+# define A01 (p->u.s[1])
+# define A02 (p->u.s[2])
+# define A03 (p->u.s[3])
+# define A04 (p->u.s[4])
+# define A10 (p->u.s[5])
+# define A11 (p->u.s[6])
+# define A12 (p->u.s[7])
+# define A13 (p->u.s[8])
+# define A14 (p->u.s[9])
+# define A20 (p->u.s[10])
+# define A21 (p->u.s[11])
+# define A22 (p->u.s[12])
+# define A23 (p->u.s[13])
+# define A24 (p->u.s[14])
+# define A30 (p->u.s[15])
+# define A31 (p->u.s[16])
+# define A32 (p->u.s[17])
+# define A33 (p->u.s[18])
+# define A34 (p->u.s[19])
+# define A40 (p->u.s[20])
+# define A41 (p->u.s[21])
+# define A42 (p->u.s[22])
+# define A43 (p->u.s[23])
+# define A44 (p->u.s[24])
+# define ROL64(a,x) ((a<<x)|(a>>(64-x)))
+
+ for(i=0; i<24; i+=4){
+ C0 = A00^A10^A20^A30^A40;
+ C1 = A01^A11^A21^A31^A41;
+ C2 = A02^A12^A22^A32^A42;
+ C3 = A03^A13^A23^A33^A43;
+ C4 = A04^A14^A24^A34^A44;
+ D0 = C4^ROL64(C1, 1);
+ D1 = C0^ROL64(C2, 1);
+ D2 = C1^ROL64(C3, 1);
+ D3 = C2^ROL64(C4, 1);
+ D4 = C3^ROL64(C0, 1);
+
+ B0 = (A00^D0);
+ B1 = ROL64((A11^D1), 44);
+ B2 = ROL64((A22^D2), 43);
+ B3 = ROL64((A33^D3), 21);
+ B4 = ROL64((A44^D4), 14);
+ A00 = B0 ^((~B1)& B2 );
+ A00 ^= RC[i];
+ A11 = B1 ^((~B2)& B3 );
+ A22 = B2 ^((~B3)& B4 );
+ A33 = B3 ^((~B4)& B0 );
+ A44 = B4 ^((~B0)& B1 );
+
+ B2 = ROL64((A20^D0), 3);
+ B3 = ROL64((A31^D1), 45);
+ B4 = ROL64((A42^D2), 61);
+ B0 = ROL64((A03^D3), 28);
+ B1 = ROL64((A14^D4), 20);
+ A20 = B0 ^((~B1)& B2 );
+ A31 = B1 ^((~B2)& B3 );
+ A42 = B2 ^((~B3)& B4 );
+ A03 = B3 ^((~B4)& B0 );
+ A14 = B4 ^((~B0)& B1 );
+
+ B4 = ROL64((A40^D0), 18);
+ B0 = ROL64((A01^D1), 1);
+ B1 = ROL64((A12^D2), 6);
+ B2 = ROL64((A23^D3), 25);
+ B3 = ROL64((A34^D4), 8);
+ A40 = B0 ^((~B1)& B2 );
+ A01 = B1 ^((~B2)& B3 );
+ A12 = B2 ^((~B3)& B4 );
+ A23 = B3 ^((~B4)& B0 );
+ A34 = B4 ^((~B0)& B1 );
+
+ B1 = ROL64((A10^D0), 36);
+ B2 = ROL64((A21^D1), 10);
+ B3 = ROL64((A32^D2), 15);
+ B4 = ROL64((A43^D3), 56);
+ B0 = ROL64((A04^D4), 27);
+ A10 = B0 ^((~B1)& B2 );
+ A21 = B1 ^((~B2)& B3 );
+ A32 = B2 ^((~B3)& B4 );
+ A43 = B3 ^((~B4)& B0 );
+ A04 = B4 ^((~B0)& B1 );
+
+ B3 = ROL64((A30^D0), 41);
+ B4 = ROL64((A41^D1), 2);
+ B0 = ROL64((A02^D2), 62);
+ B1 = ROL64((A13^D3), 55);
+ B2 = ROL64((A24^D4), 39);
+ A30 = B0 ^((~B1)& B2 );
+ A41 = B1 ^((~B2)& B3 );
+ A02 = B2 ^((~B3)& B4 );
+ A13 = B3 ^((~B4)& B0 );
+ A24 = B4 ^((~B0)& B1 );
+
+ C0 = A00^A20^A40^A10^A30;
+ C1 = A11^A31^A01^A21^A41;
+ C2 = A22^A42^A12^A32^A02;
+ C3 = A33^A03^A23^A43^A13;
+ C4 = A44^A14^A34^A04^A24;
+ D0 = C4^ROL64(C1, 1);
+ D1 = C0^ROL64(C2, 1);
+ D2 = C1^ROL64(C3, 1);
+ D3 = C2^ROL64(C4, 1);
+ D4 = C3^ROL64(C0, 1);
+
+ B0 = (A00^D0);
+ B1 = ROL64((A31^D1), 44);
+ B2 = ROL64((A12^D2), 43);
+ B3 = ROL64((A43^D3), 21);
+ B4 = ROL64((A24^D4), 14);
+ A00 = B0 ^((~B1)& B2 );
+ A00 ^= RC[i+1];
+ A31 = B1 ^((~B2)& B3 );
+ A12 = B2 ^((~B3)& B4 );
+ A43 = B3 ^((~B4)& B0 );
+ A24 = B4 ^((~B0)& B1 );
+
+ B2 = ROL64((A40^D0), 3);
+ B3 = ROL64((A21^D1), 45);
+ B4 = ROL64((A02^D2), 61);
+ B0 = ROL64((A33^D3), 28);
+ B1 = ROL64((A14^D4), 20);
+ A40 = B0 ^((~B1)& B2 );
+ A21 = B1 ^((~B2)& B3 );
+ A02 = B2 ^((~B3)& B4 );
+ A33 = B3 ^((~B4)& B0 );
+ A14 = B4 ^((~B0)& B1 );
+
+ B4 = ROL64((A30^D0), 18);
+ B0 = ROL64((A11^D1), 1);
+ B1 = ROL64((A42^D2), 6);
+ B2 = ROL64((A23^D3), 25);
+ B3 = ROL64((A04^D4), 8);
+ A30 = B0 ^((~B1)& B2 );
+ A11 = B1 ^((~B2)& B3 );
+ A42 = B2 ^((~B3)& B4 );
+ A23 = B3 ^((~B4)& B0 );
+ A04 = B4 ^((~B0)& B1 );
+
+ B1 = ROL64((A20^D0), 36);
+ B2 = ROL64((A01^D1), 10);
+ B3 = ROL64((A32^D2), 15);
+ B4 = ROL64((A13^D3), 56);
+ B0 = ROL64((A44^D4), 27);
+ A20 = B0 ^((~B1)& B2 );
+ A01 = B1 ^((~B2)& B3 );
+ A32 = B2 ^((~B3)& B4 );
+ A13 = B3 ^((~B4)& B0 );
+ A44 = B4 ^((~B0)& B1 );
+
+ B3 = ROL64((A10^D0), 41);
+ B4 = ROL64((A41^D1), 2);
+ B0 = ROL64((A22^D2), 62);
+ B1 = ROL64((A03^D3), 55);
+ B2 = ROL64((A34^D4), 39);
+ A10 = B0 ^((~B1)& B2 );
+ A41 = B1 ^((~B2)& B3 );
+ A22 = B2 ^((~B3)& B4 );
+ A03 = B3 ^((~B4)& B0 );
+ A34 = B4 ^((~B0)& B1 );
+
+ C0 = A00^A40^A30^A20^A10;
+ C1 = A31^A21^A11^A01^A41;
+ C2 = A12^A02^A42^A32^A22;
+ C3 = A43^A33^A23^A13^A03;
+ C4 = A24^A14^A04^A44^A34;
+ D0 = C4^ROL64(C1, 1);
+ D1 = C0^ROL64(C2, 1);
+ D2 = C1^ROL64(C3, 1);
+ D3 = C2^ROL64(C4, 1);
+ D4 = C3^ROL64(C0, 1);
+
+ B0 = (A00^D0);
+ B1 = ROL64((A21^D1), 44);
+ B2 = ROL64((A42^D2), 43);
+ B3 = ROL64((A13^D3), 21);
+ B4 = ROL64((A34^D4), 14);
+ A00 = B0 ^((~B1)& B2 );
+ A00 ^= RC[i+2];
+ A21 = B1 ^((~B2)& B3 );
+ A42 = B2 ^((~B3)& B4 );
+ A13 = B3 ^((~B4)& B0 );
+ A34 = B4 ^((~B0)& B1 );
+
+ B2 = ROL64((A30^D0), 3);
+ B3 = ROL64((A01^D1), 45);
+ B4 = ROL64((A22^D2), 61);
+ B0 = ROL64((A43^D3), 28);
+ B1 = ROL64((A14^D4), 20);
+ A30 = B0 ^((~B1)& B2 );
+ A01 = B1 ^((~B2)& B3 );
+ A22 = B2 ^((~B3)& B4 );
+ A43 = B3 ^((~B4)& B0 );
+ A14 = B4 ^((~B0)& B1 );
+
+ B4 = ROL64((A10^D0), 18);
+ B0 = ROL64((A31^D1), 1);
+ B1 = ROL64((A02^D2), 6);
+ B2 = ROL64((A23^D3), 25);
+ B3 = ROL64((A44^D4), 8);
+ A10 = B0 ^((~B1)& B2 );
+ A31 = B1 ^((~B2)& B3 );
+ A02 = B2 ^((~B3)& B4 );
+ A23 = B3 ^((~B4)& B0 );
+ A44 = B4 ^((~B0)& B1 );
+
+ B1 = ROL64((A40^D0), 36);
+ B2 = ROL64((A11^D1), 10);
+ B3 = ROL64((A32^D2), 15);
+ B4 = ROL64((A03^D3), 56);
+ B0 = ROL64((A24^D4), 27);
+ A40 = B0 ^((~B1)& B2 );
+ A11 = B1 ^((~B2)& B3 );
+ A32 = B2 ^((~B3)& B4 );
+ A03 = B3 ^((~B4)& B0 );
+ A24 = B4 ^((~B0)& B1 );
+
+ B3 = ROL64((A20^D0), 41);
+ B4 = ROL64((A41^D1), 2);
+ B0 = ROL64((A12^D2), 62);
+ B1 = ROL64((A33^D3), 55);
+ B2 = ROL64((A04^D4), 39);
+ A20 = B0 ^((~B1)& B2 );
+ A41 = B1 ^((~B2)& B3 );
+ A12 = B2 ^((~B3)& B4 );
+ A33 = B3 ^((~B4)& B0 );
+ A04 = B4 ^((~B0)& B1 );
+
+ C0 = A00^A30^A10^A40^A20;
+ C1 = A21^A01^A31^A11^A41;
+ C2 = A42^A22^A02^A32^A12;
+ C3 = A13^A43^A23^A03^A33;
+ C4 = A34^A14^A44^A24^A04;
+ D0 = C4^ROL64(C1, 1);
+ D1 = C0^ROL64(C2, 1);
+ D2 = C1^ROL64(C3, 1);
+ D3 = C2^ROL64(C4, 1);
+ D4 = C3^ROL64(C0, 1);
+
+ B0 = (A00^D0);
+ B1 = ROL64((A01^D1), 44);
+ B2 = ROL64((A02^D2), 43);
+ B3 = ROL64((A03^D3), 21);
+ B4 = ROL64((A04^D4), 14);
+ A00 = B0 ^((~B1)& B2 );
+ A00 ^= RC[i+3];
+ A01 = B1 ^((~B2)& B3 );
+ A02 = B2 ^((~B3)& B4 );
+ A03 = B3 ^((~B4)& B0 );
+ A04 = B4 ^((~B0)& B1 );
+
+ B2 = ROL64((A10^D0), 3);
+ B3 = ROL64((A11^D1), 45);
+ B4 = ROL64((A12^D2), 61);
+ B0 = ROL64((A13^D3), 28);
+ B1 = ROL64((A14^D4), 20);
+ A10 = B0 ^((~B1)& B2 );
+ A11 = B1 ^((~B2)& B3 );
+ A12 = B2 ^((~B3)& B4 );
+ A13 = B3 ^((~B4)& B0 );
+ A14 = B4 ^((~B0)& B1 );
+
+ B4 = ROL64((A20^D0), 18);
+ B0 = ROL64((A21^D1), 1);
+ B1 = ROL64((A22^D2), 6);
+ B2 = ROL64((A23^D3), 25);
+ B3 = ROL64((A24^D4), 8);
+ A20 = B0 ^((~B1)& B2 );
+ A21 = B1 ^((~B2)& B3 );
+ A22 = B2 ^((~B3)& B4 );
+ A23 = B3 ^((~B4)& B0 );
+ A24 = B4 ^((~B0)& B1 );
+
+ B1 = ROL64((A30^D0), 36);
+ B2 = ROL64((A31^D1), 10);
+ B3 = ROL64((A32^D2), 15);
+ B4 = ROL64((A33^D3), 56);
+ B0 = ROL64((A34^D4), 27);
+ A30 = B0 ^((~B1)& B2 );
+ A31 = B1 ^((~B2)& B3 );
+ A32 = B2 ^((~B3)& B4 );
+ A33 = B3 ^((~B4)& B0 );
+ A34 = B4 ^((~B0)& B1 );
+
+ B3 = ROL64((A40^D0), 41);
+ B4 = ROL64((A41^D1), 2);
+ B0 = ROL64((A42^D2), 62);
+ B1 = ROL64((A43^D3), 55);
+ B2 = ROL64((A44^D4), 39);
+ A40 = B0 ^((~B1)& B2 );
+ A41 = B1 ^((~B2)& B3 );
+ A42 = B2 ^((~B3)& B4 );
+ A43 = B3 ^((~B4)& B0 );
+ A44 = B4 ^((~B0)& B1 );
+ }
+}
+
+/*
+** Initialize a new hash. iSize determines the size of the hash
+** in bits and should be one of 224, 256, 384, or 512. Or iSize
+** can be zero to use the default hash size of 256 bits.
+*/
+static void SHA3Init(SHA3Context *p, int iSize){
+ memset(p, 0, sizeof(*p));
+ if( iSize>=128 && iSize<=512 ){
+ p->nRate = (1600 - ((iSize + 31)&~31)*2)/8;
+ }else{
+ p->nRate = (1600 - 2*256)/8;
+ }
+#if BYTEORDER==1234
+ /* Known to be little-endian at compile-time. No-op */
+#elif BYTEORDER==4321
+ p->ixMask = 7; /* Big-endian */
+#else
+ {
+ static unsigned int one = 1;
+ if( 1==*(unsigned char*)&one ){
+ /* Little endian. No byte swapping. */
+ p->ixMask = 0;
+ }else{
+ /* Big endian. Byte swap. */
+ p->ixMask = 7;
+ }
+ }
+#endif
+}
+
+/*
+** Make consecutive calls to the SHA3Update function to add new content
+** to the hash
+*/
+static void SHA3Update(
+ SHA3Context *p,
+ const unsigned char *aData,
+ unsigned int nData
+){
+ unsigned int i = 0;
+#if BYTEORDER==1234
+ if( (p->nLoaded % 8)==0 && ((aData - (const unsigned char*)0)&7)==0 ){
+ for(; i+7<nData; i+=8){
+ p->u.s[p->nLoaded/8] ^= *(u64*)&aData[i];
+ p->nLoaded += 8;
+ if( p->nLoaded>=p->nRate ){
+ KeccakF1600Step(p);
+ p->nLoaded = 0;
+ }
+ }
+ }
+#endif
+ for(; i<nData; i++){
+#if BYTEORDER==1234
+ p->u.x[p->nLoaded] ^= aData[i];
+#elif BYTEORDER==4321
+ p->u.x[p->nLoaded^0x07] ^= aData[i];
+#else
+ p->u.x[p->nLoaded^p->ixMask] ^= aData[i];
+#endif
+ p->nLoaded++;
+ if( p->nLoaded==p->nRate ){
+ KeccakF1600Step(p);
+ p->nLoaded = 0;
+ }
+ }
+}
+
+/*
+** After all content has been added, invoke SHA3Final() to compute
+** the final hash. The function returns a pointer to the binary
+** hash value.
+*/
+static unsigned char *SHA3Final(SHA3Context *p){
+ unsigned int i;
+ if( p->nLoaded==p->nRate-1 ){
+ const unsigned char c1 = 0x86;
+ SHA3Update(p, &c1, 1);
+ }else{
+ const unsigned char c2 = 0x06;
+ const unsigned char c3 = 0x80;
+ SHA3Update(p, &c2, 1);
+ p->nLoaded = p->nRate - 1;
+ SHA3Update(p, &c3, 1);
+ }
+ for(i=0; i<p->nRate; i++){
+ p->u.x[i+p->nRate] = p->u.x[i^p->ixMask];
+ }
+ return &p->u.x[p->nRate];
+}
+
+/*
+** Convert a digest into base-16. digest should be declared as
+** "unsigned char digest[20]" in the calling function. The SHA3
+** digest is stored in the first 20 bytes. zBuf should
+** be "char zBuf[41]".
+*/
+static void DigestToBase16(unsigned char *digest, char *zBuf, int nByte){
+ static const char zEncode[] = "0123456789abcdef";
+ int ix;
+
+ for(ix=0; ix<nByte; ix++){
+ *zBuf++ = zEncode[(*digest>>4)&0xf];
+ *zBuf++ = zEncode[*digest++ & 0xf];
+ }
+ *zBuf = '\0';
+}
+
+
+/*
+** Compute the SHA3 checksum of a file on disk. Store the resulting
+** checksum in the blob pCksum. pCksum is assumed to be initialized.
+**
+** Return the number of errors.
+*/
+static int sha3sum_file(const char *zFilename, int iSize, char *pCksum){
+ FILE *in;
+ SHA3Context ctx;
+ char zBuf[10240];
+
+ in = fopen(zFilename,"rb");
+ if( in==0 ){
+ return 1;
+ }
+ SHA3Init(&ctx, iSize);
+ for(;;){
+ int n = (int)fread(zBuf, 1, sizeof(zBuf), in);
+ if( n<=0 ) break;
+ SHA3Update(&ctx, (unsigned char*)zBuf, (unsigned)n);
+ }
+ fclose(in);
+ DigestToBase16(SHA3Final(&ctx), pCksum, iSize/8);
+ return 0;
+}
+
+/*
+** The SHA1 implementation below is adapted from:
+**
+** $NetBSD: sha1.c,v 1.6 2009/11/06 20:31:18 joerg Exp $
+** $OpenBSD: sha1.c,v 1.9 1997/07/23 21:12:32 kstailey Exp $
+**
+** SHA-1 in C
+** By Steve Reid <steve@edmweb.com>
+** 100% Public Domain
+*/
+typedef struct SHA1Context SHA1Context;
+struct SHA1Context {
+ unsigned int state[5];
+ unsigned int count[2];
+ unsigned char buffer[64];
+};
+
+/*
+ * blk0() and blk() perform the initial expand.
+ * I got the idea of expanding during the round function from SSLeay
+ *
+ * blk0le() for little-endian and blk0be() for big-endian.
+ */
+#if __GNUC__ && (defined(__i386__) || defined(__x86_64__))
+/*
+ * GCC by itself only generates left rotates. Use right rotates if
+ * possible to be kinder to dinky implementations with iterative rotate
+ * instructions.
+ */
+#define SHA_ROT(op, x, k) \
+ ({ unsigned int y; asm(op " %1,%0" : "=r" (y) : "I" (k), "0" (x)); y; })
+#define rol(x,k) SHA_ROT("roll", x, k)
+#define ror(x,k) SHA_ROT("rorl", x, k)
+
+#else
+/* Generic C equivalent */
+#define SHA_ROT(x,l,r) ((x) << (l) | (x) >> (r))
+#define rol(x,k) SHA_ROT(x,k,32-(k))
+#define ror(x,k) SHA_ROT(x,32-(k),k)
+#endif
+
+
+
+
+
+#define blk0le(i) (block[i] = (ror(block[i],8)&0xFF00FF00) \
+ |(rol(block[i],8)&0x00FF00FF))
+#define blk0be(i) block[i]
+#define blk(i) (block[i&15] = rol(block[(i+13)&15]^block[(i+8)&15] \
+ ^block[(i+2)&15]^block[i&15],1))
+
+/*
+ * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1
+ *
+ * Rl0() for little-endian and Rb0() for big-endian. Endianness is
+ * determined at run-time.
+ */
+#define Rl0(v,w,x,y,z,i) \
+ z+=((w&(x^y))^y)+blk0le(i)+0x5A827999+rol(v,5);w=ror(w,2);
+#define Rb0(v,w,x,y,z,i) \
+ z+=((w&(x^y))^y)+blk0be(i)+0x5A827999+rol(v,5);w=ror(w,2);
+#define R1(v,w,x,y,z,i) \
+ z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=ror(w,2);
+#define R2(v,w,x,y,z,i) \
+ z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=ror(w,2);
+#define R3(v,w,x,y,z,i) \
+ z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=ror(w,2);
+#define R4(v,w,x,y,z,i) \
+ z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=ror(w,2);
+
+/*
+ * Hash a single 512-bit block. This is the core of the algorithm.
+ */
+#define a qq[0]
+#define b qq[1]
+#define c qq[2]
+#define d qq[3]
+#define e qq[4]
+
+static void SHA1Transform(
+ unsigned int state[5],
+ const unsigned char buffer[64]
+){
+ unsigned int qq[5]; /* a, b, c, d, e; */
+ static int one = 1;
+ unsigned int block[16];
+ memcpy(block, buffer, 64);
+ memcpy(qq,state,5*sizeof(unsigned int));
+
+ /* Copy context->state[] to working vars */
+ /*
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+ e = state[4];
+ */
+
+ /* 4 rounds of 20 operations each. Loop unrolled. */
+ if( 1 == *(unsigned char*)&one ){
+ Rl0(a,b,c,d,e, 0); Rl0(e,a,b,c,d, 1); Rl0(d,e,a,b,c, 2); Rl0(c,d,e,a,b, 3);
+ Rl0(b,c,d,e,a, 4); Rl0(a,b,c,d,e, 5); Rl0(e,a,b,c,d, 6); Rl0(d,e,a,b,c, 7);
+ Rl0(c,d,e,a,b, 8); Rl0(b,c,d,e,a, 9); Rl0(a,b,c,d,e,10); Rl0(e,a,b,c,d,11);
+ Rl0(d,e,a,b,c,12); Rl0(c,d,e,a,b,13); Rl0(b,c,d,e,a,14); Rl0(a,b,c,d,e,15);
+ }else{
+ Rb0(a,b,c,d,e, 0); Rb0(e,a,b,c,d, 1); Rb0(d,e,a,b,c, 2); Rb0(c,d,e,a,b, 3);
+ Rb0(b,c,d,e,a, 4); Rb0(a,b,c,d,e, 5); Rb0(e,a,b,c,d, 6); Rb0(d,e,a,b,c, 7);
+ Rb0(c,d,e,a,b, 8); Rb0(b,c,d,e,a, 9); Rb0(a,b,c,d,e,10); Rb0(e,a,b,c,d,11);
+ Rb0(d,e,a,b,c,12); Rb0(c,d,e,a,b,13); Rb0(b,c,d,e,a,14); Rb0(a,b,c,d,e,15);
+ }
+ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+
+ /* Add the working vars back into context.state[] */
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+ state[4] += e;
+}
+
+
+/*
+ * SHA1Init - Initialize new context
+ */
+static void SHA1Init(SHA1Context *context){
+ /* SHA1 initialization constants */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xEFCDAB89;
+ context->state[2] = 0x98BADCFE;
+ context->state[3] = 0x10325476;
+ context->state[4] = 0xC3D2E1F0;
+ context->count[0] = context->count[1] = 0;
+}
+
+
+/*
+ * Run your data through this.
+ */
+static void SHA1Update(
+ SHA1Context *context,
+ const unsigned char *data,
+ unsigned int len
+){
+ unsigned int i, j;
+
+ j = context->count[0];
+ if ((context->count[0] += len << 3) < j)
+ context->count[1] += (len>>29)+1;
+ j = (j >> 3) & 63;
+ if ((j + len) > 63) {
+ (void)memcpy(&context->buffer[j], data, (i = 64-j));
+ SHA1Transform(context->state, context->buffer);
+ for ( ; i + 63 < len; i += 64)
+ SHA1Transform(context->state, &data[i]);
+ j = 0;
+ } else {
+ i = 0;
+ }
+ (void)memcpy(&context->buffer[j], &data[i], len - i);
+}
+
+
+/*
+ * Add padding and return the message digest.
+ */
+static void SHA1Final(unsigned char *digest, SHA1Context *context){
+ unsigned int i;
+ unsigned char finalcount[8];
+
+ for (i = 0; i < 8; i++) {
+ finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
+ >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
+ }
+ SHA1Update(context, (const unsigned char *)"\200", 1);
+ while ((context->count[0] & 504) != 448)
+ SHA1Update(context, (const unsigned char *)"\0", 1);
+ SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
+
+ if (digest) {
+ for (i = 0; i < 20; i++)
+ digest[i] = (unsigned char)
+ ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
+ }
+}
+
+
+/*
+** Compute the SHA1 checksum of a file on disk. Store the resulting
+** checksum in the blob pCksum. pCksum is assumed to be initialized.
+**
+** Return the number of errors.
+*/
+static int sha1sum_file(const char *zFilename, char *pCksum){
+ FILE *in;
+ SHA1Context ctx;
+ unsigned char zResult[20];
+ char zBuf[10240];
+
+ in = fopen(zFilename,"rb");
+ if( in==0 ){
+ return 1;
+ }
+ SHA1Init(&ctx);
+ for(;;){
+ int n = (int)fread(zBuf, 1, sizeof(zBuf), in);
+ if( n<=0 ) break;
+ SHA1Update(&ctx, (unsigned char*)zBuf, (unsigned)n);
+ }
+ fclose(in);
+ SHA1Final(zResult, &ctx);
+ DigestToBase16(zResult, pCksum, 20);
+ return 0;
+}
+
+/*
+** Print a usage comment and quit.
+*/
+static void usage(const char *argv0){
+ fprintf(stderr,
+ "Usage: %s manifest\n"
+ "Options:\n"
+ " -v Diagnostic output\n"
+ , argv0);
+ exit(1);
+}
+
+/*
+** Find the first whitespace character in a string. Set that whitespace
+** to a \000 terminator and return a pointer to the next character.
+*/
+static char *nextToken(char *z){
+ while( *z && !isspace(*z) ) z++;
+ if( *z==0 ) return z;
+ *z = 0;
+ return &z[1];
+}
+
+
+int main(int argc, char **argv){
+ const char *zManifest = 0;
+ int i;
+ int bVerbose = 0;
+ FILE *in;
+ int allValid = 1;
+ int rc;
+ SHA3Context ctx;
+ char zDate[50];
+ char zHash[100];
+ char zLine[20000];
+
+ for(i=1; i<argc; i++){
+ const char *z = argv[i];
+ if( z[0]=='-' ){
+ if( z[1]=='-' ) z++;
+ if( strcmp(z, "-v")==0 ){
+ bVerbose = 1;
+ }else
+ {
+ fprintf(stderr, "unknown option \"%s\"", argv[i]);
+ exit(1);
+ }
+ }else if( zManifest!=0 ){
+ usage(argv[0]);
+ }else{
+ zManifest = z;
+ }
+ }
+ if( zManifest==0 ) usage(argv[0]);
+ zDate[0] = 0;
+ in = fopen(zManifest, "rb");
+ if( in==0 ){
+ fprintf(stderr, "cannot open \"%s\" for reading\n", zManifest);
+ exit(1);
+ }
+ SHA3Init(&ctx, 256);
+ while( fgets(zLine, sizeof(zLine), in) ){
+ if( strncmp(zLine,"# Remove this line", 18)!=0 ){
+ SHA3Update(&ctx, (unsigned char*)zLine, (unsigned)strlen(zLine));
+ }
+ if( strncmp(zLine, "D 20", 4)==0 ){
+ memcpy(zDate, &zLine[2], 10);
+ zDate[10] = ' ';
+ memcpy(&zDate[11], &zLine[13], 8);
+ zDate[19] = 0;
+ continue;
+ }
+ if( strncmp(zLine, "F ", 2)==0 ){
+ char *zFilename = &zLine[2];
+ char *zMHash = nextToken(zFilename);
+ nextToken(zMHash);
+ if( strlen(zMHash)==40 ){
+ rc = sha1sum_file(zFilename, zHash);
+ }else{
+ rc = sha3sum_file(zFilename, 256, zHash);
+ }
+ if( rc ){
+ allValid = 0;
+ if( bVerbose ){
+ printf("hash failed: %s\n", zFilename);
+ }
+ }else if( strcmp(zHash, zMHash)!=0 ){
+ allValid = 0;
+ if( bVerbose ){
+ printf("wrong hash: %s\n", zFilename);
+ printf("... expected: %s\n", zMHash);
+ printf("... got: %s\n", zHash);
+ }
+ }
+ }
+ }
+ fclose(in);
+ DigestToBase16(SHA3Final(&ctx), zHash, 256/8);
+ if( !allValid ){
+ printf("%s %.60salt1\n", zDate, zHash);
+ }else{
+ printf("%s %s\n", zDate, zHash);
+ }
+ return 0;
+}
diff --git a/chromium/third_party/sqlite/src/tool/mksqlite3c.tcl b/chromium/third_party/sqlite/src/tool/mksqlite3c.tcl
index 596787d4fd0..8ea3e81c91c 100644
--- a/chromium/third_party/sqlite/src/tool/mksqlite3c.tcl
+++ b/chromium/third_party/sqlite/src/tool/mksqlite3c.tcl
@@ -224,6 +224,8 @@ proc copy_file {filename} {
if {![info exists varonly_hdr($tail)]
&& [regexp $declpattern $line all rettype funcname rest]} {
regsub {^SQLITE_API } $line {} line
+ regsub {^SQLITE_API } $rettype {} rettype
+
# Add the SQLITE_PRIVATE or SQLITE_API keyword before functions.
# so that linkage can be modified at compile-time.
if {[regexp {^sqlite3[a-z]*_} $funcname]} {
@@ -240,7 +242,13 @@ proc copy_file {filename} {
}
}
append line $funcname $rest
- puts $out $line
+ if {$funcname=="sqlite3_sourceid" && !$linemacros} {
+ # The sqlite3_sourceid() routine is synthesized at the end of
+ # the amalgamation
+ puts $out "/* $line */"
+ } else {
+ puts $out $line
+ }
} else {
puts $out "SQLITE_PRIVATE $line"
}
@@ -386,6 +394,7 @@ foreach file {
fts3_icu.c
sqlite3rbu.c
dbstat.c
+ dbpage.c
sqlite3session.c
json1.c
fts5.c
@@ -394,4 +403,34 @@ foreach file {
copy_file tsrc/$file
}
+# Synthesize an alternative sqlite3_sourceid() implementation that
+# that tries to detects changes in the amalgamation source text
+# and modify returns a modified source-id if changes are detected.
+#
+# The only detection mechanism we have is the __LINE__ macro. So only
+# edits that changes the number of lines of source code are detected.
+#
+if {!$linemacros} {
+ flush $out
+ set in2 [open sqlite3.c]
+ set cnt 0
+ set oldsrcid {}
+ while {![eof $in2]} {
+ incr cnt
+ gets $in2 line
+ if {[regexp {^#define SQLITE_SOURCE_ID } $line]} {set oldsrcid $line}
+ }
+ close $in2
+ regsub {[0-9a-flt]{4}"} $oldsrcid {alt2"} oldsrcid
+ puts $out \
+"#if __LINE__!=[expr {$cnt+0}]
+#undef SQLITE_SOURCE_ID
+$oldsrcid
+#endif
+/* Return the source-id for this library */
+SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }"
+}
+puts $out \
+"/************************** End of sqlite3.c ******************************/"
+
close $out
diff --git a/chromium/third_party/sqlite/src/tool/mksqlite3h.tcl b/chromium/third_party/sqlite/src/tool/mksqlite3h.tcl
index 5106a838579..5b4c48bb749 100644
--- a/chromium/third_party/sqlite/src/tool/mksqlite3h.tcl
+++ b/chromium/third_party/sqlite/src/tool/mksqlite3h.tcl
@@ -51,24 +51,12 @@ set zVersion [string trim [read $in]]
close $in
set nVersion [eval format "%d%03d%03d" [split $zVersion .]]
-# Get the fossil-scm version number from $TOP/manifest.uuid.
+# Get the source-id
#
-set in [open $TOP/manifest.uuid]
-set zUuid [string trim [read $in]]
-close $in
-
-# Get the fossil-scm check-in date from the "D" card of $TOP/manifest.
-#
-set in [open $TOP/manifest]
-set zDate {}
-while {![eof $in]} {
- set line [gets $in]
- if {[regexp {^D (2[-0-9T:]+)} $line all date]} {
- set zDate [string map {T { }} $date]
- break
- }
-}
-close $in
+set PWD [pwd]
+cd $TOP
+set zSourceId [exec $PWD/mksourceid manifest]
+cd $PWD
# Set up patterns for recognizing API declarations.
#
@@ -125,7 +113,7 @@ foreach file $filelist {
regsub -- --VERS-- $line $zVersion line
regsub -- --VERSION-NUMBER-- $line $nVersion line
- regsub -- --SOURCE-ID-- $line "$zDate $zUuid" line
+ regsub -- --SOURCE-ID-- $line "$zSourceId" line
if {[regexp $varpattern $line] && ![regexp {^ *typedef} $line]} {
set line "SQLITE_API $line"
diff --git a/chromium/third_party/sqlite/src/tool/speed-check.sh b/chromium/third_party/sqlite/src/tool/speed-check.sh
index 22adec5fc25..be79a1a73de 100644
--- a/chromium/third_party/sqlite/src/tool/speed-check.sh
+++ b/chromium/third_party/sqlite/src/tool/speed-check.sh
@@ -29,13 +29,14 @@ SIZE=5
LEAN_OPTS="-DSQLITE_THREADSAFE=0"
LEAN_OPTS="$LEAN_OPTS -DSQLITE_DEFAULT_MEMSTATUS=0"
LEAN_OPTS="$LEAN_OPTS -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1"
-LEAN_OPTS="$LEAN_OPTS -DSQLITE_LIKE_DOESNT_MATCH_BLOB"
+LEAN_OPTS="$LEAN_OPTS -DSQLITE_LIKE_DOESNT_MATCH_BLOBS"
LEAN_OPTS="$LEAN_OPTS -DSQLITE_MAX_EXPR_DEPTH=0"
LEAN_OPTS="$LEAN_OPTS -DSQLITE_OMIT_DECLTYPE"
LEAN_OPTS="$LEAN_OPTS -DSQLITE_OMIT_DEPRECATED"
LEAN_OPTS="$LEAN_OPTS -DSQLITE_OMIT_PROGRESS_CALLBACK"
LEAN_OPTS="$LEAN_OPTS -DSQLITE_OMIT_SHARED_CACHE"
LEAN_OPTS="$LEAN_OPTS -DSQLITE_USE_ALLOCA"
+BASELINE="trunk"
doExplain=0
doCachegrind=1
while test "$1" != ""; do
@@ -116,9 +117,12 @@ while test "$1" != ""; do
--orm)
SPEEDTEST_OPTS="$SPEEDTEST_OPTS --testset orm"
;;
- *)
+ -*)
CC_OPTS="$CC_OPTS $1"
;;
+ *)
+ BASELINE=$1
+ ;;
esac
shift
done
@@ -147,10 +151,12 @@ size sqlite3.o | tee -a summary-$NAME.txt
wc sqlite3.c
if test $doCachegrind -eq 1; then
cg_anno.tcl cachegrind.out.* >cout-$NAME.txt
+ echo '*****************************************************' >>cout-$NAME.txt
+ sed 's/^[0-9=-]\{9\}/==00000==/' summary-$NAME.txt >>cout-$NAME.txt
fi
if test $doExplain -eq 1; then
./speedtest1 --explain $SPEEDTEST_OPTS | ./sqlite3 >explain-$NAME.txt
fi
-if test "$NAME" != "trunk"; then
- fossil test-diff --tk -c 20 cout-trunk.txt cout-$NAME.txt
+if test "$NAME" != "$BASELINE"; then
+ fossil test-diff --tk -c 20 cout-$BASELINE.txt cout-$NAME.txt
fi
diff --git a/chromium/third_party/sqlite/src/tool/split-sqlite3c.tcl b/chromium/third_party/sqlite/src/tool/split-sqlite3c.tcl
index 287b752828f..230e3f2549c 100644
--- a/chromium/third_party/sqlite/src/tool/split-sqlite3c.tcl
+++ b/chromium/third_party/sqlite/src/tool/split-sqlite3c.tcl
@@ -15,6 +15,7 @@ set END {^/\*+ End of %s \*+/}
set in [open sqlite3.c]
set out1 [open sqlite3-all.c w]
+fconfigure $out1 -translation lf
# Copy the header from sqlite3.c into sqlite3-all.c
#
@@ -48,6 +49,7 @@ proc write_one_file {content} {
global filecnt
incr filecnt
set out [open sqlite3-$filecnt.c w]
+ fconfigure $out -translation lf
puts -nonewline $out $content
close $out
puts $::out1 "#include \"sqlite3-$filecnt.c\""
diff --git a/chromium/third_party/sqlite/src/tool/sqlite3_analyzer.c.in b/chromium/third_party/sqlite/src/tool/sqlite3_analyzer.c.in
new file mode 100644
index 00000000000..547b22ffe1e
--- /dev/null
+++ b/chromium/third_party/sqlite/src/tool/sqlite3_analyzer.c.in
@@ -0,0 +1,27 @@
+/*
+** Read an SQLite database file and analyze its space utilization. Generate
+** text on standard output.
+*/
+#define TCLSH_INIT_PROC sqlite3_analyzer_init_proc
+#define SQLITE_ENABLE_DBSTAT_VTAB 1
+#undef SQLITE_THREADSAFE
+#define SQLITE_THREADSAFE 0
+#undef SQLITE_ENABLE_COLUMN_METADATA
+#define SQLITE_OMIT_DECLTYPE 1
+#define SQLITE_OMIT_DEPRECATED 1
+#define SQLITE_OMIT_PROGRESS_CALLBACK 1
+#define SQLITE_OMIT_SHARED_CACHE 1
+#define SQLITE_DEFAULT_MEMSTATUS 0
+#define SQLITE_MAX_EXPR_DEPTH 0
+#define SQLITE_OMIT_LOAD_EXTENSION 1
+INCLUDE sqlite3.c
+INCLUDE $ROOT/src/tclsqlite.c
+
+const char *sqlite3_analyzer_init_proc(Tcl_Interp *interp){
+ (void)interp;
+ return
+BEGIN_STRING
+INCLUDE $ROOT/tool/spaceanal.tcl
+END_STRING
+;
+}
diff --git a/chromium/third_party/sqlite/src/tool/tostr.tcl b/chromium/third_party/sqlite/src/tool/tostr.tcl
deleted file mode 100644
index cb06ee947f9..00000000000
--- a/chromium/third_party/sqlite/src/tool/tostr.tcl
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/usr/bin/tcl
-#
-# Convert input text into a C string
-#
-set in [open [lindex $argv 0] rb]
-while {![eof $in]} {
- set line [gets $in]
- if {[eof $in]} break;
- set x [string map "\\\\ \\\\\\\\ \\\" \\\\\"" $line]
- puts "\"$x\\n\""
-}
-close $in
diff --git a/chromium/third_party/sqlite/src/tool/warnings-clang.sh b/chromium/third_party/sqlite/src/tool/warnings-clang.sh
index 8d1e1943d59..b7458d14f18 100644
--- a/chromium/third_party/sqlite/src/tool/warnings-clang.sh
+++ b/chromium/third_party/sqlite/src/tool/warnings-clang.sh
@@ -3,12 +3,12 @@
# Run this script in a directory with a working makefile to check for
# compiler warnings in SQLite.
#
-rm -f sqlite3.c
-make sqlite3.c
+rm -f sqlite3.c shell.c
+make sqlite3.c shell.c
echo '************* FTS4 and RTREE ****************'
scan-build gcc -c -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE \
-DSQLITE_DEBUG -DSQLITE_ENABLE_STAT3 sqlite3.c 2>&1 | grep -v 'ANALYZE:'
echo '********** ENABLE_STAT3. THREADSAFE=0 *******'
scan-build gcc -c -I. -DSQLITE_ENABLE_STAT3 -DSQLITE_THREADSAFE=0 \
-DSQLITE_DEBUG \
- sqlite3.c ../sqlite/src/shell.c -ldl 2>&1 | grep -v 'ANALYZE:'
+ sqlite3.c shell.c -ldl 2>&1 | grep -v 'ANALYZE:'