]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Partial hand-merge of shell.c.in (not buildable) cli_extension_wip
authorlarrybr <larrybr@noemail.net>
Sun, 3 Dec 2023 19:32:37 +0000 (19:32 +0000)
committerlarrybr <larrybr@noemail.net>
Sun, 3 Dec 2023 19:32:37 +0000 (19:32 +0000)
FossilOrigin-Name: 62e90c9ba80c257da417ab57549f142f9628c10bd924ab3334a2c518976b3c6d

62 files changed:
1  2 
Makefile.in
Makefile.msc
README.md
VERSION
configure
configure.ac
ext/fts3/fts3_write.c
ext/fts5/fts5_expr.c
ext/fts5/fts5_index.c
ext/misc/fileio.c
ext/recover/dbdata.c
ext/rtree/rtree.c
ext/rtree/rtree1.test
ext/wasm/api/sqlite3-api-worker1.js
ext/wasm/api/sqlite3-opfs-async-proxy.js
ext/wasm/api/sqlite3-vfs-opfs.c-pp.js
ext/wasm/tester1.c-pp.js
main.mk
manifest
manifest.uuid
src/alter.c
src/btreeInt.h
src/expr.c
src/fkey.c
src/func.c
src/json.c
src/loadext.c
src/main.c
src/mutex_unix.c
src/mutex_w32.c
src/os_unix.c
src/os_win.c
src/pager.c
src/parse.y
src/pcache.c
src/pragma.c
src/prepare.c
src/select.c
src/shell.c.in
src/sqlite.h.in
src/test1.c
src/test8.c
src/treeview.c
src/util.c
src/vdbe.c
src/vdbeInt.h
src/vdbeapi.c
src/vdbemem.c
src/vdbesort.c
src/vtab.c
src/wal.c
src/whereInt.h
src/wherecode.c
src/window.c
test/fuzzcheck.c
test/joinH.test
test/permutations.test
test/shell1.test
test/window1.test
tool/mksqlite3c.tcl
tool/sqldiff.c
tool/src-verify.c

diff --cc Makefile.in
index fc0fa9b3baf2cb808945080a30623cbfcd85b80b,b5c98fb8b87290a8cf6706e4618e735b60e7aab0..ca6515de05a791706c5e923fa5c2d40eb0596bdc
mode 100755,100644..100644
@@@ -1147,36 -1147,39 +1175,40 @@@ keywordhash.h:       $(TOP)/tool/mkkeywordhas
        $(BCC) -o mkkeywordhash$(BEXE) $(OPT_FEATURE_FLAGS) $(OPTS) $(TOP)/tool/mkkeywordhash.c
        ./mkkeywordhash$(BEXE) >keywordhash.h
  
 +$(TOP)/ext/misc/basexx.c: $(TOP)/ext/misc/base64.c $(TOP)/ext/misc/base85.c
 +
  # Source files that go into making shell.c
  SHELL_SRC = \
 -      $(TOP)/src/shell.c.in \
 -      $(TOP)/ext/consio/console_io.c \
 -      $(TOP)/ext/consio/console_io.h \
 -      $(TOP)/ext/misc/appendvfs.c \
 -      $(TOP)/ext/misc/completion.c \
 -      $(TOP)/ext/misc/decimal.c \
 -      $(TOP)/ext/misc/basexx.c \
 -      $(TOP)/ext/misc/base64.c \
 -      $(TOP)/ext/misc/base85.c \
 -      $(TOP)/ext/misc/fileio.c \
 -      $(TOP)/ext/misc/ieee754.c \
 -      $(TOP)/ext/misc/regexp.c \
 -      $(TOP)/ext/misc/series.c \
 -      $(TOP)/ext/misc/shathree.c \
 -      $(TOP)/ext/misc/sqlar.c \
 -      $(TOP)/ext/misc/uint.c \
 -      $(TOP)/ext/expert/sqlite3expert.c \
 -      $(TOP)/ext/expert/sqlite3expert.h \
 -      $(TOP)/ext/misc/zipfile.c \
 -      $(TOP)/ext/misc/memtrace.c \
 -      $(TOP)/ext/misc/pcachetrace.c \
 -      $(TOP)/ext/recover/dbdata.c \
 -      $(TOP)/ext/recover/sqlite3recover.c \
 -      $(TOP)/ext/recover/sqlite3recover.h \
 -      $(TOP)/src/test_windirent.c
 +  $(TOP)/src/shell.c.in \
++  $(TOP)/ext/consio/console_io.c \
++  $(TOP)/ext/consio/console_io.h \
++  $(TOP)/ext/misc/appendvfs.c \
++  $(TOP)/ext/misc/completion.c \
 +  $(TOP)/ext/expert/sqlite3expert.c \
 +  $(TOP)/ext/expert/sqlite3expert.h \
 +  $(TOP)/ext/misc/appendvfs.c \
 +  $(TOP)/ext/misc/basexx.c \
 +  $(TOP)/ext/misc/completion.c \
 +  $(TOP)/ext/misc/decimal.c \
 +  $(TOP)/ext/misc/fileio.c \
 +  $(TOP)/ext/misc/ieee754.c \
 +  $(TOP)/ext/misc/regexp.c \
 +  $(TOP)/ext/misc/series.c \
 +  $(TOP)/ext/misc/shathree.c \
 +  $(TOP)/ext/misc/sqlar.c \
 +  $(TOP)/ext/misc/uint.c \
 +  $(TOP)/ext/misc/memtrace.c \
 +  $(TOP)/ext/misc/pcachetrace.c \
 +  $(TOP)/src/shext_linkage.h \
 +  $(TOP)/src/obj_interfaces.h \
 +  $(TOP)/src/resmanage.h \
 +  $(TOP)/src/resmanage.c \
 +  $(TOP)/ext/recover/dbdata.c \
 +  $(TOP)/ext/misc/zipfile.c \
 +  $(TOP)/src/test_windirent.c
  
- shell.c:      $(SHELL_SRC) $(TOP)/tool/mkshellc.tcl
+ shell.c:      $(SHELL_SRC) $(TOP)/tool/mkshellc.tcl has_tclsh84
 -      $(TCLSH_CMD) $(TOP)/tool/mkshellc.tcl >shell.c
 -
 -
 -
 +      $(MKSHELL_TOOL) >shell.c
  
  # Rules to build the extension objects.
  #
@@@ -1417,17 -1390,10 +1467,17 @@@ valgrindtest:        $(TESTPROGS) valgrindfuz
  smoketest:    $(TESTPROGS) fuzzcheck$(TEXE)
        ./testfixture$(TEXE) $(TOP)/test/main.test $(TESTOPTS)
  
 +TESTRUNS_SHX = \
 + $(TOP)/test/shell_x/shell9.test \
 + $(TOP)/test/shell_x/shell10.test
 +
 +shellxtest: $(TESTPROGS_SHX)
 +      ./testfixture$(TEXE) $(TESTRUNS_SHX)
 +
  shelltest: $(TESTPROGS)
 -      ./testfixture$(TEXT) $(TOP)/test/permutations.test shell
 +      ./testfixture$(TEXE) $(TOP)/test/permutations.test shell
  
- sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in
+ sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in has_tclsh85
        $(TCLSH_CMD) $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in >sqlite3_analyzer.c
  
  sqlite3_analyzer$(TEXE): sqlite3_analyzer.c
diff --cc Makefile.msc
index b683fef23d47ea5377d1cd2f18634c74076038f1,3a4d46b01f048bd00cf634e029798aeb9807beae..3e7dd5bd6e706060c69292a55883b2acd6a0c790
mode 100755,100644..100644
@@@ -1675,11 -1690,10 +1704,13 @@@ SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OP
  SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_FTS4=1
  SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS=1
  SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC=1
+ SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION=1
+ SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_STMT_SCANSTATUS=1
  !ENDIF
  
 +# 
 +SHELL_NOEXT_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSHELL_OMIT_EXTENSIONS=7
 +
  # <<mark>>
  # Extra compiler options for various test tools.
  #
@@@ -2250,28 -2260,28 +2281,30 @@@ keywordhash.h:       $(TOP)\tool\mkkeywordhas
  
  # Source files that go into making shell.c
  SHELL_SRC = \
 -      $(TOP)\src\shell.c.in \
 -      $(TOP)\ext\consio\console_io.c \
 -      $(TOP)\ext\consio\console_io.h \
 -      $(TOP)\ext\misc\appendvfs.c \
 -      $(TOP)\ext\misc\completion.c \
 -      $(TOP)\ext\misc\base64.c \
 -      $(TOP)\ext\misc\base85.c \
 -      $(TOP)\ext\misc\decimal.c \
 -      $(TOP)\ext\misc\fileio.c \
 -      $(TOP)\ext\misc\ieee754.c \
 -      $(TOP)\ext\misc\regexp.c \
 -      $(TOP)\ext\misc\series.c \
 -      $(TOP)\ext\misc\shathree.c \
 -      $(TOP)\ext\misc\uint.c \
 -      $(TOP)\ext\expert\sqlite3expert.c \
 -      $(TOP)\ext\expert\sqlite3expert.h \
 -      $(TOP)\ext\misc\memtrace.c \
 -      $(TOP)\ext\misc\pcachetrace.c \
 -      $(TOP)\ext\recover\dbdata.c \
 -      $(TOP)\ext\recover\sqlite3recover.c \
 -      $(TOP)\ext\recover\sqlite3recover.h \
 -      $(TOP)\src\test_windirent.c
 +  $(TOP)\src\shell.c.in \
++  $(TOP)\ext\consio\console_io.c \
++  $(TOP)\ext\consio\console_io.h \
 +  $(TOP)\ext\misc\appendvfs.c \
 +  $(TOP)\ext\misc\completion.c \
 +  $(TOP)\ext\misc\base64.c \
 +  $(TOP)\ext\misc\base85.c \
 +  $(TOP)\ext\misc\decimal.c \
 +  $(TOP)\ext\misc\fileio.c \
 +  $(TOP)\ext\misc\ieee754.c \
 +  $(TOP)\ext\misc\regexp.c \
 +  $(TOP)\ext\misc\series.c \
 +  $(TOP)\ext\misc\shathree.c \
 +  $(TOP)\ext\misc\uint.c \
 +  $(TOP)\ext\expert\sqlite3expert.c \
 +  $(TOP)\ext\expert\sqlite3expert.h \
 +  $(TOP)\ext\misc\memtrace.c \
 +  $(TOP)\ext\misc\pcachetrace.c \
 +  $(TOP)\ext\recover\dbdata.c \
 +  $(TOP)\ext\recover\sqlite3recover.c \
 +  $(TOP)\ext\recover\sqlite3recover.h \
 +  $(TOP)\src\resmanage.h \
 +  $(TOP)\src\resmanage.c \
 +  $(TOP)\src\test_windirent.c
  
  # If use of zlib is enabled, add the "zipfile.c" source file.
  #
diff --cc README.md
index 10262653e729b452a1941d846051a85468222ca6,ebb917e218dc4e39bf6fecded16861ecdd53aa1e..ebb917e218dc4e39bf6fecded16861ecdd53aa1e
mode 100755,100644..100755
+++ b/README.md
diff --cc VERSION
index a9184766ba110a5739a4fb4359c4585f2f8d09f4,ff3ff28f6bd3125fb760fd6638e99e8a2cea203e..ff3ff28f6bd3125fb760fd6638e99e8a2cea203e
mode 100755,100644..100755
+++ b/VERSION
diff --cc configure
index 6a2113e24f4360a21bde4c51c5b7eb74e8e47a52,6a47c4dcc893bc6b8427fb26027a72ac042f67a0..f97ad8ae6e3c2b501fb08d17535fe72ecdf50360
+++ b/configure
@@@ -776,7 -776,7 +776,8 @@@ OPT_FEATURE_FLAG
  HAVE_ZLIB
  USE_AMALGAMATION
  TARGET_DEBUG
 +EXTENSION_DEBUG
+ TARGET_HAVE_LINENOISE
  TARGET_HAVE_EDITLINE
  TARGET_HAVE_READLINE
  TARGET_READLINE_INC
  { $as_echo "$as_me:${as_lineno-$LINENO}: checking build type" >&5
  $as_echo_n "checking build type... " >&6; }
  if test "${enable_debug}" = "yes" ; then
-   TARGET_DEBUG="-DSQLITE_DEBUG=1 -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE -O0"
+   TARGET_DEBUG="-DSQLITE_DEBUG=1 -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE -O0 -Wall"
 +  EXTENSION_DEBUG="-DSQLITE_DEBUG=1"
    { $as_echo "$as_me:${as_lineno-$LINENO}: result: debug" >&5
  $as_echo "debug" >&6; }
  else
diff --cc configure.ac
index 73b06fedc0571e9816f90c18750126420179ac09,54f985fd709824792fb219109a130076c0224a21..b7716115f7b0105f8737abdacfab47206b8ca28d
@@@ -615,8 -632,7 +632,8 @@@ AC_SEARCH_LIBS(fdatasync, [rt]
  AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug],[enable debugging & verbose explain]))
  AC_MSG_CHECKING([build type])
  if test "${enable_debug}" = "yes" ; then
-   TARGET_DEBUG="-DSQLITE_DEBUG=1 -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE -O0"
+   TARGET_DEBUG="-DSQLITE_DEBUG=1 -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE -O0 -Wall"
 +  EXTENSION_DEBUG="-DSQLITE_DEBUG=1"
    AC_MSG_RESULT([debug])
  else
    TARGET_DEBUG="-DNDEBUG"
index 32b483b349340987a09b66af720325628f9be854,0f894943dd8571bdda8716ec2f152587ec4a4182..0f894943dd8571bdda8716ec2f152587ec4a4182
mode 100755,100644..100755
index 0e018420d0713048ef059c1296fb86d859852c8f,f5101ba0654cd4c48f9d81f00a9b52fac6939446..f5101ba0654cd4c48f9d81f00a9b52fac6939446
mode 100755,100644..100755
index 7b9d21e87f00bd96e405bf81b7939109eb0cee7d,ba3ce6536aafa497e547c7cc949db1a86c77c920..ba3ce6536aafa497e547c7cc949db1a86c77c920
mode 100755,100644..100755
Simple merge
index e3bec33d8d7ed68de16b7f50dafd6601e61402a7,25a6e9fd6a9dc1441bbb1189b9c24ab06edac65b..25a6e9fd6a9dc1441bbb1189b9c24ab06edac65b
mode 100755,100644..100755
index c89fdbf1360886cd85da0a2ec4e7a7331669e678,1705abd51c69c9e437ffd9e50b1ed1ff9c8bd191..1705abd51c69c9e437ffd9e50b1ed1ff9c8bd191
mode 100755,100644..100755
index 633d0a5d5fa1d9830ac39dfb4fc869c4e134b2a5,61664e1529c428f999db7f7915c847ee709bc4f8..61664e1529c428f999db7f7915c847ee709bc4f8
mode 100755,100644..100755
index 9a386c13e71e1de15f55f04098643ab4b76c00ae,7c65dd1d3e8695061317d447d4dfb4cb054c9383..7c65dd1d3e8695061317d447d4dfb4cb054c9383
mode 100755,100644..100755
index 179a8163586a3d20f2fe1a02b98ced04b8809b9e,cafd296c61bf8add8f97d95efc17b43978f09335..cafd296c61bf8add8f97d95efc17b43978f09335
mode 100755,100644..100755
index 07dfa0f960b0a7809945563dd96ebf296987c107,af89f216f7667430b643f52e4290b5045cd02f58..af89f216f7667430b643f52e4290b5045cd02f58
mode 100755,100644..100755
index 1fb3303df11600566967ae91c636cc4681b94528,36ca4c976f3d7ad6a766f8ff4ae13142006833bf..36ca4c976f3d7ad6a766f8ff4ae13142006833bf
mode 100755,100644..100755
diff --cc main.mk
Simple merge
diff --cc manifest
index 69a2ecc342a13848cf08d1c744cbb1533b92f27a,a6dac2dd9abbff29f79750211004434b5e1d1399..d42b15de09a2e86104f472522eba0c0155deb358
+++ b/manifest
@@@ -1,13 -1,13 +1,13 @@@
- C Sync\sw/trunk
- D 2023-06-29T17:58:51.696
 -C Merge\sconsole\sI/O\schanges\sfor\sWindows\sCLI.
 -D 2023-11-21T18:26:06.197
++C Partial\shand-merge\sof\sshell.c.in\s(not\sbuildable)
++D 2023-12-03T19:32:37.645
  F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
  F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
  F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
- F Makefile.in dcc5b1491fff94b9a8f16f00714ed6a6c886d853970d0cd4a4066296063e96fd x
- F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241
- F Makefile.msc 7b31410d0f91251d4268b1abcab7b1a26b52d37193dd7ead87b2acb302ecf6b6 x
- F README.md c1c4218efcc4071a6e26db2b517fdbc1035696a29b370edd655faddbef02b224 x
- F VERSION c6366dc72582d3144ce87b013cc35fe48d62f6d07d5be0c9716ea33c862144aa x
 -F Makefile.in 890caf094636c308bc981032baf8f9208bf307755f9197ae4218a9fbcec2e449
++F Makefile.in 1efc7da5949765d66012ff1b09435af19903ad88bc1426c010304fca114139d3
+ F Makefile.linux-gcc f3842a0b1efbfbb74ac0ef60e56b301836d05b4d867d014f714fa750048f1ab6
 -F Makefile.msc 59bb36dba001f0b38212be0794fb838f25371008b180929bcf08aa799694c168
 -F README.md 963d30019abf0cc06b263cd2824bce022893f3f93a531758f6f04ff2194a16a8
 -F VERSION 73573d4545343f001bf5dc5461173a7c78c203dd046cabcf99153878cf25d3a6
++F Makefile.msc 6fc99388059fdc06cda41b7b21fe648c76dabe8c961545240a5efa09c8c6ac1f
++F README.md 963d30019abf0cc06b263cd2824bce022893f3f93a531758f6f04ff2194a16a8 x
++F VERSION 73573d4545343f001bf5dc5461173a7c78c203dd046cabcf99153878cf25d3a6 x
  F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
  F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
  F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
@@@ -33,16 -33,15 +33,18 @@@ F autoconf/tea/win/nmakehlp.c b01f822ea
  F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
  F config.guess 883205ddf25b46f10c181818bf42c09da9888884af96f79e1719264345053bd6
  F config.sub c2d0260f17f3e4bc0b6808fccf1b291cb5e9126c14fc5890efc77b9fd0175559
- F configure 697e926af786eb6ddb94ade8aace9f42814902d939ddc6a7bc5f11c3eca7dd51 x
- F configure.ac 510be9293c7efca69c0cc7f427f223b0597f82dda214af7491887db25fa4e237
 -F configure bcb1042e92775424a1021d2f4c89c78a699a6225df01fa8c593df7df0be6ad10 x
 -F configure.ac f25bd7843120f2c2b8bc9db5a92b0502bbdd28e68907415c3d42fc8e57c657b9
++F configure de42b25c1d02edbd8810c1324caff516fee76fc12f392037e7ac2e2a4b6aaf94 x
++F configure.ac 1f46ffbe9d7cd4ca6e703fe1f1c4cc4ea284bab9790b76636bf4a40ffa5ef646
  F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
  F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
+ F doc/compile-for-windows.md 50b27d77be96195c66031a3181cb8684ed822327ea834e07f9c014213e5e3bcf
 +F doc/extensible_shell.md 3a32ed1d6f9d59d9cd8c94d149a33c448cfdfcff20aaa9031681699f9e82710e x
  F doc/json-enhancements.md e356fc834781f1f1aa22ee300027a270b2c960122468499bf347bb123ce1ea4f
- F doc/lemon.html d2862dbef72496e87f7996f37e814b146848190a742c12161d13fd15346051b0
+ F doc/lemon.html 44a53a1d2b42d7751f7b2f478efb23c978e258d794bfd172442307a755b9fa44
  F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
 +F doc/shell_extend.html 61e649726612004ae6efb07507301c120969426c052024dd21550606657ecb9b x
 +F doc/tcl_extension_intro.md 4c0505365c6a37dbfb93c66e72e228c517947e9daa9f3040ef4390461cb5740b x
+ F doc/testrunner.md 2434864be2219d4f0b6ffc99d0a2172d531c4ca4345340776f67ad4edd90dc90
  F doc/trusted-schema.md 33625008620e879c7bcfbbfa079587612c434fa094d338b08242288d358c3e8a
  F doc/vdbesort-memory.md 4da2639c14cd24a31e0af694b1a8dd37eaf277aff3867e9a8cc14046bc49df56
  F doc/vfs-shm.txt e101f27ea02a8387ce46a05be2b1a902a021d37a
@@@ -79,7 -80,7 +83,7 @@@ F ext/fts3/fts3_tokenizer.h 64c6ef6c527
  F ext/fts3/fts3_tokenizer1.c c1de4ae28356ad98ccb8b2e3388a7fdcce7607b5523738c9afb6275dab765154
  F ext/fts3/fts3_unicode.c de426ff05c1c2e7bce161cf6b706638419c3a1d9c2667de9cb9dc0458c18e226
  F ext/fts3/fts3_unicode2.c 416eb7e1e81142703520d284b768ca2751d40e31fa912cae24ba74860532bf0f
- F ext/fts3/fts3_write.c d28d9ef383ef848a7b77df4b9964abcc90d67a2b584120c0ad465972dce416e6 x
 -F ext/fts3/fts3_write.c 5bb4721330ca589f906e72bb824dd4080b313c6d4c4231fa541e9db32dc67982
++F ext/fts3/fts3_write.c 5bb4721330ca589f906e72bb824dd4080b313c6d4c4231fa541e9db32dc67982 x
  F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
  F ext/fts3/tool/fts3cov.sh c331d006359456cf6f8f953e37f2b9c7d568f3863f00bb5f7eb87fea4ac01b73
  F ext/fts3/tool/fts3view.c 413c346399159df81f86c4928b7c4a455caab73bfbc8cd68f950f632e5751674
@@@ -88,28 -89,28 +92,28 @@@ F ext/fts3/unicode/UnicodeData.txt cd07
  F ext/fts3/unicode/mkunicode.tcl d5aebf022fa4577ee8cdf27468f0d847879993959101f6dbd6348ef0cfc324a7
  F ext/fts3/unicode/parseunicode.tcl a981bd6466d12dd17967515801c3ff23f74a281be1a03cf1e6f52a6959fc77eb
  F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0
- F ext/fts5/fts5.h c132a9323f22a972c4c93a8d5a3d901113a6e612faf30ca8e695788438c5ca2a
- F ext/fts5/fts5Int.h ed48a096418ff4a7c02ac9bd1e8d40c46de21b79a132b8b08d3f32233703de7d
- F ext/fts5/fts5_aux.c 572d5ec92ba7301df2fea3258576332f2f4d2dfd66d8263afd157d9deceac480
+ F ext/fts5/fts5.h 05501612cc655504c5dce8ba765ab621d50fc478490089beaa0d75e00b23e520
+ F ext/fts5/fts5Int.h 78a63cc0795186cde5384816a9403a68c65774b35d952e05b81a1b4b158e07c8
+ F ext/fts5/fts5_aux.c ee770eec0af8646db9e18fc01a0dad7345b5f5e8cbba236704cfae2d777022ad
  F ext/fts5/fts5_buffer.c 3001fbabb585d6de52947b44b455235072b741038391f830d6b729225eeaf6a5
- F ext/fts5/fts5_config.c 051056a9052f5d3a4d1c695f996fd364f920e341f136c60ab2c04aa7e267113f
- F ext/fts5/fts5_expr.c 58fb8ceddfb1cefcd54510f9f2f33c220ef9d1b3fa77462111f5ae2a825ab7b1 x
- F ext/fts5/fts5_hash.c d4fb70940359f2120ccd1de7ffe64cc3efe65de9e8995b822cd536ff64c96982
- F ext/fts5/fts5_index.c fe98ebd8835760b9c787d20f6b50d648a761afd8e3b55780e718ee34c694743b x
- F ext/fts5/fts5_main.c b4dba04a36aaf9b8e8cef0100b6dbb422cc74753eacc11d6401cac7a87c0f38d
- F ext/fts5/fts5_storage.c 76c6085239eb44424004c022e9da17a5ecd5aaec859fba90ad47d3b08f4c8082
+ F ext/fts5/fts5_config.c 054359543566cbff1ba65a188330660a5457299513ac71c53b3a07d934c7b081
 -F ext/fts5/fts5_expr.c bd3b81ce669c4104e34ffe66570af1999a317b142c15fccb112de9fb0caa57a6
++F ext/fts5/fts5_expr.c bd3b81ce669c4104e34ffe66570af1999a317b142c15fccb112de9fb0caa57a6 x
+ F ext/fts5/fts5_hash.c 076058f93327051952a752dc765df1acfe783eb11b419b30652aa1fc1f987902
 -F ext/fts5/fts5_index.c 809407c520c6afc3c1a0b8080cbd9080e4d84442f52a31654cc0e3d3acccea17
++F ext/fts5/fts5_index.c 809407c520c6afc3c1a0b8080cbd9080e4d84442f52a31654cc0e3d3acccea17 x
+ F ext/fts5/fts5_main.c a07ed863b8bd9e6fefb62db2fd40a3518eb30a5f7dcfda5be915dd2db45efa2f
+ F ext/fts5/fts5_storage.c 5d10b9bdcce5b90656cad13c7d12ad4148677d4b9e3fca0481fca56d6601426d
  F ext/fts5/fts5_tcl.c b1445cbe69908c411df8084a10b2485500ac70a9c747cdc8cda175a3da59d8ae
  F ext/fts5/fts5_test_mi.c 08c11ec968148d4cb4119d96d819f8c1f329812c568bac3684f5464be177d3ee
- F ext/fts5/fts5_test_tok.c a2bed8edb25f6432e8cdb62aad5916935c19dba8dac2b8324950cfff397e25ff
- F ext/fts5/fts5_tokenize.c 5e251efb0f1af99a25ed50010ba6b1ad1250aca5921af1988fdcabe5ebc3cb43
+ F ext/fts5/fts5_test_tok.c 3cb0a9b508b30d17ef025ccddd26ae3dc8ddffbe76c057616e59a9aa85d36f3b
+ F ext/fts5/fts5_tokenize.c 83cfcede3898001cab84432a36ce1503e3080cf9b1c682b022ec82e267ea4c13
  F ext/fts5/fts5_unicode2.c eca63dbc797f8ff0572e97caf4631389c0ab900d6364861b915bdd4735973f00
  F ext/fts5/fts5_varint.c e64d2113f6e1bfee0032972cffc1207b77af63319746951bf1d09885d1dadf80
- F ext/fts5/fts5_vocab.c 12138e84616b56218532e3e8feb1d3e0e7ae845e33408dbe911df520424dc9d6
+ F ext/fts5/fts5_vocab.c aed56169ae5c1aa9b8189c779ffeef04ed516d3c712c06914e6d91a6759f4e4a
  F ext/fts5/fts5parse.y eb526940f892ade5693f22ffd6c4f2702543a9059942772526eac1fde256bb05
  F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
  F ext/fts5/test/fts5_common.tcl a9de9c2209cc4e7ae3c753e783504e67206c6c1467d08f209cd0c5923d3e8d8b
- F ext/fts5/test/fts5aa.test 5bd43427b7d08ce2e19c488a26534be450538b9232d4d5305049e8de236e9aa9
+ F ext/fts5/test/fts5aa.test ba5158eba7d61359becdfca895ef471072c7bf7b20e5e60dcb4d024c8419c926
 -F ext/fts5/test/fts5ab.test bd932720c748383277456b81f91bc00453de2174f9762cd05f95d0495dc50390
 +F ext/fts5/test/fts5ab.test bd932720c748383277456b81f91bc00453de2174f9762cd05f95d0495dc50390 x
  F ext/fts5/test/fts5ac.test a7aa7e1fefc6e1918aa4d3111d5c44a09177168e962c5fd2cca9620de8a7ed6d
  F ext/fts5/test/fts5ad.test e8cf959dfcd57c8e46d6f5f25665686f3b6627130a9a981371dafdf6482790de
  F ext/fts5/test/fts5ae.test 1142d16d9cc193894dc13cc8f9c7a8a21411ac61b5567a878514df6f9f0d7bb7
@@@ -122,9 -123,9 +126,9 @@@ F ext/fts5/test/fts5ak.test f459a64c9d3
  F ext/fts5/test/fts5al.test 00c4c1c6a1366b73aa48ce2068c634520867c3cf7f5d1676ebbb775ee1f35734
  F ext/fts5/test/fts5alter.test 5565f7e4605512b69171ac18ca84398603f9f6456dbe377beeca97e83cc242cd
  F ext/fts5/test/fts5auto.test 78989e6527ce69c9eddbef7392fea5c10b0010cd2b2ae68eec7bc869c471e691
- F ext/fts5/test/fts5aux.test ebf6f2ff7cb556e83f66991b7f12bff016d3c83d4eab36704b649dd6b1437318
+ F ext/fts5/test/fts5aux.test 3f194345fcd581f49f7fbb2e5495400efcc7d2835b77816328d8283c942f41b8
  F ext/fts5/test/fts5auxdata.test eacc97ff04892f1a5f3d4df5a73f8bcbc3955ea1d12c9f24137eb1fc079e7611
 -F ext/fts5/test/fts5bigid.test 2860854c2561a57594192b00c33a29f91cb85e25f3d6c03b5c2b8f62708f39dd
 +F ext/fts5/test/fts5bigid.test 2860854c2561a57594192b00c33a29f91cb85e25f3d6c03b5c2b8f62708f39dd x
  F ext/fts5/test/fts5bigpl.test 6466c89b38439f0aba26ac09e232a6b963f29b1cbe1304f6a664fe1e7a8f5fd3
  F ext/fts5/test/fts5bigtok.test 541119e616c637caea925a8c028c37c2c29e94383e00aa2f9198d530724b6e36
  F ext/fts5/test/fts5cat.test daba0b80659460b0cb60bd1f40b402478a761fe7ea414c3c94c2be25568cc33a
@@@ -132,16 -133,21 +136,21 @@@ F ext/fts5/test/fts5circref.test f880df
  F ext/fts5/test/fts5colset.test 7031ce84fb4d312df5a99fc4e7b324e660ccb513c97eccdef469bfd52d3d0f8f
  F ext/fts5/test/fts5columnsize.test 45459ce4dd9fd853b6044cdc9674921bff89e3d840f348ca8c1630f9edbf5482
  F ext/fts5/test/fts5config.test 60094712debc59286c59aef0e6cf511c37d866802776a825ce437d26afe0817f
- F ext/fts5/test/fts5conflict.test 655925678e630d3cdf145d18725a558971806416f453ac8410ca8c04d934238d
+ F ext/fts5/test/fts5conflict.test bf6030a77dbb1bedfcc42e589ed7980846c995765d77460551e448b56d741244
  F ext/fts5/test/fts5connect.test 08030168fc96fc278fa81f28654fb7e90566f33aff269c073e19b3ae9126b2f4
- F ext/fts5/test/fts5content.test 213506436fb2c87567b8e31f6d43ab30aab99354cec74ed679f22aad0cdbf283
- F ext/fts5/test/fts5corrupt.test 77ae6f41a7eba10620efb921cf7dbe218b0ef232b04519deb43581cb17a57ebe
- F ext/fts5/test/fts5corrupt2.test 7453752ba12ce91690c469a6449d412561cc604b1dec994e16ab132952e7805f
+ F ext/fts5/test/fts5content.test 219a4e49386b9b197b9b7cadca97ea10ddff858ecd8b763a1cb8bb07575afc2a
+ F ext/fts5/test/fts5contentless.test 1cd1237894eeff11feb1ff8180044eac0b17dde22c181f7a722f2dcbfdb3377c
+ F ext/fts5/test/fts5contentless2.test 14c83bdacf8230f5f7ca74ecf2926b87d8a7cb788a69ce9937020428ac4fe192
+ F ext/fts5/test/fts5contentless3.test 353d871c5ea08992aed3e2ebda0b1bdc35116cd24fe330fe7cf05be1e2b49fd7
+ F ext/fts5/test/fts5contentless4.test dd33ead36b048c9447b81ec358bd4a27166c49ffaac65a54e95eabf59f338947
+ F ext/fts5/test/fts5contentless5.test 96041cbf5ef781a68a5d0f0d18a88030c47a52b156b17876ed6ce36e80e27a7e
+ F ext/fts5/test/fts5corrupt.test b6d4034b682bb3387bc44c510c71b3c67d4349e4df139490fc0b69e6a972b99f
+ F ext/fts5/test/fts5corrupt2.test 99e7e23a58b4d89eb7167c6de1669cbc595cd3c79ab333e0eb56405473319e77
  F ext/fts5/test/fts5corrupt3.test 7da9895dafa404efd20728f66ff4b94399788bdc042c36fe2689801bba2ccd78
  F ext/fts5/test/fts5corrupt4.test f4c08e2182a48d8b70975fd869ee5391855c06d8a0ff87b6a2529e7c5a88a1d3
 -F ext/fts5/test/fts5corrupt5.test eb6ba5ca28ef7c4c6b01e850d388cdb3dacc8c4c2f383f79d0a98128257742b4
 +F ext/fts5/test/fts5corrupt5.test eb6ba5ca28ef7c4c6b01e850d388cdb3dacc8c4c2f383f79d0a98128257742b4 x
  F ext/fts5/test/fts5corrupt6.test bf8eeae07825b088b9665d9d8e4accbd8dc9bf3cb85b6c64cf6c9e18ccc420a4
 -F ext/fts5/test/fts5corrupt7.test 80ad7f683a8bda2404731bb77e8c3dbbb620c1f6cc583cca8239f6accd6338c0
 +F ext/fts5/test/fts5corrupt7.test 80ad7f683a8bda2404731bb77e8c3dbbb620c1f6cc583cca8239f6accd6338c0 x
  F ext/fts5/test/fts5delete.test 619295b20dbc1d840b403ee07c878f52378849c3c02e44f2ee143b3e978a0aa7
  F ext/fts5/test/fts5detail.test 54015e9c43ec4ba542cfb93268abdf280e0300f350efd08ee411284b03595cc4
  F ext/fts5/test/fts5determin.test 1b77879b2ae818b5b71c859e534ee334dac088b7cf3ff3bf76a2c82b1c788d11
@@@ -281,26 -360,26 +363,26 @@@ F ext/misc/base64.c a71b131e50300c654a6
  F ext/misc/base85.c 073054111988db593ef5fdb87ab8c459df1ea0c3aaaddf0f5bfa3d72b7e6280a
  F ext/misc/basexx.c 89ad6b76558efbceb627afd5e2ef1d84b2e96d9aaf9b7ecb20e3d00b51be6fcf
  F ext/misc/blobio.c a867c4c4617f6ec223a307ebfe0eabb45e0992f74dd47722b96f3e631c0edb2a
- F ext/misc/btreeinfo.c d28ce349b40054eaa9473e835837bad7a71deec33ba13e39f963d50933bfa0f9
- F ext/misc/carray.c 0ba03f1e6647785d4e05b51be567f5652f06941314ff9d3d3763900aa353b6b5
+ F ext/misc/btreeinfo.c cb952620eedf5c0b7625b678f0f08e54d2ec0011d4e50efda5ebdc97f3df7d04
+ F ext/misc/carray.c 34fac63770971611c5285de0a9f0ac67d504eaf66be891f637add9290f1c76a5
  F ext/misc/carray.h 503209952ccf2431c7fd899ebb92bf46bf7635b38aace42ec8aa1b8d7b6e98a5
  F ext/misc/cksumvfs.c 9224e33cc0cb6aa61ff1d7d7b8fd6fe56beca9f9c47954fa4ae0a69bef608f69
- F ext/misc/closure.c dbfd8543b2a017ae6b1a5843986b22ddf99ff126ec9634a2f4047cd14c85c243
- F ext/misc/completion.c 6dafd7f4348eecc7be9e920d4b419d1fb2af75d938cd9c59a20cfe8beb2f22b9
+ F ext/misc/closure.c 0e04f52d93e678dd6f950f195f365992edf3c380df246f3d80425cba4c13891e
+ F ext/misc/completion.c ef78835483b43ac18c96be312b90b615d8368189909be03513ab7a9338131298
  F ext/misc/compress.c 3354c77a7c8e86e07d849916000cdac451ed96500bfb5bd83b20eb61eee012c9
- F ext/misc/csv.c ca8d6dafc5469639de81937cb66ae2e6b358542aba94c4f791910d355a8e7f73
+ F ext/misc/csv.c 575c2c05fba0a451586a4d42c2c81e711780c41e797126f198d8d9e0a308dcdb
  F ext/misc/dbdump.c b8592f6f2da292c62991a13864a60d6c573c47a9cc58362131b9e6a64f823e01
- F ext/misc/decimal.c 24ccb63e9af6ed7de2e8e3b300061ad91169a44cc0c35dab92b7d2e1e7574f28
+ F ext/misc/decimal.c 172cf81a8634e6a0f0bedaf71a8372fee63348cf5a3c4e1b78bb233c35889fdc
  F ext/misc/eval.c 04bc9aada78c888394204b4ed996ab834b99726fb59603b0ee3ed6e049755dc1
- F ext/misc/explain.c 0086fab288d4352ea638cf40ac382aad3b0dc5e845a1ea829a694c015fd970fe
- F ext/misc/fileio.c 37f19acaf22562bae05f530c81c7b24b2c5c091503b115b54ec127958fb5c8bb
- F ext/misc/fossildelta.c 1240b2d3e52eab1d50c160c7fe1902a9bd210e052dc209200a750bbf885402d5
- F ext/misc/fuzzer.c eae560134f66333e9e1ca4c8ffea75df42056e2ce8456734565dbe1c2a92bf3d
- F ext/misc/ieee754.c 984d51fe23e956484ec1049df6f5257002e3ab338cabceb39761c2e80ad10bf4
- F ext/misc/memstat.c 3017a0832c645c0f8c773435620d663855f04690172316bd127270d1a7523d4d
+ F ext/misc/explain.c 606100185fb90d6a1eade1ed0414d53503c86820d8956a06e3b0a56291894f2b
 -F ext/misc/fileio.c d88e60f63557d76d4e38acffda5556b2ab42e98f5d830897f22aba65930d975c
++F ext/misc/fileio.c d668e9867629036cbe254d62b1757657db696292231a13e940a655cb7c94458b
+ F ext/misc/fossildelta.c 8c026e086e406e2b69947f1856fa3b848fff5379962276430d10085b8756b05a
+ F ext/misc/fuzzer.c 8b28acf1a7e95d50e332bdd47e792ff27054ad99d3f9bc2e91273814d4b31a5a
+ F ext/misc/ieee754.c 62a90978204d2c956d5036eb89e548e736ca5fac0e965912867ddd7bb833256d
+ F ext/misc/memstat.c 5b284b78be431c1f5fa154b18eade2407e42c65ed32ec9e9fbf195d114778d7d
  F ext/misc/memtrace.c 7c0d115d2ef716ad0ba632c91e05bd119cb16c1aedf3bec9f06196ead2d5537b
  F ext/misc/memvfs.c 7dffa8cc89c7f2d73da4bd4ccea1bcbd2bd283e3bb4cea398df7c372a197291b
- F ext/misc/mmapwarm.c 347caa99915fb254e8949ec131667b7fae99e2a9ce91bd468efb6dc372d9b7a9
+ F ext/misc/mmapwarm.c a81af4aaec00f24f308e2f4c19bf1d88f3ac3ce848c36daa7a4cd38145c4080d
  F ext/misc/nextchar.c 7877914c2a80c2f181dd04c3dbef550dfb54c93495dc03da2403b5dd58f34edd
  F ext/misc/noop.c 81efe4cad9ec740e64388b14281cb983e6e2c223fed43eb77ab3e34946e0c1ab
  F ext/misc/normalize.c bd84355c118e297522aba74de34a4fd286fc775524e0499b14473918d09ea61f
@@@ -317,14 -396,13 +399,14 @@@ F ext/misc/series.c 80692f675de989629ee
  F ext/misc/sha1.c 4011aef176616872b2a0d5bccf0ecfb1f7ce3fe5c3d107f3a8e949d8e1e3f08d
  F ext/misc/shathree.c 543af7ce71d391cd3a9ab6924a6a1124efc63211fd0f2e240dc4b56077ba88ac
  F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
- F ext/misc/spellfix.c 94df9bbfa514a563c1484f684a2df3d128a2f7209a84ca3ca100c68a0163e29f
+ F ext/misc/spellfix.c c0aa7b80d6df45f7da59d912b38752bcac1af53a5766966160e6c5cdd397dbea
  F ext/misc/sqlar.c 53e7d48f68d699a24f1a92e68e71eca8b3a9ff991fe9588c2a05bde103c6e7b7
- F ext/misc/stmt.c bc30d60d55e70d0133f10ac6103fe9336543f673740b73946f98758a2bb16dd7
+ F ext/misc/stmt.c b090086cd6bd6281c21271d38d576eeffe662f0e6b67536352ce32bbaa438321
 +F ext/misc/tclshext.c.in eaf544f41cedc1a824e369ab782e3bf3e36f227c9da10d8bdf7187937f80e10a x
- F ext/misc/templatevtab.c 8a16a91a5ceaccfcbd6aaaa56d46828806e460dd194965b3f77bf38f14b942c4
+ F ext/misc/templatevtab.c 10f15b165b95423ddef593bc5dcb915ec4eb5e0f1066d585e5435a368b8bc22b
  F ext/misc/totype.c fa4aedeb07f66169005dffa8de3b0a2b621779fd44f85c103228a42afa71853b
  F ext/misc/uint.c 053fed3bce2e89583afcd4bf804d75d659879bbcedac74d0fa9ed548839a030b
- F ext/misc/unionvtab.c 36237f0607ca954ac13a4a0e2d2ac40c33bc6e032a5f55f431713061ef1625f9
+ F ext/misc/unionvtab.c 716d385256d5fb4beea31b0efede640807e423e85c9784d21d22f0cce010a785
  F ext/misc/urifuncs.c f71360d14fa9e7626b563f1f781c6148109462741c5235ac63ae0f8917b9c751
  F ext/misc/uuid.c 5bb2264c1b64d163efa46509544fd7500cb8769cb7c16dd52052da8d961505cf
  F ext/misc/vfslog.c 3932ab932eeb2601dbc4447cb14d445aaa9fbe43b863ef5f014401c3420afd20
@@@ -381,7 -459,7 +463,7 @@@ F ext/rbu/rbuvacuum4.test ffccd22f67e2d
  F ext/rbu/sqlite3rbu.c d4ddf8f0e93772556e452a6c2814063cf47efb760a0834391a9d0cd9859fa4b9
  F ext/rbu/sqlite3rbu.h 9d923eb135c5d04aa6afd7c39ca47b0d1d0707c100e02f19fdde6a494e414304
  F ext/rbu/test_rbu.c ee6ede75147bc081fe9bc3931e6b206277418d14d3fbceea6fdc6216d9b47055
- F ext/recover/dbdata.c 81661e3a98cabb70be8f2760a67a8d6d5bf7aaa7a4055a53ff915ac884221a64 x
 -F ext/recover/dbdata.c fc7147a68422cbbbaa481ee92ae1752cc25f5a24302bece1c70dcb76345bd736
++F ext/recover/dbdata.c fc7147a68422cbbbaa481ee92ae1752cc25f5a24302bece1c70dcb76345bd736 x
  F ext/recover/recover1.test c484d01502239f11b61f23c1cee9f5dd19fa17617f8974e42e74d64639c524cf
  F ext/recover/recover_common.tcl a61306c1eb45c0c3fc45652c35b2d4ec19729e340bdf65a272ce4c229cefd85a
  F ext/recover/recoverbuild.test c74170e0f7b02456af41838afeb5353fdb985a48cc2331d661bbabbca7c6b8e3
@@@ -408,10 -486,10 +490,10 @@@ F ext/repair/test/checkfreelist01.test 
  F ext/repair/test/checkindex01.test b530f141413b587c9eb78ff734de6bb79bc3515c335096108c12c01bddbadcec
  F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
  F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
- F ext/rtree/geopoly.c 971e0b5bd9adaf0811feb8c0842a310811159da10319eb0e74fdb42bf26b99ca
- F ext/rtree/rtree.c fb36e05027505f2c0dab24564e1d58ca4b789a6dfa48cf51aeee570018cf4814 x
+ F ext/rtree/geopoly.c 0dd4775e896cee6067979d67aff7c998e75c2c9d9cd8d62a1a790c09cde7adca
 -F ext/rtree/rtree.c 2e1452a9338fe4db057fa677277bed86b65c667ed48b9b59144adae99f85a7cb
++F ext/rtree/rtree.c 2e1452a9338fe4db057fa677277bed86b65c667ed48b9b59144adae99f85a7cb x
  F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
- F ext/rtree/rtree1.test 877d40b8b61b1f88cec9d4dc0ff8334f5b05299fac12a35141532e2881860e9d x
 -F ext/rtree/rtree1.test 2b5b8c719c6a4abe377f57766f428a49af36a93061cb146cccfdc3b30000c0a4
++F ext/rtree/rtree1.test 2b5b8c719c6a4abe377f57766f428a49af36a93061cb146cccfdc3b30000c0a4 x
  F ext/rtree/rtree2.test 9d9deddbb16fd0c30c36e6b4fdc3ee3132d765567f0f9432ee71e1303d32603d
  F ext/rtree/rtree3.test 272594f88c344e973864008bbe4c71fd3a41a264c097d568593ee7886d83d409
  F ext/rtree/rtree4.test 304de65d484540111b896827e4261815e5dca4ce28eeecd58be648cd73452c4b
@@@ -470,12 -549,14 +553,14 @@@ F ext/session/sessionbig.test 47c381e7a
  F ext/session/sessiondiff.test ad13dd65664bae26744e1f18eb3cbd5588349b7e9118851d8f9364248d67bcec
  F ext/session/sessionfault.test 573bf027fb870d57bd4e7cf50822a3e4b17b2b923407438747aaa918dec57a09
  F ext/session/sessionfault2.test b0d6a7c1d7398a7e800d84657404909c7d385965ea8576dc79ed344c46fbf41c
+ F ext/session/sessionfault3.test 7c7547202775de268f3fe6f074c4d0d165151829710b4e64f90d4a01645ba9e7
  F ext/session/sessioninvert.test 04075517a9497a80d39c495ba6b44f3982c7371129b89e2c52219819bc105a25
  F ext/session/sessionmem.test f2a735db84a3e9e19f571033b725b0b2daf847f3f28b1da55a0c1a4e74f1de09
+ F ext/session/sessionnoact.test 506526a5fe29421ecc50d371774ef1bb04cbd9d906a8a468f0556cdbde184c22
  F ext/session/sessionnoop.test a9366a36a95ef85f8a3687856ebef46983df399541174cb1ede2ee53b8011bc7
 -F ext/session/sessionnoop2.test de4672dce88464396ec9f30ed08c6c01643a69c53ae540fadbbf6d30642d64e8
 +F ext/session/sessionnoop2.test de4672dce88464396ec9f30ed08c6c01643a69c53ae540fadbbf6d30642d64e8 x
  F ext/session/sessionrebase.test 702378bdcb5062f1106e74457beca8797d09c113a81768734a58b197b5b334e2
 -F ext/session/sessionrowid.test 85187c2f1b38861a5844868126f69f9ec62223a03449a98a80600a44396f7363
 +F ext/session/sessionrowid.test 85187c2f1b38861a5844868126f69f9ec62223a03449a98a80600a44396f7363 x
  F ext/session/sessionsize.test 8fcf4685993c3dbaa46a24183940ab9f5aa9ed0d23e5fb63bfffbdb56134b795
  F ext/session/sessionstat1.test b039e38e2ba83767b464baf39b297cc0b1cc6f3292255cb467ea7e12d0d0280c
  F ext/session/sessionwor.test 6fd9a2256442cebde5b2284936ae9e0d54bde692d0f5fd009ecef8511f4cf3fc
@@@ -498,61 -584,62 +588,62 @@@ F ext/wasm/api/extern-pre-js.js cc61c09
  F ext/wasm/api/post-js-footer.js cd0a8ec768501d9bd45d325ab0442037fb0e33d1f3b4f08902f15c34720ee4a1
  F ext/wasm/api/post-js-header.js 47b6b281f39ad59fa6e8b658308cd98ea292c286a68407b35ff3ed9cfd281a62
  F ext/wasm/api/pre-js.c-pp.js ad906703f7429590f2fbf5e6498513bf727a1a4f0ebfa057afb08161d7511219
- F ext/wasm/api/sqlite3-api-cleanup.js cc21e3486da748463e02bbe51e2464c6ac136587cdfd5aa00cd0b5385f6ca808
- F ext/wasm/api/sqlite3-api-glue.js f1b2dcb944de5138bb5bd9a1559d2e76a4f3ec25260963d709e8237476688803
+ F ext/wasm/api/sqlite3-api-cleanup.js d235ad237df6954145404305040991c72ef8b1881715d2a650dda7b3c2576d0e
+ F ext/wasm/api/sqlite3-api-glue.js 119b91c8a7ce6648679eb66fcdd1ed07ef7fd892eb501d658fbfefcc962012d9
 -F ext/wasm/api/sqlite3-api-oo1.js 9678dc4d9a5d39632b6ffe6ea94a023119260815bf32f265bf5f6c36c9516db8
 +F ext/wasm/api/sqlite3-api-oo1.js 9678dc4d9a5d39632b6ffe6ea94a023119260815bf32f265bf5f6c36c9516db8 x
- F ext/wasm/api/sqlite3-api-prologue.js 17f4ec398ba34c5c666fea8e8c4eb82064a35b302f2f2eb355283cd8d3f68ed5
- F ext/wasm/api/sqlite3-api-worker1.js 9f32af64df1a031071912eea7a201557fe39b1738645c0134562bb84e88e2fec x
+ F ext/wasm/api/sqlite3-api-prologue.js 9aeba7b45cf41b3a26d34d7fb2525633cd1adfc544888c1ea8dbb077496f4ce9
 -F ext/wasm/api/sqlite3-api-worker1.js 88770ac01fc756f89a3e060eec17111d6c1688e89ebfd34cb9d9e54d25affbb9
++F ext/wasm/api/sqlite3-api-worker1.js 88770ac01fc756f89a3e060eec17111d6c1688e89ebfd34cb9d9e54d25affbb9 x
  F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
- F ext/wasm/api/sqlite3-opfs-async-proxy.js 961bbc3ccc1fa4e91d6519a96e8811ad7ae60173bd969fee7775dacb6eee1da2 x
- F ext/wasm/api/sqlite3-v-helper.js e5c202a9ecde9ef818536d3f5faf26c03a1a9f5192b1ddea8bdabf30d75ef487
- F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 05f2563ddebfdc7a0f0ac0eb7cb381bb72043299aae1600ba9367c12f52b3fcc x
- F ext/wasm/api/sqlite3-wasi.h 25356084cfe0d40458a902afb465df8c21fc4152c1d0a59b563a3fba59a068f9
- F ext/wasm/api/sqlite3-wasm.c 12a096d8e58a0af0589142bae5a3c27a0c7e19846755a1a37d2c206352fbedda
 -F ext/wasm/api/sqlite3-opfs-async-proxy.js 8cf8a897726f14071fae6be6648125162b256dfb4f96555b865dbb7a6b65e379
++F ext/wasm/api/sqlite3-opfs-async-proxy.js 8cf8a897726f14071fae6be6648125162b256dfb4f96555b865dbb7a6b65e379 x
+ F ext/wasm/api/sqlite3-v-helper.js 7daa0eab0a513a25b05e9abae7b5beaaa39209b3ed12f86aeae9ef8d2719ed25
+ F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 595953994aa3ae2287c889c4da39ab3d6f17b6461ecf4bec334b7a3faafddb02
 -F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 46c4afa6c50d7369252c104f274ad977a97e91ccfafc38b400fe36e90bdda88e
++F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js 46c4afa6c50d7369252c104f274ad977a97e91ccfafc38b400fe36e90bdda88e x
+ F ext/wasm/api/sqlite3-wasm.c d0e09eb5ed3743c00294e30019e591c3aa150572ae7ffe8a8994568a7377589f
 -F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js bc06df0d599e625bde6a10a394e326dc68da9ff07fa5404354580f81566e591f
 +F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js bc06df0d599e625bde6a10a394e326dc68da9ff07fa5404354580f81566e591f x
- F ext/wasm/api/sqlite3-worker1.c-pp.js da509469755035e919c015deea41b4514b5e84c12a1332e6cc8d42cb2cc1fb75
+ F ext/wasm/api/sqlite3-worker1.c-pp.js a541112aa51e16705f13a99bb943c64efe178aa28c86704a955f8fd9afe4ba37
  F ext/wasm/batch-runner.html 4deeed44fe41496dc6898d9fb17938ea3291f40f4bfb977e29d0cef96fbbe4c8
  F ext/wasm/batch-runner.js 0dad6a02ad796f1003d3b7048947d275c4d6277f63767b8e685c27df8fdac93e
  F ext/wasm/c-pp.c 6d80d8569d85713effe8b0818a3cf51dc779e3f0bf8dc88771b8998552ee25b4
 -F ext/wasm/common/SqliteTestUtil.js 7adaeffef757d8708418dc9190f72df22367b531831775804b31598b44f6aa51
 +F ext/wasm/common/SqliteTestUtil.js 7adaeffef757d8708418dc9190f72df22367b531831775804b31598b44f6aa51 x
  F ext/wasm/common/emscripten.css 11bd104b6c0d597c67d40cc8ecc0a60dae2b965151e3b6a37fa5708bac3acd15
- F ext/wasm/common/testing.css 0ff15602a3ab2bad8aef2c3bd120c7ee3fd1c2054ad2ace7e214187ae68d926f
- F ext/wasm/common/whwasmutil.js 03407d7b61b817fd135c82401987e56688a45ee4d6b9c0eced160c0000d6e4c2
+ F ext/wasm/common/testing.css e97549bab24126c24e0daabfe2de9bb478fb0a69fdb2ddd0a73a992c091aad6f
+ F ext/wasm/common/whwasmutil.js 4c64594eecc7af4ae64259e95a71ba2a7edf118881aaff0bba86d0c7164e78e4
  F ext/wasm/demo-123-worker.html a0b58d9caef098a626a1a1db567076fca4245e8d60ba94557ede8684350a81ed
  F ext/wasm/demo-123.html 8c70a412ce386bd3796534257935eb1e3ea5c581e5d5aea0490b8232e570a508
- F ext/wasm/demo-123.js ebae30756585bca655b4ab2553ec9236a87c23ad24fc8652115dcedb06d28df6
+ F ext/wasm/demo-123.js 38aa8faec4d0ace1c973bc8a7a1533584463ebeecd4c420daa7d9687beeb9cb5
  F ext/wasm/demo-jsstorage.html 409c4be4af5f207fb2877160724b91b33ea36a3cd8c204e8da1acb828ffe588e
  F ext/wasm/demo-jsstorage.js 44e3ae7ec2483b6c511384c3c290beb6f305c721186bcf5398ca4e00004a06b8
  F ext/wasm/demo-worker1-promiser.html 1de7c248c7c2cfd4a5783d2aa154bce62d74c6de98ab22f5786620b3354ed15f
 -F ext/wasm/demo-worker1-promiser.js 5e5c7d7c91cd7aae9cc733afd02569ba9c6928292db413b550e8b842f4b75e87
 +F ext/wasm/demo-worker1-promiser.js 5e5c7d7c91cd7aae9cc733afd02569ba9c6928292db413b550e8b842f4b75e87 x
  F ext/wasm/demo-worker1.html 2c178c1890a2beb5a5fecb1453e796d067a4b8d3d2a04d65ca2eb1ab2c68ef5d
 -F ext/wasm/demo-worker1.js 836bece8615b17b1b572584f7b15912236a5947fe8c68b98d2737d7e287447ef
 +F ext/wasm/demo-worker1.js 836bece8615b17b1b572584f7b15912236a5947fe8c68b98d2737d7e287447ef x
- F ext/wasm/dist.make 451fb1b732257849f6e898d2a862512a0401500ed369ef53bdfeddf9c77bc3b9
+ F ext/wasm/dist.make 3a851858aad72e246a5d9c5aaf6b6a144305f1bf898ac1846760ea7bab95c9a3
  F ext/wasm/example_extra_init.c 2347cd69d19d839ef4e5e77b7855103a7fe3ef2af86f2e8c95839afd8b05862f
- F ext/wasm/fiddle.make dbe36b90b8907ae28ecb9c0e9fd8389dbdaecf117ea4fb2ea33864bdfa498a94
+ F ext/wasm/fiddle.make fa2ba6e90457ba2a71cb745f200d409caf773076df75ae5b177cc225d7627a11
  F ext/wasm/fiddle/emscripten.css 3d253a6fdb8983a2ac983855bfbdd4b6fa1ff267c28d69513dd6ef1f289ada3f
- F ext/wasm/fiddle/fiddle-worker.js 163d6139a93fab4bcb72064923df050d4e7c0ff0d8aa061ce8776a6e75da8a10
+ F ext/wasm/fiddle/fiddle-worker.js e0153f9af6500805c6f09c0b3cfdb7d857e9d6863dbee9d50d1628fccf5f4b4d
  F ext/wasm/fiddle/fiddle.js 974b995119ac443685d7d94d3b3c58c6a36540e9eb3fed7069d5653284071715
  F ext/wasm/fiddle/index.html 5daf54e8f3d7777cbb1ca4f93affe28858dbfff25841cb4ab81d694efed28ec2
  F ext/wasm/index-dist.html 22379774f0ad4edcaaa8cf9c674c82e794cc557719a8addabed74eb8069d412e
- F ext/wasm/index.html dd900891844caebd9cadbddd704f66bd841d7c12fd69ce5af490e2c10fb49f45
+ F ext/wasm/index.html 4e7847b909f4ae0da8c829b150b79454050e53b3658431f138636257729cd42b
  F ext/wasm/jaccwabyt/jaccwabyt.js 1264710db3cfbcb6887d95665b7aeba60c1126eaef789ca4cf1a4a17d5bc7f54
  F ext/wasm/jaccwabyt/jaccwabyt.md 37911f00db12cbcca73aa1ed72594430365f30aafae2fa9c886961de74e5e0eb
- F ext/wasm/module-symbols.html 841de62fc198988b8330e238c260e70ec93028b096e1a1234db31b187a899d10
- F ext/wasm/scratchpad-wasmfs-main.html 20cf6f1a8f368e70d01e8c17200e3eaa90f1c8e1029186d836d14b83845fbe06
- F ext/wasm/scratchpad-wasmfs-main.js 4c140457f4d6da9d646a49addd91edb6e9ad1643c6c48e3258b5bce24725dc18
- F ext/wasm/speedtest1-wasmfs.html 7a301f4f5b6ad4f5d37fd6e7ca03a2f5d5547fd289da60a39075a93d7646d354
- F ext/wasm/speedtest1-worker.html 82869822e641c1bef3ec0cd2d7d2b6a42d0b4f68a7b160fb2e1dd0b523940a9b
- F ext/wasm/speedtest1-worker.js 13b57c4a41729678a1194014afec2bd5b94435dcfc8d1039dfa9a533ac819ee1
+ F ext/wasm/module-symbols.html dc476b403369b26a1a23773e13b80f41b9a49f0825e81435fe3600a7cfbbe337
 -F ext/wasm/scratchpad-wasmfs.html a3d7388f3c4b263676b58b526846e9d02dfcb4014ff29d3a5040935286af5b96
 -F ext/wasm/scratchpad-wasmfs.mjs 66034b9256b218de59248aad796760a1584c1dd842231505895eff00dbd57c63
++F ext/wasm/scratchpad-wasmfs.html a3d7388f3c4b263676b58b526846e9d02dfcb4014ff29d3a5040935286af5b96 w ext/wasm/scratchpad-wasmfs-main.html
++F ext/wasm/scratchpad-wasmfs.mjs 66034b9256b218de59248aad796760a1584c1dd842231505895eff00dbd57c63 w ext/wasm/scratchpad-wasmfs-main.js
+ F ext/wasm/speedtest1-wasmfs.html 0e9d335a9b5b5fafe6e1bc8dc0f0ca7e22e6eb916682a2d7c36218bb7d67379d
+ F ext/wasm/speedtest1-wasmfs.mjs ac5cadbf4ffe69e9eaac8b45e8523f030521e02bb67d654c6eb5236d9c456cbe
+ F ext/wasm/speedtest1-worker.html e33e2064bda572c0c3ebaec7306c35aa758d9d27e245d67e807f8cc4a9351cc5
+ F ext/wasm/speedtest1-worker.js 315d26198c46be7c85e26fda15d80ef882424276abde25ffd8b026fb02a35d8c
  F ext/wasm/speedtest1.html ff048b4a623aa192e83e143e48f1ce2a899846dd42c023fdedc8772b6e3f07da
  F ext/wasm/split-speedtest1-script.sh a3e271938d4d14ee49105eb05567c6a69ba4c1f1293583ad5af0cd3a3779e205 x
  F ext/wasm/sql/000-mandelbrot.sql 775337a4b80938ac8146aedf88808282f04d02d983d82675bd63d9c2d97a15f0
  F ext/wasm/sql/001-sudoku.sql 35b7cb7239ba5d5f193bc05ec379bcf66891bce6f2a5b3879f2f78d0917299b5
  F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555e685bce3da8c3f
- F ext/wasm/test-opfs-vfs.js f09266873e1a34d9bdb6d3981ec8c9e382f31f215c9fd2f9016d2394b8ae9b7b
+ F ext/wasm/test-opfs-vfs.js 1618670e466f424aa289859fe0ec8ded223e42e9e69b5c851f809baaaca1a00c
 -F ext/wasm/tester1-worker.html ebc4b820a128963afce328ecf63ab200bd923309eb939f4110510ab449e9814c
 +F ext/wasm/tester1-worker.html ebc4b820a128963afce328ecf63ab200bd923309eb939f4110510ab449e9814c x
  F ext/wasm/tester1.c-pp.html 1c1bc78b858af2019e663b1a31e76657b73dc24bede28ca92fbe917c3a972af2
- F ext/wasm/tester1.c-pp.js 1a05497ae2b2fcca008d43b37072f9b841e1c970c06c01eb0faf675db567bfc8 x
 -F ext/wasm/tester1.c-pp.js a92dc256738dbd1b50f142d1fd0c835294ba09b7bb6526650360e942f88cb63f
++F ext/wasm/tester1.c-pp.js a92dc256738dbd1b50f142d1fd0c835294ba09b7bb6526650360e942f88cb63f x
  F ext/wasm/tests/opfs/concurrency/index.html 0802373d57034d51835ff6041cda438c7a982deea6079efd98098d3e42fbcbc1
  F ext/wasm/tests/opfs/concurrency/test.js a98016113eaf71e81ddbf71655aa29b0fed9a8b79a3cdd3620d1658eb1cc9a5d
  F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2
@@@ -561,7 -647,7 +651,7 @@@ F ext/wasm/wasmfs.make 8a4955882aaa0783
  F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
  F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
  F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
- F main.mk 3c80caf303240df102d4a59f19bfd660d44470d55707d1ead8b71698491f03bf
 -F main.mk 51fd5fc8565007266e6bfd9e299199c752b171707a667b8914a204b38258e1b1
++F main.mk ff98c33b4fc267701260ea661e1ef68d0ff51d9513a90a7966e4aff90e8604e9
  F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
  F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
  F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421
@@@ -570,131 -656,126 +660,131 @@@ F mptest/mptest.c aa41ace6dbc5050d76b02
  F mptest/multiwrite01.test dab5c5f8f9534971efce679152c5146da265222d
  F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
  F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
- F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
+ F sqlite3.1 acdff36db796e2d00225b911d3047d580cd136547298435426ce9d40347973cc
  F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
 -F sqlite3_x86.exe 871926af39a0a54f90df3ad8a4270a15cb01be59af42e81afd220525812be3d3 x
  F sqlite_cfg.h.in baf2e409c63d4e7a765e17769b6ff17c5a82bbd9cbf1e284fd2e4cefaff3fcf2
- F src/alter.c 3ff8c2fca0c0636d43459154bb40d79c882df1b34df77f89c4ec47ab2e2389f5 x
 -F src/alter.c 30c2333b8bb3af71e4eb9adeadee8aa20edb15917ed44b8422e5cd15f3dfcddc
 -F src/analyze.c d4cc28738c29e009640ec20ebb6936ba6fcefff0d11aa93398d9bb9a5ead6c1f
++F src/alter.c 30c2333b8bb3af71e4eb9adeadee8aa20edb15917ed44b8422e5cd15f3dfcddc x
 +F src/analyze.c d4cc28738c29e009640ec20ebb6936ba6fcefff0d11aa93398d9bb9a5ead6c1f x
  F src/attach.c cc9d00d30da916ff656038211410ccf04ed784b7564639b9b61d1839ed69fd39
 -F src/auth.c 19b7ccacae3dfba23fc6f1d0af68134fa216e9040e53b0681b4715445ea030b4
 +F src/auth.c 19b7ccacae3dfba23fc6f1d0af68134fa216e9040e53b0681b4715445ea030b4 x
  F src/backup.c 5c97e8023aab1ce14a42387eb3ae00ba5a0644569e3476f38661fa6f824c3523
 -F src/bitvec.c 9eac5f42c11914d5ef00a75605bb205e934f435c579687f985f1f8b0995c8645
 -F src/btmutex.c 79a43670447eacc651519a429f6ece9fd638563cf95b469d6891185ddae2b522
 +F src/bitvec.c 9eac5f42c11914d5ef00a75605bb205e934f435c579687f985f1f8b0995c8645 x
 +F src/btmutex.c 79a43670447eacc651519a429f6ece9fd638563cf95b469d6891185ddae2b522 x
- F src/btree.c c0c93b6cb4dc133b528c1290bb4ad0f2414452f9a5758ff2b106af718874f39e x
- F src/btree.h aa354b9bad4120af71e214666b35132712b8f2ec11869cb2315c52c81fad45cc
- F src/btreeInt.h 3b4eff7155c0cea6971dc51f62e3529934a15a6640ec607dd42a767e379cb3a9 x
- F src/build.c a8ae3b32d9aa9bbd2c0e97d7c0dd80def9fbca408425de1608f57ee6f47f45f4
+ F src/btree.c f3b09c5414de3a11db73e11e1d66f4c5e53c9e89876ff3b531a887ab656ca303 x
+ F src/btree.h 03e3356f5208bcab8eed4e094240fdac4a7f9f5ddf5e91045ce589f67d47c240
 -F src/btreeInt.h ef12a72b708677e48d6bc8dcd66fed25434740568b89e2cfa368093cfc5b9d15
++F src/btreeInt.h ef12a72b708677e48d6bc8dcd66fed25434740568b89e2cfa368093cfc5b9d15 x
+ F src/build.c 189e4517d67f09f0a3e0d8e1faa6e2ef0c2e95f6ac82e33c912cb7efa2a359cc
  F src/callback.c db3a45e376deff6a16c0058163fe0ae2b73a2945f3f408ca32cf74960b28d490
  F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
- F src/ctime.c 20507cc0b0a6c19cd882fcd0eaeda32ae6a4229fb4b024cfdf3183043d9b703d
- F src/date.c f73f203b3877cef866c60ab402aec2bf89597219b60635cf50cbe3c5e4533e94
- F src/dbpage.c f3eea5f7ec47e09ee7da40f42b25092ecbe961fc59566b8e5f705f34335b2387
- F src/dbstat.c ec92074baa61d883de58c945162d9e666c13cd7cf3a23bc38b4d1c4d0b2c2bef
- F src/delete.c cd5f5cd06ed0b6a882ec1a8c2a0d73b3cecb28479ad19e9931c4706c5e2182be
- F src/expr.c 8d1656b65e26af3e34f78e947ac423f0d20c214ed25a67486e433bf16ca6b543 x
+ F src/ctime.c 23331529e654be40ca97d171cbbffe9b3d4c71cc53b78fe5501230675952da8b
+ F src/date.c 3b8d02977d160e128469de38493b4085f7c5cf4073193459909a6af3cf6d7c91
+ F src/dbpage.c 80e46e1df623ec40486da7a5086cb723b0275a6e2a7b01d9f9b5da0f04ba2782
+ F src/dbstat.c 3b677254d512fcafd4d0b341bf267b38b235ccfddbef24f9154e19360fa22e43
+ F src/delete.c cb766727c78e715f9fb7ec8a7d03658ed2a3016343ca687acfcec9083cdca500
 -F src/expr.c e9a491c7f156e5b25641c28af11b735a424e108a21b9f83b6f3e51c99a8141d9
++F src/expr.c e9a491c7f156e5b25641c28af11b735a424e108a21b9f83b6f3e51c99a8141d9 x
  F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
- F src/fkey.c a7fcbf7e66d14dbb73cf49f31489ebf66d0e6006c62b95246924a3bae9f37b36 x
- F src/func.c 8ada46d362a153b8dfb5385c3aaa9a7d75ebf306b33d2e663aa03920126a1bc3 x
- F src/global.c bd0892ade7289f6e20bff44c07d06371f2ff9b53cea359e7854b9b72f65adc30
 -F src/fkey.c a47610f0a5c6cb0ad79f8fcef039c01833dec0c751bb695f28dc0ec6a4c3ba00
 -F src/func.c 472f6dcfa39cf54f89a6aec76c79c225fb880a6c14469c15d361331662b9bf43
++F src/fkey.c a47610f0a5c6cb0ad79f8fcef039c01833dec0c751bb695f28dc0ec6a4c3ba00 x
++F src/func.c 472f6dcfa39cf54f89a6aec76c79c225fb880a6c14469c15d361331662b9bf43 x
+ F src/global.c 29f56a330ed9d1b5cd9b79ac0ca36f97ac3afc730ff8bfa987b0db9e559d684d
 -F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220
 +F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220 x
  F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
 -F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6
 +F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6 x
  F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
  F src/insert.c 3f0a94082d978bbdd33c38fefea15346c6c6bffb70bc645a71dc0f1f87dd3276
- F src/json.c 14c474fb1249a46eb44e878e2361f36abfe686b134039b0d1883d93d61505b4a x
 -F src/json.c f93bf3df3651b1e01e2b57f7dc56f727e7b0e212d934eacf21c6fc8b31bf685e
++F src/json.c f93bf3df3651b1e01e2b57f7dc56f727e7b0e212d934eacf21c6fc8b31bf685e x
  F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
- F src/loadext.c 176d6b2cb18a6ad73b133db17f6fc351c4d9a2d510deebdb76c22bde9cfd1465 x
- F src/main.c 5fd4b65d61ae6155f36756ed508a39b38b49355b031188961e8d923f43f4bc49 x
- F src/malloc.c 47b82c5daad557d9b963e3873e99c22570fb470719082c6658bf64e3012f7d23
 -F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36
 -F src/main.c 1b89f3de98d1b59fec5bac1d66d6ece21f703821b8eaa0d53d9604c35309f6f9
++F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36 x
++F src/main.c 1b89f3de98d1b59fec5bac1d66d6ece21f703821b8eaa0d53d9604c35309f6f9 x
+ F src/malloc.c f016922435dc7d1f1f5083a03338a3e91f8c67ce2c5bdcfa4cdef62e612f5fcc
  F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
 -F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
 +F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2 x
  F src/mem2.c c8bfc9446fd0798bddd495eb5d9dbafa7d4b7287d8c22d50a83ac9daa26d8a75
  F src/mem3.c 30301196cace2a085cbedee1326a49f4b26deff0af68774ca82c1f7c06fda4f6
  F src/mem5.c b7da5c10a726aacacc9ad7cdcb0667deec643e117591cc69cf9b4b9e7f3e96ff
  F src/memdb.c 559c42e61eb70cd6d4bc692b042497133c6d96c09a3d514d92f3dac72268e223
  F src/memjournal.c c283c6c95d940eb9dc70f1863eef3ee40382dbd35e5a1108026e7817c206e8a0
  F src/msvc.h 80b35f95d93bf996ccb3e498535255f2ef1118c78764719a7cd15ab4106ccac9
- F src/mutex.c 5e3409715552348732e97b9194abe92fdfcd934cfb681df4ba0ab87ac6c18d25
+ F src/mutex.c 1b4c7e5e3621b510e0c18397210be27cd54c8084141144fbbafd003fde948e88
  F src/mutex.h a7b2293c48db5f27007c3bdb21d438873637d12658f5a0bf8ad025bb96803c4a
  F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4
- F src/mutex_unix.c bd52ec50e44a41fe1e3deb5a6e3fe98edb6f2059da3e46d196363d0fa3192cda x
- F src/mutex_w32.c 38b56d0bc8d54c17c20cbaaad3719b0c36b92fd07a7e34360d0c6a18d5589912 x
- F src/notify.c 89a97dc854c3aa62ad5f384ef50c5a4a11d70fcc69f86de3e991573421130ed6
 -F src/mutex_unix.c f7ee5a2061a4c11815a2bf4fc0e2bfa6fb8d9dc89390eb613ca0cec32fc9a3d1
 -F src/mutex_w32.c 28f8d480387db5b2ef5248705dd4e19db0cfc12c3ba426695a7d2c45c48e6885
++F src/mutex_unix.c f7ee5a2061a4c11815a2bf4fc0e2bfa6fb8d9dc89390eb613ca0cec32fc9a3d1 x
++F src/mutex_w32.c 28f8d480387db5b2ef5248705dd4e19db0cfc12c3ba426695a7d2c45c48e6885 x
+ F src/notify.c 57c2d1a2805d6dee32acd5d250d928ab94e02d76369ae057dee7d445fd64e878
 -F src/os.c 509452169d5ea739723e213b8e2481cf0e587f0e88579a912d200db5269f5f6d
 +F src/obj_interfaces.h f991295c0dc7c2aca595a9966d5918f3d19eb5dcf62df6819c4680c8cc00084d x
 +F src/os.c 509452169d5ea739723e213b8e2481cf0e587f0e88579a912d200db5269f5f6d x
  F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63
  F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e06
  F src/os_kv.c 4d39e1f1c180b11162c6dc4aa8ad34053873a639bac6baae23272fc03349986a
  F src/os_setup.h 6011ad7af5db4e05155f385eb3a9b4470688de6f65d6166b8956e58a3d872107
- F src/os_unix.c 95b407307deb902a3bd9a5d5666c7838709cccb337baeee6ef0a53f512d3673e x
- F src/os_win.c 7038223a1cda0a47e2ab4db47f63bf1833fe53ba0542f0f283a062ea13894103 x
 -F src/os_unix.c dc5404b56da7fb13cf272ddb94c3753cf9e82d32a65cba35dbb6aadcb849419c
 -F src/os_win.c 4a50a154aeebc66a1f8fb79c1ff6dd5fe3d005556533361e0d460d41cb6a45a8
++F src/os_unix.c dc5404b56da7fb13cf272ddb94c3753cf9e82d32a65cba35dbb6aadcb849419c x
++F src/os_win.c 4a50a154aeebc66a1f8fb79c1ff6dd5fe3d005556533361e0d460d41cb6a45a8 x
  F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
- F src/pager.c 5ddf3a74c633a008ea6b2f5b3186167e88e2c8ca8a252ecab06ab3f1eb48e60f x
- F src/pager.h f82e9844166e1585f5786837ddc7709966138ced17f568c16af7ccf946c2baa3
- F src/parse.y 8828f9e15f04d469eab9c0f2aed504e534b1c97c68836bed6f07afab29c2ac0b x
- F src/pcache.c 4cd4a0043167da9ba7e19b4d179a0e6354e7fe32c16f781ecf9bf0a5ff63b40b x
 -F src/pager.c 987ab3a2cd9065d62e9955474470ff733445e2357432a67e3d0f5a8f9313e334
++F src/pager.c 987ab3a2cd9065d62e9955474470ff733445e2357432a67e3d0f5a8f9313e334 x
+ F src/pager.h f4d33fec8052603758792045493423b8871a996da2d0973927b7d36cd6070473
 -F src/parse.y 020d80386eb216ec9520549106353c517d2bbc89be28752ffdca649a9eaf56ec
 -F src/pcache.c 040b165f30622a21b7a9a77c6f2e4877a32fb7f22d4c7f0d2a6fa6833a156a75
++F src/parse.y 020d80386eb216ec9520549106353c517d2bbc89be28752ffdca649a9eaf56ec x
++F src/pcache.c 040b165f30622a21b7a9a77c6f2e4877a32fb7f22d4c7f0d2a6fa6833a156a75 x
  F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
 -F src/pcache1.c 602acb23c471bb8d557a6f0083cc2be641d6cafcafa19e481eba7ef4c9ca0f00
 -F src/pragma.c b3b4ad9c0298d63098a067acca613c21a5f56b4d176d5842922bcd0b07b7164e
 +F src/pcache1.c 602acb23c471bb8d557a6f0083cc2be641d6cafcafa19e481eba7ef4c9ca0f00 x
- F src/pragma.c 37b8fb02d090262280c86e1e2654bf59d8dbfbfe8dc6733f2b968a11374c095a x
++F src/pragma.c b3b4ad9c0298d63098a067acca613c21a5f56b4d176d5842922bcd0b07b7164e x
  F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7
- F src/prepare.c d6c4354f8ea0dc06962fbabc4b68c4471a45276a2918c929be00f9f537f69eb1 x
- F src/printf.c a87473be34fa2acafa27692b8ae078275c7e23360956c93c07ff22f5d609cbd7
 -F src/prepare.c 371f6115cb69286ebc12c6f2d7511279c2e47d9f54f475d46a554d687a3b312c
++F src/prepare.c 371f6115cb69286ebc12c6f2d7511279c2e47d9f54f475d46a554d687a3b312c x
+ F src/printf.c 9da63b9ae1c14789bcae12840f5d800fd9302500cd2d62733fac77f0041b4750
  F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
- F src/resolve.c 37953a5f36c60bea413c3c04efcd433b6177009f508ef2ace0494728912fe2e9
 +F src/resmanage.c b85f77821ea0280c73a6afc1dc3b6884ba3a402515c6bf27ba1567408e4f121d x
 +F src/resmanage.h eb63130e49d7b696a33c6d39d1c437a050bbef42b4f6f4405a15fc563c7dd61e x
 -F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
 -F src/select.c 85857bedd2913d888aa571755b48c54cd2e6e7fcb0087e19b226ee0368cfda1e
 -F src/shell.c.in 345be14456aeadfaaeced4149563a4a6d70942d8a38a1cd27b75d4e491757028
 -F src/sqlite.h.in d93a4821d2f792467a60f7dc81268d1bb8634f40c31694ef254cab4f9921f96a
+ F src/resolve.c d017bad7ba8e778617701a0e986fdeb393d67d6afa84fb28ef4e8b8ad2acf916
- F src/select.c 383b9dba12493c365ee2036bcadd73013b7c0f7d2afcda0c378317c335d60ac2 x
- F src/shell.c.in 3d9053cee4ccb6744e4b18f1f980d037bfebc8a01c162fbc6f35e194858a4ab1
 +F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97 x
- F src/sqlite.h.in 3076d78836b6dac53b3ab0875fc8fd15bca8077aad4d33c85336e05af6aef8c7 x
++F src/select.c 85857bedd2913d888aa571755b48c54cd2e6e7fcb0087e19b226ee0368cfda1e x
++F src/shell.c.in 99ff6acd07521bc0505fb6faa6d58f32df9136559d7665e8d065d14302fe757c
 +F src/shext_linkage.h 4a686427844d5d2b71f2095cb032280fb262490795f0710487ebbedb3732f1cb x
++F src/sqlite.h.in d93a4821d2f792467a60f7dc81268d1bb8634f40c31694ef254cab4f9921f96a x
  F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
- F src/sqlite3ext.h da473ce2b3d0ae407a6300c4a164589b9a6bfdbec9462688a8593ff16f3bb6e4
- F src/sqliteInt.h f7e904f7fdeccfd5606ca4457122e647dcbaf307ed8615ac4865f8b5f536f77b
+ F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
+ F src/sqliteInt.h cd171cba32c7a553e7623fbd82b68b36a1b6c81079ab963260777ea9b3abe4d9
 -F src/sqliteLimit.h 33b1c9baba578d34efe7dfdb43193b366111cdf41476b1e82699e14c11ee1fb6
 +F src/sqliteLimit.h 33b1c9baba578d34efe7dfdb43193b366111cdf41476b1e82699e14c11ee1fb6 x
  F src/status.c 160c445d7d28c984a0eae38c144f6419311ed3eace59b44ac6dafc20db4af749
  F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
 -F src/tclsqlite.c ecbc3c99c0d0c3ed122a913f143026c26d38d57f33e06bb71185dd5c1efe37cd
 -F src/test1.c f9620e8f0d0fa4edb239201a732c4dd1562f0cdd9741955c89332d49e14a5edd
 +F src/tclsqlite.c ecbc3c99c0d0c3ed122a913f143026c26d38d57f33e06bb71185dd5c1efe37cd x
- F src/test1.c e6ab4a00671f052366a01bcb7fdf2e2f6bb4aa884cd01e738c5590dcf47a99ca x
- F src/test2.c 827446e259a3b7ab949da1542953edda7b5117982576d3e6f1c24a0dd20a5cef
++F src/test1.c f9620e8f0d0fa4edb239201a732c4dd1562f0cdd9741955c89332d49e14a5edd x
+ F src/test2.c 54520d0565ef2b9bf0f8f1dcac43dc4d06baf4ffe13d10905f8d8c3ad3e4b9ab
 -F src/test3.c e5178558c41ff53236ae0271e9acb3d6885a94981d2eb939536ee6474598840e
 +F src/test3.c e5178558c41ff53236ae0271e9acb3d6885a94981d2eb939536ee6474598840e x
  F src/test4.c 4533b76419e7feb41b40582554663ed3cd77aaa54e135cf76b3205098cd6e664
  F src/test5.c 328aae2c010c57a9829d255dc099d6899311672d
 -F src/test6.c e53bc69dc3cb3815fb74df74f38159ec05ba6dd5273216062e26bc797f925530
 -F src/test8.c 303c2e3bcf7795e888810a7ef03809602b851f0ebec8d6e06a429ed85cafd9a2
 +F src/test6.c e53bc69dc3cb3815fb74df74f38159ec05ba6dd5273216062e26bc797f925530 x
- F src/test8.c ccc5d3e2a2bf7248f7da185e2afc4c08b4c6840447f5eb4dd106db165fddbdbc x
++F src/test8.c 303c2e3bcf7795e888810a7ef03809602b851f0ebec8d6e06a429ed85cafd9a2 x
  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 68c62586d2ae9f032903fe53be743657d0c2aac0a850b880938b668e1161d516
+ F src/test_bestindex.c f6af1e41cb7901edafb065a8198e4a0192dd42432b642d038965be5e628dec12
  F src/test_blob.c ae4a0620b478548afb67963095a7417cd06a4ec0a56adb453542203bfdcb31ce
  F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274
 -F src/test_config.c f0cc1f517deaa96dd384822ae2bb91534fa56aa458528b439830d709941d3932
 +F src/test_config.c f0cc1f517deaa96dd384822ae2bb91534fa56aa458528b439830d709941d3932 x
  F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f
  F src/test_demovfs.c 38a459d1c78fd9afa770445b224c485e079018d6ac07332ff9bd07b54d2b8ce9
 -F src/test_devsym.c 649434ed34d0b03fbd5a6b42df80f0f9a7e53f94dd1710aad5dd8831e91c4e86
 +F src/test_devsym.c 649434ed34d0b03fbd5a6b42df80f0f9a7e53f94dd1710aad5dd8831e91c4e86 x
- F src/test_fs.c ba1e1dc18fd3159fdba0b9c4256f14032159785320dfbd6776eb9973cb75d480
+ F src/test_fs.c 56cc17e4fdc57efa61695026e2ba96e910b17060d7ee01d775ec048791522e2f
  F src/test_func.c 24df3a346c012b1fc9e1001d346db6054deb426db0a7437e92490630e71c9b0a
  F src/test_hexio.c 9478e56a0f08e07841a014a93b20e4ba2709ab56d039d1ca8020e26846aa19bd
 -F src/test_init.c f2cc4774b7c9140f76e45ecbb2ae219f68e3acbbe248c0179db666a70eae9f08
 +F src/test_init.c f2cc4774b7c9140f76e45ecbb2ae219f68e3acbbe248c0179db666a70eae9f08 x
- F src/test_intarray.c 39b4181662a0f33a427748d87218e7578d913e683dc27eab7098bb41617cac71
+ F src/test_intarray.c 26ffba666beb658d73cd925d9b4fb56913a3ca9aaeac122b3691436abb192b92
 -F src/test_intarray.h 6c3534641108cd1bea517a8e117dcba237081310a29a4c35bd2190caa8972293
 +F src/test_intarray.h 6c3534641108cd1bea517a8e117dcba237081310a29a4c35bd2190caa8972293 x
  F src/test_journal.c a0b9709b2f12b1ec819eea8a1176f283bca6d688a6d4a502bd6fd79786f4e287
  F src/test_loadext.c 337056bae59f80b9eb00ba82088b39d0f4fe6dfd
  F src/test_malloc.c 21121ea85b49ec0bdb69995847cef9036ef9beca3ce63bbb776e4ea2ecc44b97
 -F src/test_md5.c 0472c86d561f7f9e4ff94080100c2783196f50e583bb83375b759450c5b81802
 -F src/test_multiplex.c 70479161239d65af2a231550b270e9d11ece717ad7bf0e13ef42206586e9dd7f
 -F src/test_multiplex.h f0ff5b6f4462bfd46dac165d6375b9530d08089b7bcbe75e88e0926110db5363
 -F src/test_mutex.c cd5bac43f2fd168f43c4326b1febe0966439217fac52afb270a6b8215f94cb40
 +F src/test_md5.c 0472c86d561f7f9e4ff94080100c2783196f50e583bb83375b759450c5b81802 x
 +F src/test_multiplex.c 70479161239d65af2a231550b270e9d11ece717ad7bf0e13ef42206586e9dd7f x
 +F src/test_multiplex.h f0ff5b6f4462bfd46dac165d6375b9530d08089b7bcbe75e88e0926110db5363 x
 +F src/test_mutex.c cd5bac43f2fd168f43c4326b1febe0966439217fac52afb270a6b8215f94cb40 x
  F src/test_onefile.c f31e52e891c5fef6709b9fcef54ce660648a34172423a9cbdf4cbce3ba0049f4
- F src/test_osinst.c d341f9d7613e007c8c3f7eba6cd307230047506aa8f97858c1fd21f5069616bd
+ F src/test_osinst.c 8e11faf10f5d4df10d3450ecee0b8f4cfa2b62e0f341fafbeb480a08cefeaec4
 -F src/test_pcache.c 3960cd2c1350adc992c4bf7adcfb0d1ac0574733012bd1a5f94e195928577599
 -F src/test_quota.c ea44c05f29b995bdb71c55eb0c602604884e55681d59b7736e604bbcc68b0464
 +F src/test_pcache.c 3960cd2c1350adc992c4bf7adcfb0d1ac0574733012bd1a5f94e195928577599 x
 +F src/test_quota.c ea44c05f29b995bdb71c55eb0c602604884e55681d59b7736e604bbcc68b0464 x
  F src/test_quota.h 2a8ad1952d1d2ca9af0ce0465e56e6c023b5e15d
  F src/test_rtree.c 671f3fae50ff116ef2e32a3bf1fe21b5615b4b7b
- F src/test_schema.c f5d6067dfc2f2845c4dd56df63e66ee826fb23877855c785f75cc2ca83fd0c1b
+ F src/test_schema.c cbfd7a9a9b6b40d4377d0c76a6c5b2a58387385977f26edab4e77eb5f90a14ce
 +F src/test_shellext_c.c 9caae730dbbea057cbded37bcab0df4e5fdf87007bbe590d53c33c6044bf1d6e x
 +F src/test_shellext_cpp.cpp 244f35ee4ead819ac9d3a4e91e961adfa0d74b92476697b9f3b23320a8dca68a x
  F src/test_sqllog.c 540feaea7280cd5f926168aee9deb1065ae136d0bbbe7361e2ef3541783e187a
  F src/test_superlock.c 4839644b9201da822f181c5bc406c0b2385f672e
  F src/test_syscall.c 9fdb13b1df05e639808d44fcb8f6064aaded32b6565c00b215cfd05a060d1aca
@@@ -709,34 -790,34 +799,34 @@@ F src/test_windirent.h da2e5b73c32d0990
  F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394ba3f
  F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
  F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
- F src/tokenize.c 0fb405f9adf3f757c26bfc1ae6d58ac5dccbb918917ba9e5ef0e6673a06563d3
- F src/treeview.c 1d52fbc4e97161e65858d36e3424ea6e3fc045dd8a679c82b4b9593dc30de3bd x
- F src/trigger.c ad6ab9452715fa9a8075442e15196022275b414b9141b566af8cdb7a1605f2b0
- F src/update.c 0aa36561167a7c40d01163238c297297962f31a15a8d742216b3c37cdf25f731
- F src/upsert.c 5303dc6c518fa7d4b280ec65170f465c7a70b7ac2b22491598f6d0b4875b3145
+ F src/tokenize.c 23d9f4539880b40226254ad9072f4ecf12eb1902e62aea47aac29928afafcfd5
 -F src/treeview.c c6fc972683fd00f975d8b32a81c1f25d2fb7d4035366bf45c9f5622d3ccd70ee
++F src/treeview.c c6fc972683fd00f975d8b32a81c1f25d2fb7d4035366bf45c9f5622d3ccd70ee x
+ F src/trigger.c 0905b96b04bb6658509f711a8207287f1315cdbc3df1a1b13ba6483c8e341c81
+ F src/update.c 6904814dd62a7a93bbb86d9f1419c7f134a9119582645854ab02b36b676d9f92
+ F src/upsert.c fa125a8d3410ce9a97b02cb50f7ae68a2476c405c76aa692d3acf6b8586e9242
  F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
- F src/util.c a6b41c67ff2a5379b46b77e587b2e0adb2d2ddcc5669691674ca4d28e2755ae4 x
 -F src/util.c b22cc9f203a8c0b9ee5338a67f8860347d14845864c10248bebe84518a781677
 -F src/vacuum.c 604fcdaebe76f3497c855afcbf91b8fa5046b32de3045bab89cc008d68e40104
 -F src/vdbe.c 319af2cf092d20e233e8ad4267ae49bfe33c50ac4db4ee7e47af898f824c2368
 -F src/vdbe.h 41485521f68e9437fdb7ec4a90f9d86ab294e9bb8281e33b235915e29122cfc0
 -F src/vdbeInt.h 949669dfd8a41550d27dcb905b494f2ccde9a2e6c1b0b04daa1227e2e74c2b2c
 -F src/vdbeapi.c b07df805110dc6e81f2a3f9cd4e83f56ea523277a59bcec489a12b740c1079e7
++F src/util.c b22cc9f203a8c0b9ee5338a67f8860347d14845864c10248bebe84518a781677 x
 +F src/vacuum.c 604fcdaebe76f3497c855afcbf91b8fa5046b32de3045bab89cc008d68e40104 x
- F src/vdbe.c c993304c609326cf625b4ad30cbb0e15a3f64c941cf2c9713d0c360b4abbaa98 x
++F src/vdbe.c 319af2cf092d20e233e8ad4267ae49bfe33c50ac4db4ee7e47af898f824c2368 x
 +F src/vdbe.h 41485521f68e9437fdb7ec4a90f9d86ab294e9bb8281e33b235915e29122cfc0 x
- F src/vdbeInt.h 7bd49eef8f89c1a271fbf12d80a206bf56c876814c5fc6bee340f4e1907095ae x
- F src/vdbeapi.c de9703f8705afc393cc2864669ce28cf9516983c8331d59aa2b978de01634365 x
- F src/vdbeaux.c 4d5e68a3850d0b193a692eca6442d7afe35252aaf29728a67adcb542ecabd9ce
- F src/vdbeblob.c 2516697b3ee8154eb8915f29466fb5d4f1ae39ee8b755ea909cefaf57ec5e2ce
- F src/vdbemem.c 710119a8e35e47813681c48703d65a80ba22792192de90bc51dc0d6366f2a79e x
- F src/vdbesort.c 0d40dca073c94e158ead752ef4225f4fee22dee84145e8c00ca2309afb489015 x
++F src/vdbeInt.h 949669dfd8a41550d27dcb905b494f2ccde9a2e6c1b0b04daa1227e2e74c2b2c x
++F src/vdbeapi.c b07df805110dc6e81f2a3f9cd4e83f56ea523277a59bcec489a12b740c1079e7 x
+ F src/vdbeaux.c b34dfbc09403ccb676608da16ff0780d23d466470563d24fdf6350b8d2271d5e
+ F src/vdbeblob.c 13f9287b55b6356b4b1845410382d6bede203ceb29ef69388a4a3d007ffacbe5
 -F src/vdbemem.c 0012d5f01cc866833847c2f3ae4c318ac53a1cb3d28acad9c35e688039464cf0
 -F src/vdbesort.c 237840ca1947511fa59bd4e18b9eeae93f2af2468c34d2427b059f896230a547
++F src/vdbemem.c 0012d5f01cc866833847c2f3ae4c318ac53a1cb3d28acad9c35e688039464cf0 x
++F src/vdbesort.c 237840ca1947511fa59bd4e18b9eeae93f2af2468c34d2427b059f896230a547 x
  F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823
- F src/vdbevtab.c aae4bd769410eb7e1d02c42613eec961d514459b1c3c1c63cfc84e92a137daac
- F src/vtab.c 1ecf8c3745d29275688d583e12822fa984d421e0286b5ef50c137bc3bf6d7a64 x
+ F src/vdbevtab.c 2143db7db0ceed69b21422581f434baffc507a08d831565193a7a02882a1b6a7
 -F src/vtab.c 154725ebecd3bc02f7fbd7ad3974334f73fff76e02a964e828e48a7c5fb7efff
++F src/vtab.c 154725ebecd3bc02f7fbd7ad3974334f73fff76e02a964e828e48a7c5fb7efff x
  F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
- F src/wal.c cbfeeb7415baa545efa244dd34bb5af4ae953a206fed720c6fa7f1ef763ec122 x
- F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
 -F src/wal.c 69aa3ce60b2862a24cd86bb528e653e2137388ead258ef64db49ec9038807f5f
++F src/wal.c 69aa3ce60b2862a24cd86bb528e653e2137388ead258ef64db49ec9038807f5f x
+ F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
  F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2
- F src/where.c 94c90f838057e8f1ac6ab6e4caf64bbf487f4d0d33e64643731ff99e80a50b54 x
- F src/whereInt.h c7d19902863beadec1d04e66aca39c0bcd60b74f05f0eaa7422c7005dfc5d51a x
- F src/wherecode.c bff0bc56cb1a382de266c2db3a691135c18a4360b6ad5e069e5c415d57eb0c38 x
+ F src/where.c 1fdc69ce1333e9bd6d7d3df9fa5af1373a3f5bfdd52108d1dbc0ca85a55f777e
 -F src/whereInt.h 4b38c5889514e3aead3f27d0ee9a26e47c3f150efc59e2a8b4e3bc8835e4d7a1
 -F src/wherecode.c 5d77db30a2a3dd532492ae882de114edba2fae672622056b1c7fd61f5917a8f1
 -F src/whereexpr.c dc5096eca5ed503999be3bdee8a90c51361289a678d396a220912e9cb73b3c00
 -F src/window.c 5b1387d59df30d481ed14cceef5f4d1dab1f8752aa106ba72c8b62777bd139d2
++F src/whereInt.h 4b38c5889514e3aead3f27d0ee9a26e47c3f150efc59e2a8b4e3bc8835e4d7a1 x
++F src/wherecode.c 5d77db30a2a3dd532492ae882de114edba2fae672622056b1c7fd61f5917a8f1 x
 +F src/whereexpr.c dc5096eca5ed503999be3bdee8a90c51361289a678d396a220912e9cb73b3c00 x
- F src/window.c b7ad9cff3ce8ae6f8cc25e18e1a258426cb6bd2999aace6f5248d781b2a74098 x
++F src/window.c 5b1387d59df30d481ed14cceef5f4d1dab1f8752aa106ba72c8b62777bd139d2 x
  F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
  F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
  F test/affinity3.test f094773025eddf31135c7ad4cde722b7696f8eb07b97511f98585addf2a510a9
@@@ -764,9 -846,9 +855,9 @@@ F test/alterqf.test 8ec03d776de9c391daa
  F test/altertab.test 8a2712f9076da5012a002d0b5cc0a421398a5bf61c25bab41b77c427586a7a27
  F test/altertab2.test 62597b6fd08feaba1b6bfe7d31dac6117c67e06dc9ce9c478a3abe75b5926de0
  F test/altertab3.test 6c432fbb9963e0bd6549bf1422f6861d744ee5a80cb3298564e81e556481df16
- F test/altertrig.test fb5951d21a2c954be3b8a8cf8e10b5c0fa20687c53fd67d63cea88d08dd058d5
+ F test/altertrig.test aacc980b657354fe2d3d4d3a004f07d04ccc1a93e5ef82d68a79088c274ddc6b
  F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
 -F test/analyze.test 2fb21d7d64748636384e6cb8998dbf83968caf644c07fcb4f76c18f2e7ede94b
 +F test/analyze.test 2fb21d7d64748636384e6cb8998dbf83968caf644c07fcb4f76c18f2e7ede94b x
  F test/analyze3.test 03f4b3d794760cf15da2d85a52df9bae300e51c8fefe9c36cfae1f86dc10d23f
  F test/analyze4.test 68bd069f3ac7ac1e652ddd9f04f57d5606ddb4208450f5297005db7aa0dd707d
  F test/analyze5.test fa5131952303ac4146aba101b116b9c8cb89e2637531c334a6df7f7d19dddc0d
@@@ -1132,7 -1221,7 +1230,7 @@@ F test/fuzz3.test 9c813e6613b837cb7a277
  F test/fuzz4.test c229bcdb45518a89e1d208a21343e061503460ac69fae1539320a89f572eb634
  F test/fuzz_common.tcl b7197de6ed1ee8250a4f82d67876f4561b42ee8cbbfc6160dcb66331bad3f830
  F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2
- F test/fuzzcheck.c 29a2f0237553375498f891c9487a2ef3267b47deecc5d5b4335fa37f904cb8d3 x
 -F test/fuzzcheck.c 69b8549e112fb815931a8c14c7955a0c407ae91a79356eecb82458384f2cb989
++F test/fuzzcheck.c 69b8549e112fb815931a8c14c7955a0c407ae91a79356eecb82458384f2cb989 x
  F test/fuzzdata1.db 3e86d9cf5aea68ddb8e27c02d7dfdaa226347426c7eb814918e4d95475bf8517
  F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
  F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
@@@ -1223,7 -1313,7 +1322,7 @@@ F test/joinC.test 1f1a602c2127f55f136e2
  F test/joinD.test 2ce62e7353a0702ca5e70008faf319c1d4686aa19fba34275c6d1da0e960be28
  F test/joinE.test d5d182f3812771e2c0d97c9dcf5dbe4c41c8e21c82560e59358731c4a3981d6b
  F test/joinF.test 53dd66158806823ea680dd7543b5406af151b5aafa5cd06a7f3231cd94938127
- F test/joinH.test c9550bb6a0257cf99668a28485bb309bac542081702e89261b95542ab5f676b1 x
 -F test/joinH.test f69e5b53b7d887914e854b6a131efbed4ea9f5ca52bdab81788bfc3e79299f43
++F test/joinH.test f69e5b53b7d887914e854b6a131efbed4ea9f5ca52bdab81788bfc3e79299f43 x
  F test/journal1.test c7b768041b7f494471531e17abc2f4f5ebf9e5096984f43ed17c4eb80ba34497
  F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4
  F test/journal3.test 7c3cf23ffc77db06601c1fcfc9743de8441cb77db9d1aa931863d94f5ffa140e
@@@ -1239,10 -1329,10 +1338,10 @@@ F test/json102.test 4c69694773a470f1fda
  F test/json103.test 53df87f83a4e5fa0c0a56eb29ff6c94055c6eb919f33316d62161a8880112dbe
  F test/json104.test 1b844a70cddcfa2e4cd81a5db0657b2e61e7f00868310f24f56a9ba0114348c1
  F test/json105.test 11670a4387f4308ae0318cadcbd6a918ea7edcd19fbafde020720a073952675d
- F test/json501.test f71710f60fa45b19dc336fbaac9e8362f70f80cf81badefdb845ed3f7c7c2ccc
+ F test/json501.test c419deb835b70c1a2c8532936927bcc1146730328edd2052276715bfd209724d
  F test/json502.test 98c38e3c4573841028a1381dfb81d4c3f9b105d39668167da10d055e503f6d0b
  F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
 -F test/kvtest.c 6e0228409ea7ca0497dad503fbd109badb5e59545d131014b6aaac68b56f484a
 +F test/kvtest.c 6e0228409ea7ca0497dad503fbd109badb5e59545d131014b6aaac68b56f484a x
  F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
  F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
  F test/lemon-test01.y 58b764610fd934e189ffbb0bbfa33d171b9cb06019b55bdc04d090d6767e11d7
@@@ -1370,9 -1460,9 +1469,9 @@@ F test/pagesize.test 5769fc62d8c890a83a
  F test/parser1.test 6ccdf5e459a5dc4673d3273dc311a7e9742ca952dd0551a6a6320d27035ce4b3
  F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
  F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
- F test/pendingrace.test cbdf0f74bc939fb43cebad64dda7a0b5a3941a10b7e9cc2b596ff3e423a18156
+ F test/pendingrace.test 6aa33756b950c4529f79c4f3817a9a1e4025bd0d9961571a05c0279bd183d9c6
  F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
- F test/permutations.test aeebc29c7b225487c0235fc8be65f51e2cc19c7ff00c4c0c342315ca6957c0d1
 -F test/permutations.test f7caf8dd5c7b1da74842a48df116f7f193399c656d4ffc805cd0d9658568c675
++F test/permutations.test 20b30816421e9fc3027d1c3bfaf6e3bdadb32d8edbf0eaaf371ff6f3c761e36c
  F test/pg_common.tcl 3b27542224db1e713ae387459b5d117c836a5f6e328846922993b6d2b7640d9f
  F test/pragma.test 57a36226218c03cfb381019fe43234b2cefbd8a1f12825514f906a17ccf7991e
  F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
@@@ -1385,10 -1475,10 +1484,10 @@@ F test/printf.test 512152dca7f2f578f045
  F test/printf2.test 3f55c1871a5a65507416076f6eb97e738d5210aeda7595a74ee895f2224cce60
  F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
  F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
 -F test/pushdown.test 1495a09837a1cedfc0adf07ba42dc6b83be05a2c15de331b67c39a0e22078238
 +F test/pushdown.test 1495a09837a1cedfc0adf07ba42dc6b83be05a2c15de331b67c39a0e22078238 x
  F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca
  F test/quick.test 1681febc928d686362d50057c642f77a02c62e57
- F test/quickcheck.test f86b25b33455af0189b4d3fe7bd6e553115e80b2d7ec9bbe9a6b37fce0881bfe
+ F test/quickcheck.test a4b7e878cd97e46108291c409b0bf8214f29e18fddd68a42bc5c1375ad1fb80a
  F test/quota-glob.test 32901e9eed6705d68ca3faee2a06b73b57cb3c26
  F test/quota.test bfb269ce81ea52f593f9648316cd5013d766dd2a
  F test/quota2.test 7dc12e08b11cbc4c16c9ba2aa2e040ea8d8ab4b8
@@@ -1478,11 -1567,11 +1576,11 @@@ F test/sharedA.test 64bdd21216dda2c6a3b
  F test/sharedB.test 1a84863d7a2204e0d42f2e1606577c5e92e4473fa37ea0f5bdf829e4bf8ee707
  F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
  F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
- F test/shell1.test cac1fd2d681e0b79de9488069e4b2287da30788ce96a34788cbffbfe57e7b0a4
 -F test/shell1.test 0bb36232873d7df2ba627ed25cff1332f6d98c0f7f244b425702c1ab1850bd15
 -F test/shell2.test 35226c070a8c7f64fd016dfac2a0db2a40f709b3131f61daacd9dad61536c9cb
 -F test/shell3.test 91febeac0412812bf6370abb8ed72700e32bf8f9878849414518f662dfd55e8a
 -F test/shell4.test 9abd0c12a7e20a4c49e84d5be208d2124fa6c09e728f56f1f4bee0f02853935f
 -F test/shell5.test c8b6c54f26ec537f8558273d7ed293ca3725ef42e6b12b8f151718628bd1473b
++F test/shell1.test 21a66a73bcc765f59eec7ae96941db60773e0316698429b283fca9a109f7a697
 +F test/shell2.test c4471c97c0da342c9b02160abd5263de118b4bbb411b3318ee2a179d7bf18a08
 +F test/shell3.test 5dc710deede6e811e7af2bd91867d4128f023edc5a6cff6b8ad89e32af54c033
 +F test/shell4.test 8116d7b9dbefe6e2237908afbd6738637e0426486373231d3ad8984471d4e04c
 +F test/shell5.test ec82248dda87329f7dfced8637515b68db4ee75d94c8129dc017376fb61a8247
  F test/shell6.test 1ceb51b2678c472ba6cf1e5da96679ce8347889fe2c3bf93a0e0fa73f00b00d3
  F test/shell7.test 115132f66d0463417f408562cc2cf534f6bbc6d83a6d50f0072a9eb171bae97f
  F test/shell8.test 3fd093d481aaa94dc77fb73f1044c1f19c7efe3477a395cc4f7450133bc54915
@@@ -1565,9 -1652,9 +1663,9 @@@ F test/temptable.test d2c9b87a54147161b
  F test/temptable2.test 76821347810ecc88203e6ef0dd6897b6036ac788e9dd3e6b04fd4d1631311a16
  F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
  F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
 -F test/tester.tcl 68454ef88508c196d19e8694daa27bff7107a91857799eaa12f417188ae53ede
 +F test/tester.tcl 176a2ea601e01ad15450fbbb88b28ae66efbf94e684f52307741b26206f1cefb
- F test/testrunner.tcl 59490f189cac99b16b0376d0cc0a7ecfb753a84b89c9f4c361af337d88db53ac
- F test/testrunner_data.tcl 8169c68654ac8906833b8a6aadca973358a441ebf88270dd05c153e5f96f76b8
+ F test/testrunner.tcl 8a6721213bce1cfd3b33e1588cc6431143d96b98819206bf91f5a205fbb150d4
+ F test/testrunner_data.tcl e4d5017290a6d5c11785e36cc94c67d8bb950c8cdc2dbe4c1db2a3a583812560
  F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
  F test/thread002.test c24c83408e35ba5a952a3638b7ac03ccdf1ce4409289c54a050ac4c5f1de7502
  F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@@ -1780,9 -1867,9 +1878,9 @@@ F test/upfrom1.tcl 8859d9d437f03b44174c
  F test/upfrom1.test 8cb06689e99cd707d884faa16da0e8eb26ff658bb01c47ddf72fadade666e6e1
  F test/upfrom2.test 66f3ebf721b3cebd922faee5c386bf244f816d416b57c000753ff51af62328a1
  F test/upfrom3.test 6130f24ebf97f5ea865e5d2a14a2d543fe5428a62e87cc60f62d875e45c1f5f0
 -F test/upfrom4.test 78f742a6577c91a7a55c64edb8811004e7c6aa99b8d57b2320f70a918c357807
 +F test/upfrom4.test 78f742a6577c91a7a55c64edb8811004e7c6aa99b8d57b2320f70a918c357807 x
  F test/upfromfault.test 3a10075a0043f0c4fad6614b2c371f88a8ba5a4acab68b907438413865d6a8d6
- F test/upsert1.test b0ae2f58680c5205b4bc1cdeed3c3d444057c506f6c44494fa3eac60731d68a2
+ F test/upsert1.test a512e2f884d3a36159fce2e45108c236f78ae38e35bda55f4050db580ceb25d3
  F test/upsert2.test 720e94d09f7362a282bc69b3c6b83d51daeaaf0440eb4920a08b86518b8c7496
  F test/upsert3.test 88d7d590a1948a9cb6eac1b54b0642f67a9f35a1fc0f19b200e97d5d39e3179c
  F test/upsert4.test 25d2a1da92f149331ae0c51ca6e3eee78189577585eab92de149900d62994fa5
@@@ -1900,7 -1986,7 +1997,7 @@@ F test/win32heap.test 10fd891266bd00af6
  F test/win32lock.test e0924eb8daac02bf80e9da88930747bd44dd9b230b7759fed927b1655b467c9c
  F test/win32longpath.test 4baffc3acb2e5188a5e3a895b2b543ed09e62f7c72d713c1feebf76222fe9976
  F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
- F test/window1.test 1e7e13d36235b9a08fcb9790f2b05383f2f8c9538532b027f455766686926114 x
 -F test/window1.test 5e8abe56a7d667eeddbba6de180086dcf69ed528d046447a25464f945ece101f
++F test/window1.test 5e8abe56a7d667eeddbba6de180086dcf69ed528d046447a25464f945ece101f x
  F test/window2.tcl 492c125fa550cda1dd3555768a2303b3effbeceee215293adf8871efc25f1476
  F test/window2.test e466a88bd626d66edc3d352d7d7e1d5531e0079b549ba44efb029d1fbff9fd3c
  F test/window3.tcl acea6e86a4324a210fd608d06741010ca83ded9fde438341cb978c49928faf03
@@@ -1949,10 -2035,11 +2046,11 @@@ F tool/GetFile.cs 47852aa0d806fe47ed1ac
  F tool/GetTclKit.bat d84033c6a93dfe735d247f48ba00292a1cc284dcf69963e5e672444e04534bbf
  F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91
  F tool/build-all-msvc.bat c817b716e0edeecaf265a6775b63e5f45c34a6544f1d4114a222701ed5ac79ab x
- F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367
+ F tool/build-shell.sh f193b5e3eb4afcb4abbf96bf1475be6cfb74763ee2e50c82bc7ca105e8a136c5
  F tool/cg_anno.tcl c1f875f5a4c9caca3d59937b16aff716f8b1883935f1b4c9ae23124705bc8099 x
  F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2
 -F tool/custom.txt 6cdf298f43e1db4bb91406d14777669b8fb1df790837823fa6754c4308decc27
+ F tool/cktclsh.sh 6075eef9c6b9ba4b38fef2ca2a66d25f2311bd3c610498d18a9b01f861629cca
 +F tool/custom.txt ed0e9237b8dcc0f7c203d0dc20aa5aaa9ef8680d9396fb382d4f371df9afa157 x
  F tool/dbhash.c 5da0c61032d23d74f2ab84ffc5740f0e8abec94f2c45c0b4306be7eb3ae96df0
  F tool/dbtotxt.c ca48d34eaca6d6b6e4bd6a7be2b72caf34475869054240244c60fa7e69a518d6
  F tool/dbtotxt.md c9a57af8739957ef36d2cfad5c4b1443ff3688ed33e4901ee200c8b651f43f3c
@@@ -1974,22 -2061,23 +2072,23 @@@ F tool/loadfts.c c3c64e4d5e90e8ba411592
  F tool/logest.c c34e5944318415de513d29a6098df247a9618c96d83c38d4abd88641fe46e669
  F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439
  F tool/merge-test.tcl de76b62f2de2a92d4c1ca4f976bce0aea6899e0229e250479b229b2a1914b176
- F tool/mkautoconfamal.sh f62353eb6c06ab264da027fd4507d09914433dbdcab9cb011cdc18016f1ab3b8
+ F tool/mkautoconfamal.sh cbdcf993fa83dccbef7fb77b39cdeb31ef9f77d9d88c9e343b58d35ca3898a6a
  F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x
- F tool/mkctimec.tcl 38e3db33210a200aae791635125052a643a27aa0619a0debf19aa9c55e1b2dde x
+ F tool/mkctimec.tcl a16682eae5f01f85e5861b2aa215ca0d46b4230658ee25977e02b4508566fb75 x
  F tool/mkkeywordhash.c b9faa0ae7e14e4dbbcd951cddd786bf46b8a65bb07b129ba8c0cfade723aaffd
 -F tool/mkmsvcmin.tcl 8897d515ef7f94772322db95a3b6fce6c614d84fe0bdd06ba5a1c786351d5a1d
 +F tool/mkmsvcmin.tcl 8897d515ef7f94772322db95a3b6fce6c614d84fe0bdd06ba5a1c786351d5a1d x
  F tool/mkopcodec.tcl 33d20791e191df43209b77d37f0ff0904620b28465cca6990cf8d60da61a07ef
  F tool/mkopcodeh.tcl 769d9e6a8b462323150dc13a8539d6064664b72974f7894befe2491cc73e05cd
  F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa
- F tool/mkpragmatab.tcl bd07bd59d45d0f3448e123d6937e9811195f9908a51e09d774609883055bfd3d
+ F tool/mkpragmatab.tcl 32e359ccb21011958a821955254bd7a5fa7915d01a8c16fed91ffc8b40cb4adf
 -F tool/mkshellc.tcl b7adf08b82de60811d2cb6af05ff59fc17e5cd6f3e98743c14eaaa3f8971fed0
 +F tool/mkshellc.tcl 602b339e31af1a95943b3da1280645bcc16f7c53b861c1e337a06b08fb410cbd x
  F tool/mksourceid.c 36aa8020014aed0836fd13c51d6dc9219b0df1761d6b5f58ff5b616211b079b9
  F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
  F tool/mksqlite3c-noext.tcl 4f7cfef5152b0c91920355cbfc1d608a4ad242cb819f1aea07f6d0274f584a7f
- F tool/mksqlite3c.tcl 44bc3bdb675a9e3a507f4d82575332bccd7e6f830a47c9aa29460ea2240593a9 x
 -F tool/mksqlite3c.tcl 2c760ab786cb509b47f00c96fea82994866cb99f5e046df81c768288f57897b4
++F tool/mksqlite3c.tcl 2c760ab786cb509b47f00c96fea82994866cb99f5e046df81c768288f57897b4 x
  F tool/mksqlite3h.tcl d391cff7cad0a372ee1406faee9ccc7dad9cb80a0c95cae0f73d10dd26e06762
  F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b
+ F tool/mktoolzip.tcl c7a9b685f5131d755e7d941cec50cee7f34178b9e34c9a89811eeb08617f8423
  F tool/mkvsix.tcl b9e0777a213c23156b6542842c238479e496ebf5
  F tool/offsets.c 8ed2b344d33f06e71366a9b93ccedaa38c096cc1dbd4c3c26ad08c6115285845
  F tool/omittest-msvc.tcl d6b8f501ac1d7798c4126065030f89812379012cad98a1735d6d7221492abc08
@@@ -2014,14 -2102,15 +2113,15 @@@ F tool/speedtest16.c ecb6542862151c3e65
  F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
  F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
  F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd
 -F tool/spellsift.tcl 52b4b04dc4333c7ab024f09d9d66ed6b6f7c6eb00b38497a09f338fa55d40618 x
 +F tool/spellsift.tcl 2265f37504e68b73c659a3a09cb4354da9b24de7d5d21b91e1ba1fb62040d0b9 x
  F tool/split-sqlite3c.tcl 5aa60643afca558bc732b1444ae81a522326f91e1dc5665b369c54f09e20de60
- F tool/sqldiff.c 2a693b4e7c1818c23f871f82f0c3fe67d80b67e3f087893089d33da29c1e387e x
 -F tool/sqldiff.c fcccbc07da942b4534d0c769e9fcc21c67cbd7086ddc1c8f13372c40a83d4634
++F tool/sqldiff.c fcccbc07da942b4534d0c769e9fcc21c67cbd7086ddc1c8f13372c40a83d4634 x
  F tool/sqlite3_analyzer.c.in f88615bf33098945e0a42f17733f472083d150b58bdaaa5555a7129d0a51621c
  F tool/sqltclsh.c.in 1bcc2e9da58fadf17b0bf6a50e68c1159e602ce057210b655d50bad5aaaef898
  F tool/sqltclsh.tcl 862f4cf1418df5e1315b5db3b5ebe88969e2a784525af5fbf9596592f14ed848
- F tool/src-verify.c f0cef434a8d8629c4928a02a644fb85e33c8b875a7f2352ba68cc50965a7d213 x
 -F tool/src-verify.c 41c586dee84d0b190ad13e0282ed83d4a65ec9fefde9adf4943efdf6558eea7f
++F tool/src-verify.c 41c586dee84d0b190ad13e0282ed83d4a65ec9fefde9adf4943efdf6558eea7f x
  F tool/srcck1.c 371de5363b70154012955544f86fdee8f6e5326f
+ F tool/srctree-check.tcl c15f860a3c97d5f7b4c14b60392d9466af29dd006c4ef18127f502641e2977a8
  F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43
  F tool/stripccomments.c 20b8aabc4694d0d4af5566e42da1f1a03aff057689370326e9269a9ddcffdc37
  F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d
@@@ -2029,8 -2118,9 +2129,9 @@@ F tool/symbols.sh 1612bd947750e21e7b47b
  F tool/varint.c 5d94cb5003db9dbbcbcc5df08d66f16071aee003
  F tool/vdbe-compress.tcl 1dcb7632e57cf57105248029e6e162fddaf6c0fccb3bb9e6215603752c5a2d4a
  F tool/vdbe_profile.tcl 3ac5a4a9449f4baf77059358ea050db3e34395ccf59c5464d29b91746d5b961e
 -F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd72273503ae7d5
++F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd72273503ae7d5 w ext/wasm/version-info.c
  F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
- F tool/warnings.sh ab651bb82586c43ff8b560beceac959735bf917b44c5e0f67ba3426e474f29f8
+ F tool/warnings.sh 49a486c5069de041aedcbde4de178293e0463ae9918ecad7539eedf0ec77a139
  F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
  F vsixtest/App.xaml b76d3b48860e7454775c47ea38ffea9c4abe3e85
  F vsixtest/App.xaml.cpp 41158ee43269820136fa3bba00c0bd91b26cc38b650ee392aec2a8d823e54318
@@@ -2053,8 -2143,8 +2154,11 @@@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a9
  F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
  F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
  F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
- P a61f9377014ee582ec469f1066196e07b745295724c6d3ff4baffcaed22ae5a1 24927c1377314a10177da4a57191593440aa97fd0c5949fdf25a22df1d947600 2f9d4444aa503102a00d6e6769dadc57d4b26a2c07f145f23f2f28e0c161246d
- R bd3140ab1e0bb2a93e6d3c105e3f3689
 -P 8936daa08243729d8538bb7288bbefb43f3bd842a0d4b2e8019092f5701c2926 448d6a1182d29940d5d34be2ce67df5601b688cd902dbbe97e95073f982a49ce
 -R 764d6a65ddcbf1b62de463cc42b71475
++P fe9aa2e9c17f33a8f6045e9cf755f8251d261c34f89a59d658b72f7c99a6a12c 935a8a8ee76d0014df42c1480e044fd1c2dfc26e78abb587d99d861d2ae5eb27
++R 40c6061165d6a82110ccfb8fd65d8e10
++T *branch * cli_extension_wip
++T *sym-cli_extension_wip *
++T -sym-cli_extension *
  U larrybr
- Z 497f78a875664dfe4baa50f499afe15b
 -Z 9d8c4f0e647c59f8c21d5587e8bd311b
++Z 17233161c9dda79cae81102879ab1fff
  # Remove this line to create a well-formed Fossil manifest.
diff --cc manifest.uuid
index 4b532a727a85f6299ff9ebd3bbf84610847aa174,094c6b93acf074bd02e9de9a1dd20d0062351daa..c28635187dcad4b02c460a540f9462a1ac076eb8
@@@ -1,1 -1,1 +1,1 @@@
- fe9aa2e9c17f33a8f6045e9cf755f8251d261c34f89a59d658b72f7c99a6a12c
 -935a8a8ee76d0014df42c1480e044fd1c2dfc26e78abb587d99d861d2ae5eb27
++62e90c9ba80c257da417ab57549f142f9628c10bd924ab3334a2c518976b3c6d
diff --cc src/alter.c
index d0b1f7f696600b5b2179f4ce60b86ed86b36e6fe,ec45e14331e0973e0ec2e738b241ea63a9bcd38a..ec45e14331e0973e0ec2e738b241ea63a9bcd38a
mode 100755,100644..100755
diff --cc src/btreeInt.h
index 3e692061936f780bd049568f13254b506357c2ec,563e15f8ac7d8fc23e6e95a99f96655788c5f094..563e15f8ac7d8fc23e6e95a99f96655788c5f094
mode 100755,100644..100755
diff --cc src/expr.c
index a8e552f2c71b19bb4d864b2b951c7a4f366992bb,8a664ffb9cf87e3a8d4eeabf3ee66ae2568c7235..8a664ffb9cf87e3a8d4eeabf3ee66ae2568c7235
mode 100755,100644..100755
diff --cc src/fkey.c
index 3142e0ca685546344f94232fc5f610aedb368004,bace1ae5e2d3b57285ad7c983083faf75bacb08a..bace1ae5e2d3b57285ad7c983083faf75bacb08a
mode 100755,100644..100755
diff --cc src/func.c
index c505c37d69ac79bf009a444d9c8fab04dd41db59,58ef4fef9c4c0186207bf4d34e018d58ea8c8e6e..58ef4fef9c4c0186207bf4d34e018d58ea8c8e6e
mode 100755,100644..100755
diff --cc src/json.c
index 6bad1c1e75007dcbe36a901941b2ffd2dff54f3f,0f11ace02bc34636516bbfc972e1b7faa6b6cbfc..0f11ace02bc34636516bbfc972e1b7faa6b6cbfc
mode 100755,100644..100755
diff --cc src/loadext.c
index 4fc1352e03e4a416a0acbb8202dd1662309ad151,7e0ae25437f27457f2d70e071fc4c93b7eab4d9d..7e0ae25437f27457f2d70e071fc4c93b7eab4d9d
mode 100755,100644..100755
diff --cc src/main.c
index 7e3fab88614885a374f5e3207459e0302bd1508c,6acfdc325d8da35eebe2547e31855c33180827b0..6acfdc325d8da35eebe2547e31855c33180827b0
mode 100755,100644..100755
index ac4331a67b0e68a1aee9b79ff22940e35cc63c12,beae877f987816f33d37616367727ee57274d18b..beae877f987816f33d37616367727ee57274d18b
mode 100755,100644..100755
diff --cc src/mutex_w32.c
index e0e0dfb06c7d3305ad38287e11343b35470d23dc,7eb5b50be15c749d3f828f8483e5233592d68f36..7eb5b50be15c749d3f828f8483e5233592d68f36
mode 100755,100644..100755
diff --cc src/os_unix.c
index aed4ac213fbbdecbc441b337d538e276639e2d48,dab03c97fb1afb3c912dede4d9cfa69e282db37f..dab03c97fb1afb3c912dede4d9cfa69e282db37f
mode 100755,100644..100755
diff --cc src/os_win.c
index 73a2f946d8aec72ca13dc711a3762feaa352eb55,dc16c08b51b8b26fa75bbfaa7662a10fba18395d..dc16c08b51b8b26fa75bbfaa7662a10fba18395d
mode 100755,100644..100755
diff --cc src/pager.c
index 7f2cb5ba76388b1c55b5fae5e7deb3790c4ce93f,4687ab0f1947f87a8bef03766810f3172d0217d6..4687ab0f1947f87a8bef03766810f3172d0217d6
mode 100755,100644..100755
diff --cc src/parse.y
index 6085c4bbe26d778e63bd33a56e8d7c8b09d0f779,19491192e3a330a1c8a4fc820c1d02f49e1afb01..19491192e3a330a1c8a4fc820c1d02f49e1afb01
mode 100755,100644..100755
diff --cc src/pcache.c
index 42f22b70343011697723762b83cd0dd898e0fa0d,2974b0810a75021b1e5b1f426bbf43f4109d0249..2974b0810a75021b1e5b1f426bbf43f4109d0249
mode 100755,100644..100755
diff --cc src/pragma.c
index f15c1be279570d0ae2c72d3145501dd7902fcac9,90076b0c264ce31e022f6caffd9a3fc01921f836..90076b0c264ce31e022f6caffd9a3fc01921f836
mode 100755,100644..100755
diff --cc src/prepare.c
index 39e8dcf655b854cd76752a5f277bfeb24884d83f,87569ee91d6b6c13fb83617cdd13b500144c7a6c..87569ee91d6b6c13fb83617cdd13b500144c7a6c
mode 100755,100644..100755
diff --cc src/select.c
index 71610484b1f767b18def68aeb894f9a7572b5e06,e5312c7ee7e5483a8e08a33b06a61c0584ab4920..e5312c7ee7e5483a8e08a33b06a61c0584ab4920
mode 100755,100644..100755
diff --cc src/shell.c.in
index 802a2cb57b1c2daf1e9192ead6f88e8a00be395f,62420741278282c3535f54be303eba97913424ad..4c7139a9b9b2f800517cc80ffa7fbb25a35ca603
@@@ -1608,7 -1071,7 +1608,7 @@@ static void shellDtostr
    char z[400];
    if( n<1 ) n = 1;
    if( n>350 ) n = 350;
-   sprintf(z, "%#+.*e", n, r);
 -  sqlite3_snprintf(sizeof(z), z, "%#+.*e", n, r);
++  snprintf(z, sizeof(z)-1, "%#+.*e", n, r);
    sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
  }
  
@@@ -1807,209 -1265,51 +1807,221 @@@ struct EQPGraph 
    char zPrefix[100];    /* Graph prefix */
  };
  
 -/* Parameters affecting columnar mode result display (defaulting together) */
 -typedef struct ColModeOpts {
 -  int iWrap;            /* In columnar modes, wrap lines reaching this limit */
 -  u8 bQuote;            /* Quote results for .mode box and table */
 -  u8 bWordWrap;         /* In columnar modes, wrap at word boundaries  */
 -} ColModeOpts;
 -#define ColModeOpts_default { 60, 0, 0 }
 -#define ColModeOpts_default_qbox { 60, 1, 0 }
 +/* By default, omit the extension options that are not done yet.
 + * "SHELL_EXTENSIONS" is short for "Some shell extensions are built in." */
 +#ifndef SHELL_OMIT_EXTENSIONS
 +# define SHELL_OMIT_EXTENSIONS 4
 +# define SHELL_EXTENSIONS 1
 +#else
 +# define SHELL_EXTENSIONS \
 +  (0!=((~SHELL_OMIT_EXTENSIONS) & SHELL_ALL_EXTENSIONS))
 +#endif
  
 -/*
 -** State information about the database connection is contained in an
 -** instance of the following structure.
 +#ifdef SQLITE_OMIT_LOAD_EXTENSION
 +# define SHELL_OMIT_LOAD_EXTENSION 1
 +#else
 +# define SHELL_OMIT_LOAD_EXTENSION 0
 +#endif
 +
 +/* Selectively omit features with one PP variable. Value is true iff
 +** either x is not defined or defined with 0 in bitnum bit position.
  */
 -typedef struct ShellState ShellState;
 -struct ShellState {
 -  sqlite3 *db;           /* The database */
 -  u8 autoExplain;        /* Automatically turn on .explain mode */
 -  u8 autoEQP;            /* Run EXPLAIN QUERY PLAN prior to each SQL stmt */
 -  u8 autoEQPtest;        /* autoEQP is in test mode */
 -  u8 autoEQPtrace;       /* autoEQP is in trace mode */
 -  u8 scanstatsOn;        /* True to display scan stats before each finalize */
 -  u8 openMode;           /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
 -  u8 doXdgOpen;          /* Invoke start/open/xdg-open in output_reset() */
 -  u8 nEqpLevel;          /* Depth of the EQP output graph */
 +#define NOT_IFDEF_BIT(x,bitnum) (x? (!(x & (1<<bitnum))) : !(x+0))
 +
 +/* Whether build will include extended input parsing option */
 +#define SHEXT_PARSING_BIT 0
 +#define SHELL_EXTENDED_PARSING \
 +  NOT_IFDEF_BIT(SHELL_OMIT_EXTENSIONS, SHEXT_PARSING_BIT)
 +/* Whether build will include runtime extension via .shxload */
 +#define SHEXT_DYNEXT_BIT 1
 +#define SHELL_DYNAMIC_EXTENSION ( !SHELL_OMIT_LOAD_EXTENSION \
 +  && NOT_IFDEF_BIT(SHELL_OMIT_EXTENSIONS, SHEXT_DYNEXT_BIT) )
 +/* Whether build will include expansion of variables in dot-commands */
 +#define SHEXT_VAREXP_BIT 2
 +#define SHELL_VARIABLE_EXPANSION \
 +  NOT_IFDEF_BIT(SHELL_OMIT_EXTENSIONS, SHEXT_VAREXP_BIT)
 +
 +#define SHELL_ALL_EXTENSIONS \
 +  (1<<SHEXT_PARSING_BIT)+(1<<SHEXT_DYNEXT_BIT)+(1<<SHEXT_VAREXP_BIT)
 +
 +/* Runtime test for shell extended parsing, given ShellInState pointer */
 +#if SHELL_EXTENDED_PARSING
 +# define SHEXT_PARSING(psi) ((psi->bExtendedDotCmds&(1<<SHEXT_PARSING_BIT))!=0)
 +#else
 +# define SHEXT_PARSING(psi) 0
 +#endif
 +
 +/* Runtime test for shell variable expansion, given ShellInState pointer */
 +#if SHELL_EXTENDED_PARSING
 +# define SHEXT_VAREXP(psi) ((psi->bExtendedDotCmds&(1<<SHEXT_VAREXP_BIT))!=0)
 +#else
 +# define SHEXT_VAREXP(psi) 0
 +#endif
 +
 +/* Enable use of ExportHandler and ImportHandler interfaces for built-in I/O.
 +** (This deactivates "shuffled" older code which can be deleted some day. The
 +** code has been partitioned and moved as part of built-in exporters.) */
 +#define SHELL_DATAIO_EXT 1
 +
 +#if SHELL_DYNAMIC_EXTENSION
 +
 +/* This is only used to support extensions that need this information.
 + * For example, they might need to locate and load related files. */
 +# if defined(_WIN32) || defined(WIN32)
 +static char startupDir[MAX_PATH+1] = {0};
 +# define initStartupDir() (_getcwd(startupDir,MAX_PATH)!=0)
 +#  define IS_PATH_SEP(c) ((c)=='/'||(c)=='\\')
 +# else
 +static char startupDir[PATH_MAX+1] = {0};
 +# define initStartupDir() (getcwd(startupDir, sizeof(startupDir))!=0)
 +  /* Above useless expression avoids an "unused result" warning. */
 +#  define IS_PATH_SEP(c) ((c)=='/')
 +# endif
 +
 +# ifndef SHELL_OMIT_EXTBYNAME
 +/* Is a program invocation name one used for a shell to start as extensible? */
 +static int isExtendedBasename(const char *zPgm){
 +  int ixe = (zPgm)? (int)strlen(zPgm)-1 : 0;
 +  if( ixe==0 ) return 0;
 +  while( ixe>=0 && !IS_PATH_SEP(zPgm[ixe]) ) --ixe;
 +  /* index is just before the basename with extension(s) */
 +  return sqlite3_strnicmp(&zPgm[ixe+1], "sqlite3x", 8)==0;
 +}
 +# else
 +#  define isExtendedBasename(pathname) 0
 +# endif
 +
 +/* Tracking and use info for loaded shell extensions
 + * An instance is kept for each shell extension that is currently loaded.
 + * They are kept in a simple list (aka dynamic array), index into which
 + * is used internally to get the extension's object. These indices are
 + * kept in the dbShell and updated there as the list content changes.
 + */
 +typedef struct ShExtInfo {
 +  ExtensionId extId;        /* The xInit function pointer */
 +  void (*extDtor)(void *);  /* Extension shutdown on exit or unload */
 +  void *pvExtObj;           /* Passed to extDtor(...) at shutdown */
 +  /* Each shell extension library registers 0 or more of its extension
 +   * implementations, interfaces to which are kept in below dynamic.
 +   * arrays. The dbShell DB keeps indices into these arrays and into
 +   * an array of instances of this struct to facilitate lookup by name
 +   * of pointers to the implementations. */
 +  int numDotCommands;
 +  DotCommand **ppDotCommands;
 +  int numExportHandlers;
 +  ExportHandler **ppExportHandlers;
 +  int numImportHandlers;
 +  ImportHandler **ppImportHandlers;
 +  DotCommand *pUnknown;  /* .unknown registered for this extension (unowned) */
 +} ShExtInfo;
 +#define SHEXT_INFO_INIT {0,0,NULL, 0,NULL, 0,NULL, 0,NULL, NULL}
 +#endif
 +
 +/* Parameters affecting columnar mode result display (defaulting together) */
 +typedef struct ColModeOpts {
 +  int iWrap;            /* In columnar modes, wrap lines reaching this limit */
 +  u8 bQuote;            /* Quote results for .mode box and table */
 +  u8 bWordWrap;         /* In columnar modes, wrap at word boundaries  */
 +} ColModeOpts;
 +#define ColModeOpts_default { 60, 0, 0 }
 +#define ColModeOpts_default_qbox { 60, 1, 0 }
 +
 +/*
 +** Stored output mode state, for partial save and later restore.
 +** Returned by:
 +**   outputModeSave *outputModeSave(ShellInState *p, SaveModeWhat what).
 +** Accepted by:
 +**   outputModeRestore(ShellInState *p, OutputModeSave *pSaved).
 +** See enum SaveWhatMode regarding what to save and restore.
 +** Also see outputModePush(...), outputModePushSome(...) and
 +** outputModePop(...) for usages spanning more than one call.
 +*/
 +typedef struct OutputModeSave{
 +  u16 what;           /* Set upon creation. See SaveWhatMode for values. */
 +  char itsValues[1];  /* This size is inaccurate unless nothing is saved. */
 +} OutputModeSave;
 +#define MODE_STACK_MAX 3 /* How many levels of saved output mode to allow. */
 +
 +/*
 +** Shell state information is contained in an instance of the following struct
 +** and in a ShellExState struct defined in shext_linkage.h, partitioned thus:
 +**
 +** Data not exposed for shell extension use, (and which need not be stable),
 +** are kept in a ShellInState instance. These include facts about the database
 +** connection, specialized display mode setup, safe mode control, and other
 +** data associated with the shell's means of operation.
 +**
 +** Data which is exposed for shell extension use, (and which should be stable
 +** or grown only with new members at the end, to preserve layout), is kept
 +** in the ShellExState instance, which contains a ShellInState pointer, pSIS.
 +*/
 +
 +/* Oft-used macros for transition to internal/external shell state access
 + * ISS(psx) : internal shell state (pointer)
 + * XSS(psi) : external shell state (pointer)
 + * DBI(psi) : DB from internal pointer
 + * DBX(psx) : DB from external pointer
 + */
 +#define ISS(psx) (psx)->pSIS
 +#define XSS(psi) (psi)->pSXS
 +#define DBI(psi) (psi)->pSXS->dbUser
 +#define DBX(psx) (psx)->dbUser
++#ifdef SQLITE_DEBUG
++# define CAST_AS_XSS(p) \
++  (assert((ShellExState*)(p)->sizeofThis!=0),(ShellExState*)(p))
++# define CAST_AS_ISS(p) \
++  (assert((ShellInState*)(p)->zeroMarker==0),(ShellInState*)(p))
++#else
++# define CAST_AS_XSS(p) ((ShellExState*)(p))
++# define CAST_AS_ISS(p) ((ShellInState*)(p))
++#endif
 +
 +typedef struct ShellInState {
++#ifdef SQLITE_DEBUG
++  int zeroMarker;        /* Distinguishes ShellInState from ShellExState */
++#endif
 +  int openFlags;         /* Additional flags to open.  (SQLITE_OPEN_NOFOLLOW) */
 +  u8 openMode;           /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
 +  sqlite3_int64 szMax;   /* --maxsize argument to .open */
 +  u8 autoExplain;        /* Automatically turn on .explain mode */
 +  u8 autoEQP;            /* Run EXPLAIN QUERY PLAN prior to each SQL stmt */
 +  u8 autoEQPtest;        /* autoEQP is in test mode */
 +  u8 autoEQPtrace;       /* autoEQP is in trace mode */
 +  u8 scanstatsOn;        /* True to display scan stats before each finalize */
 +  u8 doXdgOpen;          /* Invoke start/open/xdg-open in output_reset() */
 +  u8 nEqpLevel;          /* Depth of the EQP output graph */
    u8 eTraceType;         /* SHELL_TRACE_* value for type of trace */
 -  u8 bSafeMode;          /* True to prohibit unsafe operations */
 -  u8 bSafeModePersist;   /* The long-term value of bSafeMode */
 +  u8 bSafeMode;          /* True when unsafe operations are prohibited */
 +  u8 bSafeModeFuture;    /* See updateSafeMode regarding use of this. */
 +  u8 bAllowSysDump;      /* Allow .dump use for sqlite_* tables. */
 +  u8 bExtendedDotCmds;   /* Bits set to enable various shell extensions */
 +  /* Output mode state subject to systematic save/restore: (See OM_STATE.) */
 +  u8 showHeader;         /* True to show column names in List or Column mode */
 +  u16 shellFlgs;         /* Various flags */
 +  u8 mode;               /* An output mode setting */
    ColModeOpts cmOpts;    /* Option values affecting columnar mode output */
 +  char colSeparator[20]; /* Column separator character for several modes */
 +  char rowSeparator[20]; /* Row separator character for MODE_Ascii */
 +  /* Output mode state-keep for systematic save/restore: (See OM_STATE.) */
 +  u8 nSavedModes;        /* number of valid items in next array */
 +  OutputModeSave *pModeStack[MODE_STACK_MAX]; /* saved mode data buffers */
 +  /* Output mode state-keep for certain save/restore operations: */
 +  u8 cMode;              /* temporary output mode for the current query */
 +  u8 normalMode;         /* Output mode before ".explain on" */
 +  char nullValue[20];    /* Text to print for NULL retrieved from database */
 +
    unsigned statsOn;      /* True to display memory stats before each finalize */
    unsigned mEqpLines;    /* Mask of vertical lines in the EQP output graph */
 -  int inputNesting;      /* Track nesting level of .read and other redirects */
    int outCount;          /* Revert to stdout when reaching zero */
 -  int cnt;               /* Number of records displayed so far */
 -  int lineno;            /* Line number of last line read from in */
 -  int openFlags;         /* Additional flags to open.  (SQLITE_OPEN_NOFOLLOW) */
 -  FILE *in;              /* Read commands from this stream */
 +
 +  int inputNesting;      /* Track nesting level of .read and other redirects */
 +  InSource *pInSource;   /* Read commands and SQL from this stream source */
 +
    FILE *out;             /* Write results here */
    FILE *traceOut;        /* Output for sqlite3_trace() */
 +
    int nErr;              /* Number of errors seen */
 -  int mode;              /* An output mode setting */
 -  int modePrior;         /* Saved mode */
 -  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 nProgress;    /* Number of progress callbacks encountered */
    unsigned mxProgress;   /* Maximum progress callbacks before failing */
@@@ -2165,55 -1420,44 +2177,56 @@@ static void updateSafeMode(ShellInStat
  #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 */
 -#define MODE_EQP     12  /* Converts EXPLAIN QUERY PLAN output into a graph */
 -#define MODE_Json    13  /* Output JSON */
 -#define MODE_Markdown 14 /* Markdown formatting */
 -#define MODE_Table   15  /* MySQL-style table formatting */
 -#define MODE_Box     16  /* Unicode box-drawing characters */
 -#define MODE_Count   17  /* Output only a count of the rows of output */
 -#define MODE_Off     18  /* No query output shown */
 -#define MODE_ScanExp 19  /* Like MODE_Explain, but for ".scanstats vm" */
 -
 -static const char *modeDescr[] = {
 -  "line",
 -  "column",
 -  "list",
 -  "semi",
 -  "html",
 -  "insert",
 -  "quote",
 -  "tcl",
 -  "csv",
 -  "explain",
 -  "ascii",
 -  "prettyprint",
 -  "eqp",
 -  "json",
 -  "markdown",
 -  "table",
 -  "box",
 -  "count",
 -  "off"
 +#define MODE_Html     3  /* Generate an XHTML table */
 +#define MODE_Tcl      4  /* Generate ANSI-C or TCL quoted elements */
 +#define MODE_Csv      5  /* Quote strings, numbers are plain */
 +#define MODE_Tab      6  /* Transitory, an alias for MODE_List with tabs */
 +#define MODE_Insert   7  /* Generate SQL "insert" statements */
 +#define MODE_Quote    8  /* Quote values as for SQL */
 +#define MODE_Ascii    9  /* Use ASCII unit and record separators (0x1F/0x1E) */
 +#define MODE_Markdown 10 /* Markdown formatting */
 +#define MODE_Table    11 /* MySQL-style table formatting */
 +#define MODE_Box      12 /* Unicode box-drawing characters */
- #define MODE_Count    13 /* Output only a count of the rows of output */
- #define MODE_Off      14 /* No query output shown */
- #define MODE_Json     15 /* Output JSON */
++#define MODE_Json     13 /* Output JSON */
++#define MODE_Count    14 /* Output only a count of the rows of output */
++#define MODE_Off      15 /* No query output shown */
 +#define MODE_EQP      16 /* Converts EXPLAIN QUERY PLAN output into a graph */
 +#define MODE_Explain  17 /* Like MODE_Column, but do not truncate data */
 +#define MODE_Pretty   18 /* Pretty-print schemas */
 +#define MODE_Semi     19 /* Same as MODE_List but append ";" to each line */
- #define MODE_COUNT_OF 20 /* also a known invalid MODE_x value */
++#define MODE_ScanExp  20 /* Like MODE_Explain, but for ".scanstats vm" */
++#define MODE_COUNT_OF 21 /* also a known invalid MODE_x value */
 +
 +/* Note that some of above ordering is assumed for this mode classification. */
 +#define MODE_IS_COLUMNAR(m) \
 +  ( (m)==MODE_Column||((m)>=MODE_Markdown&&(m)<=MODE_Box) )
 +
 +static struct {
 +  const char *zModeName;
 +  u8 bMayPluralize;
 +  u8 bUserBlocked;
 +  u8 iAliasFor;
 +} modeDescr[] = {
 +  { "line", 1, 0, MODE_Line },
 +  { "column", 1, 0, MODE_Column },
 +  { "list", 0, 0, MODE_List },
 +  { "html", 0, 0, MODE_Html },
 +  { "tcl", 0, 0, MODE_Tcl },
 +  { "csv", 0, 0, MODE_Csv },
 +  { "tab", 1, 0, MODE_List },
 +  { "insert", 0, 0, MODE_Insert },
 +  { "quote", 0, 0, MODE_Quote },
 +  { "ascii", 0, 0, MODE_Ascii },
 +  { "markdown", 0, 0, MODE_Markdown },
 +  { "table", 0, 0, MODE_Table },
 +  { "box", 0, 0, MODE_Box },
 +  { "count", 0, 0, MODE_Count },
 +  { "off", 0, 0, MODE_Off },
 +  { "json", 0, 0, MODE_Json },
 +  { "eqp", 0, 1, MODE_EQP },
 +  { "explain", 0, 1, MODE_Explain },
 +  { "prettyprint", 0, 1, MODE_Pretty },
 +  { "semi", 0, 1, MODE_Semi }
  };
  
  /*
@@@ -3352,38 -2403,58 +3365,59 @@@ static int shell_callback
        }
        break;
      }
+     case MODE_ScanExp:
      case MODE_Explain: {
-       static const int aExplainWidth[] = {4, 13, 4, 4, 4, 13, 2, 13};
-       if( nArg>ArraySize(aExplainWidth) ){
-         nArg = ArraySize(aExplainWidth);
+       static const int aExplainWidth[] = {4,       13, 4, 4, 4, 13, 2, 13};
+       static const int aExplainMap[] =   {0,       1,  2, 3, 4, 5,  6, 7 };
+       static const int aScanExpWidth[] = {4, 6, 6, 13, 4, 4, 4, 13, 2, 13};
+       static const int aScanExpMap[] =   {0, 9, 8, 1,  2, 3, 4, 5,  6, 7 };
+       const int *aWidth = aExplainWidth;
+       const int *aMap = aExplainMap;
+       int nWidth = ArraySize(aExplainWidth);
+       int iIndent = 1;
+       if( p->cMode==MODE_ScanExp ){
+         aWidth = aScanExpWidth;
+         aMap = aScanExpMap;
+         nWidth = ArraySize(aScanExpWidth);
+         iIndent = 3;
        }
 -      if( p->cnt++==0 ){
+       if( nArg>nWidth ) nArg = nWidth;
+       /* If this is the first row seen, print out the headers */
 +      if( psx->resultCount++==0 ){
          for(i=0; i<nArg; i++){
 -          utf8_width_print(aWidth[i], azCol[ aMap[i] ]);
 -          oputz(i==nArg-1 ? "\n" : "  ");
 +          int w = aExplainWidth[i];
-           utf8_width_print(out, w, azCol[i]);
++          utf8_width_print(psi->out, aWidth[i], azCol[aMap[i]]);
 +          fputs(i==nArg-1 ? "\n" : "  ", out);
          }
          for(i=0; i<nArg; i++){
-           int w = aExplainWidth[i];
-           print_dashes(out, w);
 -          print_dashes(aWidth[i]);
 -          oputz(i==nArg-1 ? "\n" : "  ");
++          print_dashes(out, aWidth[i]);
 +          fputs(i==nArg-1 ? "\n" : "  ", out);
          }
        }
+       /* If there is no data, exit early. */
        if( azArg==0 ) break;
        for(i=0; i<nArg; i++){
-         int w = aExplainWidth[i];
+         const char *zSep = "  ";
+         int w = aWidth[i];
+         const char *zVal = azArg[ aMap[i] ];
          if( i==nArg-1 ) w = 0;
-         if( azArg[i] && strlenChar(azArg[i])>w ){
-           w = strlenChar(azArg[i]);
+         if( zVal && strlenChar(zVal)>w ){
+           w = strlenChar(zVal);
+           zSep = " ";
          }
-         if( i==1 && psi->aiIndent && psi->pStmt ){
 -        if( i==iIndent && p->aiIndent && p->pStmt ){
 -          if( p->iIndent<p->nIndent ){
 -            oputf("%*.s", p->aiIndent[p->iIndent], "");
++        if( i==iIndent && psi->aiIndent && psi->pStmt ){
 +          if( psi->iIndent<psi->nIndent ){
 +            utf8_printf(out, "%*.s", psi->aiIndent[psi->iIndent], "");
            }
 -          p->iIndent++;
 +          psi->iIndent++;
          }
-         utf8_width_print(out, w, azArg[i] ? azArg[i] : psi->nullValue);
-         fputs(i==nArg-1 ? "\n" : "  ", out);
 -        utf8_width_print(w, zVal ? zVal : p->nullValue);
 -        oputz(i==nArg-1 ? "\n" : zSep);
++        utf8_width_print(out, w, zVal ? zVal : psi->nullValue);
++        fputs(i==nArg-1 ? "\n" : zSep, out);
        }
        break;
      }
@@@ -4174,16 -3217,13 +4208,10 @@@ static int scanStatsHeight(sqlite3_stm
  }
  #endif
  
- /*
- ** Display scan stats.
- */
- static void display_scanstats(sqlite3 *db, ShellInState *psi){
- #ifndef SQLITE_ENABLE_STMT_SCANSTATUS
-   UNUSED_PARAMETER(db);
-   UNUSED_PARAMETER(psi);
- #else
+ #ifdef SQLITE_ENABLE_STMT_SCANSTATUS
 -static void display_explain_scanstats(
 -  sqlite3 *db,                    /* Database to query */
 -  ShellState *pArg                /* Pointer to ShellState */
 -){
++static void display_explain_scanstats(sqlite3 *db, ShellInState *psi){
    static const int f = SQLITE_SCANSTAT_COMPLEX;
 -  sqlite3_stmt *p = pArg->pStmt;
 +  sqlite3_stmt *p = psi->pStmt;
    int ii = 0;
    i64 nTotal = 0;
    int nWidth = 0;
      sqlite3_free(zText);
    }
  
 -  eqp_render(pArg, nTotal);
 +  eqp_render(psi, nTotal);
- #endif
  }
+ #endif
  
 -
  /*
  ** Parameter azArray points to a zero-terminated array of strings. zStr
  ** points to a single nul-terminated string. Return non-zero if zStr
@@@ -4289,11 -3332,8 +4317,9 @@@ static int str_in_array(const char *zSt
  **       then indent all opcodes between the earlier instruction
  **       and "Goto" by 2 spaces.
  */
 -static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
 +static void explain_data_prepare(ShellInState *psi, 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 *ai;                        /* Temporary aiIndent[] (to avoid leak) */
    int nAlloc = 0;                 /* Allocated size of p->aiIndent[], abYield */
    int iOp;                        /* Index of operation in p->aiIndent[] */
  
                              "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 ){
-     psi->cMode = psi->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) ){
-     psi->cMode = psi->mode;
-     return;
-   }
+   /* The caller guarantees that the leftmost 4 columns of the statement
+   ** passed to this function are equivalent to the leftmost 4 columns
+   ** of EXPLAIN statement output. In practice the statement may be
+   ** an EXPLAIN, or it may be a query on the bytecode() virtual table.  */
+   assert( sqlite3_column_count(pSql)>=4 );
+   assert( 0==sqlite3_stricmp( sqlite3_column_name(pSql, 0), "addr" ) );
+   assert( 0==sqlite3_stricmp( sqlite3_column_name(pSql, 1), "opcode" ) );
+   assert( 0==sqlite3_stricmp( sqlite3_column_name(pSql, 2), "p1" ) );
+   assert( 0==sqlite3_stricmp( sqlite3_column_name(pSql, 3), "p2" ) );
  
 +  smem_ptr_holder((void**)&abYield);
++
    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);
 -    int p1 = sqlite3_column_int(pSql, 2);
 -    int p2 = sqlite3_column_int(pSql, 3);
  
-     /* 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);
+     /* 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 p2op = (p2 + (iOp-iAddr));
  
      /* Grow the p->aiIndent array as required */
      if( iOp>=nAlloc ){
-       if( iOp==0 ){
-         /* Do further verification 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( cli_strcmp(sqlite3_column_name(pSql,jj),explainCols[jj])!=0 ){
-             psi->cMode = psi->mode;
-             release_holder();
-             sqlite3_reset(pSql);
-             return;
-           }
-         }
-       }
        nAlloc += 100;
 -      p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int));
 -      shell_check_oom(p->aiIndent);
 +      ai = (int*)sqlite3_realloc64(psi->aiIndent, nAlloc*sizeof(int));
 +      shell_check_ooms(ai);
 +      psi->aiIndent = ai;
        abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int));
 -      shell_check_oom(abYield);
 +      shell_check_ooms(abYield);
      }
      abYield[iOp] = str_in_array(zOp, azYield);
 -    p->aiIndent[iOp] = 0;
 -    p->nIndent = iOp+1;
 +    psi->aiIndent[iOp] = 0;
 +    psi->nIndent = iOp+1;
 +
      if( str_in_array(zOp, azNext) && p2op>0 ){
 -      for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
 +      for(i=p2op; i<iOp; i++) psi->aiIndent[i] += 2;
      }
-     if( str_in_array(zOp, azGoto) && p2op<psi->nIndent
-      && (abYield[p2op] || sqlite3_column_int(pSql, 2))
-     ){
+     if( str_in_array(zOp, azGoto) && p2op<iOp && (abYield[p2op] || p1) ){
 -      for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
 +      for(i=p2op; i<iOp; i++) psi->aiIndent[i] += 2;
      }
    }
  
  /*
  ** 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;
 +static void explain_data_delete(ShellInState *psi){
 +  sqlite3_free(psi->aiIndent);
 +  psi->aiIndent = 0;
 +  psi->nIndent = 0;
 +  psi->iIndent = 0;
  }
  
 -static void exec_prepared_stmt(ShellState*, sqlite3_stmt*);
++static void exec_prepared_stmt(ShellExState*, sqlite3_stmt*);
+ /*
+ ** Display scan stats.
+ */
+ static void display_scanstats(
+   sqlite3 *db,                    /* Database to query */
 -  ShellState *pArg                /* Pointer to ShellState */
++  ShellInState *psi
+ ){
+ #ifndef SQLITE_ENABLE_STMT_SCANSTATUS
+   UNUSED_PARAMETER(db);
 -  UNUSED_PARAMETER(pArg);
++  UNUSED_PARAMETER(psi);
+ #else
 -  if( pArg->scanstatsOn==3 ){
++  if( psi->scanstatsOn==3 ){
+     const char *zSql =
+       "  SELECT addr, opcode, p1, p2, p3, p4, p5, comment, nexec,"
+       "   round(ncycle*100.0 / (sum(ncycle) OVER ()), 2)||'%' AS cycles"
+       "   FROM bytecode(?)";
 -
 -    int rc = SQLITE_OK;
+     sqlite3_stmt *pStmt = 0;
 -    rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
++    int rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
+     if( rc==SQLITE_OK ){
 -      sqlite3_stmt *pSave = pArg->pStmt;
 -      pArg->pStmt = pStmt;
++      sqlite3_stmt *pSave = psi->pStmt;
++      psi->pStmt = pStmt;
+       sqlite3_bind_pointer(pStmt, 1, pSave, "stmt-pointer", 0);
 -
+       pArg->cnt = 0;
+       pArg->cMode = MODE_ScanExp;
 -      explain_data_prepare(pArg, pStmt);
 -      exec_prepared_stmt(pArg, pStmt);
 -      explain_data_delete(pArg);
++      explain_data_prepare(psi, pStmt);
++      exec_prepared_stmt(psi, pStmt);
++      explain_data_delete(psi);
+       sqlite3_finalize(pStmt);
 -      pArg->pStmt = pSave;
++      psi->pStmt = pSave;
+     }
+   }else{
 -    display_explain_scanstats(db, pArg);
++    display_explain_scanstats(db, psi);
+   }
+ #endif
+ }
  /*
 -** Disable and restore .wheretrace and .treetrace/.selecttrace settings.
 +** Disable and restore .wheretrace and .selecttrace settings.
  */
  static unsigned int savedSelectTrace;
  static unsigned int savedWhereTrace;
@@@ -5308,76 -4228,64 +5352,69 @@@ static int shell_exec
        }
  
        /* Show the EXPLAIN QUERY PLAN if .eqp is on */
 -      if( pArg && pArg->autoEQP && sqlite3_stmt_isexplain(pStmt)==0 ){
 -        sqlite3_stmt *pExplain;
 +      if( psx && psi->autoEQP && sqlite3_stmt_isexplain(pStmt)==0 ){
++        sqlite3_stmt *pExplain = pStmt;
          int triggerEQP = 0;
          disable_debug_trace_modes();
          sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP);
 -        if( pArg->autoEQP>=AUTOEQP_trigger ){
 +        if( psi->autoEQP>=AUTOEQP_trigger ){
            sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0);
          }
-         zEQP = smprintf("EXPLAIN QUERY PLAN %s", zStmtSql);
-         rc = s3_prep_noom_free(db, &zEQP, &pExplain);
 -        pExplain = pStmt;
+         sqlite3_reset(pExplain);
+         rc = sqlite3_stmt_explain(pExplain, 2);
          if( rc==SQLITE_OK ){
            while( sqlite3_step(pExplain)==SQLITE_ROW ){
              const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);
              int iEqpId = sqlite3_column_int(pExplain, 0);
              int iParentId = sqlite3_column_int(pExplain, 1);
              if( zEQPLine==0 ) zEQPLine = "";
 -            if( zEQPLine[0]=='-' ) eqp_render(pArg, 0);
 -            eqp_append(pArg, iEqpId, iParentId, zEQPLine);
 +            if( zEQPLine[0]=='-' ) eqp_render(psi, 0);
 +            eqp_append(psi, iEqpId, iParentId, zEQPLine);
            }
 -          eqp_render(pArg, 0);
 +          eqp_render(psi, 0);
          }
-         sqlite3_finalize(pExplain);
-         pExplain = 0;
 -        if( pArg->autoEQP>=AUTOEQP_full ){
 +        if( psi->autoEQP>=AUTOEQP_full ){
            /* Also do an EXPLAIN for ".eqp full" mode */
-           zEQP = smprintf("EXPLAIN %s", zStmtSql);
-           rc = s3_prep_noom_free(db, &zEQP, &pExplain);
+           sqlite3_reset(pExplain);
+           rc = sqlite3_stmt_explain(pExplain, 1);
            if( rc==SQLITE_OK ){
-             explain_data_prepare(psi, pExplain);
-             psi->cMode = MODE_Explain;
-             {
 -            pArg->cMode = MODE_Explain;
 +#if SHELL_DATAIO_EXT
-               ExportHandler *pexSave = psi->pActiveExporter;
-               psi->pActiveExporter = psi->pFreeformExporter;
++            ExportHandler *pexSave = psi->pActiveExporter;
++            psi->pActiveExporter = psi->pFreeformExporter;
 +#endif
-               exec_prepared_stmt(psx, pExplain);
++            psi->cMode = MODE_Explain;
+             assert( sqlite3_stmt_isexplain(pExplain)==1 );
 -            explain_data_prepare(pArg, pExplain);
 -            exec_prepared_stmt(pArg, pExplain);
 -            explain_data_delete(pArg);
++            explain_data_prepare(psi, pExplain);
++            exec_prepared_stmt(psx, pExplain);
++            explain_data_delete(psi);
 +#if SHELL_DATAIO_EXT
-               psi->pActiveExporter = pexSave;
++            psi->pActiveExporter = pexSave;
 +#endif
-             }
-             explain_data_delete(psi);
            }
-           sqlite3_finalize(pExplain);
-           pExplain = 0;
          }
 -        if( pArg->autoEQP>=AUTOEQP_trigger && triggerEQP==0 ){
 +        if( psi->autoEQP>=AUTOEQP_trigger && triggerEQP==0 ){
            sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 0, 0);
-           /* Reprepare pStmt before reactivating trace modes */
-           sqlite3_finalize(pStmt);
-           pStmt = 0;
-           s3_prepare_v2_noom(db, zSql, -1, &pStmt, 0);
-           if( psx ) psi->pStmt = pStmt;
          }
+         sqlite3_reset(pStmt);
+         sqlite3_stmt_explain(pStmt, 0);
          restore_debug_trace_modes();
        }
  
 -      if( pArg ){
 +      if( psx ){
+         int bIsExplain = (sqlite3_stmt_isexplain(pStmt)==1);
 -        pArg->cMode = pArg->mode;
 -        if( pArg->autoExplain ){
 -          if( bIsExplain ){
 -            pArg->cMode = MODE_Explain;
 -          }
 -          if( sqlite3_stmt_isexplain(pStmt)==2 ){
 -            pArg->cMode = MODE_EQP;
 +        psi->cMode = psi->mode;
 +        if( psi->autoExplain ){
-           if( sqlite3_stmt_isexplain(pStmt)==1 ){
++          if( bIsExplain  ){
 +            psi->cMode = MODE_Explain;
-           }
-           if( sqlite3_stmt_isexplain(pStmt)==2 ){
++          }else if( sqlite3_stmt_isexplain(pStmt)==2 ){
 +            psi->cMode = MODE_EQP;
            }
          }
  
          /* If the shell is currently in ".explain" mode, gather the extra
          ** data required to add indents to the output.*/
-         if( psi->cMode==MODE_Explain ){
 -        if( pArg->cMode==MODE_Explain && bIsExplain ){
 -          explain_data_prepare(pArg, pStmt);
++        if( psi->cMode==MODE_Explain && bIsExplain ){
 +          explain_data_prepare(psi, pStmt);
          }
        }
  
@@@ -9465,1814 -6748,882 +9502,1843 @@@ static void free_all_shext_tracking(She
    }
  }
  
 -/*
 -** Create a prepared statement using printf-style arguments for the SQL.
 -**
 -** This routine is could be marked "static".  But it is not always used,
 -** depending on compile-time options.  By omitting the "static", we avoid
 -** nuisance compiler warnings about "defined but not used".
 -*/
 -void shellPreparePrintf(
 -  sqlite3 *db,
 -  int *pRc,
 -  sqlite3_stmt **ppStmt,
 -  const char *zFmt,
 -  ...
 -){
 -  *ppStmt = 0;
 -  if( *pRc==SQLITE_OK ){
 -    va_list ap;
 -    char *z;
 -    va_start(ap, zFmt);
 -    z = sqlite3_vmprintf(zFmt, ap);
 -    va_end(ap);
 -    if( z==0 ){
 -      *pRc = SQLITE_NOMEM;
 -    }else{
 -      shellPrepare(db, pRc, z, ppStmt);
 -      sqlite3_free(z);
 +static DotCommand *command_by_index(ShellInState *psi, int extIx, int cmdIx){
 +  assert(extIx>=0);
 +  if( extIx>=0 && extIx<psi->numExtLoaded ){
 +    ShExtInfo *psei = & psi->pShxLoaded[extIx];
 +    if( cmdIx>=0 && cmdIx<psei->numDotCommands ){
 +      return psei->ppDotCommands[cmdIx];
      }
    }
 +  return 0;
  }
  
 -/* Finalize the prepared statement created using shellPreparePrintf().
 -**
 -** This routine is could be marked "static".  But it is not always used,
 -** depending on compile-time options.  By omitting the "static", we avoid
 -** nuisance compiler warnings about "defined but not used".
 -*/
 -void shellFinalize(
 -  int *pRc,
 -  sqlite3_stmt *pStmt
 -){
 -  if( pStmt ){
 -    sqlite3 *db = sqlite3_db_handle(pStmt);
 -    int rc = sqlite3_finalize(pStmt);
 -    if( *pRc==SQLITE_OK ){
 -      if( rc!=SQLITE_OK ){
 -        eputf("SQL error: %s\n", sqlite3_errmsg(db));
 -      }
 -      *pRc = rc;
 +static int load_shell_extension(ShellExState *psx, const char *zFile,
 +                                const char *zProc, char **pzErr,
 +                                int nLoadArgs, char **azLoadArgs){
 +  ShellExtensionLink shxLink = {
 +    sizeof(ShellExtensionLink),
 +    &shellExtAPI,
 +    psx, /* pSXS */
 +    0,   /* zErrMsg */
 +    0,   /* ExtensionId */
 +    0,   /* Extension destructor */
 +    0,   /* Extension data ref */
 +    nLoadArgs, azLoadArgs /* like-named members */
 +  }; //extDtor(pvExtObj)
 +  ShellInState *psi = ISS(psx);
 +  /* save script support state for possible fallback if load fails */
 +  ScriptSupport *pssSave = psi->script;
 +  ExtensionId ssiSave = psi->scriptXid;
 +  int rc;
 +
 +  if( pzErr ) *pzErr = 0;
 +  if( psx->dbShell==0 || ISS(psx)->numExtLoaded==0 ){
 +    rc = begin_db_dispatch(psx);
 +    if( rc!=SQLITE_OK ) return rc;
 +    assert(ISS(psx)->numExtLoaded==1 && psx->dbShell!=0);
 +  }
 +  psi->ixExtPending = psi->numExtLoaded;
 +  sqlite3_create_function(psx->dbShell, "shext_pointer", 1,
 +                          SQLITE_DIRECTONLY|SQLITE_UTF8,
 +                          &shxLink, shell_linkage, 0, 0);
 +  rc = sqlite3_load_extension(psx->dbShell, zFile, zProc, &shxLink.zErrMsg);
 +  sqlite3_create_function(psx->dbShell, "shext_pointer", 1,
 +                          SQLITE_DIRECTONLY|SQLITE_UTF8,
 +                          0, 0, 0, 0); /* unregister */
 +  if( pzErr!=0 ) *pzErr = shxLink.zErrMsg;
 +  if( rc==SQLITE_OK ){
 +    /* Keep extension's id and destructor for later disposal. */
 +    ShExtInfo *psei = pending_ext_info(psi);
 +    if( psei->extId!=0 && psei->extId!=shxLink.eid ) rc = SQLITE_MISUSE;
 +    psei->extId = shxLink.eid;
 +    psei->extDtor = shxLink.extensionDestruct;
 +    psei->pvExtObj = shxLink.pvExtensionObject;
 +  }else{
 +    /* Release all resources extension might have registered before failing. */
 +    if( psi->ixExtPending < psi->numExtLoaded ){
 +      run_one_shext_dtors(psi->pShxLoaded+psi->ixExtPending);
 +      free_ShExtInfo(psi->pShxLoaded+psi->ixExtPending);
 +      --psi->numExtLoaded;
 +    }
 +    /* And make it unwind any scripting linkage it might have setup. */
 +    if( psi->script!=0 ) psi->script->pMethods->destruct(psi->script);
 +    psi->script = pssSave;
 +    psi->scriptXid = ssiSave;
 +  }
 +  psi->ixExtPending = 0;
 +  if( rc!=SQLITE_OK ){
 +    if( rc==SQLITE_MISUSE && pzErr!=0 ){
 +      *pzErr = smprintf("extension id mismatch %z\n", *pzErr);
      }
 +    rc = SQLITE_ERROR;
    }
 +  return rc;
  }
 +#endif
  
 -/* Reset the prepared statement created using shellPreparePrintf().
 -**
 -** This routine is could be marked "static".  But it is not always used,
 -** depending on compile-time options.  By omitting the "static", we avoid
 -** nuisance compiler warnings about "defined but not used".
 +/* Dot-command implementation functions are defined in this section.
 +COMMENT  Define dot-commands and provide for their dispatch and .help text.
 +COMMENT  These should be kept in command name order for coding convenience
 +COMMENT  except where dot-commands share implementation. (The ordering
 +COMMENT  required for dispatch and help text is effected regardless.) The
 +COMMENT  effect of this configuration can be seen in generated output or by
 +COMMENT  executing tool/mkshellc.tcl --parameters (or --details or --help).
 +COMMENT  Generally, this section defines dispatchable functions inline and
 +COMMENT  causes collection of command_table entry initializers, to be later
 +COMMENT  emitted by a macro invocation. (See EMIT_DOTCMD_INIT further on.)
 +** All dispatchable dot-command execute functions have this signature:
 +static int someCommand(char *azArg[], int nArg, ShellExState *p, char **pzErr);
  */
 -void shellReset(
 -  int *pRc,
 -  sqlite3_stmt *pStmt
 -){
 -  int rc = sqlite3_reset(pStmt);
 -  if( *pRc==SQLITE_OK ){
 -    if( rc!=SQLITE_OK ){
 -      sqlite3 *db = sqlite3_db_handle(pStmt);
 -      eputf("SQL error: %s\n", sqlite3_errmsg(db));
 -    }
 -    *pRc = rc;
 +DISPATCH_CONFIG[
 +  RETURN_TYPE=DotCmdRC
 +  STORAGE_CLASS=static
 +  ARGS_SIGNATURE=char *$arg4\[\], int $arg5, ShellExState *$arg6, char **$arg7
 +  DISPATCH_ENTRY={ "$cmd", ${cmd}Command, $arg1, $arg2, $arg3 },
 +  DOTCMD_INIT={ DOT_CMD_INFO(${cmd}, $arg1,$arg2,$arg3), {<HT0>, <HT1>}, 0 },
 +  CMD_CAPTURE_RE=^\s*{\s*"(\w+)"
 +  DISPATCHEE_NAME=${cmd}Command
 +  DC_ARG1_DEFAULT=[string length $cmd]
 +  DC_ARG2_DEFAULT=0
 +  DC_ARG3_DEFAULT=0
 +  DC_ARG4_DEFAULT=azArg
 +  DC_ARG5_DEFAULT=nArg
 +  DC_ARG6_DEFAULT=p
 +  DC_ARG7_DEFAULT=pzErr
 +  DC_ARG_COUNT=8
 +];
 +
 +CONDITION_COMMAND(seeargs !defined(SHELL_OMIT_SEEARGS));
 +/*****************
 + * The .seeargs command
 + */
 +COLLECT_HELP_TEXT[
 +  ",seeargs                 Echo arguments suffixed with |",
 +];
 +DISPATCHABLE_COMMAND( seeargs ? 0 0 azArg nArg p ){
 +  int ia = 0;
 +  for (ia=1; ia<nArg; ++ia)
 +    raw_printf(ISS(p)->out, "%s%s", azArg[ia], (ia==nArg-1)? "|\n" : "|");
 +  return DCR_Ok;
 +}
 +
 +CONDITION_COMMAND(archive ARCHIVE_ENABLE && !defined(SQLITE_SHELL_FIDDLE));
 +/*****************
 + * The .archive command
 + */
 +COLLECT_HELP_TEXT[
 +  ".archive ...             Manage SQL archives",
 +  "   Each command must have exactly one of the following options:",
 +  "     -c, --create               Create a new archive",
 +  "     -u, --update               Add or update files with changed mtime",
 +  "     -i, --insert               Like -u but always add even if unchanged",
 +  "     -r, --remove               Remove files from archive",
 +  "     -t, --list                 List contents of archive",
 +  "     -x, --extract              Extract files from archive",
 +  "   Optional arguments:",
 +  "     -v, --verbose              Print each filename as it is processed",
 +  "     -f FILE, --file FILE       Use archive FILE (default is current db)",
 +  "     -a FILE, --append FILE     Open FILE using the apndvfs VFS",
 +  "     -C DIR, --directory DIR    Read/extract files from directory DIR",
 +  "     -g, --glob                 Use glob matching for names in archive",
 +  "     -n, --dryrun               Show the SQL that would have occurred",
 +  "   Examples:",
 +  "     .ar -cf ARCHIVE foo bar  # Create ARCHIVE from files foo and bar",
 +  "     .ar -tf ARCHIVE          # List members of ARCHIVE",
 +  "     .ar -xvf ARCHIVE         # Verbosely extract files from ARCHIVE",
 +  "   See also:",
 +  "      http://sqlite.org/cli.html#sqlite_archive_support",
 +];
 +DISPATCHABLE_COMMAND( archive ? 2 0 azArg nArg p ){
 +  open_db(p, 0);
 +  if( ISS(p)->bSafeMode ) return DCR_AbortError;
 +  return arDotCommand(p, 0, azArg, nArg);
 +}
 +
 +/*****************
 + * The .auth command
 + */
 +CONDITION_COMMAND(auth !defined(SQLITE_OMIT_AUTHORIZATION));
 +COLLECT_HELP_TEXT[
 +  ".auth ON|OFF             Show authorizer callbacks",
 +];
 +DISPATCHABLE_COMMAND( auth 3 2 2 azArg nArg p ){
 +  open_db(p, 0);
 +  if( booleanValue(azArg[1]) ){
 +    sqlite3_set_authorizer(DBX(p), shellAuth, p);
 +  }else if( ISS(p)->bSafeModeFuture ){
 +    sqlite3_set_authorizer(DBX(p), safeModeAuth, p);
 +  }else{
 +    sqlite3_set_authorizer(DBX(p), 0, 0);
    }
 +  return DCR_Ok;
  }
 -#endif /* !defined SQLITE_OMIT_VIRTUALTABLE */
  
 -#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
 -/******************************************************************************
 -** The ".archive" or ".ar" command.
 -*/
 -/*
 -** Structure representing a single ".ar" command.
 -*/
 -typedef struct ArCommand ArCommand;
 -struct ArCommand {
 -  u8 eCmd;                        /* An AR_CMD_* value */
 -  u8 bVerbose;                    /* True if --verbose */
 -  u8 bZip;                        /* True if the archive is a ZIP */
 -  u8 bDryRun;                     /* True if --dry-run */
 -  u8 bAppend;                     /* True if --append */
 -  u8 bGlob;                       /* True if --glob */
 -  u8 fromCmdLine;                 /* Run from -A instead of .archive */
 -  int nArg;                       /* Number of command arguments */
 -  char *zSrcTable;                /* "sqlar", "zipfile($file)" or "zip" */
 -  const char *zFile;              /* --file argument, or NULL */
 -  const char *zDir;               /* --directory argument, or NULL */
 -  char **azArg;                   /* Array of command arguments */
 -  ShellState *p;                  /* Shell state */
 -  sqlite3 *db;                    /* Database containing the archive */
 -};
 +/*****************
 + * The .backup and .save commands (aliases for each other)
 + * These defer to writeDb in the dispatch table, so are not here.
 + */
 +CONDITION_COMMAND(backup !defined(SQLITE_SHELL_FIDDLE));
 +CONDITION_COMMAND(save !defined(SQLITE_SHELL_FIDDLE) );
 +COLLECT_HELP_TEXT[
 +  ".backup ?DB? FILE        Backup DB (default \"main\") to FILE",
 +  "   Options:",
 +  "     --append               Use the appendvfs",
 +  "     --async                Write the FILE without journal and fsync()",
 +  ".save ?DB? FILE          Write DB (default \"main\") to FILE",
 +  "   Options:",
 +  "     --append               Use the appendvfs",
 +  "     --async                Write the FILE without journal and fsync()",
 +];
 +DISPATCHABLE_COMMAND( backup 4 2 5 ){
 +  return writeDb( azArg, nArg, p, pzErr);
 +}
 +DISPATCHABLE_COMMAND( save 3 2 5 ){
 +  return writeDb( azArg, nArg, p, pzErr);
 +}
  
 -/*
 -** Print a usage message for the .ar command to stderr and return SQLITE_ERROR.
 -*/
 -static int arUsage(FILE *f){
 -  showHelp(f,"archive");
 -  return SQLITE_ERROR;
 +/*****************
 + * The .bail command
 + */
 +COLLECT_HELP_TEXT[
 +  ".bail on|off             Stop after hitting an error.  Default OFF",
 +];
 +DISPATCHABLE_COMMAND( bail 3 2 2 ){
 +  bail_on_error = booleanValue(azArg[1]);
 +  return DCR_Ok;
  }
  
 -/*
 -** Print an error message for the .ar command to stderr and return
 -** SQLITE_ERROR.
 -*/
 -static int arErrorMsg(ArCommand *pAr, const char *zFmt, ...){
 -  va_list ap;
 -  char *z;
 -  va_start(ap, zFmt);
 -  z = sqlite3_vmprintf(zFmt, ap);
 -  va_end(ap);
 -  eputf("Error: %s\n", z);
 -  if( pAr->fromCmdLine ){
 -    eputz("Use \"-A\" for more help\n");
 +CONDITION_COMMAND(cd !defined(SQLITE_SHELL_FIDDLE));
 +/*****************
 + * The .binary and .cd commands
 + */
 +COLLECT_HELP_TEXT[
-   ".binary on|off           Turn binary output on or off.  Default OFF",
-   ".cd DIRECTORY            Change the working directory to DIRECTORY",
++  ",binary on|off           Turn binary output on or off.  Default OFF",
 +];
- DISPATCHABLE_COMMAND( binary 3 2 2 ){
++DISPATCHABLE_COMMAND( binary 3 1 2 ){
++  if( nArg<2 ){
++    raw_printf(stderr,
++               "The \".binary\" command is deprecated."
++               " Use \".crnl\" instead.\n"
++               "Usage: .binary on|off\n");
++    return DCR_Error;
++  }
 +  if( booleanValue(azArg[1]) ){
 +    setBinaryMode(ISS(p)->out, 1);
    }else{
 -    eputz("Use \".archive --help\" for more help\n");
 +    setTextMode(ISS(p)->out, 1);
    }
 -  sqlite3_free(z);
 -  return SQLITE_ERROR;
 +  return DCR_Ok;
  }
  
 -/*
 -** Values for ArCommand.eCmd.
 -*/
 -#define AR_CMD_CREATE       1
 -#define AR_CMD_UPDATE       2
 -#define AR_CMD_INSERT       3
 -#define AR_CMD_EXTRACT      4
 -#define AR_CMD_LIST         5
 -#define AR_CMD_HELP         6
 -#define AR_CMD_REMOVE       7
++CONDITION_COMMAND( crnl (defined(_WIN32) || defined(WIN32)) );
++COLLECT_HELP_TEXT[
++  ".cd DIRECTORY            Change the working directory to DIRECTORY",
++  ".crnl on|off             Translate \\n to \\r\\n.  Default ON",
++];
 +DISPATCHABLE_COMMAND( cd ? 2 2 ){
 +  int rc=0;
 +  if( ISS(p)->bSafeMode ) return DCR_AbortError;
 +  else{
 +#if defined(_WIN32) || defined(WIN32)
 +    wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]);
 +    shell_check_ooms(z);
 +    rc = (z)? !SetCurrentDirectoryW(z) : 1;
 +    sqlite3_free(z);
 +#else
 +    rc = chdir(azArg[1]);
 +#endif
 +  }
 +  if( rc ){
 +    utf8_printf(STD_ERR, "Cannot change to directory \"%s\"\n", azArg[1]);
 +    rc = 1;
 +  }
 +  return DCR_Ok|rc;
 +}
  
 -/*
 -** Other (non-command) switches.
 -*/
 -#define AR_SWITCH_VERBOSE     8
 -#define AR_SWITCH_FILE        9
 -#define AR_SWITCH_DIRECTORY  10
 -#define AR_SWITCH_APPEND     11
 -#define AR_SWITCH_DRYRUN     12
 -#define AR_SWITCH_GLOB       13
++DISPATCHABLE_COMMAND( crnl 4 1 2 ){
++  if( nArg==2 ){
++    if( booleanValue(azArg[1]) ){
++      setTextMode(ISS(p)->out, 1);
++    }else{
++      setBinaryMode(ISS(p)->out, 1);
++    }
++    return DCR_Ok;
++  }else{
++#if !(defined(_WIN32)||defined(WIN32))
++    raw_printf(stderr, "\".crnl\" is a no-op on non-Windows machines.\n");
++#else
++    raw_printf(stderr, "Usage: .crnl on|off\n");
++#endif
++    return DCR_Error;
++  }
++}
 -static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){
 -  switch( eSwitch ){
 -    case AR_CMD_CREATE:
 -    case AR_CMD_EXTRACT:
 -    case AR_CMD_LIST:
 -    case AR_CMD_REMOVE:
 -    case AR_CMD_UPDATE:
 -    case AR_CMD_INSERT:
 -    case AR_CMD_HELP:
 -      if( pAr->eCmd ){
 -        return arErrorMsg(pAr, "multiple command options");
 -      }
 -      pAr->eCmd = eSwitch;
 -      break;
 +/* The ".breakpoint" command causes a call to the no-op routine named
 + * test_breakpoint(). It is undocumented.
 +*/
 +COLLECT_HELP_TEXT[
 +  ",breakpoint              calls test_breakpoint(). (a debugging aid)",
 +];
 +DISPATCHABLE_COMMAND( breakpoint 3 1 1 ){
 +  test_breakpoint();
 +  return DCR_Ok;
 +}
  
 -    case AR_SWITCH_DRYRUN:
 -      pAr->bDryRun = 1;
 -      break;
 -    case AR_SWITCH_GLOB:
 -      pAr->bGlob = 1;
 -      break;
 -    case AR_SWITCH_VERBOSE:
 -      pAr->bVerbose = 1;
 -      break;
 -    case AR_SWITCH_APPEND:
 -      pAr->bAppend = 1;
 -      deliberate_fall_through;
 -    case AR_SWITCH_FILE:
 -      pAr->zFile = zArg;
 -      break;
 -    case AR_SWITCH_DIRECTORY:
 -      pAr->zDir = zArg;
 -      break;
 +CONDITION_COMMAND(check !defined(SQLITE_SHELL_FIDDLE));
 +CONDITION_COMMAND(clone !defined(SQLITE_SHELL_FIDDLE));
 +/*****************
 + * The .changes, .check, .clone and .connection commands
 + */
 +COLLECT_HELP_TEXT[
 +  ".changes on|off          Show number of rows changed by SQL",
 +  ",check GLOB              Fail if output since .testcase does not match",
 +  ".clone NEWDB             Clone data into NEWDB from the existing database",
 +  ".connection [close] [#]  Open or close an auxiliary database connection",
 +];
 +DISPATCHABLE_COMMAND( changes 3 2 2 ){
 +  setOrClearFlag(p, SHFLG_CountChanges, azArg[1]);
 +  return DCR_Ok;
 +}
 +DISPATCHABLE_COMMAND( check 3 0 0 ){
 +  /* 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.
 +  */
 +  char *zRes = 0;
 +  DotCmdRC rv = DCR_Ok;
 +  output_reset(ISS(p));
 +  if( nArg!=2 ){
 +    return DCR_ArgWrong;
 +  }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){
 +    *pzErr = smprintf("Error: cannot read 'testcase-out.txt'\n");
 +    rv = DCR_Return;
 +  }else if( testcase_glob(azArg[1],zRes)==0 ){
 +    *pzErr =
 +      smprintf("testcase-%s FAILED\n Expected: [%s]\n      Got: [%s]\n",
 +               ISS(p)->zTestcase, azArg[1], zRes);
 +    rv = DCR_Error;
 +  }else{
 +    utf8_printf(STD_OUT, "testcase-%s ok\n", ISS(p)->zTestcase);
 +    ISS(p)->nCheck++;
    }
 -
 -  return SQLITE_OK;
 +  sqlite3_free(zRes);
 +  return (zRes==0)? DCR_Abort : rv;
 +}
 +DISPATCHABLE_COMMAND( clone ? 2 2 ){
 +  if( ISS(p)->bSafeMode ) return DCR_AbortError;
 +  tryToClone(p, azArg[1]);
 +  return DCR_Ok;
 +}
 +DISPATCHABLE_COMMAND( connection ? 1 4 ){
 +  ShellInState *psi = ISS(p);
 +  if( nArg==1 ){
 +    /* List available connections */
 +    int i;
 +    for(i=0; i<ArraySize(psi->aAuxDb); i++){
 +      const char *zFile = psi->aAuxDb[i].zDbFilename;
 +      if( psi->aAuxDb[i].db==0 && psi->pAuxDb!=&psi->aAuxDb[i] ){
 +        zFile = "(not open)";
 +      }else if( zFile==0 ){
 +        zFile = "(memory)";
 +      }else if( zFile[0]==0 ){
 +        zFile = "(temporary-file)";
 +      }
 +      if( psi->pAuxDb == &psi->aAuxDb[i] ){
 +        utf8_printf(STD_OUT, "ACTIVE %d: %s\n", i, zFile);
 +      }else if( psi->aAuxDb[i].db!=0 ){
 +        utf8_printf(STD_OUT, "       %d: %s\n", i, zFile);
 +      }
 +    }
 +  }else if( nArg==2 && IsDigit(azArg[1][0]) && azArg[1][1]==0 ){
 +    int i = azArg[1][0] - '0';
 +    if( psi->pAuxDb != &psi->aAuxDb[i] && i>=0 && i<ArraySize(psi->aAuxDb) ){
 +      psi->pAuxDb->db = DBX(p);
 +      psi->pAuxDb = &psi->aAuxDb[i];
 +#if SHELL_DYNAMIC_EXTENSION
 +      if( DBX(p)!=0 ) notify_subscribers(psi, NK_DbUserVanishing, DBX(p));
 +#endif
 +      globalDb = DBX(p) = psi->pAuxDb->db;
 +#if SHELL_DYNAMIC_EXTENSION
 +      if( DBX(p)!=0 ) notify_subscribers(psi, NK_DbUserAppeared, DBX(p));
 +#endif
 +      psi->pAuxDb->db = 0;
 +    }
 +  }else if( nArg==3 && cli_strcmp(azArg[1], "close")==0
 +            && IsDigit(azArg[2][0]) && azArg[2][1]==0 ){
 +    int i = azArg[2][0] - '0';
 +    if( i<0 || i>=ArraySize(psi->aAuxDb) ){
 +      /* No-op */
 +    }else if( psi->pAuxDb == &psi->aAuxDb[i] ){
 +      raw_printf(STD_ERR, "cannot close the active database connection\n");
 +      return DCR_Error;
 +    }else if( psi->aAuxDb[i].db ){
 +      session_close_all(psi, i);
 +      close_db(psi->aAuxDb[i].db);
 +      psi->aAuxDb[i].db = 0;
 +    }
 +  }else{
 +    return DCR_ArgWrong;
 +  }
 +  return DCR_Ok;
  }
  
 -/*
 -** Parse the command line for an ".ar" command. The results are written into
 -** structure (*pAr). SQLITE_OK is returned if the command line is parsed
 -** successfully, otherwise an error message is written to stderr and
 -** SQLITE_ERROR returned.
 -*/
 -static int arParseCommand(
 -  char **azArg,                   /* Array of arguments passed to dot command */
 -  int nArg,                       /* Number of entries in azArg[] */
 -  ArCommand *pAr                  /* Populate this object */
 -){
 -  struct ArSwitch {
 -    const char *zLong;
 -    char cShort;
 -    u8 eSwitch;
 -    u8 bArg;
 -  } aSwitch[] = {
 -    { "create",    'c', AR_CMD_CREATE,       0 },
 -    { "extract",   'x', AR_CMD_EXTRACT,      0 },
 -    { "insert",    'i', AR_CMD_INSERT,       0 },
 -    { "list",      't', AR_CMD_LIST,         0 },
 -    { "remove",    'r', AR_CMD_REMOVE,       0 },
 -    { "update",    'u', AR_CMD_UPDATE,       0 },
 -    { "help",      'h', AR_CMD_HELP,         0 },
 -    { "verbose",   'v', AR_SWITCH_VERBOSE,   0 },
 -    { "file",      'f', AR_SWITCH_FILE,      1 },
 -    { "append",    'a', AR_SWITCH_APPEND,    1 },
 -    { "directory", 'C', AR_SWITCH_DIRECTORY, 1 },
 -    { "dryrun",    'n', AR_SWITCH_DRYRUN,    0 },
 -    { "glob",      'g', AR_SWITCH_GLOB,      0 },
 -  };
 -  int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
 -  struct ArSwitch *pEnd = &aSwitch[nSwitch];
 +CONDITION_COMMAND(dbinfo SQLITE_SHELL_HAVE_RECOVER);
 +/*****************
 + * The .databases, .dbconfig and .dbinfo commands
 + */
 +COLLECT_HELP_TEXT[
 +  ".databases               List names and files of attached databases",
 +  ".dbconfig ?op? ?val?     List or change sqlite3_db_config() options",
 +  ".dbinfo ?DB?             Show status information about the database",
 +];
 +/* Allow garbage arguments on this, to be ignored. */
 +DISPATCHABLE_COMMAND( databases 2 1 0 ){
 +  int rc;
 +  char **azName = 0;
 +  int nName = 0;
 +  sqlite3_stmt *pStmt = 0;
 +  sqlite3 *db = open_db(p, 0);
  
 -  if( nArg<=1 ){
 -    eputz("Wrong number of arguments.  Usage:\n");
 -    return arUsage(stderr);
 +  rc = s3_prepare_v2_noom(db, "PRAGMA database_list", -1, &pStmt, 0);
 +  stmt_holder(pStmt);
 +  if( rc || pStmt==0 ){
 +    *pzErr = smprintf("%s\n", sqlite3_errmsg(db));
 +    rc = 1;
    }else{
 -    char *z = azArg[1];
 -    if( z[0]!='-' ){
 -      /* Traditional style [tar] invocation */
 -      int i;
 -      int iArg = 2;
 -      for(i=0; z[i]; i++){
 -        const char *zArg = 0;
 -        struct ArSwitch *pOpt;
 -        for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
 -          if( z[i]==pOpt->cShort ) break;
 -        }
 -        if( pOpt==pEnd ){
 -          return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
 -        }
 -        if( pOpt->bArg ){
 -          if( iArg>=nArg ){
 -            return arErrorMsg(pAr, "option requires an argument: %c",z[i]);
 -          }
 -          zArg = azArg[iArg++];
 -        }
 -        if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
 -      }
 -      pAr->nArg = nArg-iArg;
 -      if( pAr->nArg>0 ){
 -        pAr->azArg = &azArg[iArg];
 -      }
 -    }else{
 -      /* Non-traditional invocation */
 -      int iArg;
 -      for(iArg=1; iArg<nArg; iArg++){
 -        int n;
 -        z = azArg[iArg];
 -        if( z[0]!='-' ){
 -          /* All remaining command line words are command arguments. */
 -          pAr->azArg = &azArg[iArg];
 -          pAr->nArg = nArg-iArg;
 -          break;
 -        }
 -        n = strlen30(z);
 +    while( s3_step_noom(pStmt)==SQLITE_ROW ){
 +      int eTxn, bRdonly;
 +      const char *zSchema = (const char *)sqlite3_column_text(pStmt,1);
 +      const char *zFile = (const char*)sqlite3_column_text(pStmt,2);
 +      if( zSchema==0 || zFile==0 ) continue;
 +      eTxn = sqlite3_txn_state(db, zSchema);
 +      bRdonly = sqlite3_db_readonly(db, zSchema);
 +      utf8_printf(ISS(p)->out, "%s: %s %s%s\n",
 +                  zSchema,
 +                  zFile[0] ? zFile : "\"\"",
 +                  bRdonly ? "r/o" : "r/w",
 +                  eTxn==SQLITE_TXN_NONE ? "" :
 +                  eTxn==SQLITE_TXN_READ ? " read-txn" : " write-txn");
 +    }
 +  }
 +  release_holder();
 +  return DCR_Ok|(rc!=0);
 +}
 +DISPATCHABLE_COMMAND( dbconfig 3 1 3 ){
 +  static const struct DbConfigChoices {
 +    const char *zName;
 +    int op;
 +  } aDbConfig[] = {
 +    { "defensive",          SQLITE_DBCONFIG_DEFENSIVE             },
 +    { "dqs_ddl",            SQLITE_DBCONFIG_DQS_DDL               },
 +    { "dqs_dml",            SQLITE_DBCONFIG_DQS_DML               },
 +    { "enable_fkey",        SQLITE_DBCONFIG_ENABLE_FKEY           },
 +    { "enable_qpsg",        SQLITE_DBCONFIG_ENABLE_QPSG           },
 +    { "enable_trigger",     SQLITE_DBCONFIG_ENABLE_TRIGGER        },
 +    { "enable_view",        SQLITE_DBCONFIG_ENABLE_VIEW           },
 +    { "fts3_tokenizer",     SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
 +    { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE    },
 +    { "legacy_file_format", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT    },
 +    { "load_extension",     SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
 +    { "no_ckpt_on_close",   SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE      },
 +    { "reset_database",     SQLITE_DBCONFIG_RESET_DATABASE        },
 +    { "reverse_scanorder",  SQLITE_DBCONFIG_REVERSE_SCANORDER     },
 +    { "stmt_scanstatus",    SQLITE_DBCONFIG_STMT_SCANSTATUS       },
 +    { "trigger_eqp",        SQLITE_DBCONFIG_TRIGGER_EQP           },
 +    { "trusted_schema",     SQLITE_DBCONFIG_TRUSTED_SCHEMA        },
 +    { "writable_schema",    SQLITE_DBCONFIG_WRITABLE_SCHEMA       },
 +  };
 +  int ii, v;
 +  open_db(p, 0);
 +  for(ii=0; ii<ArraySize(aDbConfig); ii++){
 +    if( nArg>1 && cli_strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue;
 +    if( nArg>=3 ){
 +      sqlite3_db_config(DBX(p), aDbConfig[ii].op, booleanValue(azArg[2]), 0);
 +    }
 +    sqlite3_db_config(DBX(p), aDbConfig[ii].op, -1, &v);
 +    utf8_printf(ISS(p)->out, "%19s %s\n",
 +                aDbConfig[ii].zName, v ? "on" : "off");
 +    if( nArg>1 ) break;
 +  }
 +  if( nArg>1 && ii==ArraySize(aDbConfig) ){
 +    *pzErr = smprintf("Error: unknown dbconfig \"%s\"\n"
 +                      "Enter \".dbconfig\" with no arguments for a list\n",
 +                      azArg[1]);
 +    return DCR_ArgWrong;
 +  }
 +  return DCR_Ok;
 +}
 +DISPATCHABLE_COMMAND( dbinfo 3 1 2 ){
 +  return shell_dbinfo_command(p, nArg, azArg);
 +}
  
 -        if( z[1]!='-' ){
 -          int i;
 -          /* One or more short options */
 -          for(i=1; i<n; i++){
 -            const char *zArg = 0;
 -            struct ArSwitch *pOpt;
 -            for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
 -              if( z[i]==pOpt->cShort ) break;
 -            }
 -            if( pOpt==pEnd ){
 -              return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
 -            }
 -            if( pOpt->bArg ){
 -              if( i<(n-1) ){
 -                zArg = &z[i+1];
 -                i = n;
 -              }else{
 -                if( iArg>=(nArg-1) ){
 -                  return arErrorMsg(pAr, "option requires an argument: %c",
 -                                    z[i]);
 -                }
 -                zArg = azArg[++iArg];
 -              }
 -            }
 -            if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
 -          }
 -        }else if( z[2]=='\0' ){
 -          /* A -- option, indicating that all remaining command line words
 -          ** are command arguments.  */
 -          pAr->azArg = &azArg[iArg+1];
 -          pAr->nArg = nArg-iArg-1;
 -          break;
 +/*****************
 + * The .dump, .echo and .eqp commands
 + */
 +COLLECT_HELP_TEXT[
 +  ".dump ?OBJECTS?          Render database content as SQL",
 +  "   Options:",
 +  "     --data-only            Output only INSERT statements",
 +  "     --newlines             Allow unescaped newline characters in output",
 +  "     --nosys                Omit system tables (ex: \"sqlite_stat1\")",
 +  "     --preserve-rowids      Include ROWID values in the output",
 +  "     --schema SCHEMA        Dump table(s) from given SCHEMA",
 +  "   OBJECTS is a LIKE pattern for tables, indexes, triggers or views to dump",
 +  "   Additional LIKE patterns can be given in subsequent arguments",
 +  ".echo on|off             Turn command echo on or off",
 +  ".eqp on|off|full|...     Enable or disable automatic EXPLAIN QUERY PLAN",
 +  "   Other Modes:",
 +#ifdef SQLITE_DEBUG
 +  "      test                  Show raw EXPLAIN QUERY PLAN output",
 +  "      trace                 Like \"full\" but enable \"PRAGMA vdbe_trace\"",
 +#endif
 +  "      trigger               Like \"full\" but also show trigger bytecode",
 +];
 +DISPATCHABLE_COMMAND( dump ? 1 2 ){
 +  ShellInState *psi = ISS(p);
 +  char *zLike = 0;
 +  char *zSchema = "main";
 +  char *zSql;
 +  int i;
 +  int savedShowHeader = psi->showHeader;
 +  int savedShellFlags = psi->shellFlgs;
 +  sstr_ptr_holder(&zLike);
 +  ShellClearFlag(p,
 +     SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo
 +     |SHFLG_DumpDataOnly|SHFLG_DumpNoSys);
 +  for(i=1; i<nArg; i++){
 +    if( azArg[i][0]=='-' ){
 +      const char *z = azArg[i]+1;
 +      if( z[0]=='-' ) z++;
 +      if( cli_strcmp(z,"preserve-rowids")==0 ){
 +#ifdef SQLITE_OMIT_VIRTUALTABLE
 +        *pzErr = smprintf("The --preserve-rowids option is not compatible"
 +                          " with SQLITE_OMIT_VIRTUALTABLE\n");
 +        release_holder();
 +        return DCR_ArgWrong;
 +#else
 +        ShellSetFlag(p, SHFLG_PreserveRowid);
 +#endif
 +      }else{
 +        if( cli_strcmp(z,"newlines")==0 ){
 +          ShellSetFlag(p, SHFLG_Newlines);
 +        }else if( cli_strcmp(z,"data-only")==0 ){
 +          ShellSetFlag(p, SHFLG_DumpDataOnly);
 +        }else if( cli_strcmp(z,"nosys")==0 ){
 +          ShellSetFlag(p, SHFLG_DumpNoSys);
 +        }else if( cli_strcmp(z,"schema")==0 && ++i<nArg ){
 +          zSchema = azArg[i];
          }else{
 -          /* A long option */
 -          const char *zArg = 0;             /* Argument for option, if any */
 -          struct ArSwitch *pMatch = 0;      /* Matching option */
 -          struct ArSwitch *pOpt;            /* Iterator */
 -          for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
 -            const char *zLong = pOpt->zLong;
 -            if( (n-2)<=strlen30(zLong) && 0==memcmp(&z[2], zLong, n-2) ){
 -              if( pMatch ){
 -                return arErrorMsg(pAr, "ambiguous option: %s",z);
 -              }else{
 -                pMatch = pOpt;
 -              }
 -            }
 -          }
 -
 -          if( pMatch==0 ){
 -            return arErrorMsg(pAr, "unrecognized option: %s", z);
 -          }
 -          if( pMatch->bArg ){
 -            if( iArg>=(nArg-1) ){
 -              return arErrorMsg(pAr, "option requires an argument: %s", z);
 -            }
 -            zArg = azArg[++iArg];
 -          }
 -          if( arProcessSwitch(pAr, pMatch->eSwitch, zArg) ) return SQLITE_ERROR;
 +          *pzErr = smprintf("Unknown option \"%s\" on \".dump\"\n", azArg[i]);
 +          release_holder();
 +          return DCR_ArgWrong;
          }
        }
 +    }else{
 +      /* azArg[i] contains a LIKE pattern. This ".dump" request should
 +      ** only dump data for tables for which either the table name matches
 +      ** the LIKE pattern, or the table appears to be a shadow table of
 +      ** a virtual table for which the name matches the LIKE pattern.
 +      */
 +      char *zExpr = smprintf(
 +                    "name LIKE %Q ESCAPE '\\' OR EXISTS ("
 +                    "  SELECT 1 FROM %w.sqlite_schema WHERE "
 +                    "    name LIKE %Q ESCAPE '\\' AND"
 +                    "    sql LIKE 'CREATE VIRTUAL TABLE%%' AND"
 +                    "    substr(o.name, 1, length(name)+1) == (name||'_')"
 +                    ")", azArg[i], zSchema, azArg[i]
 +                    );
 +
 +      shell_check_ooms(zExpr);
 +      if( zLike ){
 +        zLike = smprintf("%z OR %z", zLike, zExpr);
 +      }else{
 +        zLike = zExpr;
 +      }
      }
    }
 -  if( pAr->eCmd==0 ){
 -    eputz("Required argument missing.  Usage:\n");
 -    return arUsage(stderr);
 +
 +  open_db(p, 0);
 +
 +  if( (psi->shellFlgs & SHFLG_DumpDataOnly)==0 ){
 +    /* When playing back a "dump", the content might appear in an order
 +    ** which causes immediate foreign key constraints to be violated.
 +    ** So disable foreign-key constraint enforcement to prevent problems. */
 +    raw_printf(psi->out, "PRAGMA foreign_keys=OFF;\n");
 +    raw_printf(psi->out, "BEGIN TRANSACTION;\n");
 +  }
 +  psi->writableSchema = 0;
 +  psi->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_schema table is
 +  ** corrupt. */
 +  sqlite3_exec(DBX(p), "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
 +  psi->nErr = 0;
 +  if( zLike==0 ) zLike = smprintf("true");
 +  zSql = smprintf("SELECT name, type, sql FROM %w.sqlite_schema AS o "
 +                  "WHERE (%s) AND type=='table' AND sql NOT NULL"
 +                  " ORDER BY tbl_name='sqlite_sequence', rowid",
 +                  zSchema, zLike);
 +  shell_check_ooms(zSql);
 +  sstr_ptr_holder(&zSql);
 +  run_schema_dump_query(psi,zSql);
 +  if( (psi->shellFlgs & SHFLG_DumpDataOnly)==0 ){
 +    sqlite3_free(zSql);
 +    zSql = smprintf(
 +             "SELECT sql FROM sqlite_schema AS o "
 +             "WHERE (%s) AND sql NOT NULL"
 +             "  AND type IN ('index','trigger','view')",
 +             zLike
 +           );
 +    run_table_dump_query(psi, zSql);
 +  }
 +  release_holder(); /* zSql */
 +  if( psi->writableSchema ){
 +    raw_printf(psi->out, "PRAGMA writable_schema=OFF;\n");
 +    psi->writableSchema = 0;
 +  }
 +  sqlite3_exec(DBX(p), "PRAGMA writable_schema=OFF;", 0, 0, 0);
 +  sqlite3_exec(DBX(p), "RELEASE dump;", 0, 0, 0);
 +  if( (psi->shellFlgs & SHFLG_DumpDataOnly)==0 ){
 +    raw_printf(psi->out, psi->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
 +  }
 +  psi->showHeader = savedShowHeader;
 +  psi->shellFlgs = savedShellFlags;
 +  release_holder(); /* zLike */
 +
 +  return DCR_Ok;
 +}
 +DISPATCHABLE_COMMAND( echo ? 2 2 ){
 +  setOrClearFlag(p, SHFLG_Echo, azArg[1]);
 +  return DCR_Ok;
 +}
 +DISPATCHABLE_COMMAND( eqp ? 0 0 ){
 +  ShellInState *psi = ISS(p);
 +  if( nArg==2 ){
 +    psi->autoEQPtest = 0;
 +    if( psi->autoEQPtrace ){
 +      if( DBX(p) ) sqlite3_exec(DBX(p), "PRAGMA vdbe_trace=OFF;", 0, 0, 0);
 +      psi->autoEQPtrace = 0;
 +    }
 +    if( cli_strcmp(azArg[1],"full")==0 ){
 +      psi->autoEQP = AUTOEQP_full;
 +    }else if( cli_strcmp(azArg[1],"trigger")==0 ){
 +      psi->autoEQP = AUTOEQP_trigger;
 +#ifdef SQLITE_DEBUG
 +    }else if( cli_strcmp(azArg[1],"test")==0 ){
 +      psi->autoEQP = AUTOEQP_on;
 +      psi->autoEQPtest = 1;
 +    }else if( cli_strcmp(azArg[1],"trace")==0 ){
 +      psi->autoEQP = AUTOEQP_full;
 +      psi->autoEQPtrace = 1;
 +      open_db(p, 0);
 +      sqlite3_exec(DBX(p), "SELECT name FROM sqlite_schema LIMIT 1", 0, 0, 0);
 +      sqlite3_exec(DBX(p), "PRAGMA vdbe_trace=ON;", 0, 0, 0);
 +#endif
 +    }else{
 +      psi->autoEQP = (u8)booleanValue(azArg[1]);
 +    }
 +  }else{
 +    return DCR_ArgWrong;
    }
 -  return SQLITE_OK;
 +  return DCR_Ok;
  }
  
 -/*
 -** This function assumes that all arguments within the ArCommand.azArg[]
 -** array refer to archive members, as for the --extract, --list or --remove
 -** commands. It checks that each of them are "present". If any specified
 -** file is not present in the archive, an error is printed to stderr and an
 -** error code returned. Otherwise, if all specified arguments are present
 -** in the archive, SQLITE_OK is returned. Here, "present" means either an
 -** exact equality when pAr->bGlob is false or a "name GLOB pattern" match
 -** when pAr->bGlob is true.
 -**
 -** This function strips any trailing '/' characters from each argument.
 -** This is consistent with the way the [tar] command seems to work on
 -** Linux.
 -*/
 -static int arCheckEntries(ArCommand *pAr){
 -  int rc = SQLITE_OK;
 -  if( pAr->nArg ){
 -    int i, j;
 -    sqlite3_stmt *pTest = 0;
 -    const char *zSel = (pAr->bGlob)
 -      ? "SELECT name FROM %s WHERE glob($name,name)"
 -      : "SELECT name FROM %s WHERE name=$name";
 +CONDITION_COMMAND(cease !defined(SQLITE_SHELL_FIDDLE));
 +CONDITION_COMMAND(exit !defined(SQLITE_SHELL_FIDDLE));
 +CONDITION_COMMAND(quit !defined(SQLITE_SHELL_FIDDLE));
 +/*****************
 + * The .cease, .exit and .quit commands
 + * These are together so that their differing effects are apparent.
 + */
 +CONDITION_COMMAND(cease defined(SHELL_CEASE));
 +COLLECT_HELP_TEXT[
 +  ".cease ?CODE?            Cease shell operation, with optional return code",
 +  "   Return code defaults to 0, otherwise is limited to non-signal values",
 +  ".exit ?CODE?             Exit shell program, maybe with return-code CODE",
 +  "   Exit immediately if CODE != 0, else functions as \"quit this input\"",
 +  ".quit                    Stop interpreting input stream, done if primary.",
 +];
 +DISPATCHABLE_COMMAND( cease 4 1 2 ){
 +  /* .cease effects an exit, always. Only the exit code is variable. */
 +  int rc = 0;
 +  if( nArg>1 ){
 +    rc = (int)integerValue(azArg[1]);
 +    if( rc>0x7f ) rc = 0x7f;
 +  }
 +  p->shellAbruptExit = 0x100|rc;
 +  return DCR_Exit;
 +}
 +DISPATCHABLE_COMMAND( exit 3 1 0 ){
 +  /* .exit acts like .quit with no argument or a zero argument,
 +   * only returning. With a non-zero argument, it effects an exit. */
 +  int rc;
 +  if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ){
 +    rc &= 0xff;    /* Mimic effect of legacy call to exit(). */
 +#ifdef SHELL_EXIT_EXITS_PROCESS
 +    terminate_actions();
 +    exit(rc);
 +#else
 +    p->shellAbruptExit = 0x100|rc;
 +#endif
 +  }
 +  return DCR_Return;
 +}
 +DISPATCHABLE_COMMAND( quit 1 1 0 ){
 +  /* .quit would be more aptly named .return, as it does nothing more. */
 +  return DCR_Return;
 +}
  
 -    shellPreparePrintf(pAr->db, &rc, &pTest, zSel, pAr->zSrcTable);
 -    j = sqlite3_bind_parameter_index(pTest, "$name");
 -    for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
 -      char *z = pAr->azArg[i];
 -      int n = strlen30(z);
 -      int bOk = 0;
 -      while( n>0 && z[n-1]=='/' ) n--;
 -      z[n] = '\0';
 -      sqlite3_bind_text(pTest, j, z, -1, SQLITE_STATIC);
 -      if( SQLITE_ROW==sqlite3_step(pTest) ){
 -        bOk = 1;
 -      }
 -      shellReset(&rc, pTest);
 -      if( rc==SQLITE_OK && bOk==0 ){
 -        eputf("not found in archive: %s\n", z);
 -        rc = SQLITE_ERROR;
 +/*****************
 + * The .expert and .explain commands
 + */
 +CONDITION_COMMAND( expert !defined(SQLITE_OMIT_VIRTUALTABLE) );
 +COLLECT_HELP_TEXT[
 +  ".expert                  Suggest indexes for queries",
 +  ".explain ?on|off|auto?   Change the EXPLAIN formatting mode. Default: auto",
 +];
 +DISPATCHABLE_COMMAND( expert ? 1 1 ){
 +  ShellInState *psi = ISS(p);
 +  int rv = DCR_Ok;
 +  char *zErr = 0;
 +  int i;
 +  int iSample = 0;
 +
 +  if( psi->bSafeMode ) return DCR_AbortError;
 +  assert( psi->expert.pExpert==0 );
 +  memset(&psi->expert, 0, sizeof(ExpertInfo));
 +
 +  open_db(p, 0);
 +
 +  for(i=1; i<nArg; i++){
 +    char *z = azArg[i];
 +    int n;
 +    if( z[0]=='-' && z[1]=='-' ) z++;
 +    n = strlen30(z);
 +    if( n>=2 && 0==cli_strncmp(z, "-verbose", n) ){
 +      psi->expert.bVerbose = 1;
 +    }
 +    else if( n>=2 && 0==cli_strncmp(z, "-sample", n) ){
 +      if( i==(nArg-1) ){
 +        return DCR_Unpaired|i;
 +      }else{
 +        iSample = (int)integerValue(azArg[++i]);
 +        if( iSample<0 || iSample>100 ){
 +          *pzErr = smprintf("value out of range: %s\n", azArg[i]);
 +          return DCR_ArgWrong|i;
 +        }
        }
      }
 -    shellFinalize(&rc, pTest);
 +    else{
 +      return DCR_Unknown|i;
 +    }
    }
 -  return rc;
 +
 +  psi->expert.pExpert = sqlite3_expert_new(DBI(psi), &zErr);
 +  if( psi->expert.pExpert==0 ){
 +    *pzErr = smprintf("sqlite3_expert_new: %s\n",
 +                      zErr ? zErr : "out of memory");
 +    return DCR_Error;
 +  }else{
 +    sqlite3_expert_config(psi->expert.pExpert, EXPERT_CONFIG_SAMPLE, iSample);
 +  }
 +
 +  return DCR_Ok;
  }
  
 -/*
 -** Format a WHERE clause that can be used against the "sqlar" table to
 -** identify all archive members that match the command arguments held
 -** in (*pAr). Leave this WHERE clause in (*pzWhere) before returning.
 -** The caller is responsible for eventually calling sqlite3_free() on
 -** any non-NULL (*pzWhere) value. Here, "match" means strict equality
 -** when pAr->bGlob is false and GLOB match when pAr->bGlob is true.
 -*/
 -static void arWhereClause(
 -  int *pRc,
 -  ArCommand *pAr,
 -  char **pzWhere                  /* OUT: New WHERE clause */
 -){
 -  char *zWhere = 0;
 -  const char *zSameOp = (pAr->bGlob)? "GLOB" : "=";
 -  if( *pRc==SQLITE_OK ){
 -    if( pAr->nArg==0 ){
 -      zWhere = sqlite3_mprintf("1");
 +DISPATCHABLE_COMMAND( explain ? 1 2 ){
 +  /* The ".explain" command is automatic now.  It is largely
 +  ** pointless, retained purely for backwards compatibility */
 +  ShellInState *psi = ISS(p);
 +  int val = 1;
 +  if( nArg>1 ){
 +    if( cli_strcmp(azArg[1],"auto")==0 ){
 +      val = 99;
      }else{
 -      int i;
 -      const char *zSep = "";
 -      for(i=0; i<pAr->nArg; i++){
 -        const char *z = pAr->azArg[i];
 -        zWhere = sqlite3_mprintf(
 -          "%z%s name %s '%q' OR substr(name,1,%d) %s '%q/'",
 -          zWhere, zSep, zSameOp, z, strlen30(z)+1, zSameOp, z
 -        );
 -        if( zWhere==0 ){
 -          *pRc = SQLITE_NOMEM;
 -          break;
 -        }
 -        zSep = " OR ";
 -      }
 +      val = booleanValue(azArg[1]);
      }
    }
 -  *pzWhere = zWhere;
 +  if( val==1 && psi->mode!=MODE_Explain ){
 +    psi->normalMode = psi->mode;
 +    psi->mode = MODE_Explain;
 +    psi->autoExplain = 0;
 +  }else if( val==0 ){
 +    if( psi->mode==MODE_Explain ) psi->mode = psi->normalMode;
 +    psi->autoExplain = 0;
 +  }else if( val==99 ){
 +    if( psi->mode==MODE_Explain ) psi->mode = psi->normalMode;
 +    psi->autoExplain = 1;
 +  }
 +  return DCR_Ok;
  }
  
 -/*
 -** Implementation of .ar "lisT" command.
 -*/
 -static int arListCommand(ArCommand *pAr){
 -  const char *zSql = "SELECT %s FROM %s WHERE %s";
 -  const char *azCols[] = {
 -    "name",
 -    "lsmode(mode), sz, datetime(mtime, 'unixepoch'), name"
 -  };
 -
 -  char *zWhere = 0;
 -  sqlite3_stmt *pSql = 0;
 -  int rc;
 +/*****************
 + * The .excel, .once and .output commands
 + * These share much implementation, so they stick together.
 + */
 +CONDITION_COMMAND(excel !defined(SQLITE_SHELL_FIDDLE));
 +CONDITION_COMMAND(once !defined(SQLITE_SHELL_FIDDLE));
 +CONDITION_COMMAND(output !defined(SQLITE_SHELL_FIDDLE));
  
 -  rc = arCheckEntries(pAr);
 -  arWhereClause(&rc, pAr, &zWhere);
 +COLLECT_HELP_TEXT[
 +  ".excel                   Display the output of next command in spreadsheet",
 +  "   --bom                   Prefix the file with a UTF8 byte-order mark",
 +  ".once ?OPTIONS? ?FILE?   Output for the next SQL command only to FILE",
 +  "   If FILE begins with '|' then open it as a command to be piped into.",
 +  "   Options:",
 +  "     --bom                 Prefix output with a UTF8 byte-order mark",
 +  "     -e                    Send output to the system text editor",
 +  "     -x       Send output as CSV to a spreadsheet (same as \".excel\")",
 +  ".output ?FILE?           Send output to FILE or stdout if FILE is omitted",
 +  "   If FILE begins with '|' then open it as a command to be piped into.",
 +  "   Options:",
 +  "     --bom                 Prefix output with a UTF8 byte-order mark",
 +  "     -e                    Send output to the system text editor",
 +  "     -x       Send output as CSV to a spreadsheet (same as \".excel\")",
 +];
 +#ifndef SQLITE_SHELL_FIDDLE
 +/* Shared implementation of .excel, .once and .output */
 +static DotCmdRC outputRedirs(char *azArg[], int nArg,
 +                                      ShellInState *psi, char **pzErr,
 +                                      int bOnce, int eMode){
 +  /* bOnce => 0: .output, 1: .once, 2: .excel */
 +  /* eMode => 'x' for excel, else 0 */
 +  int rc = 0;
 +  char *zFile = 0;
 +  u8 bTxtMode = 0;
 +  u8 bPutBOM = 0;
 +  int i;
 +  static unsigned const char zBOM[4] = {0xef,0xbb,0xbf,0};
  
 -  shellPreparePrintf(pAr->db, &rc, &pSql, zSql, azCols[pAr->bVerbose],
 -                     pAr->zSrcTable, zWhere);
 -  if( pAr->bDryRun ){
 -    oputf("%s\n", sqlite3_sql(pSql));
 -  }else{
 -    while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
 -      if( pAr->bVerbose ){
 -        oputf("%s % 10d  %s  %s\n",
 -              sqlite3_column_text(pSql, 0), sqlite3_column_int(pSql, 1),
 -              sqlite3_column_text(pSql, 2),sqlite3_column_text(pSql, 3));
 +  sstr_ptr_holder(&zFile);
 +  if( psi->bSafeMode ) return DCR_AbortError;
 +  for(i=1; i<nArg; i++){
 +    char *z = azArg[i];
 +    if( z[0]=='-' ){
 +      if( z[1]=='-' ) z++;
 +      if( cli_strcmp(z,"-bom")==0 ){
 +        bPutBOM = 1;
 +      }else if( bOnce!=2 && cli_strcmp(z,"-x")==0 ){
 +        eMode = 'x';  /* spreadsheet */
 +      }else if( bOnce!=2 && cli_strcmp(z,"-e")==0 ){
 +        eMode = 'e';  /* text editor */
        }else{
 -        oputf("%s\n", sqlite3_column_text(pSql, 0));
 +        return DCR_Unknown|i;
 +      }
 +    }else if( zFile==0 && eMode!='e' && eMode!='x' ){
 +      zFile = smprintf("%s", z);
 +      shell_check_ooms(zFile);
 +      if( zFile[0]=='|' ){
 +        while( i+1<nArg ){
 +          zFile = smprintf("%z %s", zFile, azArg[++i]);
 +          shell_check_ooms(zFile);
 +        }
 +        break;
        }
 +    }else{
 +      release_holder();
 +      return DCR_TooMany|i;
      }
    }
 -  shellFinalize(&rc, pSql);
 -  sqlite3_free(zWhere);
 -  return rc;
 +  if( zFile==0 ){
 +    zFile = smprintf("stdout");
 +    shell_check_ooms(zFile);
 +  }
 +  if( bOnce ){
 +    psi->outCount = 2;
 +  }else{
 +    psi->outCount = 0;
 +  }
 +  output_reset(psi);
 +#ifndef SQLITE_NOHAVE_SYSTEM
 +  if( eMode=='e' || eMode=='x' ){
 +    psi->doXdgOpen = 1;
 +    outputModePush(psi);
 +    if( eMode=='x' ){
 +      /* spreadsheet mode.  Output as CSV. */
 +      newTempFile(psi, "csv");
 +      psi->shellFlgs &= ~SHFLG_Echo;
 +      psi->mode = MODE_Csv;
 +      sqlite3_snprintf(sizeof(psi->colSeparator), psi->colSeparator, SEP_Comma);
 +      sqlite3_snprintf(sizeof(psi->rowSeparator), psi->rowSeparator, SEP_CrLf);
 +    }else{
 +      /* text editor mode */
 +      newTempFile(psi, "txt");
 +      bTxtMode = 1;
 +    }
 +    sqlite3_free(zFile);
 +    zFile = smprintf("%s", psi->zTempFile);
 +  }
 +#endif /* SQLITE_NOHAVE_SYSTEM */
 +  shell_check_ooms(zFile);
 +  if( zFile[0]=='|' ){
 +#ifdef SQLITE_OMIT_POPEN
 +    *pzErr = smprintf("pipes are not supported in this OS\n");
 +    rc = 1;
 +    psi->out = STD_OUT;
 +#else
 +    psi->out = popen(zFile + 1, "w");
 +    if( psi->out==0 ){
 +      *pzErr = smprintf("cannot open pipe \"%s\"\n", zFile + 1);
 +      psi->out = STD_OUT;
 +      rc = 1;
 +    }else{
 +      if( bPutBOM ) fwrite(zBOM, 1, 3, psi->out);
 +      sqlite3_snprintf(sizeof(psi->outfile), psi->outfile, "%s", zFile);
 +    }
 +#endif
 +  }else{
 +    psi->out = output_file_open(zFile, bTxtMode);
 +    if( psi->out==0 ){
 +      if( cli_strcmp(zFile,"off")!=0 ){
 +        *pzErr = smprintf("cannot write to \"%s\"\n", zFile);
 +      }
 +      psi->out = STD_OUT;
 +      rc = 1;
 +    } else {
 +      if( bPutBOM ) fwrite(zBOM, 1, 3, psi->out);
 +      sqlite3_snprintf(sizeof(psi->outfile), psi->outfile, "%s", zFile);
 +    }
 +  }
 +  release_holder();
 +  return DCR_Ok|rc;
  }
 +#endif /* !defined(SQLITE_SHELL_FIDDLE)*/
  
 -/*
 -** Implementation of .ar "Remove" command.
 -*/
 -static int arRemoveCommand(ArCommand *pAr){
 -  int rc = 0;
 -  char *zSql = 0;
 -  char *zWhere = 0;
 +DISPATCHABLE_COMMAND( excel ? 1 2 ){
 +  return outputRedirs(azArg, nArg, ISS(p), pzErr, 2, 'x');
 +}
 +DISPATCHABLE_COMMAND( once ? 1 6 ){
 +  return outputRedirs(azArg, nArg, ISS(p), pzErr, 1, 0);
 +}
 +DISPATCHABLE_COMMAND( output ? 1 6 ){
 +  return outputRedirs(azArg, nArg, ISS(p), pzErr, 0, 0);
 +}
  
 -  if( pAr->nArg ){
 -    /* Verify that args actually exist within the archive before proceeding.
 -    ** And formulate a WHERE clause to match them.  */
 -    rc = arCheckEntries(pAr);
 -    arWhereClause(&rc, pAr, &zWhere);
 +
 +/*****************
 + * The .filectrl and fullschema commands
 + */
 +COLLECT_HELP_TEXT[
 +  ".filectrl CMD ...        Run various sqlite3_file_control() operations",
 +  "   --schema SCHEMA         Use SCHEMA instead of \"main\"",
 +  "   --help                  Show CMD details",
 +  ".fullschema ?--indent?   Show schema and the content of sqlite_stat tables",
 +];
 +DISPATCHABLE_COMMAND( filectrl ? 2 0 ){
 +  static const struct {
 +    const char *zCtrlName;   /* Name of a test-control option */
 +    int ctrlCode;            /* Integer code for that option */
 +    const char *zUsage;      /* Usage notes */
 +  } aCtrl[] = {
 +    { "chunk_size",     SQLITE_FCNTL_CHUNK_SIZE,      "SIZE"           },
 +    { "data_version",   SQLITE_FCNTL_DATA_VERSION,    ""               },
 +    { "has_moved",      SQLITE_FCNTL_HAS_MOVED,       ""               },
 +    { "lock_timeout",   SQLITE_FCNTL_LOCK_TIMEOUT,    "MILLISEC"       },
 +    { "persist_wal",    SQLITE_FCNTL_PERSIST_WAL,     "[BOOLEAN]"      },
 + /* { "pragma",         SQLITE_FCNTL_PRAGMA,          "NAME ARG"       },*/
 +    { "psow",       SQLITE_FCNTL_POWERSAFE_OVERWRITE, "[BOOLEAN]"      },
 +    { "reserve_bytes",  SQLITE_FCNTL_RESERVE_BYTES,   "[N]"            },
 +    { "size_limit",     SQLITE_FCNTL_SIZE_LIMIT,      "[LIMIT]"        },
 +    { "tempfilename",   SQLITE_FCNTL_TEMPFILENAME,    ""               },
 + /* { "win32_av_retry", SQLITE_FCNTL_WIN32_AV_RETRY,  "COUNT DELAY"    },*/
 +  };
 +  ShellInState *psi = ISS(p);
 +  int filectrl = -1;
 +  int iCtrl = -1;
 +  sqlite3_int64 iRes = 0;  /* Integer result to display if rc2==1 */
 +  int isOk = 0;            /* 0: usage  1: %lld  2: no-result */
 +  int n2, i;
 +  const char *zCmd = 0;
 +  const char *zSchema = 0;
 +
 +  open_db(p, 0);
 +  zCmd = nArg>=2 ? azArg[1] : "help";
 +
 +  if( zCmd[0]=='-'
 +      && (cli_strcmp(zCmd,"--schema")==0 || cli_strcmp(zCmd,"-schema")==0)
 +      && nArg>=4
 +      ){
 +    zSchema = azArg[2];
 +    for(i=3; i<nArg; i++) azArg[i-2] = azArg[i];
 +    nArg -= 2;
 +    zCmd = azArg[1];
    }
 -  if( rc==SQLITE_OK ){
 -    zSql = sqlite3_mprintf("DELETE FROM %s WHERE %s;",
 -                           pAr->zSrcTable, zWhere);
 -    if( pAr->bDryRun ){
 -      oputf("%s\n", zSql);
 -    }else{
 -      char *zErr = 0;
 -      rc = sqlite3_exec(pAr->db, "SAVEPOINT ar;", 0, 0, 0);
 -      if( rc==SQLITE_OK ){
 -        rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
 -        if( rc!=SQLITE_OK ){
 -          sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0);
 -        }else{
 -          rc = sqlite3_exec(pAr->db, "RELEASE ar;", 0, 0, 0);
 -        }
 +
 +  /* The argument can optionally begin with "-" or "--" */
 +  if( zCmd[0]=='-' && zCmd[1] ){
 +    zCmd++;
 +    if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
 +  }
 +
 +  /* --help lists all file-controls */
 +  if( cli_strcmp(zCmd,"help")==0 ){
 +    utf8_printf(psi->out, "Available file-controls:\n");
 +    for(i=0; i<ArraySize(aCtrl); i++){
 +      utf8_printf(psi->out, "  .filectrl %s %s\n",
 +                  aCtrl[i].zCtrlName, aCtrl[i].zUsage);
 +    }
 +    return DCR_Error;
 +  }
 +
 +  /* Convert filectrl text option to value. Allow any
 +  ** unique prefix of the option name, or a numerical value. */
 +  n2 = strlen30(zCmd);
 +  for(i=0; i<ArraySize(aCtrl); i++){
 +    if( cli_strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
 +      if( filectrl<0 ){
 +        filectrl = aCtrl[i].ctrlCode;
 +        iCtrl = i;
 +      }else{
 +        *pzErr = smprintf("ambiguous file-control: \"%s\"\n"
 +                          "Use \".filectrl --help\" for help\n", zCmd);
 +        return DCR_ArgWrong;
 +      }
 +    }
 +  }
 +  if( filectrl<0 ){
 +    *pzErr = smprintf("unknown file-control: %s\n"
 +                      "Use \".filectrl --help\" for help\n", zCmd);
 +    return DCR_ArgWrong;
 +  }else{
 +   switch(filectrl){
 +    case SQLITE_FCNTL_SIZE_LIMIT: {
 +      if( nArg!=2 && nArg!=3 ) break;
 +      iRes = nArg==3 ? integerValue(azArg[2]) : -1;
 +      sqlite3_file_control(DBX(p), zSchema, SQLITE_FCNTL_SIZE_LIMIT, &iRes);
 +      isOk = 1;
 +      break;
 +    }
 +    case SQLITE_FCNTL_LOCK_TIMEOUT:
 +    case SQLITE_FCNTL_CHUNK_SIZE: {
 +      int x;
 +      if( nArg!=3 ) break;
 +      x = (int)integerValue(azArg[2]);
 +      sqlite3_file_control(DBX(p), zSchema, filectrl, &x);
 +      isOk = 2;
 +      break;
 +    }
 +    case SQLITE_FCNTL_PERSIST_WAL:
 +    case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
 +      int x;
 +      if( nArg!=2 && nArg!=3 ) break;
 +      x = nArg==3 ? booleanValue(azArg[2]) : -1;
 +      sqlite3_file_control(DBX(p), zSchema, filectrl, &x);
 +      iRes = x;
 +      isOk = 1;
 +      break;
 +    }
 +    case SQLITE_FCNTL_DATA_VERSION:
 +    case SQLITE_FCNTL_HAS_MOVED: {
 +      int x;
 +      if( nArg!=2 ) break;
 +      sqlite3_file_control(DBX(p), zSchema, filectrl, &x);
 +      iRes = x;
 +      isOk = 1;
 +      break;
 +    }
 +    case SQLITE_FCNTL_TEMPFILENAME: {
 +      char *z = 0;
 +      if( nArg!=2 ) break;
 +      sqlite3_file_control(DBX(p), zSchema, filectrl, &z);
 +      if( z ){
 +        utf8_printf(psi->out, "%s\n", z);
 +        sqlite3_free(z);
        }
 -      if( zErr ){
 -        sputf(stdout, "ERROR: %s\n", zErr); /* stdout? */
 -        sqlite3_free(zErr);
 +      isOk = 2;
 +      break;
 +    }
 +    case SQLITE_FCNTL_RESERVE_BYTES: {
 +      int x;
 +      if( nArg>=3 ){
 +        x = atoi(azArg[2]);
 +        sqlite3_file_control(DBX(p), zSchema, filectrl, &x);
        }
 +      x = -1;
 +      sqlite3_file_control(DBX(p), zSchema, filectrl, &x);
 +      utf8_printf(psi->out,"%d\n", x);
 +      isOk = 2;
 +      break;
      }
 +   }
    }
 -  sqlite3_free(zWhere);
 -  sqlite3_free(zSql);
 -  return rc;
 +  if( isOk==0 && iCtrl>=0 ){
 +    *pzErr = smprintf("Usage: .filectrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
 +    return DCR_CmdErred;
 +  }else if( isOk==1 ){
 +    char zBuf[21];
 +    sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", iRes);
 +    raw_printf(psi->out, "%s\n", zBuf);
 +  }
 +  return DCR_Ok;
  }
  
 -/*
 -** Implementation of .ar "eXtract" command.
 -*/
 -static int arExtractCommand(ArCommand *pAr){
 -  const char *zSql1 =
 -    "SELECT "
 -    " ($dir || name),"
 -    " writefile(($dir || name), %s, mode, mtime) "
 -    "FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)"
 -    " AND name NOT GLOB '*..[/\\]*'";
 +static void modePopper(ShellInState *psi){
 +  outputModePop(psi);
 +}
  
 -  const char *azExtraArg[] = {
 -    "sqlar_uncompress(data, sz)",
 -    "data"
 -  };
 +DISPATCHABLE_COMMAND( fullschema ? 1 2 ){
 +  int rc;
 +  int doStats = 0;
 +  ShellInState *psi = ISS(p);
 +  u8 useMode = MODE_Semi;
 +  AnyResourceHolder arh = {psi, (GenericFreer)modePopper};
 +
 +  if( nArg==2 && optionMatch(azArg[1], "indent") ){
 +    useMode = MODE_Pretty;
 +    nArg = 1;
 +  }
 +  if( nArg!=1 ){
 +    return DCR_TooMany|1;
 +  }
 +  outputModePush(psi); /* Can fail to return due to OOM. */
 +  any_ref_holder(&arh);
 +  psi->showHeader = 0;
 +  psi->cMode = psi->mode = useMode;
 +  open_db(p, 0);
 +  rc = s3_exec_noom(DBX(p),
 +    "SELECT sql FROM"
 +    "  (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
 +    "     FROM sqlite_schema UNION ALL"
 +    "   SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_schema) "
 +    "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
 +    "ORDER BY x",
 +    callback, p, 0
 +  );
 +  if( rc==SQLITE_OK ){
 +    sqlite3_stmt *pStmt;
 +    rc = s3_prepare_v2_noom(p->dbUser,
 +                            "SELECT rowid FROM sqlite_schema"
 +                            " WHERE name GLOB 'sqlite_stat[134]'",
 +                            -1, &pStmt, 0);
 +    stmt_holder(pStmt);
 +    doStats = s3_step_noom(pStmt)==SQLITE_ROW;
 +    release_holder();
 +  }
 +  if( doStats==0 ){
 +    raw_printf(psi->out, "/* No STAT tables available */\n");
 +  }else{
 +    const char *zOldDestTable = p->zDestTable;
 +    raw_printf(psi->out, "ANALYZE sqlite_schema;\n");
 +    psi->cMode = psi->mode = MODE_Insert;
 +    p->zDestTable = "sqlite_stat1";
 +    shell_exec(p, "SELECT * FROM sqlite_stat1", 0);
 +    p->zDestTable = "sqlite_stat4";
 +    shell_exec(p, "SELECT * FROM sqlite_stat4", 0);
 +    raw_printf(psi->out, "ANALYZE sqlite_schema;\n");
 +    p->zDestTable = zOldDestTable;
 +  }
 +  release_holder(); /* Restore shell state */
 +  return rc > 0;
 +}
  
 -  sqlite3_stmt *pSql = 0;
 -  int rc = SQLITE_OK;
 -  char *zDir = 0;
 -  char *zWhere = 0;
 -  int i, j;
 +/*****************
 + * The .headers command
 + */
 +COLLECT_HELP_TEXT[
 +  ".headers on|off          Turn display of headers on or off",
 +];
 +DISPATCHABLE_COMMAND( headers 6 2 2 ){
 +  ISS(p)->showHeader = booleanValue(azArg[1]);
 +  ISS(p)->shellFlgs |= SHFLG_HeaderSet;
 +  return DCR_Ok;
 +}
  
 -  /* If arguments are specified, check that they actually exist within
 -  ** the archive before proceeding. And formulate a WHERE clause to
 -  ** match them.  */
 -  rc = arCheckEntries(pAr);
 -  arWhereClause(&rc, pAr, &zWhere);
 +/*****************
 + * The .help command
 + */
  
 -  if( rc==SQLITE_OK ){
 -    if( pAr->zDir ){
 -      zDir = sqlite3_mprintf("%s/", pAr->zDir);
 +/* This literal's value AND address are used for help's workings. */
 +static const char *zHelpAll = "-all";
 +
 +COLLECT_HELP_TEXT[
 +  ".help ?PATTERN?|?-all?   Show help for PATTERN or everything, or summarize",
 +  "                           Repeat -all to see undocumented commands",
 +];
 +DISPATCHABLE_COMMAND( help 3 1 3 ){
 +  const char *zPat = 0;
 +  FILE *out = ISS(p)->out;
 +  if( nArg>1 ){
 +    char *z = azArg[1];
 +    if( (nArg==2 && azArg[1][0]=='0' && azArg[1][1]==0)
 +       || (nArg==3 && cli_strcmp(z, zHelpAll)==0
 +           && cli_strcmp(azArg[2], zHelpAll)==0) ){
 +      /* Show the undocumented command help */
 +      zPat = zHelpAll;
 +    }else if( cli_strcmp(z,"-a")==0 || optionMatch(z, "all") ){
 +      zPat = "";
      }else{
 -      zDir = sqlite3_mprintf("");
 +      zPat = z;
      }
 -    if( zDir==0 ) rc = SQLITE_NOMEM;
    }
 +  if( showHelp(out, zPat, p)==0 && nArg>1 ){
 +    utf8_printf(out, "Nothing matches '%s'\n", azArg[1]);
 +  }
 +  /* Help pleas never fail! */
 +  return DCR_Ok;
 +}
  
 -  shellPreparePrintf(pAr->db, &rc, &pSql, zSql1,
 -      azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere
 -  );
 -
 -  if( rc==SQLITE_OK ){
 -    j = sqlite3_bind_parameter_index(pSql, "$dir");
 -    sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC);
 +CONDITION_COMMAND(import !defined(SQLITE_SHELL_FIDDLE));
 +/*****************
 + * The .import command
 + */
 +COLLECT_HELP_TEXT[
 +  ".import FILE TABLE       Import data from FILE into TABLE",
 +  "   Options:",
 +  "     --ascii               Use \\037 and \\036 as column and row separators",
 +  "     --csv                 Use , and \\n as column and row separators",
 +  "     --skip N              Skip the first N rows of input",
 +  "     --schema S            Target table to be S.TABLE",
 +  "     -v                    \"Verbose\" - increase auxiliary output",
 +  "   Notes:",
 +  "     *  If TABLE does not exist, it is created.  The first row of input",
 +  "        determines the column names.",
 +  "     *  If neither --csv or --ascii are used, the input mode is derived",
 +  "        from the \".mode\" output mode",
 +  "     *  If FILE begins with \"|\" then it is a command that generates the",
 +  "        input text.",
 +];
 +DISPATCHABLE_COMMAND( import ? 3 7 ){
 +  char *zTable = 0;           /* Insert data into this table */
 +  char *zSchema = 0;          /* within this schema (may default to "main") */
 +  char *zFile = 0;            /* 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 psi->colSeparator[] */
 +  char *zSql = 0;             /* An SQL statement */
 +  char *zFullTabName = 0;     /* Table name with schema if applicable */
 +  ImportCtx sCtx = {0};       /* Reader context */
 +  AnyResourceHolder arh = { &sCtx, (GenericFreer)import_cleanup };
 +  char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
 +  int eVerbose = 0;           /* Larger for more console output */
 +  int nSkip = 0;              /* Initial lines to skip */
 +  int useOutputMode = 1;      /* Use output mode to determine separators */
 +  FILE *out = ISS(p)->out;    /* output stream */
 +  char *zCreate = 0;          /* CREATE TABLE statement text */
 +  ShellInState *psi = ISS(p);
 +  ResourceMark mark = holder_mark();
 +  int rc = 0;
  
 -    /* Run the SELECT statement twice. The first time, writefile() is called
 -    ** for all archive members that should be extracted. The second time,
 -    ** only for the directories. This is because the timestamps for
 -    ** extracted directories must be reset after they are populated (as
 -    ** populating them changes the timestamp).  */
 -    for(i=0; i<2; i++){
 -      j = sqlite3_bind_parameter_index(pSql, "$dirOnly");
 -      sqlite3_bind_int(pSql, j, i);
 -      if( pAr->bDryRun ){
 -        oputf("%s\n", sqlite3_sql(pSql));
 +  if(psi->bSafeMode) return DCR_AbortError;
 +  memset(&sCtx, 0, sizeof(sCtx));
 +  if( psi->mode==MODE_Ascii ){
 +    xRead = ascii_read_one_field;
 +  }else{
 +    xRead = csv_read_one_field;
 +  }
 +  for(i=1; i<nArg; i++){
 +    char *z = azArg[i];
 +    if( z[0]=='-' && z[1]=='-' ) z++;
 +    if( z[0]!='-' ){
 +      if( zFile==0 ){
 +        zFile = z;
 +      }else if( zTable==0 ){
 +        zTable = z;
        }else{
 -        while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
 -          if( i==0 && pAr->bVerbose ){
 -            oputf("%s\n", sqlite3_column_text(pSql, 0));
 -          }
 -        }
 -      }
 -      shellReset(&rc, pSql);
 +        return DCR_TooMany|i;
 +      }
 +    }else if( cli_strcmp(z,"-v")==0 ){
 +      eVerbose++;
 +    }else if( cli_strcmp(z,"-schema")==0 && i<nArg-1 ){
 +      zSchema = azArg[++i];
 +    }else if( cli_strcmp(z,"-skip")==0 && i<nArg-1 ){
 +      nSkip = integerValue(azArg[++i]);
 +    }else if( cli_strcmp(z,"-ascii")==0 ){
 +      sCtx.cColSep = SEP_Unit[0];
 +      sCtx.cRowSep = SEP_Record[0];
 +      xRead = ascii_read_one_field;
 +      useOutputMode = 0;
 +    }else if( cli_strcmp(z,"-csv")==0 ){
 +      sCtx.cColSep = ',';
 +      sCtx.cRowSep = '\n';
 +      xRead = csv_read_one_field;
 +      useOutputMode = 0;
 +    }else{
 +      return DCR_Unknown|i;
      }
 -    shellFinalize(&rc, pSql);
    }
 +  if( zTable==0 ){
 +    *pzErr = smprintf("missing %s argument.\n", zFile==0 ? "FILE" : "TABLE");
 +    return DCR_Missing;
 +  }
 +  open_db(p, 0);
 +  if( useOutputMode ){
 +    const char *zYap = 0;
 +    /* If neither the --csv or --ascii options are specified, then set
 +    ** the column and row separator characters from the output mode. */
 +    nSep = strlen30(psi->colSeparator);
 +    if( nSep==0 ){
 +      zYap = "non-null column separator required for import";
 +    }
 +    if( nSep>1 ){
 +      zYap = "multi-character or multi-byte column separators"
 +        " not allowed for import";
 +    }
 +    nSep = strlen30(psi->rowSeparator);
 +    if( nSep==0 ){
 +      zYap = "non-null row separator required for import";
 +    }
 +    if( zYap!=0 ){
 +      *pzErr = smprintf("%s\n", zYap);
 +      return DCR_Error;
 +    }
 +    if( nSep==2 && psi->mode==MODE_Csv
 +        && cli_strcmp(psi->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(psi->rowSeparator), psi->rowSeparator, SEP_Row);
 +      nSep = strlen30(psi->rowSeparator);
 +    }
 +    if( nSep>1 ){
 +      *pzErr
 +        = smprintf("multi-character row separators not allowed for import\n");
 +      return DCR_Error;
 +    }
 +    sCtx.cColSep = (u8)psi->colSeparator[0];
 +    sCtx.cRowSep = (u8)psi->rowSeparator[0];
 +  }
 +  sCtx.zFile = zFile;
 +  sCtx.nLine = 1;
 +  if( sCtx.zFile[0]=='|' ){
 +#ifdef SQLITE_OMIT_POPEN
 +    *pzErr = smprintf("pipes are not supported in this OS\n");
 +    return DCR_Error;
 +#else
 +    sCtx.in = popen(sCtx.zFile+1, "r");
 +    sCtx.zFile = "<pipe>";
 +    sCtx.xCloser = pclose;
 +#endif
 +  }else{
 +    sCtx.in = fopen(sCtx.zFile, "rb");
 +    sCtx.xCloser = fclose;
 +  }
 +  if( sCtx.in==0 ){
 +    *pzErr = smprintf("cannot open \"%s\"\n", zFile);
 +    return DCR_Error;
 +  }
 +  /* Here and below, resources must be freed before exit. */
 +  any_ref_holder(&arh);
 +  sCtx.z = sqlite3_malloc64(120);
 +  shell_check_ooms(sCtx.z);
 +  if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){
 +    char zSep[2];
 +    zSep[1] = 0;
 +    zSep[0] = sCtx.cColSep;
 +    utf8_printf(out, "Column separator ");
 +    output_c_string(out, zSep);
 +    utf8_printf(out, ", row separator ");
 +    zSep[0] = sCtx.cRowSep;
 +    output_c_string(out, zSep);
 +    utf8_printf(out, "\n");
 +  }
 +  while( (nSkip--)>0 ){
 +    while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
 +  }
 +  if( zSchema!=0 ){
 +    zFullTabName = smprintf("\"%w\".\"%w\"", zSchema, zTable);
 +  }else{
 +    zFullTabName = smprintf("\"%w\"", zTable);
 +  }
 +  shell_check_ooms(zFullTabName);
 +  sstr_ptr_holder(&zFullTabName);
 +  zSql = smprintf("SELECT * FROM %s", zFullTabName);
 +  shell_check_ooms(zSql);
 +  sstr_ptr_holder(&zSql);
 +  nByte = strlen30(zSql);
 +  rc = s3_prepare_v2_noom(DBX(p), zSql, -1, &pStmt, 0);
 +  stmt_ptr_holder(&pStmt);
 +  import_append_char(&sCtx, 0);    /* To ensure sCtx.z is allocated */
 +  if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(DBX(p)))==0 ){
 +    zCreate = smprintf("CREATE TABLE %s", zFullTabName);
 +    sqlite3 *dbCols = 0;
 +    char *zRenames = 0;
 +    char *zColDefs;
 +    shell_check_ooms(zCreate);
 +    sstr_ptr_holder(&zCreate); /* +1 */
 +    sstr_ptr_holder(&zRenames); /* +2 */
 +    sstr_ptr_holder(&zColDefs); /* +3 */
 +    conn_ptr_holder(&dbCols);
 +    while( xRead(&sCtx) ){
 +      zAutoColumn(sCtx.z, &dbCols, 0);
 +      if( sCtx.cTerm!=sCtx.cColSep ) break;
 +    }
 +    zColDefs = zAutoColumn(0, &dbCols, &zRenames);
 +    if( zRenames!=0 ){
 +      FILE *fh = INSOURCE_IS_INTERACTIVE(psi->pInSource)?  out : STD_ERR;
 +      utf8_printf(fh, "Columns renamed during .import %s due to duplicates:\n"
 +                  "%s\n", sCtx.zFile, zRenames);
 +    }
 +    assert(dbCols==0);
 +    drop_holder(); /* dbCols */
 +    if( zColDefs==0 ){
 +      *pzErr = smprintf("%s: empty file\n", sCtx.zFile);
 +    import_fail: /* entry from outer blocks */
 +      RESOURCE_FREE(mark);
 +      return DCR_Error;
 +    }
 +    zCreate = smprintf("%z%z\n", zCreate, zColDefs);
 +    zColDefs = 0;
 +    shell_check_ooms(zCreate);
 +    if( eVerbose>=1 ){
 +      utf8_printf(out, "%s\n", zCreate);
 +    }
 +    rc = s3_exec_noom(DBX(p), zCreate, 0, 0, 0);
 +    if( rc ){
 +      *pzErr = smprintf("%s failed:\n%s\n", zCreate, sqlite3_errmsg(DBX(p)));
 +      goto import_fail;
 +    }
 +    rc = s3_prepare_v2_noom(DBX(p), zSql, -1, &pStmt, 0);
 +  }
 +  if( rc ){
 +    *pzErr = smprintf("%s\n", sqlite3_errmsg(DBX(p)));
 +    goto import_fail;
 +  }
 +  nCol = sqlite3_column_count(pStmt);
 +  sqlite3_finalize(pStmt);
 +  pStmt = 0;
 +  if( nCol==0 ) return DCR_Ok; /* no columns, no error */
 +  sqlite3_free(zSql);
 +  zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 );
 +  shell_check_ooms(zSql);
 +  sqlite3_snprintf(nByte+20, zSql, "INSERT INTO %s VALUES(?", zFullTabName);
 +  j = strlen30(zSql);
 +  for(i=1; i<nCol; i++){
 +    zSql[j++] = ',';
 +    zSql[j++] = '?';
 +  }
 +  zSql[j++] = ')';
 +  zSql[j] = 0;
 +  if( eVerbose>=2 ){
 +    utf8_printf(psi->out, "Insert using: %s\n", zSql);
 +  }
 +  rc = s3_prepare_v2_noom(DBX(p), zSql, -1, &pStmt, 0);
 +  if( rc ){
 +    *pzErr = smprintf("%s\n", sqlite3_errmsg(DBX(p)));
 +    goto import_fail;
 +  }
 +  needCommit = sqlite3_get_autocommit(DBX(p));
 +  if( needCommit ) sqlite3_exec(DBX(p), "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( psi->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(STD_ERR, "%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(STD_ERR, "%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(STD_ERR, "%s:%d: INSERT failed: %s\n", sCtx.zFile,
 +                    startLine, sqlite3_errmsg(DBX(p)));
 +        sCtx.nErr++;
 +      }else{
 +        sCtx.nRow++;
 +      }
 +    }
 +  }while( sCtx.cTerm!=EOF );
  
 -  sqlite3_free(zDir);
 -  sqlite3_free(zWhere);
 -  return rc;
 +  if( needCommit ) sqlite3_exec(DBX(p), "COMMIT", 0, 0, 0);
 +  if( eVerbose>0 ){
 +    utf8_printf(out,
 +      "Added %d rows with %d errors using %d lines of input\n",
 +      sCtx.nRow, sCtx.nErr, sCtx.nLine-1);
 +  }
 +  RESOURCE_FREE(mark);
 +  return DCR_Ok|(sCtx.nErr>0);
  }
  
 -/*
 -** Run the SQL statement in zSql.  Or if doing a --dryrun, merely print it out.
 -*/
 -static int arExecSql(ArCommand *pAr, const char *zSql){
 -  int rc;
 -  if( pAr->bDryRun ){
 -    oputf("%s\n", zSql);
 -    rc = SQLITE_OK;
 -  }else{
 -    char *zErr = 0;
 -    rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
 -    if( zErr ){
 -      sputf(stdout, "ERROR: %s\n", zErr);
 -      sqlite3_free(zErr);
 +/*****************
 + * The .keyword command
 + */
 +CONDITION_COMMAND( keyword !defined(NO_KEYWORD_COMMAND) );
 +COLLECT_HELP_TEXT[
 +  ".keyword ?KW?            List keywords, or say whether KW is one.",
 +];
 +DISPATCHABLE_COMMAND( keyword ? 1 2 ){
 +  FILE *out = ISS(p)->out;
 +  if( nArg<2 ){
 +    int i = 0;
 +    int nk = sqlite3_keyword_count();
 +    int nCol = 0;
 +    int szKW;
 +    while( i<nk ){
 +      const char *zKW = 0;
 +      if( SQLITE_OK==sqlite3_keyword_name(i++, &zKW, &szKW) ){
 +        char kwBuf[50];
 +        if( szKW < sizeof(kwBuf) ){
 +          const char *zSep = " ";
 +          if( (nCol += (1+szKW))>75){
 +            zSep = "\n";
 +            nCol = 0;
 +          }
 +          memcpy(kwBuf, zKW, szKW);
 +          kwBuf[szKW] = 0;
 +          utf8_printf(out, "%s%s", kwBuf, zSep);
 +        }
 +      }
      }
 +    if( nCol>0 ) utf8_printf(out, "\n");
 +  }else{
 +    int szKW = strlen30(azArg[1]);
 +    int isKeyword = sqlite3_keyword_check(azArg[1], szKW);
 +    utf8_printf(out, "%s is%s a keyword\n",
 +                azArg[1], (isKeyword)? "" : " not");
    }
 -  return rc;
 +  return DCR_Ok;
  }
  
 -
 -/*
 -** Implementation of .ar "create", "insert", and "update" commands.
 -**
 -**     create    ->     Create a new SQL archive
 -**     insert    ->     Insert or reinsert all files listed
 -**     update    ->     Insert files that have changed or that were not
 -**                      previously in the archive
 -**
 -** Create the "sqlar" table in the database if it does not already exist.
 -** Then add each file in the azFile[] array to the archive. Directories
 -** are added recursively. If argument bVerbose is non-zero, a message is
 -** printed on stdout for each file archived.
 -**
 -** The create command is the same as update, except that it drops
 -** any existing "sqlar" table before beginning.  The "insert" command
 -** always overwrites every file named on the command-line, where as
 -** "update" only overwrites if the size or mtime or mode has changed.
 -*/
 -static int arCreateOrUpdateCommand(
 -  ArCommand *pAr,                 /* Command arguments and options */
 -  int bUpdate,                    /* true for a --create. */
 -  int bOnlyIfChanged              /* Only update if file has changed */
 -){
 -  const char *zCreate =
 -      "CREATE TABLE IF NOT EXISTS sqlar(\n"
 -      "  name TEXT PRIMARY KEY,  -- name of the file\n"
 -      "  mode INT,               -- access permissions\n"
 -      "  mtime INT,              -- last modification time\n"
 -      "  sz INT,                 -- original file size\n"
 -      "  data BLOB               -- compressed content\n"
 -      ")";
 -  const char *zDrop = "DROP TABLE IF EXISTS sqlar";
 -  const char *zInsertFmt[2] = {
 -     "REPLACE INTO %s(name,mode,mtime,sz,data)\n"
 -     "  SELECT\n"
 -     "    %s,\n"
 -     "    mode,\n"
 -     "    mtime,\n"
 -     "    CASE substr(lsmode(mode),1,1)\n"
 -     "      WHEN '-' THEN length(data)\n"
 -     "      WHEN 'd' THEN 0\n"
 -     "      ELSE -1 END,\n"
 -     "    sqlar_compress(data)\n"
 -     "  FROM fsdir(%Q,%Q) AS disk\n"
 -     "  WHERE lsmode(mode) NOT LIKE '?%%'%s;"
 -     ,
 -     "REPLACE INTO %s(name,mode,mtime,data)\n"
 -     "  SELECT\n"
 -     "    %s,\n"
 -     "    mode,\n"
 -     "    mtime,\n"
 -     "    data\n"
 -     "  FROM fsdir(%Q,%Q) AS disk\n"
 -     "  WHERE lsmode(mode) NOT LIKE '?%%'%s;"
 -  };
 -  int i;                          /* For iterating through azFile[] */
 -  int rc;                         /* Return code */
 -  const char *zTab = 0;           /* SQL table into which to insert */
 -  char *zSql;
 -  char zTemp[50];
 -  char *zExists = 0;
 -
 -  arExecSql(pAr, "PRAGMA page_size=512");
 -  rc = arExecSql(pAr, "SAVEPOINT ar;");
 -  if( rc!=SQLITE_OK ) return rc;
 -  zTemp[0] = 0;
 -  if( pAr->bZip ){
 -    /* Initialize the zipfile virtual table, if necessary */
 -    if( pAr->zFile ){
 -      sqlite3_uint64 r;
 -      sqlite3_randomness(sizeof(r),&r);
 -      sqlite3_snprintf(sizeof(zTemp),zTemp,"zip%016llx",r);
 -      zTab = zTemp;
 -      zSql = sqlite3_mprintf(
 -         "CREATE VIRTUAL TABLE temp.%s USING zipfile(%Q)",
 -         zTab, pAr->zFile
 -      );
 -      rc = arExecSql(pAr, zSql);
 -      sqlite3_free(zSql);
 -    }else{
 -      zTab = "zip";
 +/*****************
 + * The .imposter, .iotrace, .limit, .lint and .log commands
 + */
 +#if !defined(SQLITE_OMIT_LOAD_EXTENSION) && !defined(SQLITE_SHELL_FIDDLE)
 +# define LOAD_ENABLE 1
 +#else
 +# define LOAD_ENABLE 0
 +#endif
 +CONDITION_COMMAND( imposter !defined(SQLITE_OMIT_TEST_CONTROL) );
 +CONDITION_COMMAND( iotrace defined(SQLITE_ENABLE_IOTRACE) );
 +CONDITION_COMMAND( load LOAD_ENABLE );
 +COLLECT_HELP_TEXT[
 +  ",imposter INDEX TABLE    Create imposter table TABLE on index INDEX",
 +  ",iotrace FILE            Enable I/O diagnostic logging to FILE",
 +  ".limit ?LIMIT? ?VAL?     Display or change the value of an SQLITE_LIMIT",
 +  ".lint OPTIONS            Report potential schema issues.",
 +  "     Options:",
 +  "        fkey-indexes     Find missing foreign key indexes",
 +];
 +COLLECT_HELP_TEXT[
 +#if !defined(SQLITE_SHELL_FIDDLE)
 +  ".log FILE|on|off         Turn logging on or off.  FILE can be stderr/stdout",
 +#else
 +  ".log on|off              Turn logging on or off.",
 +#endif
 +];
 +DISPATCHABLE_COMMAND( imposter ? 3 3 ){
 +  int rc = 0;
 +  char *zSql = 0;
 +  char *zCollist = 0;
 +  sqlite3_stmt *pStmt = 0;
 +  sqlite3 *db;
 +  int tnum = 0;
 +  int isWO = 0;  /* True if making an imposter of a WITHOUT ROWID table */
 +  int lenPK = 0; /* Length of the PRIMARY KEY string for isWO tables */
 +  int i;
 +  ResourceMark mark = holder_mark();
 +
 +  if( !ShellHasFlag(p,SHFLG_TestingMode) ){
 +    utf8_printf(stderr, ".%s unavailable without --unsafe-testing\n",
 +                "imposter");
 +    return DCR_Error;
 +  }
 +  if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){
 +    *pzErr = smprintf("Usage: .imposter INDEX IMPOSTER\n"
 +                      "       .imposter off\n");
 +    /* Also allowed, but not documented:
 +    **
 +    **    .imposter TABLE IMPOSTER
 +    **
 +    ** where TABLE is a WITHOUT ROWID table.  In that case, the
 +    ** imposter is another WITHOUT ROWID table with the columns in
 +    ** storage order. */
 +    return DCR_SayUsage;
 +  }
 +  db = open_db(p, 0);
 +  if( nArg==2 ){
 +    sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, "main", 0, 1);
 +    return DCR_Ok;
 +  }
 +  sstr_ptr_holder(&zSql);
 +  zSql = smprintf("SELECT rootpage, 0 FROM sqlite_schema"
 +                  " WHERE name='%q' AND type='index'"
 +                  "UNION ALL "
 +                  "SELECT rootpage, 1 FROM sqlite_schema"
 +                  " WHERE name='%q' AND type='table'"
 +                  "  AND sql LIKE '%%without%%rowid%%'",
 +                  azArg[1], azArg[1]);
 +  rc = s3_prep_noom_free(db, &zSql, &pStmt);
 +  if( rc!=SQLITE_OK ){
 +    release_holder();
 +    return DCR_Error;
 +  }
 +  stmt_ptr_holder(&pStmt);
 +  if( s3_step_noom(pStmt)==SQLITE_ROW ){
 +    tnum = sqlite3_column_int(pStmt, 0);
 +    isWO = sqlite3_column_int(pStmt, 1);
 +  }
 +  zSql = smprintf("PRAGMA index_xinfo='%q'", azArg[1]);
 +  sqlite3_finalize(pStmt);
 +  pStmt = 0;
 +  rc = s3_prep_noom_free(db, &zSql, &pStmt);
 +  i = 0;
 +  sstr_ptr_holder(&zCollist);
 +  while( rc==SQLITE_OK && 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;
 +      }
      }
 -  }else{
 -    /* Initialize the table for an SQLAR */
 -    zTab = "sqlar";
 -    if( bUpdate==0 ){
 -      rc = arExecSql(pAr, zDrop);
 -      if( rc!=SQLITE_OK ) goto end_ar_transaction;
 +    if( isWO && lenPK==0 && sqlite3_column_int(pStmt,5)==0 && zCollist ){
 +      lenPK = (int)strlen(zCollist);
 +    }
 +    if( zCollist==0 ){
 +      zCollist = smprintf("\"%w\"", zCol);
 +    }else{
 +      zCollist = smprintf("%z,\"%w\"", zCollist, zCol);
      }
 -    rc = arExecSql(pAr, zCreate);
    }
 -  if( bOnlyIfChanged ){
 -    zExists = sqlite3_mprintf(
 -      " AND NOT EXISTS("
 -          "SELECT 1 FROM %s AS mem"
 -          " WHERE mem.name=disk.name"
 -          " AND mem.mtime=disk.mtime"
 -          " AND mem.mode=disk.mode)", zTab);
 -  }else{
 -    zExists = sqlite3_mprintf("");
 +  if( i==0 || tnum==0 ){
 +    *pzErr = smprintf("no such index: \"%s\"\n", azArg[1]);
 +    RESOURCE_FREE(mark);
 +    return DCR_Error;
    }
 -  if( zExists==0 ) rc = SQLITE_NOMEM;
 -  for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
 -    char *zSql2 = sqlite3_mprintf(zInsertFmt[pAr->bZip], zTab,
 -        pAr->bVerbose ? "shell_putsnl(name)" : "name",
 -        pAr->azArg[i], pAr->zDir, zExists);
 -    rc = arExecSql(pAr, zSql2);
 -    sqlite3_free(zSql2);
 +  if( lenPK==0 ) lenPK = 100000;
 +  zSql = smprintf("CREATE TABLE \"%w\"(%s,PRIMARY KEY(%.*s))"
 +                  "WITHOUT ROWID", azArg[2], zCollist, lenPK, zCollist);
 +  shell_check_ooms(zSql);
 +  rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, "main", 1, tnum);
 +  if( rc==SQLITE_OK ){
 +    rc = s3_exec_noom(db, zSql, 0, 0, 0);
 +    sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, "main", 0, 0);
 +    if( rc ){
 +      *pzErr = smprintf("Error in [%s]: %s\n", zSql, sqlite3_errmsg(db));
 +    }else{
 +      utf8_printf(STD_OUT, "%s;\n", zSql);
 +      raw_printf(STD_OUT, "WARNING: "
 +                 "writing to an imposter table will corrupt the \"%s\" %s!\n",
 +                 azArg[1], isWO ? "table" : "index"
 +                 );
 +    }
 +  }else{
 +    *pzErr = smprintf("SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc);
    }
 -end_ar_transaction:
 -  if( rc!=SQLITE_OK ){
 -    sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0);
 +  RESOURCE_FREE(mark);
 +  return DCR_Ok|(rc != 0);
 +}
 +DISPATCHABLE_COMMAND( iotrace ? 2 2 ){
 +  SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...);
 +  if( iotrace && iotrace!=STD_OUT ) fclose(iotrace);
 +  iotrace = 0;
 +  if( nArg<2 ){
 +    sqlite3IoTrace = 0;
 +  }else if( cli_strcmp(azArg[1], "-")==0 ){
 +    sqlite3IoTrace = iotracePrintf;
 +    iotrace = STD_OUT;
    }else{
 -    rc = arExecSql(pAr, "RELEASE ar;");
 -    if( pAr->bZip && pAr->zFile ){
 -      zSql = sqlite3_mprintf("DROP TABLE %s", zTemp);
 -      arExecSql(pAr, zSql);
 -      sqlite3_free(zSql);
 +    iotrace = fopen(azArg[1], "w");
 +    if( iotrace==0 ){
 +      *pzErr = smprintf("cannot open \"%s\"\n", azArg[1]);
 +      sqlite3IoTrace = 0;
 +      return DCR_Error;
 +    }else{
 +      sqlite3IoTrace = iotracePrintf;
      }
    }
 -  sqlite3_free(zExists);
 -  return rc;
 +  return DCR_Ok;
  }
  
 -/*
 -** Implementation of ".ar" dot command.
 -*/
 -static int arDotCommand(
 -  ShellState *pState,          /* Current shell tool state */
 -  int fromCmdLine,             /* True if -A command-line option, not .ar cmd */
 -  char **azArg,                /* Array of arguments passed to dot command */
 -  int nArg                     /* Number of entries in azArg[] */
 -){
 -  ArCommand cmd;
 -  int rc;
 -  memset(&cmd, 0, sizeof(cmd));
 -  cmd.fromCmdLine = fromCmdLine;
 -  rc = arParseCommand(azArg, nArg, &cmd);
 -  if( rc==SQLITE_OK ){
 -    int eDbType = SHELL_OPEN_UNSPEC;
 -    cmd.p = pState;
 -    cmd.db = pState->db;
 -    if( cmd.zFile ){
 -      eDbType = deduceDatabaseType(cmd.zFile, 1);
 -    }else{
 -      eDbType = pState->openMode;
 +/*****************
 + * The .limits and .load commands
 + */
 +COLLECT_HELP_TEXT[
 +  ",limits ?LIMIT_NAME?     Display limit selected by its name, or all limits",
 +  ".load FILE ?ENTRY?       Load a SQLite extension library",
 +  "   If ENTRY is provided, the entry point \"sqlite_ENTRY_init\" is called.",
 +  "   Otherwise, the entry point name is derived from the FILE's name.",
 +];
 +
 +DISPATCHABLE_COMMAND( limits 5 1 3 ){
 +  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++){
 +      fprintf(STD_OUT, "%20s %d\n", aLimit[i].zLimitName,
 +             sqlite3_limit(DBX(p), aLimit[i].limitCode, -1));
      }
 -    if( eDbType==SHELL_OPEN_ZIPFILE ){
 -      if( cmd.eCmd==AR_CMD_EXTRACT || cmd.eCmd==AR_CMD_LIST ){
 -        if( cmd.zFile==0 ){
 -          cmd.zSrcTable = sqlite3_mprintf("zip");
 +  }else if( nArg>3 ){
 +    return DCR_TooMany;
 +  }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{
 -          cmd.zSrcTable = sqlite3_mprintf("zipfile(%Q)", cmd.zFile);
 +          *pzErr = smprintf("ambiguous limit: \"%s\"\n", azArg[1]);
 +          return DCR_Error;
          }
        }
 -      cmd.bZip = 1;
 -    }else if( cmd.zFile ){
 -      int flags;
 -      if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS;
 -      if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_INSERT
 -           || cmd.eCmd==AR_CMD_REMOVE || cmd.eCmd==AR_CMD_UPDATE ){
 -        flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
 -      }else{
 -        flags = SQLITE_OPEN_READONLY;
 -      }
 -      cmd.db = 0;
 -      if( cmd.bDryRun ){
 -        oputf("-- open database '%s'%s\n", cmd.zFile,
 -              eDbType==SHELL_OPEN_APPENDVFS ? " using 'apndvfs'" : "");
 -      }
 -      rc = sqlite3_open_v2(cmd.zFile, &cmd.db, flags,
 -             eDbType==SHELL_OPEN_APPENDVFS ? "apndvfs" : 0);
 -      if( rc!=SQLITE_OK ){
 -        eputf("cannot open file: %s (%s)\n", cmd.zFile, sqlite3_errmsg(cmd.db));
 -        goto end_ar_command;
 -      }
 -      sqlite3_fileio_init(cmd.db, 0, 0);
 -      sqlite3_sqlar_init(cmd.db, 0, 0);
 -      sqlite3_create_function(cmd.db, "shell_putsnl", 1, SQLITE_UTF8, cmd.p,
 -                              shellPutsFunc, 0, 0);
 -
      }
 -    if( cmd.zSrcTable==0 && cmd.bZip==0 && cmd.eCmd!=AR_CMD_HELP ){
 -      if( cmd.eCmd!=AR_CMD_CREATE
 -       && sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0)
 -      ){
 -        eputz("database does not contain an 'sqlar' table\n");
 -        rc = SQLITE_ERROR;
 -        goto end_ar_command;
 -      }
 -      cmd.zSrcTable = sqlite3_mprintf("sqlar");
 +    if( iLimit<0 ){
 +      *pzErr = smprintf("unknown limit: \"%s\"\n"
 +                        "enter \".limits\" with no arguments for a list.\n",
 +                        azArg[1]);
 +      return DCR_ArgWrong;
      }
 -
 -    switch( cmd.eCmd ){
 -      case AR_CMD_CREATE:
 -        rc = arCreateOrUpdateCommand(&cmd, 0, 0);
 -        break;
 -
 -      case AR_CMD_EXTRACT:
 -        rc = arExtractCommand(&cmd);
 -        break;
 -
 -      case AR_CMD_LIST:
 -        rc = arListCommand(&cmd);
 -        break;
 -
 -      case AR_CMD_HELP:
 -        arUsage(pState->out);
 -        break;
 -
 -      case AR_CMD_INSERT:
 -        rc = arCreateOrUpdateCommand(&cmd, 1, 0);
 -        break;
 -
 -      case AR_CMD_REMOVE:
 -        rc = arRemoveCommand(&cmd);
 -        break;
 -
 -      default:
 -        assert( cmd.eCmd==AR_CMD_UPDATE );
 -        rc = arCreateOrUpdateCommand(&cmd, 1, 1);
 -        break;
 +    if( nArg==3 ){
 +      sqlite3_limit(DBX(p), aLimit[iLimit].limitCode,
 +                    (int)integerValue(azArg[2]));
      }
 +    fprintf(STD_OUT, "%20s %d\n", aLimit[iLimit].zLimitName,
 +           sqlite3_limit(DBX(p), aLimit[iLimit].limitCode, -1));
    }
 -end_ar_command:
 -  if( cmd.db!=pState->db ){
 -    close_db(cmd.db);
 -  }
 -  sqlite3_free(cmd.zSrcTable);
 -
 -  return rc;
 +  return DCR_Ok;
  }
 -/* End of the ".archive" or ".ar" command logic
 -*******************************************************************************/
 -#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */
  
 -#if SQLITE_SHELL_HAVE_RECOVER
 +DISPATCHABLE_COMMAND( lint 3 1 0 ){
 +  sqlite3 *db;                    /* Database handle to query "main" db of */
 +  FILE *out = ISS(p)->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 */
 +  ResourceMark mark = holder_mark();
  
 -/*
 -** This function is used as a callback by the recover extension. Simply
 -** print the supplied SQL statement to stdout.
 -*/
 -static int recoverSqlCb(void *pCtx, const char *zSql){
 -  ShellState *pState = (ShellState*)pCtx;
 -  sputf(pState->out, "%s;\n", zSql);
 -  return SQLITE_OK;
 -}
 +  i = (nArg>=2 ? strlen30(azArg[1]) : 0);
 +  if( i==0 || 0!=sqlite3_strnicmp(azArg[1], "fkey-indexes", i) ){
 +    *pzErr = smprintf
 +      ("Usage %s sub-command ?switches...?\n"
 +       "Where sub-commands are:\n"
 +       "    fkey-indexes\n", azArg[0]);
 +    return DCR_SayUsage;
 +  }
 +  db = open_db(p, 0);
  
 -/*
 -** This function is called to recover data from the database. A script
 -** to construct a new database containing all recovered data is output
 -** on stream pState->out.
 -*/
 -static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
 -  int rc = SQLITE_OK;
 -  const char *zRecoveryDb = "";   /* Name of "recovery" database.  Debug only */
 -  const char *zLAF = "lost_and_found";
 -  int bFreelist = 1;              /* 0 if --ignore-freelist is specified */
 -  int bRowids = 1;                /* 0 if --no-rowids */
 -  sqlite3_recover *p = 0;
 -  int i = 0;
 +  /*
 +  ** 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 1 FROM child_table WHERE child_key=?"
 +  **
 +  **    This SELECT is similar to the one 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 1 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 ' || 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_schema 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 * USING INTEGER PRIMARY KEY (rowid=?)";
  
 -  for(i=1; i<nArg; i++){
 -    char *z = azArg[i];
 -    int n;
 -    if( z[0]=='-' && z[1]=='-' ) z++;
 -    n = strlen30(z);
 -    if( n<=17 && memcmp("-ignore-freelist", z, n)==0 ){
 -      bFreelist = 0;
 -    }else
 -    if( n<=12 && memcmp("-recovery-db", z, n)==0 && i<(nArg-1) ){
 -      /* This option determines the name of the ATTACH-ed database used
 -      ** internally by the recovery extension.  The default is "" which
 -      ** means to use a temporary database that is automatically deleted
 -      ** when closed.  This option is undocumented and might disappear at
 -      ** any moment. */
 -      i++;
 -      zRecoveryDb = azArg[i];
 -    }else
 -    if( n<=15 && memcmp("-lost-and-found", z, n)==0 && i<(nArg-1) ){
 -      i++;
 -      zLAF = azArg[i];
 -    }else
 -    if( n<=10 && memcmp("-no-rowids", z, n)==0 ){
 -      bRowids = 0;
 +  for(i=2; i<nArg; i++){
 +    int n = strlen30(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{
 -      eputf("unexpected option: %s\n", azArg[i]);
 -      showHelp(pState->out, azArg[0]);
 -      return 1;
 +      raw_printf(STD_ERR, "Usage: %s %s ?-verbose? ?-groupbyparent?\n",
 +                 azArg[0], azArg[1]
 +      );
 +      return DCR_Unknown|i;
      }
    }
  
diff --cc src/sqlite.h.in
index c5a50c01be90d72da43d0e691497ca89382f5842,ce32b85b184a543e0abfe35cc03bd3d538a1d063..ce32b85b184a543e0abfe35cc03bd3d538a1d063
mode 100755,100644..100755
diff --cc src/test1.c
index 84d36264cf12a8f37b819fef3c18929417534fb7,55be0596b08305df8ded26931017a82b622aca48..55be0596b08305df8ded26931017a82b622aca48
mode 100755,100644..100755
diff --cc src/test8.c
index f0f574310108019971430c2e5c51db78479b0ec9,4aeb555c762d06caa2182bb4a6179ea09374b270..4aeb555c762d06caa2182bb4a6179ea09374b270
mode 100755,100644..100755
diff --cc src/treeview.c
index d55adab384d5ac916daa24ae1834f5f92c1fb07c,2576532b654ff5e3027651564aff3ced4c1b9e02..2576532b654ff5e3027651564aff3ced4c1b9e02
mode 100755,100644..100755
diff --cc src/util.c
index 256ec7c5c7458cd7abda1b82b8e76121d2d335a3,e9c7cccb037486f9355e392ad89e7c514891882d..e9c7cccb037486f9355e392ad89e7c514891882d
mode 100755,100644..100755
diff --cc src/vdbe.c
index 8255f6c4a9dcccb4d27f3602299f20189b0f8079,38155a170cdee514e0ac5b930e11565bffaeae52..38155a170cdee514e0ac5b930e11565bffaeae52
mode 100755,100644..100755
diff --cc src/vdbeInt.h
index 4c3394716bfda6136c084253e9628145b68b29be,2a23c3f2855acb271ea462b98ae01613eed1996a..2a23c3f2855acb271ea462b98ae01613eed1996a
mode 100755,100644..100755
diff --cc src/vdbeapi.c
index 920780a896563f1d68fef3c14a20d75532e6ced2,570cb3d8b6c9a6bd25e760468d4221f6f33c3f2f..570cb3d8b6c9a6bd25e760468d4221f6f33c3f2f
mode 100755,100644..100755
diff --cc src/vdbemem.c
index 60bd6d6db29d0b11cf5ce05d2284aa6be4929254,d52716468544007127939bbc50f7e2732572ac48..d52716468544007127939bbc50f7e2732572ac48
mode 100755,100644..100755
diff --cc src/vdbesort.c
index 2b7da94f7f8da2fba6f9892effadb58e97ab2704,00836903088c5d48e05b78ba1fca778de4ecf794..00836903088c5d48e05b78ba1fca778de4ecf794
mode 100755,100644..100755
diff --cc src/vtab.c
index 741518991a13ccd569933805e56c11c195862186,a9cfcb9d730e636c236b829c8ec99d05f437cfa3..a9cfcb9d730e636c236b829c8ec99d05f437cfa3
mode 100755,100644..100755
diff --cc src/wal.c
index f4d0328b2b4f86ec122e11bc5ac56d82e9b1b683,d83f361d64c25adf75ac2fda8338efb2af17eb11..d83f361d64c25adf75ac2fda8338efb2af17eb11
mode 100755,100644..100755
+++ b/src/wal.c
diff --cc src/whereInt.h
index 759e774e3a78cd5c66e812593161e3d97d1f1edd,343aca9f36e8cf4e8fa483bcf6f16ec3e2705c4d..343aca9f36e8cf4e8fa483bcf6f16ec3e2705c4d
mode 100755,100644..100755
diff --cc src/wherecode.c
index 5d611f1f160d04e9e2679972c73f48b4b34f6dc9,47ce36ce38122490cb96771928f0d042c1f80acc..47ce36ce38122490cb96771928f0d042c1f80acc
mode 100755,100644..100755
diff --cc src/window.c
index d46eabc3b4471fb0b46547975d101b9679ce16ce,62df349fb3f739364e81c53273ba1ee5828a4132..62df349fb3f739364e81c53273ba1ee5828a4132
mode 100755,100644..100755
index 76ce5af0eccd64d70fbf528dd8a0c18e49c80008,23200a5f037ab16f4a3953e856a08873ae0e306b..23200a5f037ab16f4a3953e856a08873ae0e306b
mode 100755,100644..100755
diff --cc test/joinH.test
index edba26de2d8e24fe986e6d3cde37841e4ae8a97a,37022668045bf19f99bc331379b610600defe152..37022668045bf19f99bc331379b610600defe152
mode 100755,100644..100755
Simple merge
Simple merge
index 37a5183f9087fbc21712f94afb1433bad8236d11,d8348a8980e3b1dfbf9a1457525c0f147b01a287..d8348a8980e3b1dfbf9a1457525c0f147b01a287
mode 100755,100644..100755
index 2b8f08deb506c22ce8962fd036d4683b622453a0,53fa59ac7aa614fde09180de31a24b6a8da19972..53fa59ac7aa614fde09180de31a24b6a8da19972
mode 100755,100644..100755
diff --cc tool/sqldiff.c
index 5477ff97f081709a686bda3a8b59a04daeef50ca,a612566112133ad91caaec207512038a1d0c4285..a612566112133ad91caaec207512038a1d0c4285
mode 100755,100644..100755
index b73a89272a07564d546a52cde73b2e786faa4f33,762904656417f16f303191c9cf38ee91425820d5..762904656417f16f303191c9cf38ee91425820d5
mode 100755,100644..100755