Index: ext/sqlite3/shell.c
===================================================================
diff -u -N -r56c246e36e7d3db715623be3215218e6d210c4e2 -ra03d99c9d9946fdb0c6d8e42efc79ea28a0fbb9d
--- ext/sqlite3/shell.c	(.../shell.c)	(revision 56c246e36e7d3db715623be3215218e6d210c4e2)
+++ ext/sqlite3/shell.c	(.../shell.c)	(revision a03d99c9d9946fdb0c6d8e42efc79ea28a0fbb9d)
@@ -36,6 +36,18 @@
 #endif
 
 /*
+** Optionally #include a user-defined header, whereby compilation options
+** may be set prior to where they take effect, but after platform setup. 
+** If SQLITE_CUSTOM_INCLUDE=? is defined, its value names the #include
+** file. Note that this macro has a like effect on sqlite3.c compilation.
+*/
+# define SHELL_STRINGIFY_(f) #f
+# define SHELL_STRINGIFY(f) SHELL_STRINGIFY_(f)
+#ifdef SQLITE_CUSTOM_INCLUDE
+# include SHELL_STRINGIFY(SQLITE_CUSTOM_INCLUDE)
+#endif
+
+/*
 ** Determine if we are dealing with WinRT, which provides only a subset of
 ** the full Win32 API.
 */
@@ -235,6 +247,16 @@
 # define setTextMode(X,Y)
 #endif
 
+/*
+** When compiling with emcc (a.k.a. emscripten), we're building a
+** WebAssembly (WASM) bundle and need to disable and rewire a few
+** things.
+*/
+#ifdef __EMSCRIPTEN__
+#define SQLITE_SHELL_WASM_MODE
+#else
+#undef SQLITE_SHELL_WASM_MODE
+#endif
 
 /* True if the timer is enabled */
 static int enableTimer = 0;
@@ -433,16 +455,7 @@
 */
 static volatile int seenInterrupt = 0;
 
-#ifdef SQLITE_DEBUG
 /*
-** Out-of-memory simulator variables
-*/
-static unsigned int oomCounter = 0;    /* Simulate OOM when equals 1 */
-static unsigned int oomRepeat = 0;     /* Number of OOMs in a row */
-static void*(*defaultMalloc)(int) = 0; /* The low-level malloc routine */
-#endif /* SQLITE_DEBUG */
-
-/*
 ** This is the name of our program. It is set in main(), used
 ** in a number of other places, mostly for error messages.
 */
@@ -493,49 +506,13 @@
   exit(1);
 }
 
-#ifdef SQLITE_DEBUG
-/* This routine is called when a simulated OOM occurs.  It is broken
-** out as a separate routine to make it easy to set a breakpoint on
-** the OOM
+/* Check a pointer to see if it is NULL.  If it is NULL, exit with an
+** out-of-memory error.
 */
-void shellOomFault(void){
-  if( oomRepeat>0 ){
-    oomRepeat--;
-  }else{
-    oomCounter--;
-  }
+static void shell_check_oom(void *p){
+  if( p==0 ) shell_out_of_memory();
 }
-#endif /* SQLITE_DEBUG */
 
-#ifdef SQLITE_DEBUG
-/* This routine is a replacement malloc() that is used to simulate
-** Out-Of-Memory (OOM) errors for testing purposes.
-*/
-static void *oomMalloc(int nByte){
-  if( oomCounter ){
-    if( oomCounter==1 ){
-      shellOomFault();
-      return 0;
-    }else{
-      oomCounter--;
-    }
-  }
-  return defaultMalloc(nByte);
-}
-#endif /* SQLITE_DEBUG */
-
-#ifdef SQLITE_DEBUG
-/* Register the OOM simulator.  This must occur before any memory
-** allocations */
-static void registerOomSimulator(void){
-  sqlite3_mem_methods mem;
-  sqlite3_config(SQLITE_CONFIG_GETMALLOC, &mem);
-  defaultMalloc = mem.xMalloc;
-  mem.xMalloc = oomMalloc;
-  sqlite3_config(SQLITE_CONFIG_MALLOC, &mem);
-}
-#endif
-
 /*
 ** Write I/O traces to the following stream.
 */
@@ -641,19 +618,38 @@
 }
 
 /*
-** Return true if zFile does not exist or if it is not an ordinary file.
+** Return open FILE * if zFile exists, can be opened for read
+** and is an ordinary file or a character stream source.
+** Otherwise return 0.
 */
+static FILE * openChrSource(const char *zFile){
 #ifdef _WIN32
-# define notNormalFile(X) 0
+  struct _stat x = {0};
+# define STAT_CHR_SRC(mode) ((mode & (_S_IFCHR|_S_IFIFO|_S_IFREG))!=0)
+  /* On Windows, open first, then check the stream nature. This order
+  ** is necessary because _stat() and sibs, when checking a named pipe,
+  ** effectively break the pipe as its supplier sees it. */
+  FILE *rv = fopen(zFile, "rb");
+  if( rv==0 ) return 0;
+  if( _fstat(_fileno(rv), &x) != 0
+      || !STAT_CHR_SRC(x.st_mode)){
+    fclose(rv);
+    rv = 0;
+  }
+  return rv;
 #else
-static int notNormalFile(const char *zFile){
-  struct stat x;
-  int rc;
-  memset(&x, 0, sizeof(x));
-  rc = stat(zFile, &x);
-  return rc || !S_ISREG(x.st_mode);
-}
+  struct stat x = {0};
+  int rc = stat(zFile, &x);
+# define STAT_CHR_SRC(mode) (S_ISREG(mode)||S_ISFIFO(mode)||S_ISCHR(mode))
+  if( rc!=0 ) return 0;
+  if( STAT_CHR_SRC(x.st_mode) ){
+    return fopen(zFile, "rb");
+  }else{
+    return 0;
+  }
 #endif
+#undef STAT_CHR_SRC
+}
 
 /*
 ** This routine reads a line of text from FILE in, stores
@@ -672,7 +668,7 @@
     if( n+100>nLine ){
       nLine = nLine*2 + 100;
       zLine = realloc(zLine, nLine);
-      if( zLine==0 ) shell_out_of_memory();
+      shell_check_oom(zLine);
     }
     if( fgets(&zLine[n], nLine - n, in)==0 ){
       if( n==0 ){
@@ -699,7 +695,7 @@
       int nTrans = strlen30(zTrans)+1;
       if( nTrans>nLine ){
         zLine = realloc(zLine, nTrans);
-        if( zLine==0 ) shell_out_of_memory();
+        shell_check_oom(zLine);
       }
       memcpy(zLine, zTrans, nTrans);
       sqlite3_free(zTrans);
@@ -723,6 +719,7 @@
 ** be freed by the caller or else passed back into this routine via the
 ** zPrior argument for reuse.
 */
+#ifndef SQLITE_SHELL_WASM_MODE
 static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
   char *zPrompt;
   char *zResult;
@@ -742,8 +739,8 @@
   }
   return zResult;
 }
+#endif /* !SQLITE_SHELL_WASM_MODE */
 
-
 /*
 ** Return the value of a hexadecimal digit.  Return -1 if the input
 ** is not a hex digit.
@@ -830,7 +827,7 @@
 ** If the third argument, quote, is not '\0', then it is used as a
 ** quote character for zAppend.
 */
-static void appendText(ShellText *p, char const *zAppend, char quote){
+static void appendText(ShellText *p, const char *zAppend, char quote){
   int len;
   int i;
   int nAppend = strlen30(zAppend);
@@ -843,10 +840,10 @@
     }
   }
 
-  if( p->n+len>=p->nAlloc ){
+  if( p->z==0 || p->n+len>=p->nAlloc ){
     p->nAlloc = p->nAlloc*2 + len + 20;
     p->z = realloc(p->z, p->nAlloc);
-    if( p->z==0 ) shell_out_of_memory();
+    shell_check_oom(p->z);
   }
 
   if( quote ){
@@ -901,6 +898,7 @@
 
   zSql = sqlite3_mprintf("PRAGMA \"%w\".table_info=%Q;",
                          zSchema ? zSchema : "main", zName);
+  shell_check_oom(zSql);
   sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
   sqlite3_free(zSql);
   initText(&s);
@@ -917,6 +915,7 @@
     nRow++;
     appendText(&s, zDiv, 0);
     zDiv = ",";
+    if( zCol==0 ) zCol = "";
     cQuote = quoteChar(zCol);
     appendText(&s, zCol, cQuote);
   }
@@ -940,9 +939,11 @@
   int nVal,
   sqlite3_value **apVal
 ){
-  const char *zName = (const char*)sqlite3_value_text(apVal[0]);
-  char *zFake = shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName);
+  const char *zName;
+  char *zFake;
   UNUSED_PARAMETER(nVal);
+  zName = (const char*)sqlite3_value_text(apVal[0]);
+  zFake = zName ? shellFakeSchema(sqlite3_context_db_handle(pCtx), 0, zName) : 0;
   if( zFake ){
     sqlite3_result_text(pCtx, sqlite3_mprintf("/* %s */", zFake),
                         -1, sqlite3_free);
@@ -989,7 +990,7 @@
   sqlite3 *db = sqlite3_context_db_handle(pCtx);
   UNUSED_PARAMETER(nVal);
   if( zIn!=0 && strncmp(zIn, "CREATE ", 7)==0 ){
-    for(i=0; i<(int)(sizeof(aPrefix)/sizeof(aPrefix[0])); i++){
+    for(i=0; i<ArraySize(aPrefix); i++){
       int n = strlen30(aPrefix[i]);
       if( strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){
         char *z = 0;
@@ -1391,6 +1392,117 @@
 /************************* End test_windirent.c ********************/
 #define dirent DIRENT
 #endif
+/************************* Begin ../ext/misc/memtrace.c ******************/
+/*
+** 2019-01-21
+**
+** The author disclaims copyright to this source code.  In place of
+** a legal notice, here is a blessing:
+**
+**    May you do good and not evil.
+**    May you find forgiveness for yourself and forgive others.
+**    May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file implements an extension that uses the SQLITE_CONFIG_MALLOC
+** mechanism to add a tracing layer on top of SQLite.  If this extension
+** is registered prior to sqlite3_initialize(), it will cause all memory
+** allocation activities to be logged on standard output, or to some other
+** FILE specified by the initializer.
+**
+** This file needs to be compiled into the application that uses it.
+**
+** This extension is used to implement the --memtrace option of the
+** command-line shell.
+*/
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+
+/* The original memory allocation routines */
+static sqlite3_mem_methods memtraceBase;
+static FILE *memtraceOut;
+
+/* Methods that trace memory allocations */
+static void *memtraceMalloc(int n){
+  if( memtraceOut ){
+    fprintf(memtraceOut, "MEMTRACE: allocate %d bytes\n", 
+            memtraceBase.xRoundup(n));
+  }
+  return memtraceBase.xMalloc(n);
+}
+static void memtraceFree(void *p){
+  if( p==0 ) return;
+  if( memtraceOut ){
+    fprintf(memtraceOut, "MEMTRACE: free %d bytes\n", memtraceBase.xSize(p));
+  }
+  memtraceBase.xFree(p);
+}
+static void *memtraceRealloc(void *p, int n){
+  if( p==0 ) return memtraceMalloc(n);
+  if( n==0 ){
+    memtraceFree(p);
+    return 0;
+  }
+  if( memtraceOut ){
+    fprintf(memtraceOut, "MEMTRACE: resize %d -> %d bytes\n",
+            memtraceBase.xSize(p), memtraceBase.xRoundup(n));
+  }
+  return memtraceBase.xRealloc(p, n);
+}
+static int memtraceSize(void *p){
+  return memtraceBase.xSize(p);
+}
+static int memtraceRoundup(int n){
+  return memtraceBase.xRoundup(n);
+}
+static int memtraceInit(void *p){
+  return memtraceBase.xInit(p);
+}
+static void memtraceShutdown(void *p){
+  memtraceBase.xShutdown(p);
+}
+
+/* The substitute memory allocator */
+static sqlite3_mem_methods ersaztMethods = {
+  memtraceMalloc,
+  memtraceFree,
+  memtraceRealloc,
+  memtraceSize,
+  memtraceRoundup,
+  memtraceInit,
+  memtraceShutdown,
+  0
+};
+
+/* Begin tracing memory allocations to out. */
+int sqlite3MemTraceActivate(FILE *out){
+  int rc = SQLITE_OK;
+  if( memtraceBase.xMalloc==0 ){
+    rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memtraceBase);
+    if( rc==SQLITE_OK ){
+      rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &ersaztMethods);
+    }
+  }
+  memtraceOut = out;
+  return rc;
+}
+
+/* Deactivate memory tracing */
+int sqlite3MemTraceDeactivate(void){
+  int rc = SQLITE_OK;
+  if( memtraceBase.xMalloc!=0 ){
+    rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memtraceBase);
+    if( rc==SQLITE_OK ){
+      memset(&memtraceBase, 0, sizeof(memtraceBase));
+    }
+  }
+  memtraceOut = 0;
+  return rc;
+}
+
+/************************* End ../ext/misc/memtrace.c ********************/
 /************************* Begin ../ext/misc/shathree.c ******************/
 /*
 ** 2017-03-08
@@ -1413,7 +1525,7 @@
 ** The sha3(X) function computes the SHA3 hash of the input X, or NULL if
 ** X is NULL.
 **
-** The sha3_query(Y) function evalutes all queries in the SQL statements of Y
+** The sha3_query(Y) function evaluates all queries in the SQL statements of Y
 ** and returns a hash of their results.
 **
 ** The SIZE argument is optional.  If omitted, the SHA3-256 hash algorithm
@@ -1830,6 +1942,7 @@
   unsigned int nData
 ){
   unsigned int i = 0;
+  if( aData==0 ) return;
 #if SHA3_BYTEORDER==1234
   if( (p->nLoaded % 8)==0 && ((aData - (const unsigned char*)0)&7)==0 ){
     for(; i+7<nData; i+=8){
@@ -2117,2299 +2230,6 @@
 }
 
 /************************* End ../ext/misc/shathree.c ********************/
-/************************* Begin ../ext/misc/fileio.c ******************/
-/*
-** 2014-06-13
-**
-** The author disclaims copyright to this source code.  In place of
-** a legal notice, here is a blessing:
-**
-**    May you do good and not evil.
-**    May you find forgiveness for yourself and forgive others.
-**    May you share freely, never taking more than you give.
-**
-******************************************************************************
-**
-** This SQLite extension implements SQL functions readfile() and
-** writefile(), and eponymous virtual type "fsdir".
-**
-** WRITEFILE(FILE, DATA [, MODE [, MTIME]]):
-**
-**   If neither of the optional arguments is present, then this UDF
-**   function writes blob DATA to file FILE. If successful, the number
-**   of bytes written is returned. If an error occurs, NULL is returned.
-**
-**   If the first option argument - MODE - is present, then it must
-**   be passed an integer value that corresponds to a POSIX mode
-**   value (file type + permissions, as returned in the stat.st_mode
-**   field by the stat() system call). Three types of files may
-**   be written/created:
-**
-**     regular files:  (mode & 0170000)==0100000
-**     symbolic links: (mode & 0170000)==0120000
-**     directories:    (mode & 0170000)==0040000
-**
-**   For a directory, the DATA is ignored. For a symbolic link, it is
-**   interpreted as text and used as the target of the link. For a
-**   regular file, it is interpreted as a blob and written into the
-**   named file. Regardless of the type of file, its permissions are
-**   set to (mode & 0777) before returning.
-**
-**   If the optional MTIME argument is present, then it is interpreted
-**   as an integer - the number of seconds since the unix epoch. The
-**   modification-time of the target file is set to this value before
-**   returning.
-**
-**   If three or more arguments are passed to this function and an
-**   error is encountered, an exception is raised.
-**
-** READFILE(FILE):
-**
-**   Read and return the contents of file FILE (type blob) from disk.
-**
-** FSDIR:
-**
-**   Used as follows:
-**
-**     SELECT * FROM fsdir($path [, $dir]);
-**
-**   Parameter $path is an absolute or relative pathname. If the file that it
-**   refers to does not exist, it is an error. If the path refers to a regular
-**   file or symbolic link, it returns a single row. Or, if the path refers
-**   to a directory, it returns one row for the directory, and one row for each
-**   file within the hierarchy rooted at $path.
-**
-**   Each row has the following columns:
-**
-**     name:  Path to file or directory (text value).
-**     mode:  Value of stat.st_mode for directory entry (an integer).
-**     mtime: Value of stat.st_mtime for directory entry (an integer).
-**     data:  For a regular file, a blob containing the file data. For a
-**            symlink, a text value containing the text of the link. For a
-**            directory, NULL.
-**
-**   If a non-NULL value is specified for the optional $dir parameter and
-**   $path is a relative path, then $path is interpreted relative to $dir. 
-**   And the paths returned in the "name" column of the table are also 
-**   relative to directory $dir.
-*/
-/* #include "sqlite3ext.h" */
-SQLITE_EXTENSION_INIT1
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#if !defined(_WIN32) && !defined(WIN32)
-#  include <unistd.h>
-#  include <dirent.h>
-#  include <utime.h>
-#  include <sys/time.h>
-#else
-#  include "windows.h"
-#  include <io.h>
-#  include <direct.h>
-/* #  include "test_windirent.h" */
-#  define dirent DIRENT
-#  ifndef chmod
-#    define chmod _chmod
-#  endif
-#  ifndef stat
-#    define stat _stat
-#  endif
-#  define mkdir(path,mode) _mkdir(path)
-#  define lstat(path,buf) stat(path,buf)
-#endif
-#include <time.h>
-#include <errno.h>
-
-
-/*
-** Structure of the fsdir() table-valued function
-*/
-                 /*    0    1    2     3    4           5             */
-#define FSDIR_SCHEMA "(name,mode,mtime,data,path HIDDEN,dir HIDDEN)"
-#define FSDIR_COLUMN_NAME     0     /* Name of the file */
-#define FSDIR_COLUMN_MODE     1     /* Access mode */
-#define FSDIR_COLUMN_MTIME    2     /* Last modification time */
-#define FSDIR_COLUMN_DATA     3     /* File content */
-#define FSDIR_COLUMN_PATH     4     /* Path to top of search */
-#define FSDIR_COLUMN_DIR      5     /* Path is relative to this directory */
-
-
-/*
-** Set the result stored by context ctx to a blob containing the 
-** contents of file zName.  Or, leave the result unchanged (NULL)
-** if the file does not exist or is unreadable.
-**
-** If the file exceeds the SQLite blob size limit, through an
-** SQLITE_TOOBIG error.
-**
-** Throw an SQLITE_IOERR if there are difficulties pulling the file
-** off of disk.
-*/
-static void readFileContents(sqlite3_context *ctx, const char *zName){
-  FILE *in;
-  sqlite3_int64 nIn;
-  void *pBuf;
-  sqlite3 *db;
-  int mxBlob;
-
-  in = fopen(zName, "rb");
-  if( in==0 ){
-    /* File does not exist or is unreadable. Leave the result set to NULL. */
-    return;
-  }
-  fseek(in, 0, SEEK_END);
-  nIn = ftell(in);
-  rewind(in);
-  db = sqlite3_context_db_handle(ctx);
-  mxBlob = sqlite3_limit(db, SQLITE_LIMIT_LENGTH, -1);
-  if( nIn>mxBlob ){
-    sqlite3_result_error_code(ctx, SQLITE_TOOBIG);
-    fclose(in);
-    return;
-  }
-  pBuf = sqlite3_malloc64( nIn ? nIn : 1 );
-  if( pBuf==0 ){
-    sqlite3_result_error_nomem(ctx);
-    fclose(in);
-    return;
-  }
-  if( nIn==(sqlite3_int64)fread(pBuf, 1, (size_t)nIn, in) ){
-    sqlite3_result_blob64(ctx, pBuf, nIn, sqlite3_free);
-  }else{
-    sqlite3_result_error_code(ctx, SQLITE_IOERR);
-    sqlite3_free(pBuf);
-  }
-  fclose(in);
-}
-
-/*
-** Implementation of the "readfile(X)" SQL function.  The entire content
-** of the file named X is read and returned as a BLOB.  NULL is returned
-** if the file does not exist or is unreadable.
-*/
-static void readfileFunc(
-  sqlite3_context *context,
-  int argc,
-  sqlite3_value **argv
-){
-  const char *zName;
-  (void)(argc);  /* Unused parameter */
-  zName = (const char*)sqlite3_value_text(argv[0]);
-  if( zName==0 ) return;
-  readFileContents(context, zName);
-}
-
-/*
-** Set the error message contained in context ctx to the results of
-** vprintf(zFmt, ...).
-*/
-static void ctxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){
-  char *zMsg = 0;
-  va_list ap;
-  va_start(ap, zFmt);
-  zMsg = sqlite3_vmprintf(zFmt, ap);
-  sqlite3_result_error(ctx, zMsg, -1);
-  sqlite3_free(zMsg);
-  va_end(ap);
-}
-
-#if defined(_WIN32)
-/*
-** This function is designed to convert a Win32 FILETIME structure into the
-** number of seconds since the Unix Epoch (1970-01-01 00:00:00 UTC).
-*/
-static sqlite3_uint64 fileTimeToUnixTime(
-  LPFILETIME pFileTime
-){
-  SYSTEMTIME epochSystemTime;
-  ULARGE_INTEGER epochIntervals;
-  FILETIME epochFileTime;
-  ULARGE_INTEGER fileIntervals;
-
-  memset(&epochSystemTime, 0, sizeof(SYSTEMTIME));
-  epochSystemTime.wYear = 1970;
-  epochSystemTime.wMonth = 1;
-  epochSystemTime.wDay = 1;
-  SystemTimeToFileTime(&epochSystemTime, &epochFileTime);
-  epochIntervals.LowPart = epochFileTime.dwLowDateTime;
-  epochIntervals.HighPart = epochFileTime.dwHighDateTime;
-
-  fileIntervals.LowPart = pFileTime->dwLowDateTime;
-  fileIntervals.HighPart = pFileTime->dwHighDateTime;
-
-  return (fileIntervals.QuadPart - epochIntervals.QuadPart) / 10000000;
-}
-
-/*
-** This function attempts to normalize the time values found in the stat()
-** buffer to UTC.  This is necessary on Win32, where the runtime library
-** appears to return these values as local times.
-*/
-static void statTimesToUtc(
-  const char *zPath,
-  struct stat *pStatBuf
-){
-  HANDLE hFindFile;
-  WIN32_FIND_DATAW fd;
-  LPWSTR zUnicodeName;
-  extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
-  zUnicodeName = sqlite3_win32_utf8_to_unicode(zPath);
-  if( zUnicodeName ){
-    memset(&fd, 0, sizeof(WIN32_FIND_DATAW));
-    hFindFile = FindFirstFileW(zUnicodeName, &fd);
-    if( hFindFile!=NULL ){
-      pStatBuf->st_ctime = (time_t)fileTimeToUnixTime(&fd.ftCreationTime);
-      pStatBuf->st_atime = (time_t)fileTimeToUnixTime(&fd.ftLastAccessTime);
-      pStatBuf->st_mtime = (time_t)fileTimeToUnixTime(&fd.ftLastWriteTime);
-      FindClose(hFindFile);
-    }
-    sqlite3_free(zUnicodeName);
-  }
-}
-#endif
-
-/*
-** This function is used in place of stat().  On Windows, special handling
-** is required in order for the included time to be returned as UTC.  On all
-** other systems, this function simply calls stat().
-*/
-static int fileStat(
-  const char *zPath,
-  struct stat *pStatBuf
-){
-#if defined(_WIN32)
-  int rc = stat(zPath, pStatBuf);
-  if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
-  return rc;
-#else
-  return stat(zPath, pStatBuf);
-#endif
-}
-
-/*
-** This function is used in place of lstat().  On Windows, special handling
-** is required in order for the included time to be returned as UTC.  On all
-** other systems, this function simply calls lstat().
-*/
-static int fileLinkStat(
-  const char *zPath,
-  struct stat *pStatBuf
-){
-#if defined(_WIN32)
-  int rc = lstat(zPath, pStatBuf);
-  if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
-  return rc;
-#else
-  return lstat(zPath, pStatBuf);
-#endif
-}
-
-/*
-** Argument zFile is the name of a file that will be created and/or written
-** by SQL function writefile(). This function ensures that the directory
-** zFile will be written to exists, creating it if required. The permissions
-** for any path components created by this function are set in accordance
-** with the current umask.
-**
-** If an OOM condition is encountered, SQLITE_NOMEM is returned. Otherwise,
-** SQLITE_OK is returned if the directory is successfully created, or
-** SQLITE_ERROR otherwise.
-*/
-static int makeDirectory(
-  const char *zFile
-){
-  char *zCopy = sqlite3_mprintf("%s", zFile);
-  int rc = SQLITE_OK;
-
-  if( zCopy==0 ){
-    rc = SQLITE_NOMEM;
-  }else{
-    int nCopy = (int)strlen(zCopy);
-    int i = 1;
-
-    while( rc==SQLITE_OK ){
-      struct stat sStat;
-      int rc2;
-
-      for(; zCopy[i]!='/' && i<nCopy; i++);
-      if( i==nCopy ) break;
-      zCopy[i] = '\0';
-
-      rc2 = fileStat(zCopy, &sStat);
-      if( rc2!=0 ){
-        if( mkdir(zCopy, 0777) ) rc = SQLITE_ERROR;
-      }else{
-        if( !S_ISDIR(sStat.st_mode) ) rc = SQLITE_ERROR;
-      }
-      zCopy[i] = '/';
-      i++;
-    }
-
-    sqlite3_free(zCopy);
-  }
-
-  return rc;
-}
-
-/*
-** This function does the work for the writefile() UDF. Refer to 
-** header comments at the top of this file for details.
-*/
-static int writeFile(
-  sqlite3_context *pCtx,          /* Context to return bytes written in */
-  const char *zFile,              /* File to write */
-  sqlite3_value *pData,           /* Data to write */
-  mode_t mode,                    /* MODE parameter passed to writefile() */
-  sqlite3_int64 mtime             /* MTIME parameter (or -1 to not set time) */
-){
-#if !defined(_WIN32) && !defined(WIN32)
-  if( S_ISLNK(mode) ){
-    const char *zTo = (const char*)sqlite3_value_text(pData);
-    if( symlink(zTo, zFile)<0 ) return 1;
-  }else
-#endif
-  {
-    if( S_ISDIR(mode) ){
-      if( mkdir(zFile, mode) ){
-        /* The mkdir() call to create the directory failed. This might not
-        ** be an error though - if there is already a directory at the same
-        ** path and either the permissions already match or can be changed
-        ** to do so using chmod(), it is not an error.  */
-        struct stat sStat;
-        if( errno!=EEXIST
-         || 0!=fileStat(zFile, &sStat)
-         || !S_ISDIR(sStat.st_mode)
-         || ((sStat.st_mode&0777)!=(mode&0777) && 0!=chmod(zFile, mode&0777))
-        ){
-          return 1;
-        }
-      }
-    }else{
-      sqlite3_int64 nWrite = 0;
-      const char *z;
-      int rc = 0;
-      FILE *out = fopen(zFile, "wb");
-      if( out==0 ) return 1;
-      z = (const char*)sqlite3_value_blob(pData);
-      if( z ){
-        sqlite3_int64 n = fwrite(z, 1, sqlite3_value_bytes(pData), out);
-        nWrite = sqlite3_value_bytes(pData);
-        if( nWrite!=n ){
-          rc = 1;
-        }
-      }
-      fclose(out);
-      if( rc==0 && mode && chmod(zFile, mode & 0777) ){
-        rc = 1;
-      }
-      if( rc ) return 2;
-      sqlite3_result_int64(pCtx, nWrite);
-    }
-  }
-
-  if( mtime>=0 ){
-#if defined(_WIN32)
-#if !SQLITE_OS_WINRT
-    /* Windows */
-    FILETIME lastAccess;
-    FILETIME lastWrite;
-    SYSTEMTIME currentTime;
-    LONGLONG intervals;
-    HANDLE hFile;
-    LPWSTR zUnicodeName;
-    extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
-
-    GetSystemTime(&currentTime);
-    SystemTimeToFileTime(&currentTime, &lastAccess);
-    intervals = Int32x32To64(mtime, 10000000) + 116444736000000000;
-    lastWrite.dwLowDateTime = (DWORD)intervals;
-    lastWrite.dwHighDateTime = intervals >> 32;
-    zUnicodeName = sqlite3_win32_utf8_to_unicode(zFile);
-    if( zUnicodeName==0 ){
-      return 1;
-    }
-    hFile = CreateFileW(
-      zUnicodeName, FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
-      FILE_FLAG_BACKUP_SEMANTICS, NULL
-    );
-    sqlite3_free(zUnicodeName);
-    if( hFile!=INVALID_HANDLE_VALUE ){
-      BOOL bResult = SetFileTime(hFile, NULL, &lastAccess, &lastWrite);
-      CloseHandle(hFile);
-      return !bResult;
-    }else{
-      return 1;
-    }
-#endif
-#elif defined(AT_FDCWD) && 0 /* utimensat() is not universally available */
-    /* Recent unix */
-    struct timespec times[2];
-    times[0].tv_nsec = times[1].tv_nsec = 0;
-    times[0].tv_sec = time(0);
-    times[1].tv_sec = mtime;
-    if( utimensat(AT_FDCWD, zFile, times, AT_SYMLINK_NOFOLLOW) ){
-      return 1;
-    }
-#else
-    /* Legacy unix */
-    struct timeval times[2];
-    times[0].tv_usec = times[1].tv_usec = 0;
-    times[0].tv_sec = time(0);
-    times[1].tv_sec = mtime;
-    if( utimes(zFile, times) ){
-      return 1;
-    }
-#endif
-  }
-
-  return 0;
-}
-
-/*
-** Implementation of the "writefile(W,X[,Y[,Z]]])" SQL function.  
-** Refer to header comments at the top of this file for details.
-*/
-static void writefileFunc(
-  sqlite3_context *context,
-  int argc,
-  sqlite3_value **argv
-){
-  const char *zFile;
-  mode_t mode = 0;
-  int res;
-  sqlite3_int64 mtime = -1;
-
-  if( argc<2 || argc>4 ){
-    sqlite3_result_error(context, 
-        "wrong number of arguments to function writefile()", -1
-    );
-    return;
-  }
-
-  zFile = (const char*)sqlite3_value_text(argv[0]);
-  if( zFile==0 ) return;
-  if( argc>=3 ){
-    mode = (mode_t)sqlite3_value_int(argv[2]);
-  }
-  if( argc==4 ){
-    mtime = sqlite3_value_int64(argv[3]);
-  }
-
-  res = writeFile(context, zFile, argv[1], mode, mtime);
-  if( res==1 && errno==ENOENT ){
-    if( makeDirectory(zFile)==SQLITE_OK ){
-      res = writeFile(context, zFile, argv[1], mode, mtime);
-    }
-  }
-
-  if( argc>2 && res!=0 ){
-    if( S_ISLNK(mode) ){
-      ctxErrorMsg(context, "failed to create symlink: %s", zFile);
-    }else if( S_ISDIR(mode) ){
-      ctxErrorMsg(context, "failed to create directory: %s", zFile);
-    }else{
-      ctxErrorMsg(context, "failed to write file: %s", zFile);
-    }
-  }
-}
-
-/*
-** SQL function:   lsmode(MODE)
-**
-** Given a numberic st_mode from stat(), convert it into a human-readable
-** text string in the style of "ls -l".
-*/
-static void lsModeFunc(
-  sqlite3_context *context,
-  int argc,
-  sqlite3_value **argv
-){
-  int i;
-  int iMode = sqlite3_value_int(argv[0]);
-  char z[16];
-  (void)argc;
-  if( S_ISLNK(iMode) ){
-    z[0] = 'l';
-  }else if( S_ISREG(iMode) ){
-    z[0] = '-';
-  }else if( S_ISDIR(iMode) ){
-    z[0] = 'd';
-  }else{
-    z[0] = '?';
-  }
-  for(i=0; i<3; i++){
-    int m = (iMode >> ((2-i)*3));
-    char *a = &z[1 + i*3];
-    a[0] = (m & 0x4) ? 'r' : '-';
-    a[1] = (m & 0x2) ? 'w' : '-';
-    a[2] = (m & 0x1) ? 'x' : '-';
-  }
-  z[10] = '\0';
-  sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT);
-}
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-
-/* 
-** Cursor type for recursively iterating through a directory structure.
-*/
-typedef struct fsdir_cursor fsdir_cursor;
-typedef struct FsdirLevel FsdirLevel;
-
-struct FsdirLevel {
-  DIR *pDir;                 /* From opendir() */
-  char *zDir;                /* Name of directory (nul-terminated) */
-};
-
-struct fsdir_cursor {
-  sqlite3_vtab_cursor base;  /* Base class - must be first */
-
-  int nLvl;                  /* Number of entries in aLvl[] array */
-  int iLvl;                  /* Index of current entry */
-  FsdirLevel *aLvl;          /* Hierarchy of directories being traversed */
-
-  const char *zBase;
-  int nBase;
-
-  struct stat sStat;         /* Current lstat() results */
-  char *zPath;               /* Path to current entry */
-  sqlite3_int64 iRowid;      /* Current rowid */
-};
-
-typedef struct fsdir_tab fsdir_tab;
-struct fsdir_tab {
-  sqlite3_vtab base;         /* Base class - must be first */
-};
-
-/*
-** Construct a new fsdir virtual table object.
-*/
-static int fsdirConnect(
-  sqlite3 *db,
-  void *pAux,
-  int argc, const char *const*argv,
-  sqlite3_vtab **ppVtab,
-  char **pzErr
-){
-  fsdir_tab *pNew = 0;
-  int rc;
-  (void)pAux;
-  (void)argc;
-  (void)argv;
-  (void)pzErr;
-  rc = sqlite3_declare_vtab(db, "CREATE TABLE x" FSDIR_SCHEMA);
-  if( rc==SQLITE_OK ){
-    pNew = (fsdir_tab*)sqlite3_malloc( sizeof(*pNew) );
-    if( pNew==0 ) return SQLITE_NOMEM;
-    memset(pNew, 0, sizeof(*pNew));
-    sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY);
-  }
-  *ppVtab = (sqlite3_vtab*)pNew;
-  return rc;
-}
-
-/*
-** This method is the destructor for fsdir vtab objects.
-*/
-static int fsdirDisconnect(sqlite3_vtab *pVtab){
-  sqlite3_free(pVtab);
-  return SQLITE_OK;
-}
-
-/*
-** Constructor for a new fsdir_cursor object.
-*/
-static int fsdirOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
-  fsdir_cursor *pCur;
-  (void)p;
-  pCur = sqlite3_malloc( sizeof(*pCur) );
-  if( pCur==0 ) return SQLITE_NOMEM;
-  memset(pCur, 0, sizeof(*pCur));
-  pCur->iLvl = -1;
-  *ppCursor = &pCur->base;
-  return SQLITE_OK;
-}
-
-/*
-** Reset a cursor back to the state it was in when first returned
-** by fsdirOpen().
-*/
-static void fsdirResetCursor(fsdir_cursor *pCur){
-  int i;
-  for(i=0; i<=pCur->iLvl; i++){
-    FsdirLevel *pLvl = &pCur->aLvl[i];
-    if( pLvl->pDir ) closedir(pLvl->pDir);
-    sqlite3_free(pLvl->zDir);
-  }
-  sqlite3_free(pCur->zPath);
-  sqlite3_free(pCur->aLvl);
-  pCur->aLvl = 0;
-  pCur->zPath = 0;
-  pCur->zBase = 0;
-  pCur->nBase = 0;
-  pCur->nLvl = 0;
-  pCur->iLvl = -1;
-  pCur->iRowid = 1;
-}
-
-/*
-** Destructor for an fsdir_cursor.
-*/
-static int fsdirClose(sqlite3_vtab_cursor *cur){
-  fsdir_cursor *pCur = (fsdir_cursor*)cur;
-
-  fsdirResetCursor(pCur);
-  sqlite3_free(pCur);
-  return SQLITE_OK;
-}
-
-/*
-** Set the error message for the virtual table associated with cursor
-** pCur to the results of vprintf(zFmt, ...).
-*/
-static void fsdirSetErrmsg(fsdir_cursor *pCur, const char *zFmt, ...){
-  va_list ap;
-  va_start(ap, zFmt);
-  pCur->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap);
-  va_end(ap);
-}
-
-
-/*
-** Advance an fsdir_cursor to its next row of output.
-*/
-static int fsdirNext(sqlite3_vtab_cursor *cur){
-  fsdir_cursor *pCur = (fsdir_cursor*)cur;
-  mode_t m = pCur->sStat.st_mode;
-
-  pCur->iRowid++;
-  if( S_ISDIR(m) ){
-    /* Descend into this directory */
-    int iNew = pCur->iLvl + 1;
-    FsdirLevel *pLvl;
-    if( iNew>=pCur->nLvl ){
-      int nNew = iNew+1;
-      sqlite3_int64 nByte = nNew*sizeof(FsdirLevel);
-      FsdirLevel *aNew = (FsdirLevel*)sqlite3_realloc64(pCur->aLvl, nByte);
-      if( aNew==0 ) return SQLITE_NOMEM;
-      memset(&aNew[pCur->nLvl], 0, sizeof(FsdirLevel)*(nNew-pCur->nLvl));
-      pCur->aLvl = aNew;
-      pCur->nLvl = nNew;
-    }
-    pCur->iLvl = iNew;
-    pLvl = &pCur->aLvl[iNew];
-    
-    pLvl->zDir = pCur->zPath;
-    pCur->zPath = 0;
-    pLvl->pDir = opendir(pLvl->zDir);
-    if( pLvl->pDir==0 ){
-      fsdirSetErrmsg(pCur, "cannot read directory: %s", pCur->zPath);
-      return SQLITE_ERROR;
-    }
-  }
-
-  while( pCur->iLvl>=0 ){
-    FsdirLevel *pLvl = &pCur->aLvl[pCur->iLvl];
-    struct dirent *pEntry = readdir(pLvl->pDir);
-    if( pEntry ){
-      if( pEntry->d_name[0]=='.' ){
-       if( pEntry->d_name[1]=='.' && pEntry->d_name[2]=='\0' ) continue;
-       if( pEntry->d_name[1]=='\0' ) continue;
-      }
-      sqlite3_free(pCur->zPath);
-      pCur->zPath = sqlite3_mprintf("%s/%s", pLvl->zDir, pEntry->d_name);
-      if( pCur->zPath==0 ) return SQLITE_NOMEM;
-      if( fileLinkStat(pCur->zPath, &pCur->sStat) ){
-        fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath);
-        return SQLITE_ERROR;
-      }
-      return SQLITE_OK;
-    }
-    closedir(pLvl->pDir);
-    sqlite3_free(pLvl->zDir);
-    pLvl->pDir = 0;
-    pLvl->zDir = 0;
-    pCur->iLvl--;
-  }
-
-  /* EOF */
-  sqlite3_free(pCur->zPath);
-  pCur->zPath = 0;
-  return SQLITE_OK;
-}
-
-/*
-** Return values of columns for the row at which the series_cursor
-** is currently pointing.
-*/
-static int fsdirColumn(
-  sqlite3_vtab_cursor *cur,   /* The cursor */
-  sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
-  int i                       /* Which column to return */
-){
-  fsdir_cursor *pCur = (fsdir_cursor*)cur;
-  switch( i ){
-    case FSDIR_COLUMN_NAME: {
-      sqlite3_result_text(ctx, &pCur->zPath[pCur->nBase], -1, SQLITE_TRANSIENT);
-      break;
-    }
-
-    case FSDIR_COLUMN_MODE:
-      sqlite3_result_int64(ctx, pCur->sStat.st_mode);
-      break;
-
-    case FSDIR_COLUMN_MTIME:
-      sqlite3_result_int64(ctx, pCur->sStat.st_mtime);
-      break;
-
-    case FSDIR_COLUMN_DATA: {
-      mode_t m = pCur->sStat.st_mode;
-      if( S_ISDIR(m) ){
-        sqlite3_result_null(ctx);
-#if !defined(_WIN32) && !defined(WIN32)
-      }else if( S_ISLNK(m) ){
-        char aStatic[64];
-        char *aBuf = aStatic;
-        sqlite3_int64 nBuf = 64;
-        int n;
-
-        while( 1 ){
-          n = readlink(pCur->zPath, aBuf, nBuf);
-          if( n<nBuf ) break;
-          if( aBuf!=aStatic ) sqlite3_free(aBuf);
-          nBuf = nBuf*2;
-          aBuf = sqlite3_malloc64(nBuf);
-          if( aBuf==0 ){
-            sqlite3_result_error_nomem(ctx);
-            return SQLITE_NOMEM;
-          }
-        }
-
-        sqlite3_result_text(ctx, aBuf, n, SQLITE_TRANSIENT);
-        if( aBuf!=aStatic ) sqlite3_free(aBuf);
-#endif
-      }else{
-        readFileContents(ctx, pCur->zPath);
-      }
-    }
-    case FSDIR_COLUMN_PATH:
-    default: {
-      /* The FSDIR_COLUMN_PATH and FSDIR_COLUMN_DIR are input parameters.
-      ** always return their values as NULL */
-      break;
-    }
-  }
-  return SQLITE_OK;
-}
-
-/*
-** Return the rowid for the current row. In this implementation, the
-** first row returned is assigned rowid value 1, and each subsequent
-** row a value 1 more than that of the previous.
-*/
-static int fsdirRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
-  fsdir_cursor *pCur = (fsdir_cursor*)cur;
-  *pRowid = pCur->iRowid;
-  return SQLITE_OK;
-}
-
-/*
-** Return TRUE if the cursor has been moved off of the last
-** row of output.
-*/
-static int fsdirEof(sqlite3_vtab_cursor *cur){
-  fsdir_cursor *pCur = (fsdir_cursor*)cur;
-  return (pCur->zPath==0);
-}
-
-/*
-** xFilter callback.
-**
-** idxNum==1   PATH parameter only
-** idxNum==2   Both PATH and DIR supplied
-*/
-static int fsdirFilter(
-  sqlite3_vtab_cursor *cur, 
-  int idxNum, const char *idxStr,
-  int argc, sqlite3_value **argv
-){
-  const char *zDir = 0;
-  fsdir_cursor *pCur = (fsdir_cursor*)cur;
-  (void)idxStr;
-  fsdirResetCursor(pCur);
-
-  if( idxNum==0 ){
-    fsdirSetErrmsg(pCur, "table function fsdir requires an argument");
-    return SQLITE_ERROR;
-  }
-
-  assert( argc==idxNum && (argc==1 || argc==2) );
-  zDir = (const char*)sqlite3_value_text(argv[0]);
-  if( zDir==0 ){
-    fsdirSetErrmsg(pCur, "table function fsdir requires a non-NULL argument");
-    return SQLITE_ERROR;
-  }
-  if( argc==2 ){
-    pCur->zBase = (const char*)sqlite3_value_text(argv[1]);
-  }
-  if( pCur->zBase ){
-    pCur->nBase = (int)strlen(pCur->zBase)+1;
-    pCur->zPath = sqlite3_mprintf("%s/%s", pCur->zBase, zDir);
-  }else{
-    pCur->zPath = sqlite3_mprintf("%s", zDir);
-  }
-
-  if( pCur->zPath==0 ){
-    return SQLITE_NOMEM;
-  }
-  if( fileLinkStat(pCur->zPath, &pCur->sStat) ){
-    fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath);
-    return SQLITE_ERROR;
-  }
-
-  return SQLITE_OK;
-}
-
-/*
-** SQLite will invoke this method one or more times while planning a query
-** that uses the generate_series virtual table.  This routine needs to create
-** a query plan for each invocation and compute an estimated cost for that
-** plan.
-**
-** In this implementation idxNum is used to represent the
-** query plan.  idxStr is unused.
-**
-** The query plan is represented by values of idxNum:
-**
-**  (1)  The path value is supplied by argv[0]
-**  (2)  Path is in argv[0] and dir is in argv[1]
-*/
-static int fsdirBestIndex(
-  sqlite3_vtab *tab,
-  sqlite3_index_info *pIdxInfo
-){
-  int i;                 /* Loop over constraints */
-  int idxPath = -1;      /* Index in pIdxInfo->aConstraint of PATH= */
-  int idxDir = -1;       /* Index in pIdxInfo->aConstraint of DIR= */
-  int seenPath = 0;      /* True if an unusable PATH= constraint is seen */
-  int seenDir = 0;       /* True if an unusable DIR= constraint is seen */
-  const struct sqlite3_index_constraint *pConstraint;
-
-  (void)tab;
-  pConstraint = pIdxInfo->aConstraint;
-  for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
-    if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
-    switch( pConstraint->iColumn ){
-      case FSDIR_COLUMN_PATH: {
-        if( pConstraint->usable ){
-          idxPath = i;
-          seenPath = 0;
-        }else if( idxPath<0 ){
-          seenPath = 1;
-        }
-        break;
-      }
-      case FSDIR_COLUMN_DIR: {
-        if( pConstraint->usable ){
-          idxDir = i;
-          seenDir = 0;
-        }else if( idxDir<0 ){
-          seenDir = 1;
-        }
-        break;
-      }
-    } 
-  }
-  if( seenPath || seenDir ){
-    /* If input parameters are unusable, disallow this plan */
-    return SQLITE_CONSTRAINT;
-  }
-
-  if( idxPath<0 ){
-    pIdxInfo->idxNum = 0;
-    /* The pIdxInfo->estimatedCost should have been initialized to a huge
-    ** number.  Leave it unchanged. */
-    pIdxInfo->estimatedRows = 0x7fffffff;
-  }else{
-    pIdxInfo->aConstraintUsage[idxPath].omit = 1;
-    pIdxInfo->aConstraintUsage[idxPath].argvIndex = 1;
-    if( idxDir>=0 ){
-      pIdxInfo->aConstraintUsage[idxDir].omit = 1;
-      pIdxInfo->aConstraintUsage[idxDir].argvIndex = 2;
-      pIdxInfo->idxNum = 2;
-      pIdxInfo->estimatedCost = 10.0;
-    }else{
-      pIdxInfo->idxNum = 1;
-      pIdxInfo->estimatedCost = 100.0;
-    }
-  }
-
-  return SQLITE_OK;
-}
-
-/*
-** Register the "fsdir" virtual table.
-*/
-static int fsdirRegister(sqlite3 *db){
-  static sqlite3_module fsdirModule = {
-    0,                         /* iVersion */
-    0,                         /* xCreate */
-    fsdirConnect,              /* xConnect */
-    fsdirBestIndex,            /* xBestIndex */
-    fsdirDisconnect,           /* xDisconnect */
-    0,                         /* xDestroy */
-    fsdirOpen,                 /* xOpen - open a cursor */
-    fsdirClose,                /* xClose - close a cursor */
-    fsdirFilter,               /* xFilter - configure scan constraints */
-    fsdirNext,                 /* xNext - advance a cursor */
-    fsdirEof,                  /* xEof - check for end of scan */
-    fsdirColumn,               /* xColumn - read data */
-    fsdirRowid,                /* xRowid - read data */
-    0,                         /* xUpdate */
-    0,                         /* xBegin */
-    0,                         /* xSync */
-    0,                         /* xCommit */
-    0,                         /* xRollback */
-    0,                         /* xFindMethod */
-    0,                         /* xRename */
-    0,                         /* xSavepoint */
-    0,                         /* xRelease */
-    0,                         /* xRollbackTo */
-    0,                         /* xShadowName */
-  };
-
-  int rc = sqlite3_create_module(db, "fsdir", &fsdirModule, 0);
-  return rc;
-}
-#else         /* SQLITE_OMIT_VIRTUALTABLE */
-# define fsdirRegister(x) SQLITE_OK
-#endif
-
-#ifdef _WIN32
-
-#endif
-int sqlite3_fileio_init(
-  sqlite3 *db, 
-  char **pzErrMsg, 
-  const sqlite3_api_routines *pApi
-){
-  int rc = SQLITE_OK;
-  SQLITE_EXTENSION_INIT2(pApi);
-  (void)pzErrMsg;  /* Unused parameter */
-  rc = sqlite3_create_function(db, "readfile", 1, 
-                               SQLITE_UTF8|SQLITE_DIRECTONLY, 0,
-                               readfileFunc, 0, 0);
-  if( rc==SQLITE_OK ){
-    rc = sqlite3_create_function(db, "writefile", -1,
-                                 SQLITE_UTF8|SQLITE_DIRECTONLY, 0,
-                                 writefileFunc, 0, 0);
-  }
-  if( rc==SQLITE_OK ){
-    rc = sqlite3_create_function(db, "lsmode", 1, SQLITE_UTF8, 0,
-                                 lsModeFunc, 0, 0);
-  }
-  if( rc==SQLITE_OK ){
-    rc = fsdirRegister(db);
-  }
-  return rc;
-}
-
-/************************* End ../ext/misc/fileio.c ********************/
-/************************* Begin ../ext/misc/completion.c ******************/
-/*
-** 2017-07-10
-**
-** The author disclaims copyright to this source code.  In place of
-** a legal notice, here is a blessing:
-**
-**    May you do good and not evil.
-**    May you find forgiveness for yourself and forgive others.
-**    May you share freely, never taking more than you give.
-**
-*************************************************************************
-**
-** This file implements an eponymous virtual table that returns suggested
-** completions for a partial SQL input.
-**
-** Suggested usage:
-**
-**     SELECT DISTINCT candidate COLLATE nocase
-**       FROM completion($prefix,$wholeline)
-**      ORDER BY 1;
-**
-** The two query parameters are optional.  $prefix is the text of the
-** current word being typed and that is to be completed.  $wholeline is
-** the complete input line, used for context.
-**
-** The raw completion() table might return the same candidate multiple
-** times, for example if the same column name is used to two or more
-** tables.  And the candidates are returned in an arbitrary order.  Hence,
-** the DISTINCT and ORDER BY are recommended.
-**
-** This virtual table operates at the speed of human typing, and so there
-** is no attempt to make it fast.  Even a slow implementation will be much
-** faster than any human can type.
-**
-*/
-/* #include "sqlite3ext.h" */
-SQLITE_EXTENSION_INIT1
-#include <assert.h>
-#include <string.h>
-#include <ctype.h>
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-
-/* completion_vtab is a subclass of sqlite3_vtab which will
-** serve as the underlying representation of a completion virtual table
-*/
-typedef struct completion_vtab completion_vtab;
-struct completion_vtab {
-  sqlite3_vtab base;  /* Base class - must be first */
-  sqlite3 *db;        /* Database connection for this completion vtab */
-};
-
-/* completion_cursor is a subclass of sqlite3_vtab_cursor which will
-** serve as the underlying representation of a cursor that scans
-** over rows of the result
-*/
-typedef struct completion_cursor completion_cursor;
-struct completion_cursor {
-  sqlite3_vtab_cursor base;  /* Base class - must be first */
-  sqlite3 *db;               /* Database connection for this cursor */
-  int nPrefix, nLine;        /* Number of bytes in zPrefix and zLine */
-  char *zPrefix;             /* The prefix for the word we want to complete */
-  char *zLine;               /* The whole that we want to complete */
-  const char *zCurrentRow;   /* Current output row */
-  int szRow;                 /* Length of the zCurrentRow string */
-  sqlite3_stmt *pStmt;       /* Current statement */
-  sqlite3_int64 iRowid;      /* The rowid */
-  int ePhase;                /* Current phase */
-  int j;                     /* inter-phase counter */
-};
-
-/* Values for ePhase:
-*/
-#define COMPLETION_FIRST_PHASE   1
-#define COMPLETION_KEYWORDS      1
-#define COMPLETION_PRAGMAS       2
-#define COMPLETION_FUNCTIONS     3
-#define COMPLETION_COLLATIONS    4
-#define COMPLETION_INDEXES       5
-#define COMPLETION_TRIGGERS      6
-#define COMPLETION_DATABASES     7
-#define COMPLETION_TABLES        8    /* Also VIEWs and TRIGGERs */
-#define COMPLETION_COLUMNS       9
-#define COMPLETION_MODULES       10
-#define COMPLETION_EOF           11
-
-/*
-** The completionConnect() method is invoked to create a new
-** completion_vtab that describes the completion virtual table.
-**
-** Think of this routine as the constructor for completion_vtab objects.
-**
-** All this routine needs to do is:
-**
-**    (1) Allocate the completion_vtab object and initialize all fields.
-**
-**    (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
-**        result set of queries against completion will look like.
-*/
-static int completionConnect(
-  sqlite3 *db,
-  void *pAux,
-  int argc, const char *const*argv,
-  sqlite3_vtab **ppVtab,
-  char **pzErr
-){
-  completion_vtab *pNew;
-  int rc;
-
-  (void)(pAux);    /* Unused parameter */
-  (void)(argc);    /* Unused parameter */
-  (void)(argv);    /* Unused parameter */
-  (void)(pzErr);   /* Unused parameter */
-
-/* Column numbers */
-#define COMPLETION_COLUMN_CANDIDATE 0  /* Suggested completion of the input */
-#define COMPLETION_COLUMN_PREFIX    1  /* Prefix of the word to be completed */
-#define COMPLETION_COLUMN_WHOLELINE 2  /* Entire line seen so far */
-#define COMPLETION_COLUMN_PHASE     3  /* ePhase - used for debugging only */
-
-  sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
-  rc = sqlite3_declare_vtab(db,
-      "CREATE TABLE x("
-      "  candidate TEXT,"
-      "  prefix TEXT HIDDEN,"
-      "  wholeline TEXT HIDDEN,"
-      "  phase INT HIDDEN"        /* Used for debugging only */
-      ")");
-  if( rc==SQLITE_OK ){
-    pNew = sqlite3_malloc( sizeof(*pNew) );
-    *ppVtab = (sqlite3_vtab*)pNew;
-    if( pNew==0 ) return SQLITE_NOMEM;
-    memset(pNew, 0, sizeof(*pNew));
-    pNew->db = db;
-  }
-  return rc;
-}
-
-/*
-** This method is the destructor for completion_cursor objects.
-*/
-static int completionDisconnect(sqlite3_vtab *pVtab){
-  sqlite3_free(pVtab);
-  return SQLITE_OK;
-}
-
-/*
-** Constructor for a new completion_cursor object.
-*/
-static int completionOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
-  completion_cursor *pCur;
-  pCur = sqlite3_malloc( sizeof(*pCur) );
-  if( pCur==0 ) return SQLITE_NOMEM;
-  memset(pCur, 0, sizeof(*pCur));
-  pCur->db = ((completion_vtab*)p)->db;
-  *ppCursor = &pCur->base;
-  return SQLITE_OK;
-}
-
-/*
-** Reset the completion_cursor.
-*/
-static void completionCursorReset(completion_cursor *pCur){
-  sqlite3_free(pCur->zPrefix);   pCur->zPrefix = 0;  pCur->nPrefix = 0;
-  sqlite3_free(pCur->zLine);     pCur->zLine = 0;    pCur->nLine = 0;
-  sqlite3_finalize(pCur->pStmt); pCur->pStmt = 0;
-  pCur->j = 0;
-}
-
-/*
-** Destructor for a completion_cursor.
-*/
-static int completionClose(sqlite3_vtab_cursor *cur){
-  completionCursorReset((completion_cursor*)cur);
-  sqlite3_free(cur);
-  return SQLITE_OK;
-}
-
-/*
-** Advance a completion_cursor to its next row of output.
-**
-** The ->ePhase, ->j, and ->pStmt fields of the completion_cursor object
-** record the current state of the scan.  This routine sets ->zCurrentRow
-** to the current row of output and then returns.  If no more rows remain,
-** then ->ePhase is set to COMPLETION_EOF which will signal the virtual
-** table that has reached the end of its scan.
-**
-** The current implementation just lists potential identifiers and
-** keywords and filters them by zPrefix.  Future enhancements should
-** take zLine into account to try to restrict the set of identifiers and
-** keywords based on what would be legal at the current point of input.
-*/
-static int completionNext(sqlite3_vtab_cursor *cur){
-  completion_cursor *pCur = (completion_cursor*)cur;
-  int eNextPhase = 0;  /* Next phase to try if current phase reaches end */
-  int iCol = -1;       /* If >=0, step pCur->pStmt and use the i-th column */
-  pCur->iRowid++;
-  while( pCur->ePhase!=COMPLETION_EOF ){
-    switch( pCur->ePhase ){
-      case COMPLETION_KEYWORDS: {
-        if( pCur->j >= sqlite3_keyword_count() ){
-          pCur->zCurrentRow = 0;
-          pCur->ePhase = COMPLETION_DATABASES;
-        }else{
-          sqlite3_keyword_name(pCur->j++, &pCur->zCurrentRow, &pCur->szRow);
-        }
-        iCol = -1;
-        break;
-      }
-      case COMPLETION_DATABASES: {
-        if( pCur->pStmt==0 ){
-          sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1,
-                             &pCur->pStmt, 0);
-        }
-        iCol = 1;
-        eNextPhase = COMPLETION_TABLES;
-        break;
-      }
-      case COMPLETION_TABLES: {
-        if( pCur->pStmt==0 ){
-          sqlite3_stmt *pS2;
-          char *zSql = 0;
-          const char *zSep = "";
-          sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pS2, 0);
-          while( sqlite3_step(pS2)==SQLITE_ROW ){
-            const char *zDb = (const char*)sqlite3_column_text(pS2, 1);
-            zSql = sqlite3_mprintf(
-               "%z%s"
-               "SELECT name FROM \"%w\".sqlite_schema",
-               zSql, zSep, zDb
-            );
-            if( zSql==0 ) return SQLITE_NOMEM;
-            zSep = " UNION ";
-          }
-          sqlite3_finalize(pS2);
-          sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pStmt, 0);
-          sqlite3_free(zSql);
-        }
-        iCol = 0;
-        eNextPhase = COMPLETION_COLUMNS;
-        break;
-      }
-      case COMPLETION_COLUMNS: {
-        if( pCur->pStmt==0 ){
-          sqlite3_stmt *pS2;
-          char *zSql = 0;
-          const char *zSep = "";
-          sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pS2, 0);
-          while( sqlite3_step(pS2)==SQLITE_ROW ){
-            const char *zDb = (const char*)sqlite3_column_text(pS2, 1);
-            zSql = sqlite3_mprintf(
-               "%z%s"
-               "SELECT pti.name FROM \"%w\".sqlite_schema AS sm"
-                       " JOIN pragma_table_info(sm.name,%Q) AS pti"
-               " WHERE sm.type='table'",
-               zSql, zSep, zDb, zDb
-            );
-            if( zSql==0 ) return SQLITE_NOMEM;
-            zSep = " UNION ";
-          }
-          sqlite3_finalize(pS2);
-          sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pStmt, 0);
-          sqlite3_free(zSql);
-        }
-        iCol = 0;
-        eNextPhase = COMPLETION_EOF;
-        break;
-      }
-    }
-    if( iCol<0 ){
-      /* This case is when the phase presets zCurrentRow */
-      if( pCur->zCurrentRow==0 ) continue;
-    }else{
-      if( sqlite3_step(pCur->pStmt)==SQLITE_ROW ){
-        /* Extract the next row of content */
-        pCur->zCurrentRow = (const char*)sqlite3_column_text(pCur->pStmt, iCol);
-        pCur->szRow = sqlite3_column_bytes(pCur->pStmt, iCol);
-      }else{
-        /* When all rows are finished, advance to the next phase */
-        sqlite3_finalize(pCur->pStmt);
-        pCur->pStmt = 0;
-        pCur->ePhase = eNextPhase;
-        continue;
-      }
-    }
-    if( pCur->nPrefix==0 ) break;
-    if( pCur->nPrefix<=pCur->szRow
-     && sqlite3_strnicmp(pCur->zPrefix, pCur->zCurrentRow, pCur->nPrefix)==0
-    ){
-      break;
-    }
-  }
-
-  return SQLITE_OK;
-}
-
-/*
-** Return values of columns for the row at which the completion_cursor
-** is currently pointing.
-*/
-static int completionColumn(
-  sqlite3_vtab_cursor *cur,   /* The cursor */
-  sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
-  int i                       /* Which column to return */
-){
-  completion_cursor *pCur = (completion_cursor*)cur;
-  switch( i ){
-    case COMPLETION_COLUMN_CANDIDATE: {
-      sqlite3_result_text(ctx, pCur->zCurrentRow, pCur->szRow,SQLITE_TRANSIENT);
-      break;
-    }
-    case COMPLETION_COLUMN_PREFIX: {
-      sqlite3_result_text(ctx, pCur->zPrefix, -1, SQLITE_TRANSIENT);
-      break;
-    }
-    case COMPLETION_COLUMN_WHOLELINE: {
-      sqlite3_result_text(ctx, pCur->zLine, -1, SQLITE_TRANSIENT);
-      break;
-    }
-    case COMPLETION_COLUMN_PHASE: {
-      sqlite3_result_int(ctx, pCur->ePhase);
-      break;
-    }
-  }
-  return SQLITE_OK;
-}
-
-/*
-** Return the rowid for the current row.  In this implementation, the
-** rowid is the same as the output value.
-*/
-static int completionRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
-  completion_cursor *pCur = (completion_cursor*)cur;
-  *pRowid = pCur->iRowid;
-  return SQLITE_OK;
-}
-
-/*
-** Return TRUE if the cursor has been moved off of the last
-** row of output.
-*/
-static int completionEof(sqlite3_vtab_cursor *cur){
-  completion_cursor *pCur = (completion_cursor*)cur;
-  return pCur->ePhase >= COMPLETION_EOF;
-}
-
-/*
-** This method is called to "rewind" the completion_cursor object back
-** to the first row of output.  This method is always called at least
-** once prior to any call to completionColumn() or completionRowid() or 
-** completionEof().
-*/
-static int completionFilter(
-  sqlite3_vtab_cursor *pVtabCursor, 
-  int idxNum, const char *idxStr,
-  int argc, sqlite3_value **argv
-){
-  completion_cursor *pCur = (completion_cursor *)pVtabCursor;
-  int iArg = 0;
-  (void)(idxStr);   /* Unused parameter */
-  (void)(argc);     /* Unused parameter */
-  completionCursorReset(pCur);
-  if( idxNum & 1 ){
-    pCur->nPrefix = sqlite3_value_bytes(argv[iArg]);
-    if( pCur->nPrefix>0 ){
-      pCur->zPrefix = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg]));
-      if( pCur->zPrefix==0 ) return SQLITE_NOMEM;
-    }
-    iArg = 1;
-  }
-  if( idxNum & 2 ){
-    pCur->nLine = sqlite3_value_bytes(argv[iArg]);
-    if( pCur->nLine>0 ){
-      pCur->zLine = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg]));
-      if( pCur->zLine==0 ) return SQLITE_NOMEM;
-    }
-  }
-  if( pCur->zLine!=0 && pCur->zPrefix==0 ){
-    int i = pCur->nLine;
-    while( i>0 && (isalnum(pCur->zLine[i-1]) || pCur->zLine[i-1]=='_') ){
-      i--;
-    }
-    pCur->nPrefix = pCur->nLine - i;
-    if( pCur->nPrefix>0 ){
-      pCur->zPrefix = sqlite3_mprintf("%.*s", pCur->nPrefix, pCur->zLine + i);
-      if( pCur->zPrefix==0 ) return SQLITE_NOMEM;
-    }
-  }
-  pCur->iRowid = 0;
-  pCur->ePhase = COMPLETION_FIRST_PHASE;
-  return completionNext(pVtabCursor);
-}
-
-/*
-** SQLite will invoke this method one or more times while planning a query
-** that uses the completion virtual table.  This routine needs to create
-** a query plan for each invocation and compute an estimated cost for that
-** plan.
-**
-** There are two hidden parameters that act as arguments to the table-valued
-** function:  "prefix" and "wholeline".  Bit 0 of idxNum is set if "prefix"
-** is available and bit 1 is set if "wholeline" is available.
-*/
-static int completionBestIndex(
-  sqlite3_vtab *tab,
-  sqlite3_index_info *pIdxInfo
-){
-  int i;                 /* Loop over constraints */
-  int idxNum = 0;        /* The query plan bitmask */
-  int prefixIdx = -1;    /* Index of the start= constraint, or -1 if none */
-  int wholelineIdx = -1; /* Index of the stop= constraint, or -1 if none */
-  int nArg = 0;          /* Number of arguments that completeFilter() expects */
-  const struct sqlite3_index_constraint *pConstraint;
-
-  (void)(tab);    /* Unused parameter */
-  pConstraint = pIdxInfo->aConstraint;
-  for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
-    if( pConstraint->usable==0 ) continue;
-    if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
-    switch( pConstraint->iColumn ){
-      case COMPLETION_COLUMN_PREFIX:
-        prefixIdx = i;
-        idxNum |= 1;
-        break;
-      case COMPLETION_COLUMN_WHOLELINE:
-        wholelineIdx = i;
-        idxNum |= 2;
-        break;
-    }
-  }
-  if( prefixIdx>=0 ){
-    pIdxInfo->aConstraintUsage[prefixIdx].argvIndex = ++nArg;
-    pIdxInfo->aConstraintUsage[prefixIdx].omit = 1;
-  }
-  if( wholelineIdx>=0 ){
-    pIdxInfo->aConstraintUsage[wholelineIdx].argvIndex = ++nArg;
-    pIdxInfo->aConstraintUsage[wholelineIdx].omit = 1;
-  }
-  pIdxInfo->idxNum = idxNum;
-  pIdxInfo->estimatedCost = (double)5000 - 1000*nArg;
-  pIdxInfo->estimatedRows = 500 - 100*nArg;
-  return SQLITE_OK;
-}
-
-/*
-** This following structure defines all the methods for the 
-** completion virtual table.
-*/
-static sqlite3_module completionModule = {
-  0,                         /* iVersion */
-  0,                         /* xCreate */
-  completionConnect,         /* xConnect */
-  completionBestIndex,       /* xBestIndex */
-  completionDisconnect,      /* xDisconnect */
-  0,                         /* xDestroy */
-  completionOpen,            /* xOpen - open a cursor */
-  completionClose,           /* xClose - close a cursor */
-  completionFilter,          /* xFilter - configure scan constraints */
-  completionNext,            /* xNext - advance a cursor */
-  completionEof,             /* xEof - check for end of scan */
-  completionColumn,          /* xColumn - read data */
-  completionRowid,           /* xRowid - read data */
-  0,                         /* xUpdate */
-  0,                         /* xBegin */
-  0,                         /* xSync */
-  0,                         /* xCommit */
-  0,                         /* xRollback */
-  0,                         /* xFindMethod */
-  0,                         /* xRename */
-  0,                         /* xSavepoint */
-  0,                         /* xRelease */
-  0,                         /* xRollbackTo */
-  0                          /* xShadowName */
-};
-
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
-int sqlite3CompletionVtabInit(sqlite3 *db){
-  int rc = SQLITE_OK;
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-  rc = sqlite3_create_module(db, "completion", &completionModule, 0);
-#endif
-  return rc;
-}
-
-#ifdef _WIN32
-
-#endif
-int sqlite3_completion_init(
-  sqlite3 *db, 
-  char **pzErrMsg, 
-  const sqlite3_api_routines *pApi
-){
-  int rc = SQLITE_OK;
-  SQLITE_EXTENSION_INIT2(pApi);
-  (void)(pzErrMsg);  /* Unused parameter */
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-  rc = sqlite3CompletionVtabInit(db);
-#endif
-  return rc;
-}
-
-/************************* End ../ext/misc/completion.c ********************/
-/************************* Begin ../ext/misc/appendvfs.c ******************/
-/*
-** 2017-10-20
-**
-** The author disclaims copyright to this source code.  In place of
-** a legal notice, here is a blessing:
-**
-**    May you do good and not evil.
-**    May you find forgiveness for yourself and forgive others.
-**    May you share freely, never taking more than you give.
-**
-******************************************************************************
-**
-** This file implements a VFS shim that allows an SQLite database to be
-** appended onto the end of some other file, such as an executable.
-**
-** A special record must appear at the end of the file that identifies the
-** file as an appended database and provides the offset to the first page
-** of the exposed content. (Or, it is the length of the content prefix.)
-** For best performance page 1 should be located at a disk page boundary,
-** though that is not required.
-**
-** When opening a database using this VFS, the connection might treat
-** the file as an ordinary SQLite database, or it might treat it as a
-** database appended onto some other file.  The decision is made by
-** applying the following rules in order:
-**
-**  (1)  An empty file is an ordinary database.
-**
-**  (2)  If the file ends with the appendvfs trailer string
-**       "Start-Of-SQLite3-NNNNNNNN" that file is an appended database.
-**
-**  (3)  If the file begins with the standard SQLite prefix string
-**       "SQLite format 3", that file is an ordinary database.
-**
-**  (4)  If none of the above apply and the SQLITE_OPEN_CREATE flag is
-**       set, then a new database is appended to the already existing file.
-**
-**  (5)  Otherwise, SQLITE_CANTOPEN is returned.
-**
-** To avoid unnecessary complications with the PENDING_BYTE, the size of
-** the file containing the database is limited to 1GiB. (1073741824 bytes)
-** This VFS will not read or write past the 1GiB mark.  This restriction
-** might be lifted in future versions.  For now, if you need a larger
-** database, then keep it in a separate file.
-**
-** If the file being opened is a plain database (not an appended one), then
-** this shim is a pass-through into the default underlying VFS. (rule 3)
-**/
-/* #include "sqlite3ext.h" */
-SQLITE_EXTENSION_INIT1
-#include <string.h>
-#include <assert.h>
-
-/* The append mark at the end of the database is:
-**
-**     Start-Of-SQLite3-NNNNNNNN
-**     123456789 123456789 12345
-**
-** The NNNNNNNN represents a 64-bit big-endian unsigned integer which is
-** the offset to page 1, and also the length of the prefix content.
-*/
-#define APND_MARK_PREFIX     "Start-Of-SQLite3-"
-#define APND_MARK_PREFIX_SZ  17
-#define APND_MARK_FOS_SZ      8
-#define APND_MARK_SIZE       (APND_MARK_PREFIX_SZ+APND_MARK_FOS_SZ)
-
-/*
-** Maximum size of the combined prefix + database + append-mark.  This
-** must be less than 0x40000000 to avoid locking issues on Windows.
-*/
-#define APND_MAX_SIZE  (0x40000000)
-
-/*
-** Try to align the database to an even multiple of APND_ROUNDUP bytes.
-*/
-#ifndef APND_ROUNDUP
-#define APND_ROUNDUP 4096
-#endif
-#define APND_ALIGN_MASK         ((sqlite3_int64)(APND_ROUNDUP-1))
-#define APND_START_ROUNDUP(fsz) (((fsz)+APND_ALIGN_MASK) & ~APND_ALIGN_MASK)
-
-/*
-** Forward declaration of objects used by this utility
-*/
-typedef struct sqlite3_vfs ApndVfs;
-typedef struct ApndFile ApndFile;
-
-/* Access to a lower-level VFS that (might) implement dynamic loading,
-** access to randomness, etc.
-*/
-#define ORIGVFS(p)  ((sqlite3_vfs*)((p)->pAppData))
-#define ORIGFILE(p) ((sqlite3_file*)(((ApndFile*)(p))+1))
-
-/* An open appendvfs file
-**
-** An instance of this structure describes the appended database file.
-** A separate sqlite3_file object is always appended. The appended
-** sqlite3_file object (which can be accessed using ORIGFILE()) describes
-** the entire file, including the prefix, the database, and the
-** append-mark.
-**
-** The structure of an AppendVFS database is like this:
-**
-**   +-------------+---------+----------+-------------+
-**   | prefix-file | padding | database | append-mark |
-**   +-------------+---------+----------+-------------+
-**                           ^          ^
-**                           |          |
-**                         iPgOne      iMark
-**
-**
-** "prefix file" -  file onto which the database has been appended.
-** "padding"     -  zero or more bytes inserted so that "database"
-**                  starts on an APND_ROUNDUP boundary
-** "database"    -  The SQLite database file
-** "append-mark" -  The 25-byte "Start-Of-SQLite3-NNNNNNNN" that indicates
-**                  the offset from the start of prefix-file to the start
-**                  of "database".
-**
-** The size of the database is iMark - iPgOne.
-**
-** The NNNNNNNN in the "Start-Of-SQLite3-NNNNNNNN" suffix is the value
-** of iPgOne stored as a big-ending 64-bit integer.
-**
-** iMark will be the size of the underlying file minus 25 (APND_MARKSIZE).
-** Or, iMark is -1 to indicate that it has not yet been written.
-*/
-struct ApndFile {
-  sqlite3_file base;        /* Subclass.  MUST BE FIRST! */
-  sqlite3_int64 iPgOne;     /* Offset to the start of the database */
-  sqlite3_int64 iMark;      /* Offset of the append mark.  -1 if unwritten */
-  /* Always followed by another sqlite3_file that describes the whole file */
-};
-
-/*
-** Methods for ApndFile
-*/
-static int apndClose(sqlite3_file*);
-static int apndRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
-static int apndWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
-static int apndTruncate(sqlite3_file*, sqlite3_int64 size);
-static int apndSync(sqlite3_file*, int flags);
-static int apndFileSize(sqlite3_file*, sqlite3_int64 *pSize);
-static int apndLock(sqlite3_file*, int);
-static int apndUnlock(sqlite3_file*, int);
-static int apndCheckReservedLock(sqlite3_file*, int *pResOut);
-static int apndFileControl(sqlite3_file*, int op, void *pArg);
-static int apndSectorSize(sqlite3_file*);
-static int apndDeviceCharacteristics(sqlite3_file*);
-static int apndShmMap(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
-static int apndShmLock(sqlite3_file*, int offset, int n, int flags);
-static void apndShmBarrier(sqlite3_file*);
-static int apndShmUnmap(sqlite3_file*, int deleteFlag);
-static int apndFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
-static int apndUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p);
-
-/*
-** Methods for ApndVfs
-*/
-static int apndOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
-static int apndDelete(sqlite3_vfs*, const char *zName, int syncDir);
-static int apndAccess(sqlite3_vfs*, const char *zName, int flags, int *);
-static int apndFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
-static void *apndDlOpen(sqlite3_vfs*, const char *zFilename);
-static void apndDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
-static void (*apndDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
-static void apndDlClose(sqlite3_vfs*, void*);
-static int apndRandomness(sqlite3_vfs*, int nByte, char *zOut);
-static int apndSleep(sqlite3_vfs*, int microseconds);
-static int apndCurrentTime(sqlite3_vfs*, double*);
-static int apndGetLastError(sqlite3_vfs*, int, char *);
-static int apndCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
-static int apndSetSystemCall(sqlite3_vfs*, const char*,sqlite3_syscall_ptr);
-static sqlite3_syscall_ptr apndGetSystemCall(sqlite3_vfs*, const char *z);
-static const char *apndNextSystemCall(sqlite3_vfs*, const char *zName);
-
-static sqlite3_vfs apnd_vfs = {
-  3,                            /* iVersion (set when registered) */
-  0,                            /* szOsFile (set when registered) */
-  1024,                         /* mxPathname */
-  0,                            /* pNext */
-  "apndvfs",                    /* zName */
-  0,                            /* pAppData (set when registered) */ 
-  apndOpen,                     /* xOpen */
-  apndDelete,                   /* xDelete */
-  apndAccess,                   /* xAccess */
-  apndFullPathname,             /* xFullPathname */
-  apndDlOpen,                   /* xDlOpen */
-  apndDlError,                  /* xDlError */
-  apndDlSym,                    /* xDlSym */
-  apndDlClose,                  /* xDlClose */
-  apndRandomness,               /* xRandomness */
-  apndSleep,                    /* xSleep */
-  apndCurrentTime,              /* xCurrentTime */
-  apndGetLastError,             /* xGetLastError */
-  apndCurrentTimeInt64,         /* xCurrentTimeInt64 */
-  apndSetSystemCall,            /* xSetSystemCall */
-  apndGetSystemCall,            /* xGetSystemCall */
-  apndNextSystemCall            /* xNextSystemCall */
-};
-
-static const sqlite3_io_methods apnd_io_methods = {
-  3,                              /* iVersion */
-  apndClose,                      /* xClose */
-  apndRead,                       /* xRead */
-  apndWrite,                      /* xWrite */
-  apndTruncate,                   /* xTruncate */
-  apndSync,                       /* xSync */
-  apndFileSize,                   /* xFileSize */
-  apndLock,                       /* xLock */
-  apndUnlock,                     /* xUnlock */
-  apndCheckReservedLock,          /* xCheckReservedLock */
-  apndFileControl,                /* xFileControl */
-  apndSectorSize,                 /* xSectorSize */
-  apndDeviceCharacteristics,      /* xDeviceCharacteristics */
-  apndShmMap,                     /* xShmMap */
-  apndShmLock,                    /* xShmLock */
-  apndShmBarrier,                 /* xShmBarrier */
-  apndShmUnmap,                   /* xShmUnmap */
-  apndFetch,                      /* xFetch */
-  apndUnfetch                     /* xUnfetch */
-};
-
-/*
-** Close an apnd-file.
-*/
-static int apndClose(sqlite3_file *pFile){
-  pFile = ORIGFILE(pFile);
-  return pFile->pMethods->xClose(pFile);
-}
-
-/*
-** Read data from an apnd-file.
-*/
-static int apndRead(
-  sqlite3_file *pFile, 
-  void *zBuf, 
-  int iAmt, 
-  sqlite_int64 iOfst
-){
-  ApndFile *paf = (ApndFile *)pFile;
-  pFile = ORIGFILE(pFile);
-  return pFile->pMethods->xRead(pFile, zBuf, iAmt, paf->iPgOne+iOfst);
-}
-
-/*
-** Add the append-mark onto what should become the end of the file.
-*  If and only if this succeeds, internal ApndFile.iMark is updated.
-*  Parameter iWriteEnd is the appendvfs-relative offset of the new mark.
-*/
-static int apndWriteMark(
-  ApndFile *paf,
-  sqlite3_file *pFile,
-  sqlite_int64 iWriteEnd
-){
-  sqlite_int64 iPgOne = paf->iPgOne;
-  unsigned char a[APND_MARK_SIZE];
-  int i = APND_MARK_FOS_SZ;
-  int rc;
-  assert(pFile == ORIGFILE(paf));
-  memcpy(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ);
-  while( --i >= 0 ){
-    a[APND_MARK_PREFIX_SZ+i] = (unsigned char)(iPgOne & 0xff);
-    iPgOne >>= 8;
-  }
-  iWriteEnd += paf->iPgOne;
-  if( SQLITE_OK==(rc = pFile->pMethods->xWrite
-                  (pFile, a, APND_MARK_SIZE, iWriteEnd)) ){
-    paf->iMark = iWriteEnd;
-  }
-  return rc;
-}
-
-/*
-** Write data to an apnd-file.
-*/
-static int apndWrite(
-  sqlite3_file *pFile,
-  const void *zBuf,
-  int iAmt,
-  sqlite_int64 iOfst
-){
-  ApndFile *paf = (ApndFile *)pFile;
-  sqlite_int64 iWriteEnd = iOfst + iAmt;
-  if( iWriteEnd>=APND_MAX_SIZE ) return SQLITE_FULL;
-  pFile = ORIGFILE(pFile);
-  /* If append-mark is absent or will be overwritten, write it. */
-  if( paf->iMark < 0 || paf->iPgOne + iWriteEnd > paf->iMark ){
-    int rc = apndWriteMark(paf, pFile, iWriteEnd);
-    if( SQLITE_OK!=rc ) return rc;
-  }
-  return pFile->pMethods->xWrite(pFile, zBuf, iAmt, paf->iPgOne+iOfst);
-}
-
-/*
-** Truncate an apnd-file.
-*/
-static int apndTruncate(sqlite3_file *pFile, sqlite_int64 size){
-  ApndFile *paf = (ApndFile *)pFile;
-  pFile = ORIGFILE(pFile);
-  /* The append mark goes out first so truncate failure does not lose it. */
-  if( SQLITE_OK!=apndWriteMark(paf, pFile, size) ) return SQLITE_IOERR;
-  /* Truncate underlying file just past append mark */
-  return pFile->pMethods->xTruncate(pFile, paf->iMark+APND_MARK_SIZE);
-}
-
-/*
-** Sync an apnd-file.
-*/
-static int apndSync(sqlite3_file *pFile, int flags){
-  pFile = ORIGFILE(pFile);
-  return pFile->pMethods->xSync(pFile, flags);
-}
-
-/*
-** Return the current file-size of an apnd-file.
-** If the append mark is not yet there, the file-size is 0.
-*/
-static int apndFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
-  ApndFile *paf = (ApndFile *)pFile;
-  *pSize = ( paf->iMark >= 0 )? (paf->iMark - paf->iPgOne) : 0;
-  return SQLITE_OK;
-}
-
-/*
-** Lock an apnd-file.
-*/
-static int apndLock(sqlite3_file *pFile, int eLock){
-  pFile = ORIGFILE(pFile);
-  return pFile->pMethods->xLock(pFile, eLock);
-}
-
-/*
-** Unlock an apnd-file.
-*/
-static int apndUnlock(sqlite3_file *pFile, int eLock){
-  pFile = ORIGFILE(pFile);
-  return pFile->pMethods->xUnlock(pFile, eLock);
-}
-
-/*
-** Check if another file-handle holds a RESERVED lock on an apnd-file.
-*/
-static int apndCheckReservedLock(sqlite3_file *pFile, int *pResOut){
-  pFile = ORIGFILE(pFile);
-  return pFile->pMethods->xCheckReservedLock(pFile, pResOut);
-}
-
-/*
-** File control method. For custom operations on an apnd-file.
-*/
-static int apndFileControl(sqlite3_file *pFile, int op, void *pArg){
-  ApndFile *paf = (ApndFile *)pFile;
-  int rc;
-  pFile = ORIGFILE(pFile);
-  if( op==SQLITE_FCNTL_SIZE_HINT ) *(sqlite3_int64*)pArg += paf->iPgOne;
-  rc = pFile->pMethods->xFileControl(pFile, op, pArg);
-  if( rc==SQLITE_OK && op==SQLITE_FCNTL_VFSNAME ){
-    *(char**)pArg = sqlite3_mprintf("apnd(%lld)/%z", paf->iPgOne,*(char**)pArg);
-  }
-  return rc;
-}
-
-/*
-** Return the sector-size in bytes for an apnd-file.
-*/
-static int apndSectorSize(sqlite3_file *pFile){
-  pFile = ORIGFILE(pFile);
-  return pFile->pMethods->xSectorSize(pFile);
-}
-
-/*
-** Return the device characteristic flags supported by an apnd-file.
-*/
-static int apndDeviceCharacteristics(sqlite3_file *pFile){
-  pFile = ORIGFILE(pFile);
-  return pFile->pMethods->xDeviceCharacteristics(pFile);
-}
-
-/* Create a shared memory file mapping */
-static int apndShmMap(
-  sqlite3_file *pFile,
-  int iPg,
-  int pgsz,
-  int bExtend,
-  void volatile **pp
-){
-  pFile = ORIGFILE(pFile);
-  return pFile->pMethods->xShmMap(pFile,iPg,pgsz,bExtend,pp);
-}
-
-/* Perform locking on a shared-memory segment */
-static int apndShmLock(sqlite3_file *pFile, int offset, int n, int flags){
-  pFile = ORIGFILE(pFile);
-  return pFile->pMethods->xShmLock(pFile,offset,n,flags);
-}
-
-/* Memory barrier operation on shared memory */
-static void apndShmBarrier(sqlite3_file *pFile){
-  pFile = ORIGFILE(pFile);
-  pFile->pMethods->xShmBarrier(pFile);
-}
-
-/* Unmap a shared memory segment */
-static int apndShmUnmap(sqlite3_file *pFile, int deleteFlag){
-  pFile = ORIGFILE(pFile);
-  return pFile->pMethods->xShmUnmap(pFile,deleteFlag);
-}
-
-/* Fetch a page of a memory-mapped file */
-static int apndFetch(
-  sqlite3_file *pFile,
-  sqlite3_int64 iOfst,
-  int iAmt,
-  void **pp
-){
-  ApndFile *p = (ApndFile *)pFile;
-  if( p->iMark < 0 || iOfst+iAmt > p->iMark ){
-    return SQLITE_IOERR; /* Cannot read what is not yet there. */
-  }
-  pFile = ORIGFILE(pFile);
-  return pFile->pMethods->xFetch(pFile, iOfst+p->iPgOne, iAmt, pp);
-}
-
-/* Release a memory-mapped page */
-static int apndUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
-  ApndFile *p = (ApndFile *)pFile;
-  pFile = ORIGFILE(pFile);
-  return pFile->pMethods->xUnfetch(pFile, iOfst+p->iPgOne, pPage);
-}
-
-/*
-** Try to read the append-mark off the end of a file.  Return the
-** start of the appended database if the append-mark is present.
-** If there is no valid append-mark, return -1;
-**
-** An append-mark is only valid if the NNNNNNNN start-of-database offset
-** indicates that the appended database contains at least one page.  The
-** start-of-database value must be a multiple of 512.
-*/
-static sqlite3_int64 apndReadMark(sqlite3_int64 sz, sqlite3_file *pFile){
-  int rc, i;
-  sqlite3_int64 iMark;
-  int msbs = 8 * (APND_MARK_FOS_SZ-1);
-  unsigned char a[APND_MARK_SIZE];
-
-  if( APND_MARK_SIZE!=(sz & 0x1ff) ) return -1;
-  rc = pFile->pMethods->xRead(pFile, a, APND_MARK_SIZE, sz-APND_MARK_SIZE);
-  if( rc ) return -1;
-  if( memcmp(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ)!=0 ) return -1;
-  iMark = ((sqlite3_int64)(a[APND_MARK_PREFIX_SZ] & 0x7f)) << msbs;
-  for(i=1; i<8; i++){
-    msbs -= 8;
-    iMark |= (sqlite3_int64)a[APND_MARK_PREFIX_SZ+i]<<msbs;
-  }
-  if( iMark > (sz - APND_MARK_SIZE - 512) ) return -1;
-  if( iMark & 0x1ff ) return -1;
-  return iMark;
-}
-
-static const char apvfsSqliteHdr[] = "SQLite format 3";
-/*
-** Check to see if the file is an appendvfs SQLite database file.
-** Return true iff it is such. Parameter sz is the file's size.
-*/
-static int apndIsAppendvfsDatabase(sqlite3_int64 sz, sqlite3_file *pFile){
-  int rc;
-  char zHdr[16];
-  sqlite3_int64 iMark = apndReadMark(sz, pFile);
-  if( iMark>=0 ){
-    /* If file has the correct end-marker, the expected odd size, and the
-    ** SQLite DB type marker where the end-marker puts it, then it
-    ** is an appendvfs database.
-    */
-    rc = pFile->pMethods->xRead(pFile, zHdr, sizeof(zHdr), iMark);
-    if( SQLITE_OK==rc
-     && memcmp(zHdr, apvfsSqliteHdr, sizeof(zHdr))==0
-     && (sz & 0x1ff) == APND_MARK_SIZE
-     && sz>=512+APND_MARK_SIZE
-    ){
-      return 1; /* It's an appendvfs database */
-    }
-  }
-  return 0;
-}
-
-/*
-** Check to see if the file is an ordinary SQLite database file.
-** Return true iff so. Parameter sz is the file's size.
-*/
-static int apndIsOrdinaryDatabaseFile(sqlite3_int64 sz, sqlite3_file *pFile){
-  char zHdr[16];
-  if( apndIsAppendvfsDatabase(sz, pFile) /* rule 2 */
-   || (sz & 0x1ff) != 0
-   || SQLITE_OK!=pFile->pMethods->xRead(pFile, zHdr, sizeof(zHdr), 0)
-   || memcmp(zHdr, apvfsSqliteHdr, sizeof(zHdr))!=0
-  ){
-    return 0;
-  }else{
-    return 1;
-  }
-}
-
-/*
-** Open an apnd file handle.
-*/
-static int apndOpen(
-  sqlite3_vfs *pApndVfs,
-  const char *zName,
-  sqlite3_file *pFile,
-  int flags,
-  int *pOutFlags
-){
-  ApndFile *pApndFile = (ApndFile*)pFile;
-  sqlite3_file *pBaseFile = ORIGFILE(pFile);
-  sqlite3_vfs *pBaseVfs = ORIGVFS(pApndVfs);
-  int rc;
-  sqlite3_int64 sz = 0;
-  if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){
-    /* The appendvfs is not to be used for transient or temporary databases.
-    ** Just use the base VFS open to initialize the given file object and
-    ** open the underlying file. (Appendvfs is then unused for this file.)
-    */
-    return pBaseVfs->xOpen(pBaseVfs, zName, pFile, flags, pOutFlags);
-  }
-  memset(pApndFile, 0, sizeof(ApndFile));
-  pFile->pMethods = &apnd_io_methods;
-  pApndFile->iMark = -1;    /* Append mark not yet written */
-
-  rc = pBaseVfs->xOpen(pBaseVfs, zName, pBaseFile, flags, pOutFlags);
-  if( rc==SQLITE_OK ){
-    rc = pBaseFile->pMethods->xFileSize(pBaseFile, &sz);
-    if( rc ){
-      pBaseFile->pMethods->xClose(pBaseFile);
-    }
-  }
-  if( rc ){
-    pFile->pMethods = 0;
-    return rc;
-  }
-  if( apndIsOrdinaryDatabaseFile(sz, pBaseFile) ){
-    /* The file being opened appears to be just an ordinary DB. Copy
-    ** the base dispatch-table so this instance mimics the base VFS. 
-    */
-    memmove(pApndFile, pBaseFile, pBaseVfs->szOsFile);
-    return SQLITE_OK;
-  }
-  pApndFile->iPgOne = apndReadMark(sz, pFile);
-  if( pApndFile->iPgOne>=0 ){
-    pApndFile->iMark = sz - APND_MARK_SIZE; /* Append mark found */
-    return SQLITE_OK;
-  }
-  if( (flags & SQLITE_OPEN_CREATE)==0 ){
-    pBaseFile->pMethods->xClose(pBaseFile);
-    rc = SQLITE_CANTOPEN;
-    pFile->pMethods = 0;
-  }else{
-    /* Round newly added appendvfs location to #define'd page boundary. 
-    ** Note that nothing has yet been written to the underlying file.
-    ** The append mark will be written along with first content write.
-    ** Until then, paf->iMark value indicates it is not yet written.
-    */
-    pApndFile->iPgOne = APND_START_ROUNDUP(sz);
-  }
-  return rc;
-}
-
-/*
-** Delete an apnd file.
-** For an appendvfs, this could mean delete the appendvfs portion,
-** leaving the appendee as it was before it gained an appendvfs.
-** For now, this code deletes the underlying file too.
-*/
-static int apndDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
-  return ORIGVFS(pVfs)->xDelete(ORIGVFS(pVfs), zPath, dirSync);
-}
-
-/*
-** All other VFS methods are pass-thrus.
-*/
-static int apndAccess(
-  sqlite3_vfs *pVfs, 
-  const char *zPath, 
-  int flags, 
-  int *pResOut
-){
-  return ORIGVFS(pVfs)->xAccess(ORIGVFS(pVfs), zPath, flags, pResOut);
-}
-static int apndFullPathname(
-  sqlite3_vfs *pVfs, 
-  const char *zPath, 
-  int nOut, 
-  char *zOut
-){
-  return ORIGVFS(pVfs)->xFullPathname(ORIGVFS(pVfs),zPath,nOut,zOut);
-}
-static void *apndDlOpen(sqlite3_vfs *pVfs, const char *zPath){
-  return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath);
-}
-static void apndDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
-  ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg);
-}
-static void (*apndDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
-  return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym);
-}
-static void apndDlClose(sqlite3_vfs *pVfs, void *pHandle){
-  ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle);
-}
-static int apndRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
-  return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut);
-}
-static int apndSleep(sqlite3_vfs *pVfs, int nMicro){
-  return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro);
-}
-static int apndCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
-  return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut);
-}
-static int apndGetLastError(sqlite3_vfs *pVfs, int a, char *b){
-  return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b);
-}
-static int apndCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
-  return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p);
-}
-static int apndSetSystemCall(
-  sqlite3_vfs *pVfs,
-  const char *zName,
-  sqlite3_syscall_ptr pCall
-){
-  return ORIGVFS(pVfs)->xSetSystemCall(ORIGVFS(pVfs),zName,pCall);
-}
-static sqlite3_syscall_ptr apndGetSystemCall(
-  sqlite3_vfs *pVfs,
-  const char *zName
-){
-  return ORIGVFS(pVfs)->xGetSystemCall(ORIGVFS(pVfs),zName);
-}
-static const char *apndNextSystemCall(sqlite3_vfs *pVfs, const char *zName){
-  return ORIGVFS(pVfs)->xNextSystemCall(ORIGVFS(pVfs), zName);
-}
-
-  
-#ifdef _WIN32
-
-#endif
-/* 
-** This routine is called when the extension is loaded.
-** Register the new VFS.
-*/
-int sqlite3_appendvfs_init(
-  sqlite3 *db, 
-  char **pzErrMsg, 
-  const sqlite3_api_routines *pApi
-){
-  int rc = SQLITE_OK;
-  sqlite3_vfs *pOrig;
-  SQLITE_EXTENSION_INIT2(pApi);
-  (void)pzErrMsg;
-  (void)db;
-  pOrig = sqlite3_vfs_find(0);
-  if( pOrig==0 ) return SQLITE_ERROR;
-  apnd_vfs.iVersion = pOrig->iVersion;
-  apnd_vfs.pAppData = pOrig;
-  apnd_vfs.szOsFile = pOrig->szOsFile + sizeof(ApndFile);
-  rc = sqlite3_vfs_register(&apnd_vfs, 0);
-#ifdef APPENDVFS_TEST
-  if( rc==SQLITE_OK ){
-    rc = sqlite3_auto_extension((void(*)(void))apndvfsRegister);
-  }
-#endif
-  if( rc==SQLITE_OK ) rc = SQLITE_OK_LOAD_PERMANENTLY;
-  return rc;
-}
-
-/************************* End ../ext/misc/appendvfs.c ********************/
-/************************* Begin ../ext/misc/memtrace.c ******************/
-/*
-** 2019-01-21
-**
-** The author disclaims copyright to this source code.  In place of
-** a legal notice, here is a blessing:
-**
-**    May you do good and not evil.
-**    May you find forgiveness for yourself and forgive others.
-**    May you share freely, never taking more than you give.
-**
-*************************************************************************
-**
-** This file implements an extension that uses the SQLITE_CONFIG_MALLOC
-** mechanism to add a tracing layer on top of SQLite.  If this extension
-** is registered prior to sqlite3_initialize(), it will cause all memory
-** allocation activities to be logged on standard output, or to some other
-** FILE specified by the initializer.
-**
-** This file needs to be compiled into the application that uses it.
-**
-** This extension is used to implement the --memtrace option of the
-** command-line shell.
-*/
-#include <assert.h>
-#include <string.h>
-#include <stdio.h>
-
-/* The original memory allocation routines */
-static sqlite3_mem_methods memtraceBase;
-static FILE *memtraceOut;
-
-/* Methods that trace memory allocations */
-static void *memtraceMalloc(int n){
-  if( memtraceOut ){
-    fprintf(memtraceOut, "MEMTRACE: allocate %d bytes\n", 
-            memtraceBase.xRoundup(n));
-  }
-  return memtraceBase.xMalloc(n);
-}
-static void memtraceFree(void *p){
-  if( p==0 ) return;
-  if( memtraceOut ){
-    fprintf(memtraceOut, "MEMTRACE: free %d bytes\n", memtraceBase.xSize(p));
-  }
-  memtraceBase.xFree(p);
-}
-static void *memtraceRealloc(void *p, int n){
-  if( p==0 ) return memtraceMalloc(n);
-  if( n==0 ){
-    memtraceFree(p);
-    return 0;
-  }
-  if( memtraceOut ){
-    fprintf(memtraceOut, "MEMTRACE: resize %d -> %d bytes\n",
-            memtraceBase.xSize(p), memtraceBase.xRoundup(n));
-  }
-  return memtraceBase.xRealloc(p, n);
-}
-static int memtraceSize(void *p){
-  return memtraceBase.xSize(p);
-}
-static int memtraceRoundup(int n){
-  return memtraceBase.xRoundup(n);
-}
-static int memtraceInit(void *p){
-  return memtraceBase.xInit(p);
-}
-static void memtraceShutdown(void *p){
-  memtraceBase.xShutdown(p);
-}
-
-/* The substitute memory allocator */
-static sqlite3_mem_methods ersaztMethods = {
-  memtraceMalloc,
-  memtraceFree,
-  memtraceRealloc,
-  memtraceSize,
-  memtraceRoundup,
-  memtraceInit,
-  memtraceShutdown,
-  0
-};
-
-/* Begin tracing memory allocations to out. */
-int sqlite3MemTraceActivate(FILE *out){
-  int rc = SQLITE_OK;
-  if( memtraceBase.xMalloc==0 ){
-    rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memtraceBase);
-    if( rc==SQLITE_OK ){
-      rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &ersaztMethods);
-    }
-  }
-  memtraceOut = out;
-  return rc;
-}
-
-/* Deactivate memory tracing */
-int sqlite3MemTraceDeactivate(void){
-  int rc = SQLITE_OK;
-  if( memtraceBase.xMalloc!=0 ){
-    rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memtraceBase);
-    if( rc==SQLITE_OK ){
-      memset(&memtraceBase, 0, sizeof(memtraceBase));
-    }
-  }
-  memtraceOut = 0;
-  return rc;
-}
-
-/************************* End ../ext/misc/memtrace.c ********************/
 /************************* Begin ../ext/misc/uint.c ******************/
 /*
 ** 2020-04-14
@@ -5340,7 +3160,11 @@
     e += 1075;
     if( e<=0 ){
       /* Subnormal */
-      m >>= 1-e;
+      if( 1-e >= 64 ){
+        m = 0;
+      }else{
+        m >>= 1-e;
+      }
       e = 0;
     }else if( e>0x7ff ){
       e = 0x7ff;
@@ -5426,7 +3250,7 @@
   SQLITE_EXTENSION_INIT2(pApi);
   (void)pzErrMsg;  /* Unused parameter */
   for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
-    rc = sqlite3_create_function(db, aFunc[i].zFName, aFunc[i].nArg,	
+    rc = sqlite3_create_function(db, aFunc[i].zFName, aFunc[i].nArg,
                                SQLITE_UTF8|SQLITE_INNOCUOUS,
                                (void*)&aFunc[i].iAux,
                                aFunc[i].xFunc, 0, 0);
@@ -5761,11 +3585,12 @@
 **  (8)  output in descending order
 */
 static int seriesBestIndex(
-  sqlite3_vtab *tabUnused,
+  sqlite3_vtab *pVTab,
   sqlite3_index_info *pIdxInfo
 ){
   int i, j;              /* Loop over constraints */
   int idxNum = 0;        /* The query plan bitmask */
+  int bStartSeen = 0;    /* EQ constraint seen on the START column */
   int unusableMask = 0;  /* Mask of unusable constraints */
   int nArg = 0;          /* Number of arguments that seriesFilter() expects */
   int aIdx[3];           /* Constraints on start, stop, and step */
@@ -5775,7 +3600,7 @@
   ** are the last three columns in the virtual table. */
   assert( SERIES_COLUMN_STOP == SERIES_COLUMN_START+1 );
   assert( SERIES_COLUMN_STEP == SERIES_COLUMN_START+2 );
-  (void)tabUnused;
+
   aIdx[0] = aIdx[1] = aIdx[2] = -1;
   pConstraint = pIdxInfo->aConstraint;
   for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
@@ -5785,6 +3610,7 @@
     iCol = pConstraint->iColumn - SERIES_COLUMN_START;
     assert( iCol>=0 && iCol<=2 );
     iMask = 1 << iCol;
+    if( iCol==0 ) bStartSeen = 1;
     if( pConstraint->usable==0 ){
       unusableMask |=  iMask;
       continue;
@@ -5799,6 +3625,18 @@
       pIdxInfo->aConstraintUsage[j].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY;
     }
   }
+  /* The current generate_column() implementation requires at least one
+  ** argument (the START value).  Legacy versions assumed START=0 if the
+  ** first argument was omitted.  Compile with -DZERO_ARGUMENT_GENERATE_SERIES
+  ** to obtain the legacy behavior */
+#ifndef ZERO_ARGUMENT_GENERATE_SERIES
+  if( !bStartSeen ){
+    sqlite3_free(pVTab->zErrMsg);
+    pVTab->zErrMsg = sqlite3_mprintf(
+        "first argument to \"generate_series()\" missing or unusable");
+    return SQLITE_ERROR;
+  }
+#endif
   if( (unusableMask & ~idxNum)!=0 ){
     /* The start, stop, and step columns are inputs.  Therefore if there
     ** are unusable constraints on any of start, stop, or step then
@@ -5810,7 +3648,7 @@
     ** the preferred case */
     pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0));
     pIdxInfo->estimatedRows = 1000;
-    if( pIdxInfo->nOrderBy==1 ){
+    if( pIdxInfo->nOrderBy>=1 && pIdxInfo->aOrderBy[0].iColumn==0 ){
       if( pIdxInfo->aOrderBy[0].desc ){
         idxNum |= 8;
       }else{
@@ -5872,7 +3710,7 @@
   int rc = SQLITE_OK;
   SQLITE_EXTENSION_INIT2(pApi);
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-  if( sqlite3_libversion_number()<3008012 ){
+  if( sqlite3_libversion_number()<3008012 && pzErrMsg!=0 ){
     *pzErrMsg = sqlite3_mprintf(
         "generate_series() requires SQLite 3.8.12 or later");
     return SQLITE_ERROR;
@@ -6185,9 +4023,9 @@
         }
         case RE_OP_CC_EXC: {
           if( c==0 ) break;
-          /* fall-through */
+          /* fall-through */ goto re_op_cc_inc;
         }
-        case RE_OP_CC_INC: {
+        case RE_OP_CC_INC: re_op_cc_inc: {
           int j = 1;
           int n = pRe->aArg[x];
           int hit = 0;
@@ -6571,7 +4409,7 @@
         pRe->zInit[j++] = (unsigned char)(0xc0 | (x>>6));
         pRe->zInit[j++] = 0x80 | (x&0x3f);
       }else if( x<=0xffff ){
-        pRe->zInit[j++] = (unsigned char)(0xd0 | (x>>12));
+        pRe->zInit[j++] = (unsigned char)(0xe0 | (x>>12));
         pRe->zInit[j++] = 0x80 | ((x>>6)&0x3f);
         pRe->zInit[j++] = 0x80 | (x&0x3f);
       }else{
@@ -6645,18 +4483,2234 @@
   int rc = SQLITE_OK;
   SQLITE_EXTENSION_INIT2(pApi);
   (void)pzErrMsg;  /* Unused */
-  rc = sqlite3_create_function(db, "regexp", 2, SQLITE_UTF8|SQLITE_INNOCUOUS,
-                               0, re_sql_func, 0, 0);
+  rc = sqlite3_create_function(db, "regexp", 2, 
+                            SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
+                            0, re_sql_func, 0, 0);
   if( rc==SQLITE_OK ){
     /* The regexpi(PATTERN,STRING) function is a case-insensitive version
     ** of regexp(PATTERN,STRING). */
-    rc = sqlite3_create_function(db, "regexpi", 2, SQLITE_UTF8|SQLITE_INNOCUOUS,
-                                 (void*)db, re_sql_func, 0, 0);
+    rc = sqlite3_create_function(db, "regexpi", 2,
+                            SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
+                            (void*)db, re_sql_func, 0, 0);
   }
   return rc;
 }
 
 /************************* End ../ext/misc/regexp.c ********************/
+#ifndef SQLITE_SHELL_WASM_MODE
+/************************* Begin ../ext/misc/fileio.c ******************/
+/*
+** 2014-06-13
+**
+** The author disclaims copyright to this source code.  In place of
+** a legal notice, here is a blessing:
+**
+**    May you do good and not evil.
+**    May you find forgiveness for yourself and forgive others.
+**    May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This SQLite extension implements SQL functions readfile() and
+** writefile(), and eponymous virtual type "fsdir".
+**
+** WRITEFILE(FILE, DATA [, MODE [, MTIME]]):
+**
+**   If neither of the optional arguments is present, then this UDF
+**   function writes blob DATA to file FILE. If successful, the number
+**   of bytes written is returned. If an error occurs, NULL is returned.
+**
+**   If the first option argument - MODE - is present, then it must
+**   be passed an integer value that corresponds to a POSIX mode
+**   value (file type + permissions, as returned in the stat.st_mode
+**   field by the stat() system call). Three types of files may
+**   be written/created:
+**
+**     regular files:  (mode & 0170000)==0100000
+**     symbolic links: (mode & 0170000)==0120000
+**     directories:    (mode & 0170000)==0040000
+**
+**   For a directory, the DATA is ignored. For a symbolic link, it is
+**   interpreted as text and used as the target of the link. For a
+**   regular file, it is interpreted as a blob and written into the
+**   named file. Regardless of the type of file, its permissions are
+**   set to (mode & 0777) before returning.
+**
+**   If the optional MTIME argument is present, then it is interpreted
+**   as an integer - the number of seconds since the unix epoch. The
+**   modification-time of the target file is set to this value before
+**   returning.
+**
+**   If three or more arguments are passed to this function and an
+**   error is encountered, an exception is raised.
+**
+** READFILE(FILE):
+**
+**   Read and return the contents of file FILE (type blob) from disk.
+**
+** FSDIR:
+**
+**   Used as follows:
+**
+**     SELECT * FROM fsdir($path [, $dir]);
+**
+**   Parameter $path is an absolute or relative pathname. If the file that it
+**   refers to does not exist, it is an error. If the path refers to a regular
+**   file or symbolic link, it returns a single row. Or, if the path refers
+**   to a directory, it returns one row for the directory, and one row for each
+**   file within the hierarchy rooted at $path.
+**
+**   Each row has the following columns:
+**
+**     name:  Path to file or directory (text value).
+**     mode:  Value of stat.st_mode for directory entry (an integer).
+**     mtime: Value of stat.st_mtime for directory entry (an integer).
+**     data:  For a regular file, a blob containing the file data. For a
+**            symlink, a text value containing the text of the link. For a
+**            directory, NULL.
+**
+**   If a non-NULL value is specified for the optional $dir parameter and
+**   $path is a relative path, then $path is interpreted relative to $dir. 
+**   And the paths returned in the "name" column of the table are also 
+**   relative to directory $dir.
+**
+** Notes on building this extension for Windows:
+**   Unless linked statically with the SQLite library, a preprocessor
+**   symbol, FILEIO_WIN32_DLL, must be #define'd to create a stand-alone
+**   DLL form of this extension for WIN32. See its use below for details.
+*/
+/* #include "sqlite3ext.h" */
+SQLITE_EXTENSION_INIT1
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#if !defined(_WIN32) && !defined(WIN32)
+#  include <unistd.h>
+#  include <dirent.h>
+#  include <utime.h>
+#  include <sys/time.h>
+#else
+#  include "windows.h"
+#  include <io.h>
+#  include <direct.h>
+/* #  include "test_windirent.h" */
+#  define dirent DIRENT
+#  ifndef chmod
+#    define chmod _chmod
+#  endif
+#  ifndef stat
+#    define stat _stat
+#  endif
+#  define mkdir(path,mode) _mkdir(path)
+#  define lstat(path,buf) stat(path,buf)
+#endif
+#include <time.h>
+#include <errno.h>
+
+
+/*
+** Structure of the fsdir() table-valued function
+*/
+                 /*    0    1    2     3    4           5             */
+#define FSDIR_SCHEMA "(name,mode,mtime,data,path HIDDEN,dir HIDDEN)"
+#define FSDIR_COLUMN_NAME     0     /* Name of the file */
+#define FSDIR_COLUMN_MODE     1     /* Access mode */
+#define FSDIR_COLUMN_MTIME    2     /* Last modification time */
+#define FSDIR_COLUMN_DATA     3     /* File content */
+#define FSDIR_COLUMN_PATH     4     /* Path to top of search */
+#define FSDIR_COLUMN_DIR      5     /* Path is relative to this directory */
+
+
+/*
+** Set the result stored by context ctx to a blob containing the 
+** contents of file zName.  Or, leave the result unchanged (NULL)
+** if the file does not exist or is unreadable.
+**
+** If the file exceeds the SQLite blob size limit, through an
+** SQLITE_TOOBIG error.
+**
+** Throw an SQLITE_IOERR if there are difficulties pulling the file
+** off of disk.
+*/
+static void readFileContents(sqlite3_context *ctx, const char *zName){
+  FILE *in;
+  sqlite3_int64 nIn;
+  void *pBuf;
+  sqlite3 *db;
+  int mxBlob;
+
+  in = fopen(zName, "rb");
+  if( in==0 ){
+    /* File does not exist or is unreadable. Leave the result set to NULL. */
+    return;
+  }
+  fseek(in, 0, SEEK_END);
+  nIn = ftell(in);
+  rewind(in);
+  db = sqlite3_context_db_handle(ctx);
+  mxBlob = sqlite3_limit(db, SQLITE_LIMIT_LENGTH, -1);
+  if( nIn>mxBlob ){
+    sqlite3_result_error_code(ctx, SQLITE_TOOBIG);
+    fclose(in);
+    return;
+  }
+  pBuf = sqlite3_malloc64( nIn ? nIn : 1 );
+  if( pBuf==0 ){
+    sqlite3_result_error_nomem(ctx);
+    fclose(in);
+    return;
+  }
+  if( nIn==(sqlite3_int64)fread(pBuf, 1, (size_t)nIn, in) ){
+    sqlite3_result_blob64(ctx, pBuf, nIn, sqlite3_free);
+  }else{
+    sqlite3_result_error_code(ctx, SQLITE_IOERR);
+    sqlite3_free(pBuf);
+  }
+  fclose(in);
+}
+
+/*
+** Implementation of the "readfile(X)" SQL function.  The entire content
+** of the file named X is read and returned as a BLOB.  NULL is returned
+** if the file does not exist or is unreadable.
+*/
+static void readfileFunc(
+  sqlite3_context *context,
+  int argc,
+  sqlite3_value **argv
+){
+  const char *zName;
+  (void)(argc);  /* Unused parameter */
+  zName = (const char*)sqlite3_value_text(argv[0]);
+  if( zName==0 ) return;
+  readFileContents(context, zName);
+}
+
+/*
+** Set the error message contained in context ctx to the results of
+** vprintf(zFmt, ...).
+*/
+static void ctxErrorMsg(sqlite3_context *ctx, const char *zFmt, ...){
+  char *zMsg = 0;
+  va_list ap;
+  va_start(ap, zFmt);
+  zMsg = sqlite3_vmprintf(zFmt, ap);
+  sqlite3_result_error(ctx, zMsg, -1);
+  sqlite3_free(zMsg);
+  va_end(ap);
+}
+
+#if defined(_WIN32)
+/*
+** This function is designed to convert a Win32 FILETIME structure into the
+** number of seconds since the Unix Epoch (1970-01-01 00:00:00 UTC).
+*/
+static sqlite3_uint64 fileTimeToUnixTime(
+  LPFILETIME pFileTime
+){
+  SYSTEMTIME epochSystemTime;
+  ULARGE_INTEGER epochIntervals;
+  FILETIME epochFileTime;
+  ULARGE_INTEGER fileIntervals;
+
+  memset(&epochSystemTime, 0, sizeof(SYSTEMTIME));
+  epochSystemTime.wYear = 1970;
+  epochSystemTime.wMonth = 1;
+  epochSystemTime.wDay = 1;
+  SystemTimeToFileTime(&epochSystemTime, &epochFileTime);
+  epochIntervals.LowPart = epochFileTime.dwLowDateTime;
+  epochIntervals.HighPart = epochFileTime.dwHighDateTime;
+
+  fileIntervals.LowPart = pFileTime->dwLowDateTime;
+  fileIntervals.HighPart = pFileTime->dwHighDateTime;
+
+  return (fileIntervals.QuadPart - epochIntervals.QuadPart) / 10000000;
+}
+
+
+#if defined(FILEIO_WIN32_DLL) && (defined(_WIN32) || defined(WIN32))
+#  /* To allow a standalone DLL, use this next replacement function: */
+#  undef sqlite3_win32_utf8_to_unicode
+#  define sqlite3_win32_utf8_to_unicode utf8_to_utf16
+#
+LPWSTR utf8_to_utf16(const char *z){
+  int nAllot = MultiByteToWideChar(CP_UTF8, 0, z, -1, NULL, 0);
+  LPWSTR rv = sqlite3_malloc(nAllot * sizeof(WCHAR));
+  if( rv!=0 && 0 < MultiByteToWideChar(CP_UTF8, 0, z, -1, rv, nAllot) )
+    return rv;
+  sqlite3_free(rv);
+  return 0;
+}
+#endif
+
+/*
+** This function attempts to normalize the time values found in the stat()
+** buffer to UTC.  This is necessary on Win32, where the runtime library
+** appears to return these values as local times.
+*/
+static void statTimesToUtc(
+  const char *zPath,
+  struct stat *pStatBuf
+){
+  HANDLE hFindFile;
+  WIN32_FIND_DATAW fd;
+  LPWSTR zUnicodeName;
+  extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
+  zUnicodeName = sqlite3_win32_utf8_to_unicode(zPath);
+  if( zUnicodeName ){
+    memset(&fd, 0, sizeof(WIN32_FIND_DATAW));
+    hFindFile = FindFirstFileW(zUnicodeName, &fd);
+    if( hFindFile!=NULL ){
+      pStatBuf->st_ctime = (time_t)fileTimeToUnixTime(&fd.ftCreationTime);
+      pStatBuf->st_atime = (time_t)fileTimeToUnixTime(&fd.ftLastAccessTime);
+      pStatBuf->st_mtime = (time_t)fileTimeToUnixTime(&fd.ftLastWriteTime);
+      FindClose(hFindFile);
+    }
+    sqlite3_free(zUnicodeName);
+  }
+}
+#endif
+
+/*
+** This function is used in place of stat().  On Windows, special handling
+** is required in order for the included time to be returned as UTC.  On all
+** other systems, this function simply calls stat().
+*/
+static int fileStat(
+  const char *zPath,
+  struct stat *pStatBuf
+){
+#if defined(_WIN32)
+  int rc = stat(zPath, pStatBuf);
+  if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
+  return rc;
+#else
+  return stat(zPath, pStatBuf);
+#endif
+}
+
+/*
+** This function is used in place of lstat().  On Windows, special handling
+** is required in order for the included time to be returned as UTC.  On all
+** other systems, this function simply calls lstat().
+*/
+static int fileLinkStat(
+  const char *zPath,
+  struct stat *pStatBuf
+){
+#if defined(_WIN32)
+  int rc = lstat(zPath, pStatBuf);
+  if( rc==0 ) statTimesToUtc(zPath, pStatBuf);
+  return rc;
+#else
+  return lstat(zPath, pStatBuf);
+#endif
+}
+
+/*
+** Argument zFile is the name of a file that will be created and/or written
+** by SQL function writefile(). This function ensures that the directory
+** zFile will be written to exists, creating it if required. The permissions
+** for any path components created by this function are set in accordance
+** with the current umask.
+**
+** If an OOM condition is encountered, SQLITE_NOMEM is returned. Otherwise,
+** SQLITE_OK is returned if the directory is successfully created, or
+** SQLITE_ERROR otherwise.
+*/
+static int makeDirectory(
+  const char *zFile
+){
+  char *zCopy = sqlite3_mprintf("%s", zFile);
+  int rc = SQLITE_OK;
+
+  if( zCopy==0 ){
+    rc = SQLITE_NOMEM;
+  }else{
+    int nCopy = (int)strlen(zCopy);
+    int i = 1;
+
+    while( rc==SQLITE_OK ){
+      struct stat sStat;
+      int rc2;
+
+      for(; zCopy[i]!='/' && i<nCopy; i++);
+      if( i==nCopy ) break;
+      zCopy[i] = '\0';
+
+      rc2 = fileStat(zCopy, &sStat);
+      if( rc2!=0 ){
+        if( mkdir(zCopy, 0777) ) rc = SQLITE_ERROR;
+      }else{
+        if( !S_ISDIR(sStat.st_mode) ) rc = SQLITE_ERROR;
+      }
+      zCopy[i] = '/';
+      i++;
+    }
+
+    sqlite3_free(zCopy);
+  }
+
+  return rc;
+}
+
+/*
+** This function does the work for the writefile() UDF. Refer to 
+** header comments at the top of this file for details.
+*/
+static int writeFile(
+  sqlite3_context *pCtx,          /* Context to return bytes written in */
+  const char *zFile,              /* File to write */
+  sqlite3_value *pData,           /* Data to write */
+  mode_t mode,                    /* MODE parameter passed to writefile() */
+  sqlite3_int64 mtime             /* MTIME parameter (or -1 to not set time) */
+){
+  if( zFile==0 ) return 1;
+#if !defined(_WIN32) && !defined(WIN32)
+  if( S_ISLNK(mode) ){
+    const char *zTo = (const char*)sqlite3_value_text(pData);
+    if( zTo==0 || symlink(zTo, zFile)<0 ) return 1;
+  }else
+#endif
+  {
+    if( S_ISDIR(mode) ){
+      if( mkdir(zFile, mode) ){
+        /* The mkdir() call to create the directory failed. This might not
+        ** be an error though - if there is already a directory at the same
+        ** path and either the permissions already match or can be changed
+        ** to do so using chmod(), it is not an error.  */
+        struct stat sStat;
+        if( errno!=EEXIST
+         || 0!=fileStat(zFile, &sStat)
+         || !S_ISDIR(sStat.st_mode)
+         || ((sStat.st_mode&0777)!=(mode&0777) && 0!=chmod(zFile, mode&0777))
+        ){
+          return 1;
+        }
+      }
+    }else{
+      sqlite3_int64 nWrite = 0;
+      const char *z;
+      int rc = 0;
+      FILE *out = fopen(zFile, "wb");
+      if( out==0 ) return 1;
+      z = (const char*)sqlite3_value_blob(pData);
+      if( z ){
+        sqlite3_int64 n = fwrite(z, 1, sqlite3_value_bytes(pData), out);
+        nWrite = sqlite3_value_bytes(pData);
+        if( nWrite!=n ){
+          rc = 1;
+        }
+      }
+      fclose(out);
+      if( rc==0 && mode && chmod(zFile, mode & 0777) ){
+        rc = 1;
+      }
+      if( rc ) return 2;
+      sqlite3_result_int64(pCtx, nWrite);
+    }
+  }
+
+  if( mtime>=0 ){
+#if defined(_WIN32)
+#if !SQLITE_OS_WINRT
+    /* Windows */
+    FILETIME lastAccess;
+    FILETIME lastWrite;
+    SYSTEMTIME currentTime;
+    LONGLONG intervals;
+    HANDLE hFile;
+    LPWSTR zUnicodeName;
+    extern LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
+
+    GetSystemTime(&currentTime);
+    SystemTimeToFileTime(&currentTime, &lastAccess);
+    intervals = Int32x32To64(mtime, 10000000) + 116444736000000000;
+    lastWrite.dwLowDateTime = (DWORD)intervals;
+    lastWrite.dwHighDateTime = intervals >> 32;
+    zUnicodeName = sqlite3_win32_utf8_to_unicode(zFile);
+    if( zUnicodeName==0 ){
+      return 1;
+    }
+    hFile = CreateFileW(
+      zUnicodeName, FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING,
+      FILE_FLAG_BACKUP_SEMANTICS, NULL
+    );
+    sqlite3_free(zUnicodeName);
+    if( hFile!=INVALID_HANDLE_VALUE ){
+      BOOL bResult = SetFileTime(hFile, NULL, &lastAccess, &lastWrite);
+      CloseHandle(hFile);
+      return !bResult;
+    }else{
+      return 1;
+    }
+#endif
+#elif defined(AT_FDCWD) && 0 /* utimensat() is not universally available */
+    /* Recent unix */
+    struct timespec times[2];
+    times[0].tv_nsec = times[1].tv_nsec = 0;
+    times[0].tv_sec = time(0);
+    times[1].tv_sec = mtime;
+    if( utimensat(AT_FDCWD, zFile, times, AT_SYMLINK_NOFOLLOW) ){
+      return 1;
+    }
+#else
+    /* Legacy unix */
+    struct timeval times[2];
+    times[0].tv_usec = times[1].tv_usec = 0;
+    times[0].tv_sec = time(0);
+    times[1].tv_sec = mtime;
+    if( utimes(zFile, times) ){
+      return 1;
+    }
+#endif
+  }
+
+  return 0;
+}
+
+/*
+** Implementation of the "writefile(W,X[,Y[,Z]]])" SQL function.  
+** Refer to header comments at the top of this file for details.
+*/
+static void writefileFunc(
+  sqlite3_context *context,
+  int argc,
+  sqlite3_value **argv
+){
+  const char *zFile;
+  mode_t mode = 0;
+  int res;
+  sqlite3_int64 mtime = -1;
+
+  if( argc<2 || argc>4 ){
+    sqlite3_result_error(context, 
+        "wrong number of arguments to function writefile()", -1
+    );
+    return;
+  }
+
+  zFile = (const char*)sqlite3_value_text(argv[0]);
+  if( zFile==0 ) return;
+  if( argc>=3 ){
+    mode = (mode_t)sqlite3_value_int(argv[2]);
+  }
+  if( argc==4 ){
+    mtime = sqlite3_value_int64(argv[3]);
+  }
+
+  res = writeFile(context, zFile, argv[1], mode, mtime);
+  if( res==1 && errno==ENOENT ){
+    if( makeDirectory(zFile)==SQLITE_OK ){
+      res = writeFile(context, zFile, argv[1], mode, mtime);
+    }
+  }
+
+  if( argc>2 && res!=0 ){
+    if( S_ISLNK(mode) ){
+      ctxErrorMsg(context, "failed to create symlink: %s", zFile);
+    }else if( S_ISDIR(mode) ){
+      ctxErrorMsg(context, "failed to create directory: %s", zFile);
+    }else{
+      ctxErrorMsg(context, "failed to write file: %s", zFile);
+    }
+  }
+}
+
+/*
+** SQL function:   lsmode(MODE)
+**
+** Given a numberic st_mode from stat(), convert it into a human-readable
+** text string in the style of "ls -l".
+*/
+static void lsModeFunc(
+  sqlite3_context *context,
+  int argc,
+  sqlite3_value **argv
+){
+  int i;
+  int iMode = sqlite3_value_int(argv[0]);
+  char z[16];
+  (void)argc;
+  if( S_ISLNK(iMode) ){
+    z[0] = 'l';
+  }else if( S_ISREG(iMode) ){
+    z[0] = '-';
+  }else if( S_ISDIR(iMode) ){
+    z[0] = 'd';
+  }else{
+    z[0] = '?';
+  }
+  for(i=0; i<3; i++){
+    int m = (iMode >> ((2-i)*3));
+    char *a = &z[1 + i*3];
+    a[0] = (m & 0x4) ? 'r' : '-';
+    a[1] = (m & 0x2) ? 'w' : '-';
+    a[2] = (m & 0x1) ? 'x' : '-';
+  }
+  z[10] = '\0';
+  sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT);
+}
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+
+/* 
+** Cursor type for recursively iterating through a directory structure.
+*/
+typedef struct fsdir_cursor fsdir_cursor;
+typedef struct FsdirLevel FsdirLevel;
+
+struct FsdirLevel {
+  DIR *pDir;                 /* From opendir() */
+  char *zDir;                /* Name of directory (nul-terminated) */
+};
+
+struct fsdir_cursor {
+  sqlite3_vtab_cursor base;  /* Base class - must be first */
+
+  int nLvl;                  /* Number of entries in aLvl[] array */
+  int iLvl;                  /* Index of current entry */
+  FsdirLevel *aLvl;          /* Hierarchy of directories being traversed */
+
+  const char *zBase;
+  int nBase;
+
+  struct stat sStat;         /* Current lstat() results */
+  char *zPath;               /* Path to current entry */
+  sqlite3_int64 iRowid;      /* Current rowid */
+};
+
+typedef struct fsdir_tab fsdir_tab;
+struct fsdir_tab {
+  sqlite3_vtab base;         /* Base class - must be first */
+};
+
+/*
+** Construct a new fsdir virtual table object.
+*/
+static int fsdirConnect(
+  sqlite3 *db,
+  void *pAux,
+  int argc, const char *const*argv,
+  sqlite3_vtab **ppVtab,
+  char **pzErr
+){
+  fsdir_tab *pNew = 0;
+  int rc;
+  (void)pAux;
+  (void)argc;
+  (void)argv;
+  (void)pzErr;
+  rc = sqlite3_declare_vtab(db, "CREATE TABLE x" FSDIR_SCHEMA);
+  if( rc==SQLITE_OK ){
+    pNew = (fsdir_tab*)sqlite3_malloc( sizeof(*pNew) );
+    if( pNew==0 ) return SQLITE_NOMEM;
+    memset(pNew, 0, sizeof(*pNew));
+    sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY);
+  }
+  *ppVtab = (sqlite3_vtab*)pNew;
+  return rc;
+}
+
+/*
+** This method is the destructor for fsdir vtab objects.
+*/
+static int fsdirDisconnect(sqlite3_vtab *pVtab){
+  sqlite3_free(pVtab);
+  return SQLITE_OK;
+}
+
+/*
+** Constructor for a new fsdir_cursor object.
+*/
+static int fsdirOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
+  fsdir_cursor *pCur;
+  (void)p;
+  pCur = sqlite3_malloc( sizeof(*pCur) );
+  if( pCur==0 ) return SQLITE_NOMEM;
+  memset(pCur, 0, sizeof(*pCur));
+  pCur->iLvl = -1;
+  *ppCursor = &pCur->base;
+  return SQLITE_OK;
+}
+
+/*
+** Reset a cursor back to the state it was in when first returned
+** by fsdirOpen().
+*/
+static void fsdirResetCursor(fsdir_cursor *pCur){
+  int i;
+  for(i=0; i<=pCur->iLvl; i++){
+    FsdirLevel *pLvl = &pCur->aLvl[i];
+    if( pLvl->pDir ) closedir(pLvl->pDir);
+    sqlite3_free(pLvl->zDir);
+  }
+  sqlite3_free(pCur->zPath);
+  sqlite3_free(pCur->aLvl);
+  pCur->aLvl = 0;
+  pCur->zPath = 0;
+  pCur->zBase = 0;
+  pCur->nBase = 0;
+  pCur->nLvl = 0;
+  pCur->iLvl = -1;
+  pCur->iRowid = 1;
+}
+
+/*
+** Destructor for an fsdir_cursor.
+*/
+static int fsdirClose(sqlite3_vtab_cursor *cur){
+  fsdir_cursor *pCur = (fsdir_cursor*)cur;
+
+  fsdirResetCursor(pCur);
+  sqlite3_free(pCur);
+  return SQLITE_OK;
+}
+
+/*
+** Set the error message for the virtual table associated with cursor
+** pCur to the results of vprintf(zFmt, ...).
+*/
+static void fsdirSetErrmsg(fsdir_cursor *pCur, const char *zFmt, ...){
+  va_list ap;
+  va_start(ap, zFmt);
+  pCur->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap);
+  va_end(ap);
+}
+
+
+/*
+** Advance an fsdir_cursor to its next row of output.
+*/
+static int fsdirNext(sqlite3_vtab_cursor *cur){
+  fsdir_cursor *pCur = (fsdir_cursor*)cur;
+  mode_t m = pCur->sStat.st_mode;
+
+  pCur->iRowid++;
+  if( S_ISDIR(m) ){
+    /* Descend into this directory */
+    int iNew = pCur->iLvl + 1;
+    FsdirLevel *pLvl;
+    if( iNew>=pCur->nLvl ){
+      int nNew = iNew+1;
+      sqlite3_int64 nByte = nNew*sizeof(FsdirLevel);
+      FsdirLevel *aNew = (FsdirLevel*)sqlite3_realloc64(pCur->aLvl, nByte);
+      if( aNew==0 ) return SQLITE_NOMEM;
+      memset(&aNew[pCur->nLvl], 0, sizeof(FsdirLevel)*(nNew-pCur->nLvl));
+      pCur->aLvl = aNew;
+      pCur->nLvl = nNew;
+    }
+    pCur->iLvl = iNew;
+    pLvl = &pCur->aLvl[iNew];
+    
+    pLvl->zDir = pCur->zPath;
+    pCur->zPath = 0;
+    pLvl->pDir = opendir(pLvl->zDir);
+    if( pLvl->pDir==0 ){
+      fsdirSetErrmsg(pCur, "cannot read directory: %s", pCur->zPath);
+      return SQLITE_ERROR;
+    }
+  }
+
+  while( pCur->iLvl>=0 ){
+    FsdirLevel *pLvl = &pCur->aLvl[pCur->iLvl];
+    struct dirent *pEntry = readdir(pLvl->pDir);
+    if( pEntry ){
+      if( pEntry->d_name[0]=='.' ){
+       if( pEntry->d_name[1]=='.' && pEntry->d_name[2]=='\0' ) continue;
+       if( pEntry->d_name[1]=='\0' ) continue;
+      }
+      sqlite3_free(pCur->zPath);
+      pCur->zPath = sqlite3_mprintf("%s/%s", pLvl->zDir, pEntry->d_name);
+      if( pCur->zPath==0 ) return SQLITE_NOMEM;
+      if( fileLinkStat(pCur->zPath, &pCur->sStat) ){
+        fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath);
+        return SQLITE_ERROR;
+      }
+      return SQLITE_OK;
+    }
+    closedir(pLvl->pDir);
+    sqlite3_free(pLvl->zDir);
+    pLvl->pDir = 0;
+    pLvl->zDir = 0;
+    pCur->iLvl--;
+  }
+
+  /* EOF */
+  sqlite3_free(pCur->zPath);
+  pCur->zPath = 0;
+  return SQLITE_OK;
+}
+
+/*
+** Return values of columns for the row at which the series_cursor
+** is currently pointing.
+*/
+static int fsdirColumn(
+  sqlite3_vtab_cursor *cur,   /* The cursor */
+  sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
+  int i                       /* Which column to return */
+){
+  fsdir_cursor *pCur = (fsdir_cursor*)cur;
+  switch( i ){
+    case FSDIR_COLUMN_NAME: {
+      sqlite3_result_text(ctx, &pCur->zPath[pCur->nBase], -1, SQLITE_TRANSIENT);
+      break;
+    }
+
+    case FSDIR_COLUMN_MODE:
+      sqlite3_result_int64(ctx, pCur->sStat.st_mode);
+      break;
+
+    case FSDIR_COLUMN_MTIME:
+      sqlite3_result_int64(ctx, pCur->sStat.st_mtime);
+      break;
+
+    case FSDIR_COLUMN_DATA: {
+      mode_t m = pCur->sStat.st_mode;
+      if( S_ISDIR(m) ){
+        sqlite3_result_null(ctx);
+#if !defined(_WIN32) && !defined(WIN32)
+      }else if( S_ISLNK(m) ){
+        char aStatic[64];
+        char *aBuf = aStatic;
+        sqlite3_int64 nBuf = 64;
+        int n;
+
+        while( 1 ){
+          n = readlink(pCur->zPath, aBuf, nBuf);
+          if( n<nBuf ) break;
+          if( aBuf!=aStatic ) sqlite3_free(aBuf);
+          nBuf = nBuf*2;
+          aBuf = sqlite3_malloc64(nBuf);
+          if( aBuf==0 ){
+            sqlite3_result_error_nomem(ctx);
+            return SQLITE_NOMEM;
+          }
+        }
+
+        sqlite3_result_text(ctx, aBuf, n, SQLITE_TRANSIENT);
+        if( aBuf!=aStatic ) sqlite3_free(aBuf);
+#endif
+      }else{
+        readFileContents(ctx, pCur->zPath);
+      }
+    }
+    case FSDIR_COLUMN_PATH:
+    default: {
+      /* The FSDIR_COLUMN_PATH and FSDIR_COLUMN_DIR are input parameters.
+      ** always return their values as NULL */
+      break;
+    }
+  }
+  return SQLITE_OK;
+}
+
+/*
+** Return the rowid for the current row. In this implementation, the
+** first row returned is assigned rowid value 1, and each subsequent
+** row a value 1 more than that of the previous.
+*/
+static int fsdirRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
+  fsdir_cursor *pCur = (fsdir_cursor*)cur;
+  *pRowid = pCur->iRowid;
+  return SQLITE_OK;
+}
+
+/*
+** Return TRUE if the cursor has been moved off of the last
+** row of output.
+*/
+static int fsdirEof(sqlite3_vtab_cursor *cur){
+  fsdir_cursor *pCur = (fsdir_cursor*)cur;
+  return (pCur->zPath==0);
+}
+
+/*
+** xFilter callback.
+**
+** idxNum==1   PATH parameter only
+** idxNum==2   Both PATH and DIR supplied
+*/
+static int fsdirFilter(
+  sqlite3_vtab_cursor *cur, 
+  int idxNum, const char *idxStr,
+  int argc, sqlite3_value **argv
+){
+  const char *zDir = 0;
+  fsdir_cursor *pCur = (fsdir_cursor*)cur;
+  (void)idxStr;
+  fsdirResetCursor(pCur);
+
+  if( idxNum==0 ){
+    fsdirSetErrmsg(pCur, "table function fsdir requires an argument");
+    return SQLITE_ERROR;
+  }
+
+  assert( argc==idxNum && (argc==1 || argc==2) );
+  zDir = (const char*)sqlite3_value_text(argv[0]);
+  if( zDir==0 ){
+    fsdirSetErrmsg(pCur, "table function fsdir requires a non-NULL argument");
+    return SQLITE_ERROR;
+  }
+  if( argc==2 ){
+    pCur->zBase = (const char*)sqlite3_value_text(argv[1]);
+  }
+  if( pCur->zBase ){
+    pCur->nBase = (int)strlen(pCur->zBase)+1;
+    pCur->zPath = sqlite3_mprintf("%s/%s", pCur->zBase, zDir);
+  }else{
+    pCur->zPath = sqlite3_mprintf("%s", zDir);
+  }
+
+  if( pCur->zPath==0 ){
+    return SQLITE_NOMEM;
+  }
+  if( fileLinkStat(pCur->zPath, &pCur->sStat) ){
+    fsdirSetErrmsg(pCur, "cannot stat file: %s", pCur->zPath);
+    return SQLITE_ERROR;
+  }
+
+  return SQLITE_OK;
+}
+
+/*
+** SQLite will invoke this method one or more times while planning a query
+** that uses the generate_series virtual table.  This routine needs to create
+** a query plan for each invocation and compute an estimated cost for that
+** plan.
+**
+** In this implementation idxNum is used to represent the
+** query plan.  idxStr is unused.
+**
+** The query plan is represented by values of idxNum:
+**
+**  (1)  The path value is supplied by argv[0]
+**  (2)  Path is in argv[0] and dir is in argv[1]
+*/
+static int fsdirBestIndex(
+  sqlite3_vtab *tab,
+  sqlite3_index_info *pIdxInfo
+){
+  int i;                 /* Loop over constraints */
+  int idxPath = -1;      /* Index in pIdxInfo->aConstraint of PATH= */
+  int idxDir = -1;       /* Index in pIdxInfo->aConstraint of DIR= */
+  int seenPath = 0;      /* True if an unusable PATH= constraint is seen */
+  int seenDir = 0;       /* True if an unusable DIR= constraint is seen */
+  const struct sqlite3_index_constraint *pConstraint;
+
+  (void)tab;
+  pConstraint = pIdxInfo->aConstraint;
+  for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
+    if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
+    switch( pConstraint->iColumn ){
+      case FSDIR_COLUMN_PATH: {
+        if( pConstraint->usable ){
+          idxPath = i;
+          seenPath = 0;
+        }else if( idxPath<0 ){
+          seenPath = 1;
+        }
+        break;
+      }
+      case FSDIR_COLUMN_DIR: {
+        if( pConstraint->usable ){
+          idxDir = i;
+          seenDir = 0;
+        }else if( idxDir<0 ){
+          seenDir = 1;
+        }
+        break;
+      }
+    } 
+  }
+  if( seenPath || seenDir ){
+    /* If input parameters are unusable, disallow this plan */
+    return SQLITE_CONSTRAINT;
+  }
+
+  if( idxPath<0 ){
+    pIdxInfo->idxNum = 0;
+    /* The pIdxInfo->estimatedCost should have been initialized to a huge
+    ** number.  Leave it unchanged. */
+    pIdxInfo->estimatedRows = 0x7fffffff;
+  }else{
+    pIdxInfo->aConstraintUsage[idxPath].omit = 1;
+    pIdxInfo->aConstraintUsage[idxPath].argvIndex = 1;
+    if( idxDir>=0 ){
+      pIdxInfo->aConstraintUsage[idxDir].omit = 1;
+      pIdxInfo->aConstraintUsage[idxDir].argvIndex = 2;
+      pIdxInfo->idxNum = 2;
+      pIdxInfo->estimatedCost = 10.0;
+    }else{
+      pIdxInfo->idxNum = 1;
+      pIdxInfo->estimatedCost = 100.0;
+    }
+  }
+
+  return SQLITE_OK;
+}
+
+/*
+** Register the "fsdir" virtual table.
+*/
+static int fsdirRegister(sqlite3 *db){
+  static sqlite3_module fsdirModule = {
+    0,                         /* iVersion */
+    0,                         /* xCreate */
+    fsdirConnect,              /* xConnect */
+    fsdirBestIndex,            /* xBestIndex */
+    fsdirDisconnect,           /* xDisconnect */
+    0,                         /* xDestroy */
+    fsdirOpen,                 /* xOpen - open a cursor */
+    fsdirClose,                /* xClose - close a cursor */
+    fsdirFilter,               /* xFilter - configure scan constraints */
+    fsdirNext,                 /* xNext - advance a cursor */
+    fsdirEof,                  /* xEof - check for end of scan */
+    fsdirColumn,               /* xColumn - read data */
+    fsdirRowid,                /* xRowid - read data */
+    0,                         /* xUpdate */
+    0,                         /* xBegin */
+    0,                         /* xSync */
+    0,                         /* xCommit */
+    0,                         /* xRollback */
+    0,                         /* xFindMethod */
+    0,                         /* xRename */
+    0,                         /* xSavepoint */
+    0,                         /* xRelease */
+    0,                         /* xRollbackTo */
+    0,                         /* xShadowName */
+  };
+
+  int rc = sqlite3_create_module(db, "fsdir", &fsdirModule, 0);
+  return rc;
+}
+#else         /* SQLITE_OMIT_VIRTUALTABLE */
+# define fsdirRegister(x) SQLITE_OK
+#endif
+
+#ifdef _WIN32
+
+#endif
+int sqlite3_fileio_init(
+  sqlite3 *db, 
+  char **pzErrMsg, 
+  const sqlite3_api_routines *pApi
+){
+  int rc = SQLITE_OK;
+  SQLITE_EXTENSION_INIT2(pApi);
+  (void)pzErrMsg;  /* Unused parameter */
+  rc = sqlite3_create_function(db, "readfile", 1, 
+                               SQLITE_UTF8|SQLITE_DIRECTONLY, 0,
+                               readfileFunc, 0, 0);
+  if( rc==SQLITE_OK ){
+    rc = sqlite3_create_function(db, "writefile", -1,
+                                 SQLITE_UTF8|SQLITE_DIRECTONLY, 0,
+                                 writefileFunc, 0, 0);
+  }
+  if( rc==SQLITE_OK ){
+    rc = sqlite3_create_function(db, "lsmode", 1, SQLITE_UTF8, 0,
+                                 lsModeFunc, 0, 0);
+  }
+  if( rc==SQLITE_OK ){
+    rc = fsdirRegister(db);
+  }
+  return rc;
+}
+
+#if defined(FILEIO_WIN32_DLL) && (defined(_WIN32) || defined(WIN32))
+/* To allow a standalone DLL, make test_windirent.c use the same
+ * redefined SQLite API calls as the above extension code does.
+ * Just pull in this .c to accomplish this. As a beneficial side
+ * effect, this extension becomes a single translation unit. */
+#  include "test_windirent.c"
+#endif
+
+/************************* End ../ext/misc/fileio.c ********************/
+/************************* Begin ../ext/misc/completion.c ******************/
+/*
+** 2017-07-10
+**
+** The author disclaims copyright to this source code.  In place of
+** a legal notice, here is a blessing:
+**
+**    May you do good and not evil.
+**    May you find forgiveness for yourself and forgive others.
+**    May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file implements an eponymous virtual table that returns suggested
+** completions for a partial SQL input.
+**
+** Suggested usage:
+**
+**     SELECT DISTINCT candidate COLLATE nocase
+**       FROM completion($prefix,$wholeline)
+**      ORDER BY 1;
+**
+** The two query parameters are optional.  $prefix is the text of the
+** current word being typed and that is to be completed.  $wholeline is
+** the complete input line, used for context.
+**
+** The raw completion() table might return the same candidate multiple
+** times, for example if the same column name is used to two or more
+** tables.  And the candidates are returned in an arbitrary order.  Hence,
+** the DISTINCT and ORDER BY are recommended.
+**
+** This virtual table operates at the speed of human typing, and so there
+** is no attempt to make it fast.  Even a slow implementation will be much
+** faster than any human can type.
+**
+*/
+/* #include "sqlite3ext.h" */
+SQLITE_EXTENSION_INIT1
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+
+/* completion_vtab is a subclass of sqlite3_vtab which will
+** serve as the underlying representation of a completion virtual table
+*/
+typedef struct completion_vtab completion_vtab;
+struct completion_vtab {
+  sqlite3_vtab base;  /* Base class - must be first */
+  sqlite3 *db;        /* Database connection for this completion vtab */
+};
+
+/* completion_cursor is a subclass of sqlite3_vtab_cursor which will
+** serve as the underlying representation of a cursor that scans
+** over rows of the result
+*/
+typedef struct completion_cursor completion_cursor;
+struct completion_cursor {
+  sqlite3_vtab_cursor base;  /* Base class - must be first */
+  sqlite3 *db;               /* Database connection for this cursor */
+  int nPrefix, nLine;        /* Number of bytes in zPrefix and zLine */
+  char *zPrefix;             /* The prefix for the word we want to complete */
+  char *zLine;               /* The whole that we want to complete */
+  const char *zCurrentRow;   /* Current output row */
+  int szRow;                 /* Length of the zCurrentRow string */
+  sqlite3_stmt *pStmt;       /* Current statement */
+  sqlite3_int64 iRowid;      /* The rowid */
+  int ePhase;                /* Current phase */
+  int j;                     /* inter-phase counter */
+};
+
+/* Values for ePhase:
+*/
+#define COMPLETION_FIRST_PHASE   1
+#define COMPLETION_KEYWORDS      1
+#define COMPLETION_PRAGMAS       2
+#define COMPLETION_FUNCTIONS     3
+#define COMPLETION_COLLATIONS    4
+#define COMPLETION_INDEXES       5
+#define COMPLETION_TRIGGERS      6
+#define COMPLETION_DATABASES     7
+#define COMPLETION_TABLES        8    /* Also VIEWs and TRIGGERs */
+#define COMPLETION_COLUMNS       9
+#define COMPLETION_MODULES       10
+#define COMPLETION_EOF           11
+
+/*
+** The completionConnect() method is invoked to create a new
+** completion_vtab that describes the completion virtual table.
+**
+** Think of this routine as the constructor for completion_vtab objects.
+**
+** All this routine needs to do is:
+**
+**    (1) Allocate the completion_vtab object and initialize all fields.
+**
+**    (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
+**        result set of queries against completion will look like.
+*/
+static int completionConnect(
+  sqlite3 *db,
+  void *pAux,
+  int argc, const char *const*argv,
+  sqlite3_vtab **ppVtab,
+  char **pzErr
+){
+  completion_vtab *pNew;
+  int rc;
+
+  (void)(pAux);    /* Unused parameter */
+  (void)(argc);    /* Unused parameter */
+  (void)(argv);    /* Unused parameter */
+  (void)(pzErr);   /* Unused parameter */
+
+/* Column numbers */
+#define COMPLETION_COLUMN_CANDIDATE 0  /* Suggested completion of the input */
+#define COMPLETION_COLUMN_PREFIX    1  /* Prefix of the word to be completed */
+#define COMPLETION_COLUMN_WHOLELINE 2  /* Entire line seen so far */
+#define COMPLETION_COLUMN_PHASE     3  /* ePhase - used for debugging only */
+
+  sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
+  rc = sqlite3_declare_vtab(db,
+      "CREATE TABLE x("
+      "  candidate TEXT,"
+      "  prefix TEXT HIDDEN,"
+      "  wholeline TEXT HIDDEN,"
+      "  phase INT HIDDEN"        /* Used for debugging only */
+      ")");
+  if( rc==SQLITE_OK ){
+    pNew = sqlite3_malloc( sizeof(*pNew) );
+    *ppVtab = (sqlite3_vtab*)pNew;
+    if( pNew==0 ) return SQLITE_NOMEM;
+    memset(pNew, 0, sizeof(*pNew));
+    pNew->db = db;
+  }
+  return rc;
+}
+
+/*
+** This method is the destructor for completion_cursor objects.
+*/
+static int completionDisconnect(sqlite3_vtab *pVtab){
+  sqlite3_free(pVtab);
+  return SQLITE_OK;
+}
+
+/*
+** Constructor for a new completion_cursor object.
+*/
+static int completionOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
+  completion_cursor *pCur;
+  pCur = sqlite3_malloc( sizeof(*pCur) );
+  if( pCur==0 ) return SQLITE_NOMEM;
+  memset(pCur, 0, sizeof(*pCur));
+  pCur->db = ((completion_vtab*)p)->db;
+  *ppCursor = &pCur->base;
+  return SQLITE_OK;
+}
+
+/*
+** Reset the completion_cursor.
+*/
+static void completionCursorReset(completion_cursor *pCur){
+  sqlite3_free(pCur->zPrefix);   pCur->zPrefix = 0;  pCur->nPrefix = 0;
+  sqlite3_free(pCur->zLine);     pCur->zLine = 0;    pCur->nLine = 0;
+  sqlite3_finalize(pCur->pStmt); pCur->pStmt = 0;
+  pCur->j = 0;
+}
+
+/*
+** Destructor for a completion_cursor.
+*/
+static int completionClose(sqlite3_vtab_cursor *cur){
+  completionCursorReset((completion_cursor*)cur);
+  sqlite3_free(cur);
+  return SQLITE_OK;
+}
+
+/*
+** Advance a completion_cursor to its next row of output.
+**
+** The ->ePhase, ->j, and ->pStmt fields of the completion_cursor object
+** record the current state of the scan.  This routine sets ->zCurrentRow
+** to the current row of output and then returns.  If no more rows remain,
+** then ->ePhase is set to COMPLETION_EOF which will signal the virtual
+** table that has reached the end of its scan.
+**
+** The current implementation just lists potential identifiers and
+** keywords and filters them by zPrefix.  Future enhancements should
+** take zLine into account to try to restrict the set of identifiers and
+** keywords based on what would be legal at the current point of input.
+*/
+static int completionNext(sqlite3_vtab_cursor *cur){
+  completion_cursor *pCur = (completion_cursor*)cur;
+  int eNextPhase = 0;  /* Next phase to try if current phase reaches end */
+  int iCol = -1;       /* If >=0, step pCur->pStmt and use the i-th column */
+  pCur->iRowid++;
+  while( pCur->ePhase!=COMPLETION_EOF ){
+    switch( pCur->ePhase ){
+      case COMPLETION_KEYWORDS: {
+        if( pCur->j >= sqlite3_keyword_count() ){
+          pCur->zCurrentRow = 0;
+          pCur->ePhase = COMPLETION_DATABASES;
+        }else{
+          sqlite3_keyword_name(pCur->j++, &pCur->zCurrentRow, &pCur->szRow);
+        }
+        iCol = -1;
+        break;
+      }
+      case COMPLETION_DATABASES: {
+        if( pCur->pStmt==0 ){
+          sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1,
+                             &pCur->pStmt, 0);
+        }
+        iCol = 1;
+        eNextPhase = COMPLETION_TABLES;
+        break;
+      }
+      case COMPLETION_TABLES: {
+        if( pCur->pStmt==0 ){
+          sqlite3_stmt *pS2;
+          char *zSql = 0;
+          const char *zSep = "";
+          sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pS2, 0);
+          while( sqlite3_step(pS2)==SQLITE_ROW ){
+            const char *zDb = (const char*)sqlite3_column_text(pS2, 1);
+            zSql = sqlite3_mprintf(
+               "%z%s"
+               "SELECT name FROM \"%w\".sqlite_schema",
+               zSql, zSep, zDb
+            );
+            if( zSql==0 ) return SQLITE_NOMEM;
+            zSep = " UNION ";
+          }
+          sqlite3_finalize(pS2);
+          sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pStmt, 0);
+          sqlite3_free(zSql);
+        }
+        iCol = 0;
+        eNextPhase = COMPLETION_COLUMNS;
+        break;
+      }
+      case COMPLETION_COLUMNS: {
+        if( pCur->pStmt==0 ){
+          sqlite3_stmt *pS2;
+          char *zSql = 0;
+          const char *zSep = "";
+          sqlite3_prepare_v2(pCur->db, "PRAGMA database_list", -1, &pS2, 0);
+          while( sqlite3_step(pS2)==SQLITE_ROW ){
+            const char *zDb = (const char*)sqlite3_column_text(pS2, 1);
+            zSql = sqlite3_mprintf(
+               "%z%s"
+               "SELECT pti.name FROM \"%w\".sqlite_schema AS sm"
+                       " JOIN pragma_table_info(sm.name,%Q) AS pti"
+               " WHERE sm.type='table'",
+               zSql, zSep, zDb, zDb
+            );
+            if( zSql==0 ) return SQLITE_NOMEM;
+            zSep = " UNION ";
+          }
+          sqlite3_finalize(pS2);
+          sqlite3_prepare_v2(pCur->db, zSql, -1, &pCur->pStmt, 0);
+          sqlite3_free(zSql);
+        }
+        iCol = 0;
+        eNextPhase = COMPLETION_EOF;
+        break;
+      }
+    }
+    if( iCol<0 ){
+      /* This case is when the phase presets zCurrentRow */
+      if( pCur->zCurrentRow==0 ) continue;
+    }else{
+      if( sqlite3_step(pCur->pStmt)==SQLITE_ROW ){
+        /* Extract the next row of content */
+        pCur->zCurrentRow = (const char*)sqlite3_column_text(pCur->pStmt, iCol);
+        pCur->szRow = sqlite3_column_bytes(pCur->pStmt, iCol);
+      }else{
+        /* When all rows are finished, advance to the next phase */
+        sqlite3_finalize(pCur->pStmt);
+        pCur->pStmt = 0;
+        pCur->ePhase = eNextPhase;
+        continue;
+      }
+    }
+    if( pCur->nPrefix==0 ) break;
+    if( pCur->nPrefix<=pCur->szRow
+     && sqlite3_strnicmp(pCur->zPrefix, pCur->zCurrentRow, pCur->nPrefix)==0
+    ){
+      break;
+    }
+  }
+
+  return SQLITE_OK;
+}
+
+/*
+** Return values of columns for the row at which the completion_cursor
+** is currently pointing.
+*/
+static int completionColumn(
+  sqlite3_vtab_cursor *cur,   /* The cursor */
+  sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
+  int i                       /* Which column to return */
+){
+  completion_cursor *pCur = (completion_cursor*)cur;
+  switch( i ){
+    case COMPLETION_COLUMN_CANDIDATE: {
+      sqlite3_result_text(ctx, pCur->zCurrentRow, pCur->szRow,SQLITE_TRANSIENT);
+      break;
+    }
+    case COMPLETION_COLUMN_PREFIX: {
+      sqlite3_result_text(ctx, pCur->zPrefix, -1, SQLITE_TRANSIENT);
+      break;
+    }
+    case COMPLETION_COLUMN_WHOLELINE: {
+      sqlite3_result_text(ctx, pCur->zLine, -1, SQLITE_TRANSIENT);
+      break;
+    }
+    case COMPLETION_COLUMN_PHASE: {
+      sqlite3_result_int(ctx, pCur->ePhase);
+      break;
+    }
+  }
+  return SQLITE_OK;
+}
+
+/*
+** Return the rowid for the current row.  In this implementation, the
+** rowid is the same as the output value.
+*/
+static int completionRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
+  completion_cursor *pCur = (completion_cursor*)cur;
+  *pRowid = pCur->iRowid;
+  return SQLITE_OK;
+}
+
+/*
+** Return TRUE if the cursor has been moved off of the last
+** row of output.
+*/
+static int completionEof(sqlite3_vtab_cursor *cur){
+  completion_cursor *pCur = (completion_cursor*)cur;
+  return pCur->ePhase >= COMPLETION_EOF;
+}
+
+/*
+** This method is called to "rewind" the completion_cursor object back
+** to the first row of output.  This method is always called at least
+** once prior to any call to completionColumn() or completionRowid() or 
+** completionEof().
+*/
+static int completionFilter(
+  sqlite3_vtab_cursor *pVtabCursor, 
+  int idxNum, const char *idxStr,
+  int argc, sqlite3_value **argv
+){
+  completion_cursor *pCur = (completion_cursor *)pVtabCursor;
+  int iArg = 0;
+  (void)(idxStr);   /* Unused parameter */
+  (void)(argc);     /* Unused parameter */
+  completionCursorReset(pCur);
+  if( idxNum & 1 ){
+    pCur->nPrefix = sqlite3_value_bytes(argv[iArg]);
+    if( pCur->nPrefix>0 ){
+      pCur->zPrefix = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg]));
+      if( pCur->zPrefix==0 ) return SQLITE_NOMEM;
+    }
+    iArg = 1;
+  }
+  if( idxNum & 2 ){
+    pCur->nLine = sqlite3_value_bytes(argv[iArg]);
+    if( pCur->nLine>0 ){
+      pCur->zLine = sqlite3_mprintf("%s", sqlite3_value_text(argv[iArg]));
+      if( pCur->zLine==0 ) return SQLITE_NOMEM;
+    }
+  }
+  if( pCur->zLine!=0 && pCur->zPrefix==0 ){
+    int i = pCur->nLine;
+    while( i>0 && (isalnum(pCur->zLine[i-1]) || pCur->zLine[i-1]=='_') ){
+      i--;
+    }
+    pCur->nPrefix = pCur->nLine - i;
+    if( pCur->nPrefix>0 ){
+      pCur->zPrefix = sqlite3_mprintf("%.*s", pCur->nPrefix, pCur->zLine + i);
+      if( pCur->zPrefix==0 ) return SQLITE_NOMEM;
+    }
+  }
+  pCur->iRowid = 0;
+  pCur->ePhase = COMPLETION_FIRST_PHASE;
+  return completionNext(pVtabCursor);
+}
+
+/*
+** SQLite will invoke this method one or more times while planning a query
+** that uses the completion virtual table.  This routine needs to create
+** a query plan for each invocation and compute an estimated cost for that
+** plan.
+**
+** There are two hidden parameters that act as arguments to the table-valued
+** function:  "prefix" and "wholeline".  Bit 0 of idxNum is set if "prefix"
+** is available and bit 1 is set if "wholeline" is available.
+*/
+static int completionBestIndex(
+  sqlite3_vtab *tab,
+  sqlite3_index_info *pIdxInfo
+){
+  int i;                 /* Loop over constraints */
+  int idxNum = 0;        /* The query plan bitmask */
+  int prefixIdx = -1;    /* Index of the start= constraint, or -1 if none */
+  int wholelineIdx = -1; /* Index of the stop= constraint, or -1 if none */
+  int nArg = 0;          /* Number of arguments that completeFilter() expects */
+  const struct sqlite3_index_constraint *pConstraint;
+
+  (void)(tab);    /* Unused parameter */
+  pConstraint = pIdxInfo->aConstraint;
+  for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
+    if( pConstraint->usable==0 ) continue;
+    if( pConstraint->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
+    switch( pConstraint->iColumn ){
+      case COMPLETION_COLUMN_PREFIX:
+        prefixIdx = i;
+        idxNum |= 1;
+        break;
+      case COMPLETION_COLUMN_WHOLELINE:
+        wholelineIdx = i;
+        idxNum |= 2;
+        break;
+    }
+  }
+  if( prefixIdx>=0 ){
+    pIdxInfo->aConstraintUsage[prefixIdx].argvIndex = ++nArg;
+    pIdxInfo->aConstraintUsage[prefixIdx].omit = 1;
+  }
+  if( wholelineIdx>=0 ){
+    pIdxInfo->aConstraintUsage[wholelineIdx].argvIndex = ++nArg;
+    pIdxInfo->aConstraintUsage[wholelineIdx].omit = 1;
+  }
+  pIdxInfo->idxNum = idxNum;
+  pIdxInfo->estimatedCost = (double)5000 - 1000*nArg;
+  pIdxInfo->estimatedRows = 500 - 100*nArg;
+  return SQLITE_OK;
+}
+
+/*
+** This following structure defines all the methods for the 
+** completion virtual table.
+*/
+static sqlite3_module completionModule = {
+  0,                         /* iVersion */
+  0,                         /* xCreate */
+  completionConnect,         /* xConnect */
+  completionBestIndex,       /* xBestIndex */
+  completionDisconnect,      /* xDisconnect */
+  0,                         /* xDestroy */
+  completionOpen,            /* xOpen - open a cursor */
+  completionClose,           /* xClose - close a cursor */
+  completionFilter,          /* xFilter - configure scan constraints */
+  completionNext,            /* xNext - advance a cursor */
+  completionEof,             /* xEof - check for end of scan */
+  completionColumn,          /* xColumn - read data */
+  completionRowid,           /* xRowid - read data */
+  0,                         /* xUpdate */
+  0,                         /* xBegin */
+  0,                         /* xSync */
+  0,                         /* xCommit */
+  0,                         /* xRollback */
+  0,                         /* xFindMethod */
+  0,                         /* xRename */
+  0,                         /* xSavepoint */
+  0,                         /* xRelease */
+  0,                         /* xRollbackTo */
+  0                          /* xShadowName */
+};
+
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+int sqlite3CompletionVtabInit(sqlite3 *db){
+  int rc = SQLITE_OK;
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+  rc = sqlite3_create_module(db, "completion", &completionModule, 0);
+#endif
+  return rc;
+}
+
+#ifdef _WIN32
+
+#endif
+int sqlite3_completion_init(
+  sqlite3 *db, 
+  char **pzErrMsg, 
+  const sqlite3_api_routines *pApi
+){
+  int rc = SQLITE_OK;
+  SQLITE_EXTENSION_INIT2(pApi);
+  (void)(pzErrMsg);  /* Unused parameter */
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+  rc = sqlite3CompletionVtabInit(db);
+#endif
+  return rc;
+}
+
+/************************* End ../ext/misc/completion.c ********************/
+/************************* Begin ../ext/misc/appendvfs.c ******************/
+/*
+** 2017-10-20
+**
+** The author disclaims copyright to this source code.  In place of
+** a legal notice, here is a blessing:
+**
+**    May you do good and not evil.
+**    May you find forgiveness for yourself and forgive others.
+**    May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This file implements a VFS shim that allows an SQLite database to be
+** appended onto the end of some other file, such as an executable.
+**
+** A special record must appear at the end of the file that identifies the
+** file as an appended database and provides the offset to the first page
+** of the exposed content. (Or, it is the length of the content prefix.)
+** For best performance page 1 should be located at a disk page boundary,
+** though that is not required.
+**
+** When opening a database using this VFS, the connection might treat
+** the file as an ordinary SQLite database, or it might treat it as a
+** database appended onto some other file.  The decision is made by
+** applying the following rules in order:
+**
+**  (1)  An empty file is an ordinary database.
+**
+**  (2)  If the file ends with the appendvfs trailer string
+**       "Start-Of-SQLite3-NNNNNNNN" that file is an appended database.
+**
+**  (3)  If the file begins with the standard SQLite prefix string
+**       "SQLite format 3", that file is an ordinary database.
+**
+**  (4)  If none of the above apply and the SQLITE_OPEN_CREATE flag is
+**       set, then a new database is appended to the already existing file.
+**
+**  (5)  Otherwise, SQLITE_CANTOPEN is returned.
+**
+** To avoid unnecessary complications with the PENDING_BYTE, the size of
+** the file containing the database is limited to 1GiB. (1073741824 bytes)
+** This VFS will not read or write past the 1GiB mark.  This restriction
+** might be lifted in future versions.  For now, if you need a larger
+** database, then keep it in a separate file.
+**
+** If the file being opened is a plain database (not an appended one), then
+** this shim is a pass-through into the default underlying VFS. (rule 3)
+**/
+/* #include "sqlite3ext.h" */
+SQLITE_EXTENSION_INIT1
+#include <string.h>
+#include <assert.h>
+
+/* The append mark at the end of the database is:
+**
+**     Start-Of-SQLite3-NNNNNNNN
+**     123456789 123456789 12345
+**
+** The NNNNNNNN represents a 64-bit big-endian unsigned integer which is
+** the offset to page 1, and also the length of the prefix content.
+*/
+#define APND_MARK_PREFIX     "Start-Of-SQLite3-"
+#define APND_MARK_PREFIX_SZ  17
+#define APND_MARK_FOS_SZ      8
+#define APND_MARK_SIZE       (APND_MARK_PREFIX_SZ+APND_MARK_FOS_SZ)
+
+/*
+** Maximum size of the combined prefix + database + append-mark.  This
+** must be less than 0x40000000 to avoid locking issues on Windows.
+*/
+#define APND_MAX_SIZE  (0x40000000)
+
+/*
+** Try to align the database to an even multiple of APND_ROUNDUP bytes.
+*/
+#ifndef APND_ROUNDUP
+#define APND_ROUNDUP 4096
+#endif
+#define APND_ALIGN_MASK         ((sqlite3_int64)(APND_ROUNDUP-1))
+#define APND_START_ROUNDUP(fsz) (((fsz)+APND_ALIGN_MASK) & ~APND_ALIGN_MASK)
+
+/*
+** Forward declaration of objects used by this utility
+*/
+typedef struct sqlite3_vfs ApndVfs;
+typedef struct ApndFile ApndFile;
+
+/* Access to a lower-level VFS that (might) implement dynamic loading,
+** access to randomness, etc.
+*/
+#define ORIGVFS(p)  ((sqlite3_vfs*)((p)->pAppData))
+#define ORIGFILE(p) ((sqlite3_file*)(((ApndFile*)(p))+1))
+
+/* An open appendvfs file
+**
+** An instance of this structure describes the appended database file.
+** A separate sqlite3_file object is always appended. The appended
+** sqlite3_file object (which can be accessed using ORIGFILE()) describes
+** the entire file, including the prefix, the database, and the
+** append-mark.
+**
+** The structure of an AppendVFS database is like this:
+**
+**   +-------------+---------+----------+-------------+
+**   | prefix-file | padding | database | append-mark |
+**   +-------------+---------+----------+-------------+
+**                           ^          ^
+**                           |          |
+**                         iPgOne      iMark
+**
+**
+** "prefix file" -  file onto which the database has been appended.
+** "padding"     -  zero or more bytes inserted so that "database"
+**                  starts on an APND_ROUNDUP boundary
+** "database"    -  The SQLite database file
+** "append-mark" -  The 25-byte "Start-Of-SQLite3-NNNNNNNN" that indicates
+**                  the offset from the start of prefix-file to the start
+**                  of "database".
+**
+** The size of the database is iMark - iPgOne.
+**
+** The NNNNNNNN in the "Start-Of-SQLite3-NNNNNNNN" suffix is the value
+** of iPgOne stored as a big-ending 64-bit integer.
+**
+** iMark will be the size of the underlying file minus 25 (APND_MARKSIZE).
+** Or, iMark is -1 to indicate that it has not yet been written.
+*/
+struct ApndFile {
+  sqlite3_file base;        /* Subclass.  MUST BE FIRST! */
+  sqlite3_int64 iPgOne;     /* Offset to the start of the database */
+  sqlite3_int64 iMark;      /* Offset of the append mark.  -1 if unwritten */
+  /* Always followed by another sqlite3_file that describes the whole file */
+};
+
+/*
+** Methods for ApndFile
+*/
+static int apndClose(sqlite3_file*);
+static int apndRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
+static int apndWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
+static int apndTruncate(sqlite3_file*, sqlite3_int64 size);
+static int apndSync(sqlite3_file*, int flags);
+static int apndFileSize(sqlite3_file*, sqlite3_int64 *pSize);
+static int apndLock(sqlite3_file*, int);
+static int apndUnlock(sqlite3_file*, int);
+static int apndCheckReservedLock(sqlite3_file*, int *pResOut);
+static int apndFileControl(sqlite3_file*, int op, void *pArg);
+static int apndSectorSize(sqlite3_file*);
+static int apndDeviceCharacteristics(sqlite3_file*);
+static int apndShmMap(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
+static int apndShmLock(sqlite3_file*, int offset, int n, int flags);
+static void apndShmBarrier(sqlite3_file*);
+static int apndShmUnmap(sqlite3_file*, int deleteFlag);
+static int apndFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
+static int apndUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p);
+
+/*
+** Methods for ApndVfs
+*/
+static int apndOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
+static int apndDelete(sqlite3_vfs*, const char *zName, int syncDir);
+static int apndAccess(sqlite3_vfs*, const char *zName, int flags, int *);
+static int apndFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
+static void *apndDlOpen(sqlite3_vfs*, const char *zFilename);
+static void apndDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
+static void (*apndDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
+static void apndDlClose(sqlite3_vfs*, void*);
+static int apndRandomness(sqlite3_vfs*, int nByte, char *zOut);
+static int apndSleep(sqlite3_vfs*, int microseconds);
+static int apndCurrentTime(sqlite3_vfs*, double*);
+static int apndGetLastError(sqlite3_vfs*, int, char *);
+static int apndCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
+static int apndSetSystemCall(sqlite3_vfs*, const char*,sqlite3_syscall_ptr);
+static sqlite3_syscall_ptr apndGetSystemCall(sqlite3_vfs*, const char *z);
+static const char *apndNextSystemCall(sqlite3_vfs*, const char *zName);
+
+static sqlite3_vfs apnd_vfs = {
+  3,                            /* iVersion (set when registered) */
+  0,                            /* szOsFile (set when registered) */
+  1024,                         /* mxPathname */
+  0,                            /* pNext */
+  "apndvfs",                    /* zName */
+  0,                            /* pAppData (set when registered) */ 
+  apndOpen,                     /* xOpen */
+  apndDelete,                   /* xDelete */
+  apndAccess,                   /* xAccess */
+  apndFullPathname,             /* xFullPathname */
+  apndDlOpen,                   /* xDlOpen */
+  apndDlError,                  /* xDlError */
+  apndDlSym,                    /* xDlSym */
+  apndDlClose,                  /* xDlClose */
+  apndRandomness,               /* xRandomness */
+  apndSleep,                    /* xSleep */
+  apndCurrentTime,              /* xCurrentTime */
+  apndGetLastError,             /* xGetLastError */
+  apndCurrentTimeInt64,         /* xCurrentTimeInt64 */
+  apndSetSystemCall,            /* xSetSystemCall */
+  apndGetSystemCall,            /* xGetSystemCall */
+  apndNextSystemCall            /* xNextSystemCall */
+};
+
+static const sqlite3_io_methods apnd_io_methods = {
+  3,                              /* iVersion */
+  apndClose,                      /* xClose */
+  apndRead,                       /* xRead */
+  apndWrite,                      /* xWrite */
+  apndTruncate,                   /* xTruncate */
+  apndSync,                       /* xSync */
+  apndFileSize,                   /* xFileSize */
+  apndLock,                       /* xLock */
+  apndUnlock,                     /* xUnlock */
+  apndCheckReservedLock,          /* xCheckReservedLock */
+  apndFileControl,                /* xFileControl */
+  apndSectorSize,                 /* xSectorSize */
+  apndDeviceCharacteristics,      /* xDeviceCharacteristics */
+  apndShmMap,                     /* xShmMap */
+  apndShmLock,                    /* xShmLock */
+  apndShmBarrier,                 /* xShmBarrier */
+  apndShmUnmap,                   /* xShmUnmap */
+  apndFetch,                      /* xFetch */
+  apndUnfetch                     /* xUnfetch */
+};
+
+/*
+** Close an apnd-file.
+*/
+static int apndClose(sqlite3_file *pFile){
+  pFile = ORIGFILE(pFile);
+  return pFile->pMethods->xClose(pFile);
+}
+
+/*
+** Read data from an apnd-file.
+*/
+static int apndRead(
+  sqlite3_file *pFile, 
+  void *zBuf, 
+  int iAmt, 
+  sqlite_int64 iOfst
+){
+  ApndFile *paf = (ApndFile *)pFile;
+  pFile = ORIGFILE(pFile);
+  return pFile->pMethods->xRead(pFile, zBuf, iAmt, paf->iPgOne+iOfst);
+}
+
+/*
+** Add the append-mark onto what should become the end of the file.
+*  If and only if this succeeds, internal ApndFile.iMark is updated.
+*  Parameter iWriteEnd is the appendvfs-relative offset of the new mark.
+*/
+static int apndWriteMark(
+  ApndFile *paf,
+  sqlite3_file *pFile,
+  sqlite_int64 iWriteEnd
+){
+  sqlite_int64 iPgOne = paf->iPgOne;
+  unsigned char a[APND_MARK_SIZE];
+  int i = APND_MARK_FOS_SZ;
+  int rc;
+  assert(pFile == ORIGFILE(paf));
+  memcpy(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ);
+  while( --i >= 0 ){
+    a[APND_MARK_PREFIX_SZ+i] = (unsigned char)(iPgOne & 0xff);
+    iPgOne >>= 8;
+  }
+  iWriteEnd += paf->iPgOne;
+  if( SQLITE_OK==(rc = pFile->pMethods->xWrite
+                  (pFile, a, APND_MARK_SIZE, iWriteEnd)) ){
+    paf->iMark = iWriteEnd;
+  }
+  return rc;
+}
+
+/*
+** Write data to an apnd-file.
+*/
+static int apndWrite(
+  sqlite3_file *pFile,
+  const void *zBuf,
+  int iAmt,
+  sqlite_int64 iOfst
+){
+  ApndFile *paf = (ApndFile *)pFile;
+  sqlite_int64 iWriteEnd = iOfst + iAmt;
+  if( iWriteEnd>=APND_MAX_SIZE ) return SQLITE_FULL;
+  pFile = ORIGFILE(pFile);
+  /* If append-mark is absent or will be overwritten, write it. */
+  if( paf->iMark < 0 || paf->iPgOne + iWriteEnd > paf->iMark ){
+    int rc = apndWriteMark(paf, pFile, iWriteEnd);
+    if( SQLITE_OK!=rc ) return rc;
+  }
+  return pFile->pMethods->xWrite(pFile, zBuf, iAmt, paf->iPgOne+iOfst);
+}
+
+/*
+** Truncate an apnd-file.
+*/
+static int apndTruncate(sqlite3_file *pFile, sqlite_int64 size){
+  ApndFile *paf = (ApndFile *)pFile;
+  pFile = ORIGFILE(pFile);
+  /* The append mark goes out first so truncate failure does not lose it. */
+  if( SQLITE_OK!=apndWriteMark(paf, pFile, size) ) return SQLITE_IOERR;
+  /* Truncate underlying file just past append mark */
+  return pFile->pMethods->xTruncate(pFile, paf->iMark+APND_MARK_SIZE);
+}
+
+/*
+** Sync an apnd-file.
+*/
+static int apndSync(sqlite3_file *pFile, int flags){
+  pFile = ORIGFILE(pFile);
+  return pFile->pMethods->xSync(pFile, flags);
+}
+
+/*
+** Return the current file-size of an apnd-file.
+** If the append mark is not yet there, the file-size is 0.
+*/
+static int apndFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
+  ApndFile *paf = (ApndFile *)pFile;
+  *pSize = ( paf->iMark >= 0 )? (paf->iMark - paf->iPgOne) : 0;
+  return SQLITE_OK;
+}
+
+/*
+** Lock an apnd-file.
+*/
+static int apndLock(sqlite3_file *pFile, int eLock){
+  pFile = ORIGFILE(pFile);
+  return pFile->pMethods->xLock(pFile, eLock);
+}
+
+/*
+** Unlock an apnd-file.
+*/
+static int apndUnlock(sqlite3_file *pFile, int eLock){
+  pFile = ORIGFILE(pFile);
+  return pFile->pMethods->xUnlock(pFile, eLock);
+}
+
+/*
+** Check if another file-handle holds a RESERVED lock on an apnd-file.
+*/
+static int apndCheckReservedLock(sqlite3_file *pFile, int *pResOut){
+  pFile = ORIGFILE(pFile);
+  return pFile->pMethods->xCheckReservedLock(pFile, pResOut);
+}
+
+/*
+** File control method. For custom operations on an apnd-file.
+*/
+static int apndFileControl(sqlite3_file *pFile, int op, void *pArg){
+  ApndFile *paf = (ApndFile *)pFile;
+  int rc;
+  pFile = ORIGFILE(pFile);
+  if( op==SQLITE_FCNTL_SIZE_HINT ) *(sqlite3_int64*)pArg += paf->iPgOne;
+  rc = pFile->pMethods->xFileControl(pFile, op, pArg);
+  if( rc==SQLITE_OK && op==SQLITE_FCNTL_VFSNAME ){
+    *(char**)pArg = sqlite3_mprintf("apnd(%lld)/%z", paf->iPgOne,*(char**)pArg);
+  }
+  return rc;
+}
+
+/*
+** Return the sector-size in bytes for an apnd-file.
+*/
+static int apndSectorSize(sqlite3_file *pFile){
+  pFile = ORIGFILE(pFile);
+  return pFile->pMethods->xSectorSize(pFile);
+}
+
+/*
+** Return the device characteristic flags supported by an apnd-file.
+*/
+static int apndDeviceCharacteristics(sqlite3_file *pFile){
+  pFile = ORIGFILE(pFile);
+  return pFile->pMethods->xDeviceCharacteristics(pFile);
+}
+
+/* Create a shared memory file mapping */
+static int apndShmMap(
+  sqlite3_file *pFile,
+  int iPg,
+  int pgsz,
+  int bExtend,
+  void volatile **pp
+){
+  pFile = ORIGFILE(pFile);
+  return pFile->pMethods->xShmMap(pFile,iPg,pgsz,bExtend,pp);
+}
+
+/* Perform locking on a shared-memory segment */
+static int apndShmLock(sqlite3_file *pFile, int offset, int n, int flags){
+  pFile = ORIGFILE(pFile);
+  return pFile->pMethods->xShmLock(pFile,offset,n,flags);
+}
+
+/* Memory barrier operation on shared memory */
+static void apndShmBarrier(sqlite3_file *pFile){
+  pFile = ORIGFILE(pFile);
+  pFile->pMethods->xShmBarrier(pFile);
+}
+
+/* Unmap a shared memory segment */
+static int apndShmUnmap(sqlite3_file *pFile, int deleteFlag){
+  pFile = ORIGFILE(pFile);
+  return pFile->pMethods->xShmUnmap(pFile,deleteFlag);
+}
+
+/* Fetch a page of a memory-mapped file */
+static int apndFetch(
+  sqlite3_file *pFile,
+  sqlite3_int64 iOfst,
+  int iAmt,
+  void **pp
+){
+  ApndFile *p = (ApndFile *)pFile;
+  if( p->iMark < 0 || iOfst+iAmt > p->iMark ){
+    return SQLITE_IOERR; /* Cannot read what is not yet there. */
+  }
+  pFile = ORIGFILE(pFile);
+  return pFile->pMethods->xFetch(pFile, iOfst+p->iPgOne, iAmt, pp);
+}
+
+/* Release a memory-mapped page */
+static int apndUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
+  ApndFile *p = (ApndFile *)pFile;
+  pFile = ORIGFILE(pFile);
+  return pFile->pMethods->xUnfetch(pFile, iOfst+p->iPgOne, pPage);
+}
+
+/*
+** Try to read the append-mark off the end of a file.  Return the
+** start of the appended database if the append-mark is present.
+** If there is no valid append-mark, return -1;
+**
+** An append-mark is only valid if the NNNNNNNN start-of-database offset
+** indicates that the appended database contains at least one page.  The
+** start-of-database value must be a multiple of 512.
+*/
+static sqlite3_int64 apndReadMark(sqlite3_int64 sz, sqlite3_file *pFile){
+  int rc, i;
+  sqlite3_int64 iMark;
+  int msbs = 8 * (APND_MARK_FOS_SZ-1);
+  unsigned char a[APND_MARK_SIZE];
+
+  if( APND_MARK_SIZE!=(sz & 0x1ff) ) return -1;
+  rc = pFile->pMethods->xRead(pFile, a, APND_MARK_SIZE, sz-APND_MARK_SIZE);
+  if( rc ) return -1;
+  if( memcmp(a, APND_MARK_PREFIX, APND_MARK_PREFIX_SZ)!=0 ) return -1;
+  iMark = ((sqlite3_int64)(a[APND_MARK_PREFIX_SZ] & 0x7f)) << msbs;
+  for(i=1; i<8; i++){
+    msbs -= 8;
+    iMark |= (sqlite3_int64)a[APND_MARK_PREFIX_SZ+i]<<msbs;
+  }
+  if( iMark > (sz - APND_MARK_SIZE - 512) ) return -1;
+  if( iMark & 0x1ff ) return -1;
+  return iMark;
+}
+
+static const char apvfsSqliteHdr[] = "SQLite format 3";
+/*
+** Check to see if the file is an appendvfs SQLite database file.
+** Return true iff it is such. Parameter sz is the file's size.
+*/
+static int apndIsAppendvfsDatabase(sqlite3_int64 sz, sqlite3_file *pFile){
+  int rc;
+  char zHdr[16];
+  sqlite3_int64 iMark = apndReadMark(sz, pFile);
+  if( iMark>=0 ){
+    /* If file has the correct end-marker, the expected odd size, and the
+    ** SQLite DB type marker where the end-marker puts it, then it
+    ** is an appendvfs database.
+    */
+    rc = pFile->pMethods->xRead(pFile, zHdr, sizeof(zHdr), iMark);
+    if( SQLITE_OK==rc
+     && memcmp(zHdr, apvfsSqliteHdr, sizeof(zHdr))==0
+     && (sz & 0x1ff) == APND_MARK_SIZE
+     && sz>=512+APND_MARK_SIZE
+    ){
+      return 1; /* It's an appendvfs database */
+    }
+  }
+  return 0;
+}
+
+/*
+** Check to see if the file is an ordinary SQLite database file.
+** Return true iff so. Parameter sz is the file's size.
+*/
+static int apndIsOrdinaryDatabaseFile(sqlite3_int64 sz, sqlite3_file *pFile){
+  char zHdr[16];
+  if( apndIsAppendvfsDatabase(sz, pFile) /* rule 2 */
+   || (sz & 0x1ff) != 0
+   || SQLITE_OK!=pFile->pMethods->xRead(pFile, zHdr, sizeof(zHdr), 0)
+   || memcmp(zHdr, apvfsSqliteHdr, sizeof(zHdr))!=0
+  ){
+    return 0;
+  }else{
+    return 1;
+  }
+}
+
+/*
+** Open an apnd file handle.
+*/
+static int apndOpen(
+  sqlite3_vfs *pApndVfs,
+  const char *zName,
+  sqlite3_file *pFile,
+  int flags,
+  int *pOutFlags
+){
+  ApndFile *pApndFile = (ApndFile*)pFile;
+  sqlite3_file *pBaseFile = ORIGFILE(pFile);
+  sqlite3_vfs *pBaseVfs = ORIGVFS(pApndVfs);
+  int rc;
+  sqlite3_int64 sz = 0;
+  if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){
+    /* The appendvfs is not to be used for transient or temporary databases.
+    ** Just use the base VFS open to initialize the given file object and
+    ** open the underlying file. (Appendvfs is then unused for this file.)
+    */
+    return pBaseVfs->xOpen(pBaseVfs, zName, pFile, flags, pOutFlags);
+  }
+  memset(pApndFile, 0, sizeof(ApndFile));
+  pFile->pMethods = &apnd_io_methods;
+  pApndFile->iMark = -1;    /* Append mark not yet written */
+
+  rc = pBaseVfs->xOpen(pBaseVfs, zName, pBaseFile, flags, pOutFlags);
+  if( rc==SQLITE_OK ){
+    rc = pBaseFile->pMethods->xFileSize(pBaseFile, &sz);
+    if( rc ){
+      pBaseFile->pMethods->xClose(pBaseFile);
+    }
+  }
+  if( rc ){
+    pFile->pMethods = 0;
+    return rc;
+  }
+  if( apndIsOrdinaryDatabaseFile(sz, pBaseFile) ){
+    /* The file being opened appears to be just an ordinary DB. Copy
+    ** the base dispatch-table so this instance mimics the base VFS. 
+    */
+    memmove(pApndFile, pBaseFile, pBaseVfs->szOsFile);
+    return SQLITE_OK;
+  }
+  pApndFile->iPgOne = apndReadMark(sz, pFile);
+  if( pApndFile->iPgOne>=0 ){
+    pApndFile->iMark = sz - APND_MARK_SIZE; /* Append mark found */
+    return SQLITE_OK;
+  }
+  if( (flags & SQLITE_OPEN_CREATE)==0 ){
+    pBaseFile->pMethods->xClose(pBaseFile);
+    rc = SQLITE_CANTOPEN;
+    pFile->pMethods = 0;
+  }else{
+    /* Round newly added appendvfs location to #define'd page boundary. 
+    ** Note that nothing has yet been written to the underlying file.
+    ** The append mark will be written along with first content write.
+    ** Until then, paf->iMark value indicates it is not yet written.
+    */
+    pApndFile->iPgOne = APND_START_ROUNDUP(sz);
+  }
+  return rc;
+}
+
+/*
+** Delete an apnd file.
+** For an appendvfs, this could mean delete the appendvfs portion,
+** leaving the appendee as it was before it gained an appendvfs.
+** For now, this code deletes the underlying file too.
+*/
+static int apndDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
+  return ORIGVFS(pVfs)->xDelete(ORIGVFS(pVfs), zPath, dirSync);
+}
+
+/*
+** All other VFS methods are pass-thrus.
+*/
+static int apndAccess(
+  sqlite3_vfs *pVfs, 
+  const char *zPath, 
+  int flags, 
+  int *pResOut
+){
+  return ORIGVFS(pVfs)->xAccess(ORIGVFS(pVfs), zPath, flags, pResOut);
+}
+static int apndFullPathname(
+  sqlite3_vfs *pVfs, 
+  const char *zPath, 
+  int nOut, 
+  char *zOut
+){
+  return ORIGVFS(pVfs)->xFullPathname(ORIGVFS(pVfs),zPath,nOut,zOut);
+}
+static void *apndDlOpen(sqlite3_vfs *pVfs, const char *zPath){
+  return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath);
+}
+static void apndDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
+  ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg);
+}
+static void (*apndDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
+  return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym);
+}
+static void apndDlClose(sqlite3_vfs *pVfs, void *pHandle){
+  ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle);
+}
+static int apndRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
+  return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut);
+}
+static int apndSleep(sqlite3_vfs *pVfs, int nMicro){
+  return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro);
+}
+static int apndCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
+  return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut);
+}
+static int apndGetLastError(sqlite3_vfs *pVfs, int a, char *b){
+  return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b);
+}
+static int apndCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
+  return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p);
+}
+static int apndSetSystemCall(
+  sqlite3_vfs *pVfs,
+  const char *zName,
+  sqlite3_syscall_ptr pCall
+){
+  return ORIGVFS(pVfs)->xSetSystemCall(ORIGVFS(pVfs),zName,pCall);
+}
+static sqlite3_syscall_ptr apndGetSystemCall(
+  sqlite3_vfs *pVfs,
+  const char *zName
+){
+  return ORIGVFS(pVfs)->xGetSystemCall(ORIGVFS(pVfs),zName);
+}
+static const char *apndNextSystemCall(sqlite3_vfs *pVfs, const char *zName){
+  return ORIGVFS(pVfs)->xNextSystemCall(ORIGVFS(pVfs), zName);
+}
+
+  
+#ifdef _WIN32
+
+#endif
+/* 
+** This routine is called when the extension is loaded.
+** Register the new VFS.
+*/
+int sqlite3_appendvfs_init(
+  sqlite3 *db, 
+  char **pzErrMsg, 
+  const sqlite3_api_routines *pApi
+){
+  int rc = SQLITE_OK;
+  sqlite3_vfs *pOrig;
+  SQLITE_EXTENSION_INIT2(pApi);
+  (void)pzErrMsg;
+  (void)db;
+  pOrig = sqlite3_vfs_find(0);
+  if( pOrig==0 ) return SQLITE_ERROR;
+  apnd_vfs.iVersion = pOrig->iVersion;
+  apnd_vfs.pAppData = pOrig;
+  apnd_vfs.szOsFile = pOrig->szOsFile + sizeof(ApndFile);
+  rc = sqlite3_vfs_register(&apnd_vfs, 0);
+#ifdef APPENDVFS_TEST
+  if( rc==SQLITE_OK ){
+    rc = sqlite3_auto_extension((void(*)(void))apndvfsRegister);
+  }
+#endif
+  if( rc==SQLITE_OK ) rc = SQLITE_OK_LOAD_PERMANENTLY;
+  return rc;
+}
+
+/************************* End ../ext/misc/appendvfs.c ********************/
+#endif
 #ifdef SQLITE_HAVE_ZLIB
 /************************* Begin ../ext/misc/zipfile.c ******************/
 /*
@@ -6718,6 +6772,9 @@
 #define MIN(a,b) ((a)<(b) ? (a) : (b))
 
 #if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
+# define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1
+#endif
+#if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS)
 # define ALWAYS(X)      (1)
 # define NEVER(X)       (0)
 #elif !defined(NDEBUG)
@@ -7222,6 +7279,7 @@
 ** Read and return a 32-bit little-endian unsigned integer from buffer aBuf.
 */
 static u32 zipfileGetU32(const u8 *aBuf){
+  if( aBuf==0 ) return 0;
   return ((u32)(aBuf[3]) << 24)
        + ((u32)(aBuf[2]) << 16)
        + ((u32)(aBuf[1]) <<  8)
@@ -7524,7 +7582,7 @@
         aRead = (u8*)&aBlob[pNew->cds.iOffset];
       }
 
-      rc = zipfileReadLFH(aRead, &lfh);
+      if( rc==SQLITE_OK ) rc = zipfileReadLFH(aRead, &lfh);
       if( rc==SQLITE_OK ){
         pNew->iDataOff =  pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ;
         pNew->iDataOff += lfh.nFile + lfh.nExtra;
@@ -7800,13 +7858,13 @@
   int nRead;                      /* Bytes to read from file */
   int rc = SQLITE_OK;
 
+  memset(pEOCD, 0, sizeof(ZipfileEOCD));
   if( aBlob==0 ){
     i64 iOff;                     /* Offset to read from */
     i64 szFile;                   /* Total size of file in bytes */
     fseek(pFile, 0, SEEK_END);
     szFile = (i64)ftell(pFile);
     if( szFile==0 ){
-      memset(pEOCD, 0, sizeof(ZipfileEOCD));
       return SQLITE_OK;
     }
     nRead = (int)(MIN(szFile, ZIPFILE_BUFFER_SIZE));
@@ -7919,9 +7977,14 @@
     zipfileCursorErr(pCsr, "zipfile() function requires an argument");
     return SQLITE_ERROR;
   }else if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
+    static const u8 aEmptyBlob = 0;
     const u8 *aBlob = (const u8*)sqlite3_value_blob(argv[0]);
     int nBlob = sqlite3_value_bytes(argv[0]);
     assert( pTab->pFirstEntry==0 );
+    if( aBlob==0 ){
+      aBlob = &aEmptyBlob;
+      nBlob = 0;
+    }
     rc = zipfileLoadDirectory(pTab, aBlob, nBlob);
     pCsr->pFreeEntry = pTab->pFirstEntry;
     pTab->pFirstEntry = pTab->pLastEntry = 0;
@@ -8595,7 +8658,7 @@
 **   SELECT zipfile(name,mode,mtime,data) ...
 **   SELECT zipfile(name,mode,mtime,data,method) ...
 */
-void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){
+static void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){
   ZipfileCtx *p;                  /* Aggregate function context */
   ZipfileEntry e;                 /* New entry to add to zip archive */
 
@@ -8770,7 +8833,7 @@
 /*
 ** xFinalize() callback for zipfile aggregate function.
 */
-void zipfileFinal(sqlite3_context *pCtx){
+static void zipfileFinal(sqlite3_context *pCtx){
   ZipfileCtx *p;
   ZipfileEOCD eocd;
   sqlite3_int64 nZip;
@@ -8827,6 +8890,10 @@
     zipfileRollback,           /* xRollback */
     zipfileFindFunction,       /* xFindMethod */
     0,                         /* xRename */
+    0,                         /* xSavepoint */
+    0,                         /* xRelease */
+    0,                         /* xRollback */
+    0                          /* xShadowName */
   };
 
   int rc = sqlite3_create_module(db, "zipfile"  , &zipfileModule, 0);
@@ -9177,6 +9244,23 @@
 #include <string.h>
 #include <stdio.h>
 
+#if !defined(SQLITE_AMALGAMATION)
+#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
+# define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1
+#endif
+#if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS)
+# define ALWAYS(X)      (1)
+# define NEVER(X)       (0)
+#elif !defined(NDEBUG)
+# define ALWAYS(X)      ((X)?1:(assert(0),0))
+# define NEVER(X)       ((X)?(assert(0),1):0)
+#else
+# define ALWAYS(X)      (X)
+# define NEVER(X)       (X)
+#endif
+#endif /* !defined(SQLITE_AMALGAMATION) */
+
+
 #ifndef SQLITE_OMIT_VIRTUALTABLE 
 
 /* typedef sqlite3_int64 i64; */
@@ -9842,21 +9926,31 @@
 ){
   sqlite3_stmt *p1 = 0;
   int nCol = 0;
-  int nTab = STRLEN(zTab);
-  int nByte = sizeof(IdxTable) + nTab + 1;
+  int nTab;
+  int nByte;
   IdxTable *pNew = 0;
   int rc, rc2;
   char *pCsr = 0;
   int nPk = 0;
 
+  *ppOut = 0;
+  if( zTab==0 ) return SQLITE_ERROR;
+  nTab = STRLEN(zTab);
+  nByte = sizeof(IdxTable) + nTab + 1;
   rc = idxPrintfPrepareStmt(db, &p1, pzErrmsg, "PRAGMA table_xinfo=%Q", zTab);
   while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
     const char *zCol = (const char*)sqlite3_column_text(p1, 1);
+    const char *zColSeq = 0;
+    if( zCol==0 ){
+      rc = SQLITE_ERROR;
+      break;
+    }
     nByte += 1 + STRLEN(zCol);
     rc = sqlite3_table_column_metadata(
-        db, "main", zTab, zCol, 0, &zCol, 0, 0, 0
+        db, "main", zTab, zCol, 0, &zColSeq, 0, 0, 0
     );
-    nByte += 1 + STRLEN(zCol);
+    if( zColSeq==0 ) zColSeq = "binary";
+    nByte += 1 + STRLEN(zColSeq);
     nCol++;
     nPk += (sqlite3_column_int(p1, 5)>0);
   }
@@ -9876,19 +9970,23 @@
   nCol = 0;
   while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(p1) ){
     const char *zCol = (const char*)sqlite3_column_text(p1, 1);
-    int nCopy = STRLEN(zCol) + 1;
+    const char *zColSeq = 0;
+    int nCopy;
+    if( zCol==0 ) continue;
+    nCopy = STRLEN(zCol) + 1;
     pNew->aCol[nCol].zName = pCsr;
     pNew->aCol[nCol].iPk = (sqlite3_column_int(p1, 5)==1 && nPk==1);
     memcpy(pCsr, zCol, nCopy);
     pCsr += nCopy;
 
     rc = sqlite3_table_column_metadata(
-        db, "main", zTab, zCol, 0, &zCol, 0, 0, 0
+        db, "main", zTab, zCol, 0, &zColSeq, 0, 0, 0
     );
     if( rc==SQLITE_OK ){
-      nCopy = STRLEN(zCol) + 1;
+      if( zColSeq==0 ) zColSeq = "binary";
+      nCopy = STRLEN(zColSeq) + 1;
       pNew->aCol[nCol].zColl = pCsr;
-      memcpy(pCsr, zCol, nCopy);
+      memcpy(pCsr, zColSeq, nCopy);
       pCsr += nCopy;
     }
 
@@ -9899,9 +9997,9 @@
   if( rc!=SQLITE_OK ){
     sqlite3_free(pNew);
     pNew = 0;
-  }else{
+  }else if( ALWAYS(pNew!=0) ){
     pNew->zName = pCsr;
-    memcpy(pNew->zName, zTab, nTab+1);
+    if( ALWAYS(pNew->zName!=0) ) memcpy(pNew->zName, zTab, nTab+1);
   }
 
   *ppOut = pNew;
@@ -10027,6 +10125,7 @@
     IdxConstraint *pT = pTail;
     sqlite3_stmt *pInfo = 0;
     const char *zIdx = (const char*)sqlite3_column_text(pIdxList, 1);
+    if( zIdx==0 ) continue;
 
     /* Zero the IdxConstraint.bFlag values in the pEq list */
     for(pIter=pEq; pIter; pIter=pIter->pLink) pIter->bFlag = 0;
@@ -10072,6 +10171,19 @@
   return 0;
 }
 
+/* Callback for sqlite3_exec() with query with leading count(*) column.
+ * The first argument is expected to be an int*, referent to be incremented
+ * if that leading column is not exactly '0'.
+ */
+static int countNonzeros(void* pCount, int nc,
+                         char* azResults[], char* azColumns[]){
+  (void)azColumns;  /* Suppress unused parameter warning */
+  if( nc>0 && (azResults[0][0]!='0' || azResults[0][1]!=0) ){
+    *((int *)pCount) += 1;
+  }
+  return 0;
+}
+
 static int idxCreateFromCons(
   sqlite3expert *p,
   IdxScan *pScan,
@@ -10098,17 +10210,40 @@
     if( rc==SQLITE_OK ){
       /* Hash the list of columns to come up with a name for the index */
       const char *zTable = pScan->pTab->zName;
-      char *zName;                /* Index name */
-      int i;
-      for(i=0; zCols[i]; i++){
-        h += ((h<<3) + zCols[i]);
-      }
-      zName = sqlite3_mprintf("%s_idx_%08x", zTable, h);
-      if( zName==0 ){ 
+      int quoteTable = idxIdentifierRequiresQuotes(zTable);
+      char *zName = 0;          /* Index name */
+      int collisions = 0;
+      do{
+        int i;
+        char *zFind;
+        for(i=0; zCols[i]; i++){
+          h += ((h<<3) + zCols[i]);
+        }
+        sqlite3_free(zName);
+        zName = sqlite3_mprintf("%s_idx_%08x", zTable, h);
+        if( zName==0 ) break;
+        /* Is is unique among table, view and index names? */
+        zFmt = "SELECT count(*) FROM sqlite_schema WHERE name=%Q"
+          " AND type in ('index','table','view')";
+        zFind = sqlite3_mprintf(zFmt, zName);
+        i = 0;
+        rc = sqlite3_exec(dbm, zFind, countNonzeros, &i, 0);
+        assert(rc==SQLITE_OK);
+        sqlite3_free(zFind);
+        if( i==0 ){
+          collisions = 0;
+          break;
+        }
+        ++collisions;
+      }while( collisions<50 && zName!=0 );
+      if( collisions ){
+        /* This return means "Gave up trying to find a unique index name." */
+        rc = SQLITE_BUSY_TIMEOUT;
+      }else if( zName==0 ){
         rc = SQLITE_NOMEM;
       }else{
-        if( idxIdentifierRequiresQuotes(zTable) ){
-          zFmt = "CREATE INDEX '%q' ON %Q(%s)";
+        if( quoteTable ){
+          zFmt = "CREATE INDEX \"%w\" ON \"%w\"(%s)";
         }else{
           zFmt = "CREATE INDEX %s ON %s(%s)";
         }
@@ -10117,7 +10252,11 @@
           rc = SQLITE_NOMEM;
         }else{
           rc = sqlite3_exec(dbm, zIdx, 0, 0, p->pzErrmsg);
-          idxHashAdd(&rc, &p->hIdx, zName, zIdx);
+          if( rc!=SQLITE_OK ){
+            rc = SQLITE_BUSY_TIMEOUT;
+          }else{
+            idxHashAdd(&rc, &p->hIdx, zName, zIdx);
+          }
         }
         sqlite3_free(zName);
         sqlite3_free(zIdx);
@@ -10269,7 +10408,7 @@
 ** runs all the queries to see which indexes they prefer, and populates
 ** IdxStatement.zIdx and IdxStatement.zEQP with the results.
 */
-int idxFindIndexes(
+static int idxFindIndexes(
   sqlite3expert *p,
   char **pzErr                         /* OUT: Error message (sqlite3_malloc) */
 ){
@@ -10398,6 +10537,7 @@
   rc = idxPrintfPrepareStmt(p->db, &pSelect, pzErr, zSql, zTab, zTab);
   while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSelect) ){
     const char *zCreate = (const char*)sqlite3_column_text(pSelect, 0);
+    if( zCreate==0 ) continue;
     rc = sqlite3_exec(p->dbv, zCreate, 0, 0, pzErr);
   }
   idxFinalize(&rc, pSelect);
@@ -10500,8 +10640,9 @@
     const char *zName = (const char*)sqlite3_column_text(pSchema, 1);
     const char *zSql = (const char*)sqlite3_column_text(pSchema, 2);
 
+    if( zType==0 || zName==0 ) continue;
     if( zType[0]=='v' || zType[1]=='r' ){
-      rc = sqlite3_exec(p->dbv, zSql, 0, 0, pzErrmsg);
+      if( zSql ) rc = sqlite3_exec(p->dbv, zSql, 0, 0, pzErrmsg);
     }else{
       IdxTable *pTab;
       rc = idxGetTableInfo(p->db, zName, &pTab, pzErrmsg);
@@ -10638,6 +10779,7 @@
     case SQLITE_BLOB:
     case SQLITE_TEXT: {
       int nByte = sqlite3_value_bytes(argv[1]);
+      const void *pData = 0;
       if( nByte>pSlot->nByte ){
         char *zNew = (char*)sqlite3_realloc(pSlot->z, nByte*2);
         if( zNew==0 ){
@@ -10649,9 +10791,11 @@
       }
       pSlot->n = nByte;
       if( pSlot->eType==SQLITE_BLOB ){
-        memcpy(pSlot->z, sqlite3_value_blob(argv[1]), nByte);
+        pData = sqlite3_value_blob(argv[1]);
+        if( pData ) memcpy(pSlot->z, pData, nByte);
       }else{
-        memcpy(pSlot->z, sqlite3_value_text(argv[1]), nByte);
+        pData = sqlite3_value_text(argv[1]);
+        memcpy(pSlot->z, pData, nByte);
       }
       break;
     }
@@ -10862,6 +11006,7 @@
     i64 iRowid = sqlite3_column_int64(pAllIndex, 0);
     const char *zTab = (const char*)sqlite3_column_text(pAllIndex, 1);
     const char *zIdx = (const char*)sqlite3_column_text(pAllIndex, 2);
+    if( zTab==0 || zIdx==0 ) continue;
     if( p->iSample<100 && iPrev!=iRowid ){
       samplectx.target = (double)p->iSample / 100.0;
       samplectx.iTarget = p->iSample;
@@ -10928,14 +11073,14 @@
 
   /* Copy the entire schema of database [db] into [dbm]. */
   if( rc==SQLITE_OK ){
-    sqlite3_stmt *pSql;
+    sqlite3_stmt *pSql = 0;
     rc = idxPrintfPrepareStmt(pNew->db, &pSql, pzErrmsg, 
         "SELECT sql FROM sqlite_schema WHERE name NOT LIKE 'sqlite_%%'"
         " AND sql NOT LIKE 'CREATE VIRTUAL %%'"
     );
     while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
       const char *zSql = (const char*)sqlite3_column_text(pSql, 0);
-      rc = sqlite3_exec(pNew->dbm, zSql, 0, 0, pzErrmsg);
+      if( zSql ) rc = sqlite3_exec(pNew->dbm, zSql, 0, 0, pzErrmsg);
     }
     idxFinalize(&rc, pSql);
   }
@@ -11041,6 +11186,10 @@
   /* Create candidate indexes within the in-memory database file */
   if( rc==SQLITE_OK ){
     rc = idxCreateCandidates(p);
+  }else if ( rc==SQLITE_BUSY_TIMEOUT ){
+    if( pzErr )
+      *pzErr = sqlite3_mprintf("Cannot find a unique index name to propose.");
+    return rc;
   }
 
   /* Generate the stat1 data */
@@ -12018,6 +12167,15 @@
   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 }
+
 /*
 ** State information about the database connection is contained in an
 ** instance of the following structure.
@@ -12034,8 +12192,12 @@
   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 */
+  ColModeOpts cmOpts;    /* Option values affecting columnar mode output */
   unsigned statsOn;      /* True to display memory stats before each finalize */
   unsigned mEqpLines;    /* Mask of veritical 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 */
@@ -12070,23 +12232,37 @@
   char nullValue[20];    /* The text to print when a NULL comes back from
                          ** the database */
   char outfile[FILENAME_MAX]; /* Filename for *out */
-  const char *zDbFilename;    /* name of the database file */
-  char *zFreeOnClose;         /* Filename to free when closing */
-  const char *zVfs;           /* Name of VFS to use */
   sqlite3_stmt *pStmt;   /* Current statement if any. */
   FILE *pLog;            /* Write log output here */
+  struct AuxDb {         /* Storage space for auxiliary database connections */
+    sqlite3 *db;               /* Connection pointer */
+    const char *zDbFilename;   /* Filename used to open the connection */
+    char *zFreeOnClose;        /* Free this memory allocation on close */
+#if defined(SQLITE_ENABLE_SESSION)
+    int nSession;              /* Number of active sessions */
+    OpenSession aSession[4];   /* Array of sessions.  [0] is in focus. */
+#endif
+  } aAuxDb[5],           /* Array of all database connections */
+    *pAuxDb;             /* Currently active database connection */
   int *aiIndent;         /* Array of indents used in MODE_Explain */
   int nIndent;           /* Size of array aiIndent[] */
   int iIndent;           /* Index of current op in aiIndent[] */
+  char *zNonce;          /* Nonce for temporary safe-mode excapes */
   EQPGraph sGraph;       /* Information for the graphical EXPLAIN QUERY PLAN */
-#if defined(SQLITE_ENABLE_SESSION)
-  int nSession;             /* Number of active sessions */
-  OpenSession aSession[4];  /* Array of sessions.  [0] is in focus. */
+  ExpertInfo expert;     /* Valid if previous command was ".expert OPT..." */
+#ifdef SQLITE_SHELL_WASM_MODE
+  struct {
+    const char * zInput; /* Input string from wasm/JS proxy */
+    const char * zPos;   /* Cursor pos into zInput */
+  } wasm;
 #endif
-  ExpertInfo expert;        /* Valid if previous command was ".expert OPT..." */
 };
 
+#ifdef SQLITE_SHELL_WASM_MODE
+static ShellState shellState;
+#endif
 
+
 /* Allowed values for ShellState.autoEQP
 */
 #define AUTOEQP_off      0           /* Automatic EXPLAIN QUERY PLAN is off */
@@ -12126,8 +12302,8 @@
 #define SHFLG_PreserveRowid  0x00000008 /* .dump preserves rowid values */
 #define SHFLG_Newlines       0x00000010 /* .dump --newline flag */
 #define SHFLG_CountChanges   0x00000020 /* .changes setting */
-#define SHFLG_Echo           0x00000040 /* .echo or --echo setting */
-#define SHFLG_HeaderSet      0x00000080 /* .header has been used */
+#define SHFLG_Echo           0x00000040 /* .echo on/off, or --echo setting */
+#define SHFLG_HeaderSet      0x00000080 /* showHeader has been specified */
 #define SHFLG_DumpDataOnly   0x00000100 /* .dump show data only */
 #define SHFLG_DumpNoSys      0x00000200 /* .dump omits system tables */
 
@@ -12158,6 +12334,8 @@
 #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 */
 
 static const char *modeDescr[] = {
   "line",
@@ -12176,7 +12354,9 @@
   "json",
   "markdown",
   "table",
-  "box"
+  "box",
+  "count",
+  "off"
 };
 
 /*
@@ -12193,6 +12373,12 @@
 #define SEP_Record    "\x1E"
 
 /*
+** Limit input nesting via .read or any other input redirect.
+** It's not too expensive, so a generous allowance can be made.
+*/
+#define MAX_INPUT_NESTING 25
+
+/*
 ** A callback for the sqlite3_log() interface.
 */
 static void shellLog(void *pArg, int iErrCode, const char *zMsg){
@@ -12220,6 +12406,27 @@
 }
 
 /*
+** If in safe mode, print an error message described by the arguments
+** and exit immediately.
+*/
+static void failIfSafeMode(
+  ShellState *p,
+  const char *zErrMsg,
+  ...
+){
+  if( p->bSafeMode ){
+    va_list ap;
+    char *zMsg;
+    va_start(ap, zErrMsg);
+    zMsg = sqlite3_vmprintf(zErrMsg, ap);
+    va_end(ap);
+    raw_printf(stderr, "line %d: ", p->lineno);
+    utf8_printf(stderr, "%s\n", zMsg);
+    exit(1);
+  }
+}
+
+/*
 ** SQL function:   edit(VALUE)
 **                 edit(VALUE,EDITOR)
 **
@@ -12339,7 +12546,6 @@
     sqlite3_int64 i, j;
     if( hasCRNL ){
       /* If the original contains \r\n then do no conversions back to \n */
-      j = sz;
     }else{
       /* If the file did not originally contain \r\n then convert any new
       ** \r\n back into \n */
@@ -12647,18 +12853,16 @@
   if( z==0 ){
     utf8_printf(out,"%s",p->nullValue);
   }else{
-    int i;
-    int nSep = strlen30(p->colSeparator);
+    unsigned i;
     for(i=0; z[i]; i++){
-      if( needCsvQuote[((unsigned char*)z)[i]]
-         || (z[i]==p->colSeparator[0] &&
-             (nSep==1 || memcmp(z, p->colSeparator, nSep)==0)) ){
+      if( needCsvQuote[((unsigned char*)z)[i]] ){
         i = 0;
         break;
       }
     }
-    if( i==0 ){
+    if( i==0 || strstr(z, p->colSeparator)!=0 ){
       char *zQuoted = sqlite3_mprintf("\"%w\"", z);
+      shell_check_oom(zQuoted);
       utf8_printf(out, "%s", zQuoted);
       sqlite3_free(zQuoted);
     }else{
@@ -12697,6 +12901,53 @@
 
 #ifndef SQLITE_OMIT_AUTHORIZATION
 /*
+** This authorizer runs in safe mode.
+*/
+static int safeModeAuth(
+  void *pClientData,
+  int op,
+  const char *zA1,
+  const char *zA2,
+  const char *zA3,
+  const char *zA4
+){
+  ShellState *p = (ShellState*)pClientData;
+  static const char *azProhibitedFunctions[] = {
+    "edit",
+    "fts3_tokenizer",
+    "load_extension",
+    "readfile",
+    "writefile",
+    "zipfile",
+    "zipfile_cds",
+  };
+  UNUSED_PARAMETER(zA2);
+  UNUSED_PARAMETER(zA3);
+  UNUSED_PARAMETER(zA4);
+  switch( op ){
+    case SQLITE_ATTACH: {
+#ifndef SQLITE_SHELL_WASM_MODE
+      /* In WASM builds the filesystem is a virtual sandbox, so
+      ** there's no harm in using ATTACH. */
+      failIfSafeMode(p, "cannot run ATTACH in safe mode");
+#endif
+      break;
+    }
+    case SQLITE_FUNCTION: {
+      int i;
+      for(i=0; i<ArraySize(azProhibitedFunctions); i++){
+        if( sqlite3_stricmp(zA1, azProhibitedFunctions[i])==0 ){
+          failIfSafeMode(p, "cannot use the %s() function in safe mode",
+                         azProhibitedFunctions[i]);
+        }
+      }
+      break;
+    }
+  }
+  return SQLITE_OK;
+}
+
+/*
 ** When the ".auth ON" is set, the following authorizer callback is
 ** invoked.  It always returns SQLITE_OK.
 */
@@ -12738,6 +12989,7 @@
     }
   }
   raw_printf(p->out, "\n");
+  if( p->bSafeMode ) (void)safeModeAuth(pClientData, op, zA1, zA2, zA3, zA4);
   return SQLITE_OK;
 }
 #endif
@@ -12789,7 +13041,7 @@
     utf8_printf(p->out, "%d,%d,%s\n", iEqpId, p2, zText);
   }
   pNew = sqlite3_malloc64( sizeof(*pNew) + nText );
-  if( pNew==0 ) shell_out_of_memory();
+  shell_check_oom(pNew);
   pNew->iEqpId = iEqpId;
   pNew->iParentId = p2;
   memcpy(pNew->zText, zText, nText+1);
@@ -12937,6 +13189,10 @@
 
   if( azArg==0 ) return 0;
   switch( p->cMode ){
+    case MODE_Count:
+    case MODE_Off: {
+      break;
+    }
     case MODE_Line: {
       int w = 5;
       if( azArg==0 ) break;
@@ -13006,6 +13262,7 @@
         break;
       }
       z = sqlite3_mprintf("%s", azArg[0]);
+      shell_check_oom(z);
       j = 0;
       for(i=0; IsSpace(z[i]); i++){}
       for(; (c = z[i])!=0; i++){
@@ -13137,6 +13394,7 @@
           if( i>0 ) raw_printf(p->out, ",");
           if( quoteChar(azCol[i]) ){
             char *z = sqlite3_mprintf("\"%w\"", azCol[i]);
+            shell_check_oom(z);
             utf8_printf(p->out, "%s", z);
             sqlite3_free(z);
           }else{
@@ -13168,7 +13426,12 @@
           }else if( ur==0xfff0000000000000LL ){
             raw_printf(p->out, "-1e999");
           }else{
-            sqlite3_snprintf(50,z,"%!.20g", r);
+            sqlite3_int64 ir = (sqlite3_int64)r;
+            if( r==(double)ir ){
+              sqlite3_snprintf(50,z,"%lld.0", ir);
+            }else{
+              sqlite3_snprintf(50,z,"%!.20g", r);
+            }
             raw_printf(p->out, "%s", z);
           }
         }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
@@ -13382,7 +13645,7 @@
   n = strlen30(zName);
   if( cQuote ) n += n+2;
   z = p->zDestTable = malloc( n+1 );
-  if( z==0 ) shell_out_of_memory();
+  shell_check_oom(z);
   n = 0;
   if( cQuote ) z[n++] = cQuote;
   for(i=0; zName[i]; i++){
@@ -13393,7 +13656,48 @@
   z[n] = 0;
 }
 
+/*
+** Maybe construct two lines of text that point out the position of a
+** syntax error.  Return a pointer to the text, in memory obtained from
+** sqlite3_malloc().  Or, if the most recent error does not involve a
+** specific token that we can point to, return an empty string.
+**
+** In all cases, the memory returned is obtained from sqlite3_malloc64()
+** and should be released by the caller invoking sqlite3_free().
+*/
+static char *shell_error_context(const char *zSql, sqlite3 *db){
+  int iOffset;
+  size_t len;
+  char *zCode;
+  char *zMsg;
+  int i;
+  if( db==0
+   || zSql==0
+   || (iOffset = sqlite3_error_offset(db))<0
+  ){
+    return sqlite3_mprintf("");
+  }
+  while( iOffset>50 ){
+    iOffset--;
+    zSql++;
+    while( (zSql[0]&0xc0)==0x80 ){ zSql++; iOffset--; }
+  }
+  len = strlen(zSql);
+  if( len>78 ){
+    len = 78;
+    while( (zSql[len]&0xc0)==0x80 ) len--;
+  }
+  zCode = sqlite3_mprintf("%.*s", len, zSql);
+  for(i=0; zCode[i]; i++){ if( IsSpace(zSql[i]) ) zCode[i] = ' '; }
+  if( iOffset<25 ){
+    zMsg = sqlite3_mprintf("\n  %z\n  %*s^--- error here", zCode, iOffset, "");
+  }else{
+    zMsg = sqlite3_mprintf("\n  %z\n  %*serror here ---^", zCode, iOffset-14, "");
+  }
+  return zMsg;
+}
 
+
 /*
 ** Execute a query statement that will generate SQL output.  Print
 ** the result columns, comma-separated, on a line and then add a
@@ -13415,8 +13719,10 @@
   const char *z;
   rc = sqlite3_prepare_v2(p->db, zSelect, -1, &pSelect, 0);
   if( rc!=SQLITE_OK || !pSelect ){
-    utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n", rc,
-                sqlite3_errmsg(p->db));
+    char *zContext = shell_error_context(zSelect, p->db);
+    utf8_printf(p->out, "/**** ERROR: (%d) %s *****/\n%s", rc,
+                sqlite3_errmsg(p->db), zContext);
+    sqlite3_free(zContext);
     if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
     return rc;
   }
@@ -13447,17 +13753,29 @@
 }
 
 /*
-** Allocate space and save off current error string.
+** Allocate space and save off string indicating current error.
 */
 static char *save_err_msg(
-  sqlite3 *db            /* Database to query */
+  sqlite3 *db,           /* Database to query */
+  const char *zPhase,    /* When the error occcurs */
+  int rc,                /* Error code returned from API */
+  const char *zSql       /* SQL string, or NULL */
 ){
-  int nErrMsg = 1+strlen30(sqlite3_errmsg(db));
-  char *zErrMsg = sqlite3_malloc64(nErrMsg);
-  if( zErrMsg ){
-    memcpy(zErrMsg, sqlite3_errmsg(db), nErrMsg);
+  char *zErr;
+  char *zContext;
+  sqlite3_str *pStr = sqlite3_str_new(0);
+  sqlite3_str_appendf(pStr, "%s, %s", zPhase, sqlite3_errmsg(db));
+  if( rc>1 ){
+    sqlite3_str_appendf(pStr, " (%d)", rc);
   }
-  return zErrMsg;
+  zContext = shell_error_context(zSql, db);
+  if( zContext ){
+    sqlite3_str_appendall(pStr, zContext);
+    sqlite3_free(zContext);
+  }
+  zErr = sqlite3_str_finish(pStr);
+  shell_check_oom(zErr);
+  return zErr;
 }
 
 #ifdef __linux__
@@ -13635,13 +13953,20 @@
   }
 
   if( pArg->pStmt ){
+    int iHit, iMiss;
     iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP,
                                bReset);
     raw_printf(pArg->out, "Fullscan Steps:                      %d\n", iCur);
     iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
     raw_printf(pArg->out, "Sort Operations:                     %d\n", iCur);
     iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset);
     raw_printf(pArg->out, "Autoindex Inserts:                   %d\n", iCur);
+    iHit = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FILTER_HIT, bReset);
+    iMiss = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FILTER_MISS, bReset);
+    if( iHit || iMiss ){
+      raw_printf(pArg->out, "Bloom filter bypass taken:           %d/%d\n",
+            iHit, iHit+iMiss);
+    }
     iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
     raw_printf(pArg->out, "Virtual Machine Steps:               %d\n", iCur);
     iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE,bReset);
@@ -13734,6 +14059,9 @@
 **       all opcodes that occur between the p2 jump destination and the opcode
 **       itself by 2 spaces.
 **
+**     * Do the previous for "Return" instructions for when P2 is positive.
+**       See tag-20220407a in wherecode.c and vdbe.c.
+**
 **     * For each "Goto", if the jump destination is earlier in the program
 **       and ends on one of:
 **          Yield  SeekGt  SeekLt  RowSetRead  Rewind
@@ -13748,7 +14076,8 @@
   int nAlloc = 0;                 /* Allocated size of p->aiIndent[], abYield */
   int iOp;                        /* Index of operation in p->aiIndent[] */
 
-  const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", 0 };
+  const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext",
+                           "Return", 0 };
   const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead",
                             "Rewind", 0 };
   const char *azGoto[] = { "Goto", 0 };
@@ -13798,15 +14127,15 @@
       }
       nAlloc += 100;
       p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int));
-      if( p->aiIndent==0 ) shell_out_of_memory();
+      shell_check_oom(p->aiIndent);
       abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int));
-      if( abYield==0 ) shell_out_of_memory();
+      shell_check_oom(abYield);
     }
     abYield[iOp] = str_in_array(zOp, azYield);
     p->aiIndent[iOp] = 0;
     p->nIndent = iOp+1;
 
-    if( str_in_array(zOp, azNext) ){
+    if( str_in_array(zOp, azNext) && p2op>0 ){
       for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
     }
     if( str_in_array(zOp, azGoto) && p2op<p->nIndent
@@ -13832,7 +14161,7 @@
 }
 
 /*
-** Disable and restore .wheretrace and .selecttrace settings.
+** Disable and restore .wheretrace and .treetrace/.selecttrace settings.
 */
 static unsigned int savedSelectTrace;
 static unsigned int savedWhereTrace;
@@ -13976,8 +14305,135 @@
   fputs("\n", p->out);
 }
 
+/*
+** z[] is a line of text that is to be displayed the .mode box or table or
+** similar tabular formats.  z[] might contain control characters such
+** as \n, \t, \f, or \r.
+**
+** Compute characters to display on the first line of z[].  Stop at the
+** first \r, \n, or \f.  Expand \t into spaces.  Return a copy (obtained
+** from malloc()) of that first line, which caller should free sometime.
+** Write anything to display on the next line into *pzTail.  If this is
+** the last line, write a NULL into *pzTail. (*pzTail is not allocated.)
+*/
+static char *translateForDisplayAndDup(
+  const unsigned char *z,            /* Input text to be transformed */
+  const unsigned char **pzTail,      /* OUT: Tail of the input for next line */
+  int mxWidth,                       /* Max width.  0 means no limit */
+  u8 bWordWrap                       /* If true, avoid breaking mid-word */
+){
+  int i;                 /* Input bytes consumed */
+  int j;                 /* Output bytes generated */
+  int k;                 /* Input bytes to be displayed */
+  int n;                 /* Output column number */
+  unsigned char *zOut;   /* Output text */
 
+  if( z==0 ){
+    *pzTail = 0;
+    return 0;
+  }
+  if( mxWidth<0 ) mxWidth = -mxWidth;
+  if( mxWidth==0 ) mxWidth = 1000000;
+  i = j = n = 0;
+  while( n<mxWidth ){
+    if( z[i]>=' ' ){
+      n++;
+      do{ i++; j++; }while( (z[i]&0xc0)==0x80 );
+      continue;
+    }
+    if( z[i]=='\t' ){
+      do{
+        n++;
+        j++;
+      }while( (n&7)!=0 && n<mxWidth );
+      i++;
+      continue;
+    }
+    break;
+  }
+  if( n>=mxWidth && bWordWrap  ){
+    /* Perhaps try to back up to a better place to break the line */
+    for(k=i; k>i/2; k--){
+      if( isspace(z[k-1]) ) break;
+    }
+    if( k<=i/2 ){
+      for(k=i; k>i/2; k--){
+        if( isalnum(z[k-1])!=isalnum(z[k]) && (z[k]&0xc0)!=0x80 ) break;
+      }
+    }
+    if( k<=i/2 ){
+      k = i;
+    }else{
+      i = k;
+      while( z[i]==' ' ) i++;
+    }
+  }else{
+    k = i;
+  }
+  if( n>=mxWidth && z[i]>=' ' ){
+   *pzTail = &z[i];
+  }else if( z[i]=='\r' && z[i+1]=='\n' ){
+    *pzTail = z[i+2] ? &z[i+2] : 0;
+  }else if( z[i]==0 || z[i+1]==0 ){
+    *pzTail = 0;
+  }else{
+    *pzTail = &z[i+1];
+  }
+  zOut = malloc( j+1 );
+  shell_check_oom(zOut);
+  i = j = n = 0;
+  while( i<k ){
+    if( z[i]>=' ' ){
+      n++;
+      do{ zOut[j++] = z[i++]; }while( (z[i]&0xc0)==0x80 );
+      continue;
+    }
+    if( z[i]=='\t' ){
+      do{
+        n++;
+        zOut[j++] = ' ';
+      }while( (n&7)!=0 && n<mxWidth );
+      i++;
+      continue;
+    }
+    break;
+  }
+  zOut[j] = 0;
+  return (char*)zOut;  
+}
 
+/* Extract the value of the i-th current column for pStmt as an SQL literal
+** value.  Memory is obtained from sqlite3_malloc64() and must be freed by
+** the caller.
+*/
+static char *quoted_column(sqlite3_stmt *pStmt, int i){
+  switch( sqlite3_column_type(pStmt, i) ){
+    case SQLITE_NULL: {
+      return sqlite3_mprintf("NULL");
+    }
+    case SQLITE_INTEGER:
+    case SQLITE_FLOAT: {
+      return sqlite3_mprintf("%s",sqlite3_column_text(pStmt,i));
+    }
+    case SQLITE_TEXT: {
+      return sqlite3_mprintf("%Q",sqlite3_column_text(pStmt,i));
+    }
+    case SQLITE_BLOB: {
+      int j;
+      sqlite3_str *pStr = sqlite3_str_new(0);
+      const unsigned char *a = sqlite3_column_blob(pStmt,i);
+      int n = sqlite3_column_bytes(pStmt,i);
+      sqlite3_str_append(pStr, "x'", 2);
+      for(j=0; j<n; j++){
+        sqlite3_str_appendf(pStr, "%02x", a[j]);
+      }
+      sqlite3_str_append(pStr, "'", 1);
+      return sqlite3_str_finish(pStr);
+    }
+  }
+  return 0; /* Not reached */
+}
+
 /*
 ** Run a prepared statement and output the result in one of the
 ** table-oriented formats: MODE_Column, MODE_Markdown, MODE_Table,
@@ -13996,38 +14452,42 @@
   int nColumn = 0;
   char **azData = 0;
   sqlite3_int64 nAlloc = 0;
+  char *abRowDiv = 0;
+  const unsigned char *uz;
   const char *z;
+  char **azQuoted = 0;
   int rc;
   sqlite3_int64 i, nData;
   int j, nTotal, w, n;
   const char *colSep = 0;
   const char *rowSep = 0;
+  const unsigned char **azNextLine = 0;
+  int bNextLine = 0;
+  int bMultiLineRowExists = 0;
+  int bw = p->cmOpts.bWordWrap;
+  const char *zEmpty = "";
+  const char *zShowNull = p->nullValue;
 
   rc = sqlite3_step(pStmt);
   if( rc!=SQLITE_ROW ) return;
   nColumn = sqlite3_column_count(pStmt);
   nAlloc = nColumn*4;
   if( nAlloc<=0 ) nAlloc = 1;
   azData = sqlite3_malloc64( nAlloc*sizeof(char*) );
-  if( azData==0 ) shell_out_of_memory();
-  for(i=0; i<nColumn; i++){
-    azData[i] = strdup(sqlite3_column_name(pStmt,i));
+  shell_check_oom(azData);
+  azNextLine = sqlite3_malloc64( nColumn*sizeof(char*) );
+  shell_check_oom((void*)azNextLine);
+  memset((void*)azNextLine, 0, nColumn*sizeof(char*) );
+  if( p->cmOpts.bQuote ){
+    azQuoted = sqlite3_malloc64( nColumn*sizeof(char*) );
+    shell_check_oom(azQuoted);
+    memset(azQuoted, 0, nColumn*sizeof(char*) );
   }
-  do{
-    if( (nRow+2)*nColumn >= nAlloc ){
-      nAlloc *= 2;
-      azData = sqlite3_realloc64(azData, nAlloc*sizeof(char*));
-      if( azData==0 ) shell_out_of_memory();
-    }
-    nRow++;
-    for(i=0; i<nColumn; i++){
-      z = (const char*)sqlite3_column_text(pStmt,i);
-      azData[nRow*nColumn + i] = z ? strdup(z) : 0;
-    }
-  }while( (rc = sqlite3_step(pStmt))==SQLITE_ROW );
+  abRowDiv = sqlite3_malloc64( nAlloc/nColumn );
+  shell_check_oom(abRowDiv);
   if( nColumn>p->nWidth ){
-    p->colWidth = realloc(p->colWidth, nColumn*2*sizeof(int));
-    if( p->colWidth==0 ) shell_out_of_memory();
+    p->colWidth = realloc(p->colWidth, (nColumn+1)*2*sizeof(int));
+    shell_check_oom(p->colWidth);
     for(i=p->nWidth; i<nColumn; i++) p->colWidth[i] = 0;
     p->nWidth = nColumn;
     p->actualWidth = &p->colWidth[nColumn];
@@ -14038,10 +14498,58 @@
     if( w<0 ) w = -w;
     p->actualWidth[i] = w;
   }
+  for(i=0; i<nColumn; i++){
+    const unsigned char *zNotUsed;
+    int wx = p->colWidth[i];
+    if( wx==0 ){
+      wx = p->cmOpts.iWrap;
+    }
+    if( wx<0 ) wx = -wx;
+    uz = (const unsigned char*)sqlite3_column_name(pStmt,i);
+    azData[i] = translateForDisplayAndDup(uz, &zNotUsed, wx, bw);
+  }
+  do{
+    int useNextLine = bNextLine;
+    bNextLine = 0;
+    if( (nRow+2)*nColumn >= nAlloc ){
+      nAlloc *= 2;
+      azData = sqlite3_realloc64(azData, nAlloc*sizeof(char*));
+      shell_check_oom(azData);
+      abRowDiv = sqlite3_realloc64(abRowDiv, nAlloc/nColumn);
+      shell_check_oom(abRowDiv);
+    }
+    abRowDiv[nRow] = 1;
+    nRow++;
+    for(i=0; i<nColumn; i++){
+      int wx = p->colWidth[i];
+      if( wx==0 ){
+        wx = p->cmOpts.iWrap;
+      }
+      if( wx<0 ) wx = -wx;
+      if( useNextLine ){
+        uz = azNextLine[i];
+        if( uz==0 ) uz = (u8*)zEmpty;
+      }else if( p->cmOpts.bQuote ){
+        sqlite3_free(azQuoted[i]);
+        azQuoted[i] = quoted_column(pStmt,i);
+        uz = (const unsigned char*)azQuoted[i];
+      }else{
+        uz = (const unsigned char*)sqlite3_column_text(pStmt,i);
+        if( uz==0 ) uz = (u8*)zShowNull;
+      }
+      azData[nRow*nColumn + i]
+        = translateForDisplayAndDup(uz, &azNextLine[i], wx, bw);
+      if( azNextLine[i] ){
+        bNextLine = 1;
+        abRowDiv[nRow-1] = 0;
+        bMultiLineRowExists = 1;
+      }
+    }
+  }while( bNextLine || sqlite3_step(pStmt)==SQLITE_ROW );
   nTotal = nColumn*(nRow+1);
   for(i=0; i<nTotal; i++){
     z = azData[i];
-    if( z==0 ) z = p->nullValue;
+    if( z==0 ) z = (char*)zEmpty;
     n = strlenChar(z);
     j = i%nColumn;
     if( n>p->actualWidth[j] ) p->actualWidth[j] = n;
@@ -14120,6 +14628,15 @@
     utf8_width_print(p->out, w, z);
     if( j==nColumn-1 ){
       utf8_printf(p->out, "%s", rowSep);
+      if( bMultiLineRowExists && abRowDiv[i/nColumn-1] && i+1<nTotal ){
+        if( p->cMode==MODE_Table ){
+          print_row_separator(p, nColumn, "+");
+        }else if( p->cMode==MODE_Box ){
+          print_box_row_separator(p, nColumn, BOX_123, BOX_1234, BOX_134);
+        }else if( p->cMode==MODE_Column ){
+          raw_printf(p->out, "\n");
+        }
+      }
       j = -1;
       if( seenInterrupt ) goto columnar_end;
     }else{
@@ -14136,8 +14653,17 @@
     utf8_printf(p->out, "Interrupt\n");
   }
   nData = (nRow+1)*nColumn;
-  for(i=0; i<nData; i++) free(azData[i]);
+  for(i=0; i<nData; i++){
+    z = azData[i];
+    if( z!=zEmpty && z!=zShowNull ) free(azData[i]);
+  }
   sqlite3_free(azData);
+  sqlite3_free((void*)azNextLine);
+  sqlite3_free(abRowDiv);
+  if( azQuoted ){
+    for(i=0; i<nColumn; i++) sqlite3_free(azQuoted[i]);
+    sqlite3_free(azQuoted);
+  }
 }
 
 /*
@@ -14148,6 +14674,7 @@
   sqlite3_stmt *pStmt                              /* Statment to run */
 ){
   int rc;
+  sqlite3_uint64 nRow = 0;
 
   if( pArg->cMode==MODE_Column
    || pArg->cMode==MODE_Table
@@ -14168,7 +14695,7 @@
     int nCol = sqlite3_column_count(pStmt);
     void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1);
     if( !pData ){
-      rc = SQLITE_NOMEM;
+      shell_out_of_memory();
     }else{
       char **azCols = (char **)pData;      /* Names of result columns */
       char **azVals = &azCols[nCol];       /* Results */
@@ -14180,10 +14707,14 @@
         azCols[i] = (char *)sqlite3_column_name(pStmt, i);
       }
       do{
+        nRow++;
         /* extract the data and data types */
         for(i=0; i<nCol; i++){
           aiTypes[i] = x = sqlite3_column_type(pStmt, i);
-          if( x==SQLITE_BLOB && pArg && pArg->cMode==MODE_Insert ){
+          if( x==SQLITE_BLOB
+           && pArg
+           && (pArg->cMode==MODE_Insert || pArg->cMode==MODE_Quote)
+          ){
             azVals[i] = "";
           }else{
             azVals[i] = (char*)sqlite3_column_text(pStmt, i);
@@ -14207,6 +14738,11 @@
       sqlite3_free(pData);
       if( pArg->cMode==MODE_Json ){
         fputs("]\n", pArg->out);
+      }else if( pArg->cMode==MODE_Count ){
+        char zBuf[200];
+        sqlite3_snprintf(sizeof(zBuf), zBuf, "%llu row%s\n",
+                         nRow, nRow!=1 ? "s" : "");
+        printf("%s", zBuf);
       }
     }
   }
@@ -14330,14 +14866,15 @@
   if( rc==SQLITE_OK ){
     pState->expert.pExpert = sqlite3_expert_new(pState->db, &zErr);
     if( pState->expert.pExpert==0 ){
-      raw_printf(stderr, "sqlite3_expert_new: %s\n", zErr);
+      raw_printf(stderr, "sqlite3_expert_new: %s\n", zErr ? zErr : "out of memory");
       rc = SQLITE_ERROR;
     }else{
       sqlite3_expert_config(
           pState->expert.pExpert, EXPERT_CONFIG_SAMPLE, iSample
       );
     }
   }
+  sqlite3_free(zErr);
 
   return rc;
 }
@@ -14379,7 +14916,7 @@
     rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
     if( SQLITE_OK != rc ){
       if( pzErrMsg ){
-        *pzErrMsg = save_err_msg(db);
+        *pzErrMsg = save_err_msg(db, "in prepare", rc, zSql);
       }
     }else{
       if( !pStmt ){
@@ -14398,11 +14935,6 @@
         pArg->cnt = 0;
       }
 
-      /* echo the sql statement if echo on */
-      if( pArg && ShellHasFlag(pArg, SHFLG_Echo) ){
-        utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
-      }
-
       /* Show the EXPLAIN QUERY PLAN if .eqp is on */
       if( pArg && pArg->autoEQP && sqlite3_stmt_isexplain(pStmt)==0 ){
         sqlite3_stmt *pExplain;
@@ -14414,6 +14946,7 @@
           sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0);
         }
         zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zStmtSql);
+        shell_check_oom(zEQP);
         rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
         if( rc==SQLITE_OK ){
           while( sqlite3_step(pExplain)==SQLITE_ROW ){
@@ -14431,6 +14964,7 @@
         if( pArg->autoEQP>=AUTOEQP_full ){
           /* Also do an EXPLAIN for ".eqp full" mode */
           zEQP = sqlite3_mprintf("EXPLAIN %s", zStmtSql);
+          shell_check_oom(zEQP);
           rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
           if( rc==SQLITE_OK ){
             pArg->cMode = MODE_Explain;
@@ -14493,7 +15027,7 @@
         zSql = zLeftover;
         while( IsSpace(zSql[0]) ) zSql++;
       }else if( pzErrMsg ){
-        *pzErrMsg = save_err_msg(db);
+        *pzErrMsg = save_err_msg(db, "stepping", rc, 0);
       }
 
       /* clear saved stmt handle */
@@ -14543,16 +15077,18 @@
   int rc;
 
   zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab);
+  shell_check_oom(zSql);
   rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
   sqlite3_free(zSql);
   if( rc ) return 0;
   while( sqlite3_step(pStmt)==SQLITE_ROW ){
     if( nCol>=nAlloc-2 ){
       nAlloc = nAlloc*2 + nCol + 10;
       azCol = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0]));
-      if( azCol==0 ) shell_out_of_memory();
+      shell_check_oom(azCol);
     }
     azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
+    shell_check_oom(azCol[nCol]);
     if( sqlite3_column_int(pStmt, 5) ){
       nPK++;
       if( nPK==1
@@ -14586,6 +15122,7 @@
     */
     zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)"
                            " WHERE origin='pk'", zTab);
+    shell_check_oom(zSql);
     rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
     sqlite3_free(zSql);
     if( rc ){
@@ -14677,6 +15214,7 @@
        "INSERT INTO sqlite_schema(type,name,tbl_name,rootpage,sql)"
        "VALUES('table','%q','%q',0,'%q');",
        zTable, zTable, zSql);
+    shell_check_oom(zIns);
     utf8_printf(p->out, "%s\n", zIns);
     sqlite3_free(zIns);
     return 0;
@@ -14795,25 +15333,28 @@
 ** Text of help messages.
 **
 ** The help text for each individual command begins with a line that starts
-** with ".".  Subsequent lines are supplimental information.
+** with ".".  Subsequent lines are supplemental information.
 **
 ** There must be two or more spaces between the end of the command and the
 ** start of the description of what that command does.
 */
 static const char *(azHelp[]) = {
-#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
+#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE) \
+  && !defined(SQLITE_SHELL_WASM_MODE)
   ".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",
@@ -14825,18 +15366,28 @@
 #ifndef SQLITE_OMIT_AUTHORIZATION
   ".auth ON|OFF             Show authorizer callbacks",
 #endif
+#ifndef SQLITE_SHELL_WASM_MODE
   ".backup ?DB? FILE        Backup DB (default \"main\") to FILE",
+  "   Options:",
   "       --append            Use the appendvfs",
   "       --async             Write to FILE without journal and fsync()",
+#endif
   ".bail on|off             Stop after hitting an error.  Default OFF",
   ".binary on|off           Turn binary output on or off.  Default OFF",
+#ifndef SQLITE_SHELL_WASM_MODE
   ".cd DIRECTORY            Change the working directory to DIRECTORY",
+#endif
   ".changes on|off          Show number of rows changed by SQL",
+#ifndef SQLITE_SHELL_WASM_MODE
   ".check GLOB              Fail if output since .testcase does not match",
   ".clone NEWDB             Clone data into NEWDB from the existing database",
+#endif
+  ".connection [close] [#]  Open or close an auxiliary database connection",
   ".databases               List names and files of attached databases",
   ".dbconfig ?op? ?val?     List or change sqlite3_db_config() options",
+#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
   ".dbinfo ?DB?             Show status information about the database",
+#endif
   ".dump ?OBJECTS?          Render database content as SQL",
   "   Options:",
   "     --data-only            Output only INSERT statements",
@@ -14853,9 +15404,13 @@
   "      trace                 Like \"full\" but enable \"PRAGMA vdbe_trace\"",
 #endif
   "      trigger               Like \"full\" but also show trigger bytecode",
+#ifndef SQLITE_SHELL_WASM_MODE
   ".excel                   Display the output of next command in spreadsheet",
   "   --bom                   Put a UTF8 byte-order mark on intermediate file",
+#endif
+#ifndef SQLITE_SHELL_WASM_MODE
   ".exit ?CODE?             Exit this program with return-code CODE",
+#endif
   ".expert                  EXPERIMENTAL. Suggest indexes for queries",
   ".explain ?on|off|auto?   Change the EXPLAIN formatting mode.  Default: auto",
   ".filectrl CMD ...        Run various sqlite3_file_control() operations",
@@ -14864,11 +15419,13 @@
   ".fullschema ?--indent?   Show schema and the content of sqlite_stat tables",
   ".headers on|off          Turn display of headers on or off",
   ".help ?-all? ?PATTERN?   Show help text for PATTERN",
+#ifndef SQLITE_SHELL_WASM_MODE
   ".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",
@@ -14877,6 +15434,7 @@
   "        from the \".mode\" output mode",
   "     *  If FILE begins with \"|\" then it is a command that generates the",
   "        input text.",
+#endif
 #ifndef SQLITE_OMIT_TEST_CONTROL
   ".imposter INDEX TABLE    Create imposter table TABLE on index INDEX",
 #endif
@@ -14890,38 +15448,53 @@
   ".lint OPTIONS            Report potential schema issues.",
   "     Options:",
   "        fkey-indexes     Find missing foreign key indexes",
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
+#if !defined(SQLITE_OMIT_LOAD_EXTENSION) && !defined(SQLITE_SHELL_WASM_MODE)
   ".load FILE ?ENTRY?       Load an extension library",
 #endif
+#ifndef SQLITE_SHELL_WASM_MODE
   ".log FILE|off            Turn logging on or off.  FILE can be stderr/stdout",
-  ".mode MODE ?TABLE?       Set output mode",
+#endif
+  ".mode MODE ?OPTIONS?     Set output mode",
   "   MODE is one of:",
-  "     ascii     Columns/rows delimited by 0x1F and 0x1E",
-  "     box       Tables using unicode box-drawing characters",
-  "     csv       Comma-separated values",
-  "     column    Output in columns.  (See .width)",
-  "     html      HTML <table> code",
-  "     insert    SQL insert statements for TABLE",
-  "     json      Results in a JSON array",
-  "     line      One value per line",
-  "     list      Values delimited by \"|\"",
-  "     markdown  Markdown table format",
-  "     quote     Escape answers as for SQL",
-  "     table     ASCII-art table",
-  "     tabs      Tab-separated values",
-  "     tcl       TCL list elements",
+  "     ascii       Columns/rows delimited by 0x1F and 0x1E",
+  "     box         Tables using unicode box-drawing characters",
+  "     csv         Comma-separated values",
+  "     column      Output in columns.  (See .width)",
+  "     html        HTML <table> code",
+  "     insert      SQL insert statements for TABLE",
+  "     json        Results in a JSON array",
+  "     line        One value per line",
+  "     list        Values delimited by \"|\"",
+  "     markdown    Markdown table format",
+  "     qbox        Shorthand for \"box --width 60 --quote\"",
+  "     quote       Escape answers as for SQL",
+  "     table       ASCII-art table",
+  "     tabs        Tab-separated values",
+  "     tcl         TCL list elements",
+  "   OPTIONS: (for columnar modes or insert mode):",
+  "     --wrap N       Wrap output lines to no longer than N characters",
+  "     --wordwrap B   Wrap or not at word boundaries per B (on/off)",
+  "     --ww           Shorthand for \"--wordwrap 1\"",
+  "     --quote        Quote output text as SQL literals",
+  "     --noquote      Do not quote output text",
+  "     TABLE          The name of SQL table used for \"insert\" mode",
+#ifndef SQLITE_SHELL_WASM_MODE
+  ".nonce STRING            Suspend safe mode for one command if nonce matches",
+#endif
   ".nullvalue STRING        Use STRING in place of NULL values",
+#ifndef SQLITE_SHELL_WASM_MODE
   ".once ?OPTIONS? ?FILE?   Output for the next SQL command only to FILE",
   "     If FILE begins with '|' then open as a pipe",
   "       --bom  Put a UTF8 byte-order mark at the beginning",
   "       -e     Send output to the system text editor",
   "       -x     Send output as CSV to a spreadsheet (same as \".excel\")",
-#ifdef SQLITE_DEBUG
-  ".oom ?--repeat M? ?N?    Simulate an OOM error on the N-th allocation",
-#endif 
+  /* Note that .open is (partially) available in WASM builds but is
+  ** currently only intended to be used by the fiddle tool, not
+  ** end users, so is "undocumented." */
   ".open ?OPTIONS? ?FILE?   Close existing database and reopen FILE",
   "     Options:",
   "        --append        Use appendvfs to append database to the end of FILE",
+#endif
 #ifndef SQLITE_OMIT_DESERIALIZE
   "        --deserialize   Load into memory using sqlite3_deserialize()",
   "        --hexdb         Load the output of \"dbtotxt\" as an in-memory db",
@@ -14931,12 +15504,14 @@
   "        --nofollow      Do not follow symbolic links",
   "        --readonly      Open FILE readonly",
   "        --zip           FILE is a ZIP archive",
+#ifndef SQLITE_SHELL_WASM_MODE
   ".output ?FILE?           Send output to FILE or stdout if FILE is omitted",
   "   If FILE begins with '|' then open it as a pipe.",
   "   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",
+#endif
   ".parameter CMD ...       Manage SQL parameter bindings",
   "   clear                   Erase all bindings",
   "   init                    Initialize the TEMP table that holds bindings",
@@ -14953,8 +15528,11 @@
   "   --reset                   Reset the count for each input and interrupt",
 #endif
   ".prompt MAIN CONTINUE    Replace the standard prompts",
+#ifndef SQLITE_SHELL_WASM_MODE
   ".quit                    Exit this program",
-  ".read FILE               Read input from FILE",
+  ".read FILE               Read input from FILE or command output",
+  "    If FILE begins with \"|\", it is a command that generates the input.",
+#endif
 #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
   ".recover                 Recover as much data as possible from corrupt db.",
   "   --freelist-corrupt       Assume the freelist is corrupt",
@@ -14963,8 +15541,10 @@
   "   --no-rowids              Do not attempt to recover rowid values",
   "                            that are not also INTEGER PRIMARY KEYs",
 #endif
+#ifndef SQLITE_SHELL_WASM_MODE
   ".restore ?DB? FILE       Restore content of DB (default \"main\") from FILE",
-  ".save FILE               Write in-memory database into FILE",
+  ".save ?OPTIONS? FILE     Write database to FILE (an alias for .backup ...)",
+#endif
   ".scanstats on|off        Turn sqlite3_stmt_scanstatus() metrics on or off",
   ".schema ?PATTERN?        Show the CREATE statements matching PATTERN",
   "   Options:",
@@ -14998,7 +15578,7 @@
   "      --sha3-384            Use the sha3-384 algorithm",
   "      --sha3-512            Use the sha3-512 algorithm",
   "    Any other argument is a LIKE pattern for tables to hash",
-#ifndef SQLITE_NOHAVE_SYSTEM
+#if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_WASM_MODE)
   ".shell CMD ARGS...       Run CMD ARGS... in a system shell",
 #endif
   ".show                    Show the current values for various settings",
@@ -15007,11 +15587,13 @@
   "   on                       Turn on automatic stat display",
   "   stmt                     Show statement stats",
   "   vmstep                   Show the virtual machine step count only",
-#ifndef SQLITE_NOHAVE_SYSTEM
+#if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_WASM_MODE)
   ".system CMD ARGS...      Run CMD ARGS... in a system shell",
 #endif
   ".tables ?TABLE?          List names of tables matching LIKE pattern TABLE",
+#ifndef SQLITE_SHELL_WASM_MODE
   ".testcase NAME           Begin redirecting output to 'testcase-out.txt'",
+#endif
   ".testctrl CMD ...        Run various sqlite3_test_control() operations",
   "                           Run \".testctrl\" with no arguments for details",
   ".timeout MS              Try opening locked tables for MS milliseconds",
@@ -15074,6 +15656,7 @@
   }else{
     /* Look for commands that for which zPattern is an exact prefix */
     zPat = sqlite3_mprintf(".%s*", zPattern);
+    shell_check_oom(zPat);
     for(i=0; i<ArraySize(azHelp); i++){
       if( sqlite3_strglob(zPat, azHelp[i])==0 ){
         utf8_printf(out, "%s\n", azHelp[i]);
@@ -15096,6 +15679,7 @@
     /* Look for commands that contain zPattern anywhere.  Show the complete
     ** text of all commands that match. */
     zPat = sqlite3_mprintf("%%%s%%", zPattern);
+    shell_check_oom(zPat);
     for(i=0; i<ArraySize(azHelp); i++){
       if( azHelp[i][0]=='.' ) j = i;
       if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){
@@ -15174,15 +15758,16 @@
 ** Close all OpenSession objects and release all associated resources.
 */
 #if defined(SQLITE_ENABLE_SESSION)
-static void session_close_all(ShellState *p){
-  int i;
-  for(i=0; i<p->nSession; i++){
-    session_close(&p->aSession[i]);
+static void session_close_all(ShellState *p, int i){
+  int j;
+  struct AuxDb *pAuxDb = i<0 ? p->pAuxDb : &p->aAuxDb[i];
+  for(j=0; j<pAuxDb->nSession; j++){
+    session_close(&pAuxDb->aSession[j]);
   }
-  p->nSession = 0;
+  pAuxDb->nSession = 0;
 }
 #else
-# define session_close_all(X)
+# define session_close_all(X,Y)
 #endif
 
 /*
@@ -15247,8 +15832,8 @@
 #ifndef SQLITE_OMIT_DESERIALIZE
 /*
 ** Reconstruct an in-memory database using the output from the "dbtotxt"
-** program.  Read content from the file in p->zDbFilename.  If p->zDbFilename
-** is 0, then read from standard input.
+** program.  Read content from the file in p->aAuxDb[].zDbFilename.
+** If p->aAuxDb[].zDbFilename is 0, then read from standard input.
 */
 static unsigned char *readHexDb(ShellState *p, int *pnData){
   unsigned char *a = 0;
@@ -15259,12 +15844,13 @@
   int j, k;
   int rc;
   FILE *in;
+  const char *zDbFilename = p->pAuxDb->zDbFilename;
   unsigned int x[16];
   char zLine[1000];
-  if( p->zDbFilename ){
-    in = fopen(p->zDbFilename, "r");
+  if( zDbFilename ){
+    in = fopen(zDbFilename, "r");
     if( in==0 ){
-      utf8_printf(stderr, "cannot open \"%s\" for reading\n", p->zDbFilename);
+      utf8_printf(stderr, "cannot open \"%s\" for reading\n", zDbFilename);
       return 0;
     }
     nLine = 0;
@@ -15282,10 +15868,7 @@
   if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ) goto readHexDb_error;
   n = (n+pgsz-1)&~(pgsz-1);  /* Round n up to the next multiple of pgsz */
   a = sqlite3_malloc( n ? n : 1 );
-  if( a==0 ){
-    utf8_printf(stderr, "Out of memory!\n");
-    goto readHexDb_error;
-  }
+  shell_check_oom(a);
   memset(a, 0, n);
   if( pgsz<512 || pgsz>65536 || (pgsz & (pgsz-1))!=0 ){
     utf8_printf(stderr, "invalid pagesize\n");
@@ -15305,7 +15888,7 @@
                 &x[8], &x[9], &x[10], &x[11], &x[12], &x[13], &x[14], &x[15]);
     if( rc==17 ){
       k = iOffset+j;
-      if( k+16<=n ){
+      if( k+16<=n && k>=0 ){
         int ii;
         for(ii=0; ii<16; ii++) a[k+ii] = x[ii]&0xff;
       }
@@ -15416,7 +15999,7 @@
 ){
   const char *zText = (const char*)sqlite3_value_text(argv[0]);
   UNUSED_PARAMETER(argc);
-  if( zText[0]=='\'' ){
+  if( zText && zText[0]=='\'' ){
     int nText = sqlite3_value_bytes(argv[0]);
     int i;
     char zBuf1[20];
@@ -15506,17 +16089,18 @@
 */
 static void open_db(ShellState *p, int openFlags){
   if( p->db==0 ){
+    const char *zDbFilename = p->pAuxDb->zDbFilename;
     if( p->openMode==SHELL_OPEN_UNSPEC ){
-      if( p->zDbFilename==0 || p->zDbFilename[0]==0 ){
+      if( zDbFilename==0 || zDbFilename[0]==0 ){
         p->openMode = SHELL_OPEN_NORMAL;
       }else{
-        p->openMode = (u8)deduceDatabaseType(p->zDbFilename, 
+        p->openMode = (u8)deduceDatabaseType(zDbFilename, 
                              (openFlags & OPEN_DB_ZIPFILE)!=0);
       }
     }
     switch( p->openMode ){
       case SHELL_OPEN_APPENDVFS: {
-        sqlite3_open_v2(p->zDbFilename, &p->db, 
+        sqlite3_open_v2(zDbFilename, &p->db, 
            SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, "apndvfs");
         break;
       }
@@ -15530,21 +16114,21 @@
         break;
       }
       case SHELL_OPEN_READONLY: {
-        sqlite3_open_v2(p->zDbFilename, &p->db,
+        sqlite3_open_v2(zDbFilename, &p->db,
             SQLITE_OPEN_READONLY|p->openFlags, 0);
         break;
       }
       case SHELL_OPEN_UNSPEC:
       case SHELL_OPEN_NORMAL: {
-        sqlite3_open_v2(p->zDbFilename, &p->db,
+        sqlite3_open_v2(zDbFilename, &p->db,
            SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, 0);
         break;
       }
     }
     globalDb = p->db;
     if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
       utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",
-          p->zDbFilename, sqlite3_errmsg(p->db));
+          zDbFilename, sqlite3_errmsg(p->db));
       if( openFlags & OPEN_DB_KEEPALIVE ){
         sqlite3_open(":memory:", &p->db);
         return;
@@ -15554,20 +16138,24 @@
 #ifndef SQLITE_OMIT_LOAD_EXTENSION
     sqlite3_enable_load_extension(p->db, 1);
 #endif
-    sqlite3_fileio_init(p->db, 0, 0);
     sqlite3_shathree_init(p->db, 0, 0);
-    sqlite3_completion_init(p->db, 0, 0);
     sqlite3_uint_init(p->db, 0, 0);
     sqlite3_decimal_init(p->db, 0, 0);
     sqlite3_regexp_init(p->db, 0, 0);
     sqlite3_ieee_init(p->db, 0, 0);
     sqlite3_series_init(p->db, 0, 0);
+#ifndef SQLITE_SHELL_WASM_MODE
+    sqlite3_fileio_init(p->db, 0, 0);
+    sqlite3_completion_init(p->db, 0, 0);
+#endif
 #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
     sqlite3_dbdata_init(p->db, 0, 0);
 #endif
 #ifdef SQLITE_HAVE_ZLIB
-    sqlite3_zipfile_init(p->db, 0, 0);
-    sqlite3_sqlar_init(p->db, 0, 0);
+    if( !p->bSafeModePersist ){
+      sqlite3_zipfile_init(p->db, 0, 0);
+      sqlite3_sqlar_init(p->db, 0, 0);
+    }
 #endif
     sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0,
                             shellAddSchemaName, 0, 0);
@@ -15591,7 +16179,8 @@
 #endif
     if( p->openMode==SHELL_OPEN_ZIPFILE ){
       char *zSql = sqlite3_mprintf(
-         "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", p->zDbFilename);
+         "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", zDbFilename);
+      shell_check_oom(zSql);
       sqlite3_exec(p->db, zSql, 0, 0, 0);
       sqlite3_free(zSql);
     }
@@ -15602,7 +16191,7 @@
       int nData = 0;
       unsigned char *aData;
       if( p->openMode==SHELL_OPEN_DESERIALIZE ){
-        aData = (unsigned char*)readFile(p->zDbFilename, &nData);
+        aData = (unsigned char*)readFile(zDbFilename, &nData);
       }else{
         aData = readHexDb(p, &nData);
         if( aData==0 ){
@@ -15621,6 +16210,9 @@
     }
 #endif
   }
+  if( p->bSafeModePersist && p->db!=0 ){
+    sqlite3_set_authorizer(p->db, safeModeAuth, p);
+  }
 }
 
 /*
@@ -15646,11 +16238,13 @@
     sqlite3_finalize(pStmt);
     zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
                            "  FROM completion(%Q) ORDER BY 1", text);
+    shell_check_oom(zSql);
     sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
     sqlite3_free(zSql);
   }
   if( sqlite3_step(pStmt)==SQLITE_ROW ){
-    zRet = strdup((const char*)sqlite3_column_text(pStmt, 0));
+    const char *z = (const char*)sqlite3_column_text(pStmt,0);
+    zRet = z ? strdup(z) : 0;
   }else{
     sqlite3_finalize(pStmt);
     pStmt = 0;
@@ -15683,13 +16277,14 @@
   zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
                          "  FROM completion(%Q,%Q) ORDER BY 1",
                          &zLine[iStart], zLine);
+  shell_check_oom(zSql);
   sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
   sqlite3_free(zSql);
   sqlite3_exec(globalDb, "PRAGMA page_count", 0, 0, 0); /* Load the schema */
   while( sqlite3_step(pStmt)==SQLITE_ROW ){
     const char *zCompletion = (const char*)sqlite3_column_text(pStmt, 0);
     int nCompletion = sqlite3_column_bytes(pStmt, 0);
-    if( iStart+nCompletion < sizeof(zBuf)-1 ){
+    if( iStart+nCompletion < sizeof(zBuf)-1 && zCompletion ){
       memcpy(zBuf+iStart, zCompletion, nCompletion+1);
       linenoiseAddCompletion(lc, zBuf);
     }
@@ -15924,7 +16519,7 @@
   if( p->n+1>=p->nAlloc ){
     p->nAlloc += p->nAlloc + 100;
     p->z = sqlite3_realloc64(p->z, p->nAlloc);
-    if( p->z==0 ) shell_out_of_memory();
+    shell_check_oom(p->z);
   }
   p->z[p->n++] = (char)c;
 }
@@ -16076,6 +16671,7 @@
   const int spinRate = 10000;
 
   zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
+  shell_check_oom(zQuery);
   rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
   if( rc ){
     utf8_printf(stderr, "Error %d: %s on [%s]\n",
@@ -16085,7 +16681,7 @@
   }
   n = sqlite3_column_count(pQuery);
   zInsert = sqlite3_malloc64(200 + nTable + n*3);
-  if( zInsert==0 ) shell_out_of_memory();
+  shell_check_oom(zInsert);
   sqlite3_snprintf(200+nTable,zInsert,
                    "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable);
   i = strlen30(zInsert);
@@ -16148,6 +16744,7 @@
     sqlite3_free(zQuery);
     zQuery = sqlite3_mprintf("SELECT * FROM \"%w\" ORDER BY rowid DESC;",
                              zTable);
+    shell_check_oom(zQuery);
     rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
     if( rc ){
       utf8_printf(stderr, "Warning: cannot step \"%s\" backwards", zTable);
@@ -16184,6 +16781,7 @@
 
   zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
                            " WHERE %s", zWhere);
+  shell_check_oom(zQuery);
   rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
   if( rc ){
     utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
@@ -16194,6 +16792,7 @@
   while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
     zName = sqlite3_column_text(pQuery, 0);
     zSql = sqlite3_column_text(pQuery, 1);
+    if( zName==0 || zSql==0 ) continue;
     printf("%s... ", zName); fflush(stdout);
     sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
     if( zErrMsg ){
@@ -16211,16 +16810,18 @@
     sqlite3_free(zQuery);
     zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
                              " WHERE %s ORDER BY rowid DESC", zWhere);
+    shell_check_oom(zQuery);
     rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
     if( rc ){
       utf8_printf(stderr, "Error: (%d) %s on [%s]\n",
                       sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
                       zQuery);
       goto end_schema_xfer;
     }
-    while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
+    while( sqlite3_step(pQuery)==SQLITE_ROW ){
       zName = sqlite3_column_text(pQuery, 0);
       zSql = sqlite3_column_text(pQuery, 1);
+      if( zName==0 || zSql==0 ) continue;
       printf("%s... ", zName); fflush(stdout);
       sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
       if( zErrMsg ){
@@ -16313,17 +16914,18 @@
 /*
 ** Run an SQL command and return the single integer result.
 */
-static int db_int(ShellState *p, const char *zSql){
+static int db_int(sqlite3 *db, const char *zSql){
   sqlite3_stmt *pStmt;
   int res = 0;
-  sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
+  sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
   if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
     res = sqlite3_column_int(pStmt,0);
   }
   sqlite3_finalize(pStmt);
   return res;
 }
 
+#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
 /*
 ** Convert a 2-byte or 4-byte big-endian integer into a native integer
 */
@@ -16421,7 +17023,7 @@
   }
   for(i=0; i<ArraySize(aQuery); i++){
     char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
-    int val = db_int(p, zSql);
+    int val = db_int(p->db, zSql);
     sqlite3_free(zSql);
     utf8_printf(p->out, "%-20s %d\n", aQuery[i].zName, val);
   }
@@ -16430,6 +17032,8 @@
   utf8_printf(p->out, "%-20s %u\n", "data version", iDataVersion);
   return 0;
 }
+#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE)
+          && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
 
 /*
 ** Print the current sqlite3_errmsg() value to stderr and return 1.
@@ -16605,10 +17209,7 @@
   }else{
     p->zTempFile = sqlite3_mprintf("%z.%s", p->zTempFile, zSuffix);
   }
-  if( p->zTempFile==0 ){
-    raw_printf(stderr, "out of memory\n");
-    exit(1);
-  }
+  shell_check_oom(p->zTempFile);
 }
 
 
@@ -16789,14 +17390,14 @@
       const char *zCI = (const char*)sqlite3_column_text(pSql, 4);
       const char *zParent = (const char*)sqlite3_column_text(pSql, 5);
 
+      if( zEQP==0 ) continue;
+      if( zGlob==0 ) continue;
       rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
       if( rc!=SQLITE_OK ) break;
       if( SQLITE_ROW==sqlite3_step(pExplain) ){
         const char *zPlan = (const char*)sqlite3_column_text(pExplain, 3);
-        res = (
-              0==sqlite3_strglob(zGlob, zPlan)
-           || 0==sqlite3_strglob(zGlobIPK, zPlan)
-        );
+        res = zPlan!=0 && (  0==sqlite3_strglob(zGlob, zPlan)
+                          || 0==sqlite3_strglob(zGlobIPK, zPlan));
       }
       rc = sqlite3_finalize(pExplain);
       if( rc!=SQLITE_OK ) break;
@@ -16967,6 +17568,7 @@
   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" */
@@ -17014,21 +17616,24 @@
 #define AR_CMD_EXTRACT      4
 #define AR_CMD_LIST         5
 #define AR_CMD_HELP         6
+#define AR_CMD_REMOVE       7
 
 /*
 ** Other (non-command) switches.
 */
-#define AR_SWITCH_VERBOSE     7
-#define AR_SWITCH_FILE        8
-#define AR_SWITCH_DIRECTORY   9
-#define AR_SWITCH_APPEND     10
-#define AR_SWITCH_DRYRUN     11
+#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
 
 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:
@@ -17041,6 +17646,9 @@
     case AR_SWITCH_DRYRUN:
       pAr->bDryRun = 1;
       break;
+    case AR_SWITCH_GLOB:
+      pAr->bGlob = 1;
+      break;
     case AR_SWITCH_VERBOSE:
       pAr->bVerbose = 1;
       break;
@@ -17079,13 +17687,15 @@
     { "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];
@@ -17202,11 +17812,13 @@
 
 /*
 ** This function assumes that all arguments within the ArCommand.azArg[]
-** array refer to archive members, as for the --extract or --list 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.
+** 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
@@ -17217,11 +17829,11 @@
   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";
 
-    shellPreparePrintf(pAr->db, &rc, &pTest,
-        "SELECT name FROM %s WHERE name=$name", 
-        pAr->zSrcTable
-    );
+    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];
@@ -17249,14 +17861,16 @@
 ** 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.
+** 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, 
+  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");
@@ -17266,8 +17880,8 @@
       for(i=0; i<pAr->nArg; i++){
         const char *z = pAr->azArg[i];
         zWhere = sqlite3_mprintf(
-          "%z%s name = '%q' OR substr(name,1,%d) = '%q/'", 
-          zWhere, zSep, z, strlen30(z)+1, z
+          "%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;
@@ -17322,6 +17936,47 @@
 
 
 /*
+** Implementation of .ar "Remove" command.
+*/
+static int arRemoveCommand(ArCommand *pAr){
+  int rc = 0;
+  char *zSql = 0;
+  char *zWhere = 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);
+  }
+  if( rc==SQLITE_OK ){
+    zSql = sqlite3_mprintf("DELETE FROM %s WHERE %s;",
+                           pAr->zSrcTable, zWhere);
+    if( pAr->bDryRun ){
+      utf8_printf(pAr->p->out, "%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);
+        }
+      }
+      if( zErr ){
+        utf8_printf(stdout, "ERROR: %s\n", zErr);
+        sqlite3_free(zErr);
+      }
+    }
+  }
+  sqlite3_free(zWhere);
+  sqlite3_free(zSql);
+  return rc;
+}
+
+/*
 ** Implementation of .ar "eXtract" command. 
 */
 static int arExtractCommand(ArCommand *pAr){
@@ -17573,7 +18228,7 @@
       int flags;
       if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS;
       if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_INSERT 
-           || cmd.eCmd==AR_CMD_UPDATE ){
+           || cmd.eCmd==AR_CMD_REMOVE || cmd.eCmd==AR_CMD_UPDATE ){
         flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
       }else{
         flags = SQLITE_OPEN_READONLY;
@@ -17629,6 +18284,10 @@
         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);
@@ -17730,6 +18389,7 @@
   return z;
 }
 
+
 /*
 ** When running the ".recover" command, each output table, and the special
 ** orphaned row table if it is required, is represented by an instance
@@ -17843,6 +18503,7 @@
         if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPkFinder) ){
           pTab->iPk = sqlite3_column_int(pPkFinder, 0);
           zPk = (const char*)sqlite3_column_text(pPkFinder, 1);
+          if( zPk==0 ){ zPk = "_";  /* Defensive.  Should never happen */ }
         }
       }
 
@@ -17927,8 +18588,10 @@
     if( sqlite3_stricmp(zType, "table")==0 ){
       zName = (const char*)sqlite3_column_text(pStmt, 1);
       zSql = (const char*)sqlite3_column_text(pStmt, 2);
-      pRet = recoverNewTable(pRc, zName, zSql, bIntkey, nCol);
-      break;
+      if( zName!=0 && zSql!=0 ){
+        pRet = recoverNewTable(pRc, zName, zSql, bIntkey, nCol);
+        break;
+      }
     }
   }
 
@@ -18325,6 +18988,223 @@
 
 
 /*
+ * zAutoColumn(zCol, &db, ?) => Maybe init db, add column zCol to it.
+ * zAutoColumn(0, &db, ?) => (db!=0) Form columns spec for CREATE TABLE,
+ *   close db and set it to 0, and return the columns spec, to later
+ *   be sqlite3_free()'ed by the caller.
+ * The return is 0 when either:
+ *   (a) The db was not initialized and zCol==0 (There are no columns.)
+ *   (b) zCol!=0  (Column was added, db initialized as needed.)
+ * The 3rd argument, pRenamed, references an out parameter. If the
+ * pointer is non-zero, its referent will be set to a summary of renames
+ * done if renaming was necessary, or set to 0 if none was done. The out
+ * string (if any) must be sqlite3_free()'ed by the caller.
+ */
+#ifdef SHELL_DEBUG
+#define rc_err_oom_die(rc) \
+  if( rc==SQLITE_NOMEM ) shell_check_oom(0); \
+  else if(!(rc==SQLITE_OK||rc==SQLITE_DONE)) \
+    fprintf(stderr,"E:%d\n",rc), assert(0)
+#else
+static void rc_err_oom_die(int rc){
+  if( rc==SQLITE_NOMEM ) shell_check_oom(0);
+  assert(rc==SQLITE_OK||rc==SQLITE_DONE);
+}
+#endif
+
+#ifdef SHELL_COLFIX_DB /* If this is set, the DB can be in a file. */
+static char zCOL_DB[] = SHELL_STRINGIFY(SHELL_COLFIX_DB);
+#else  /* Otherwise, memory is faster/better for the transient DB. */
+static const char *zCOL_DB = ":memory:";
+#endif
+
+/* Define character (as C string) to separate generated column ordinal
+ * from protected part of incoming column names. This defaults to "_"
+ * so that incoming column identifiers that did not need not be quoted
+ * remain usable without being quoted. It must be one character.
+ */
+#ifndef SHELL_AUTOCOLUMN_SEP
+# define AUTOCOLUMN_SEP "_"
+#else
+# define AUTOCOLUMN_SEP SHELL_STRINGIFY(SHELL_AUTOCOLUMN_SEP)
+#endif
+
+static char *zAutoColumn(const char *zColNew, sqlite3 **pDb, char **pzRenamed){
+  /* Queries and D{D,M}L used here */
+  static const char * const zTabMake = "\
+CREATE TABLE ColNames(\
+ cpos INTEGER PRIMARY KEY,\
+ name TEXT, nlen INT, chop INT, reps INT, suff TEXT);\
+CREATE VIEW RepeatedNames AS \
+SELECT DISTINCT t.name FROM ColNames t \
+WHERE t.name COLLATE NOCASE IN (\
+ SELECT o.name FROM ColNames o WHERE o.cpos<>t.cpos\
+);\
+";
+  static const char * const zTabFill = "\
+INSERT INTO ColNames(name,nlen,chop,reps,suff)\
+ VALUES(iif(length(?1)>0,?1,'?'),max(length(?1),1),0,0,'')\
+";
+  static const char * const zHasDupes = "\
+SELECT count(DISTINCT (substring(name,1,nlen-chop)||suff) COLLATE NOCASE)\
+ <count(name) FROM ColNames\
+";
+#ifdef SHELL_COLUMN_RENAME_CLEAN
+  static const char * const zDedoctor = "\
+UPDATE ColNames SET chop=iif(\
+  (substring(name,nlen,1) BETWEEN '0' AND '9')\
+  AND (rtrim(name,'0123456790') glob '*"AUTOCOLUMN_SEP"'),\
+ nlen-length(rtrim(name, '"AUTOCOLUMN_SEP"0123456789')),\
+ 0\
+)\
+";
+#endif
+  static const char * const zSetReps = "\
+UPDATE ColNames AS t SET reps=\
+(SELECT count(*) FROM ColNames d \
+ WHERE substring(t.name,1,t.nlen-t.chop)=substring(d.name,1,d.nlen-d.chop)\
+ COLLATE NOCASE\
+)\
+";
+#ifdef SQLITE_ENABLE_MATH_FUNCTIONS
+  static const char * const zColDigits = "\
+SELECT CAST(ceil(log(count(*)+0.5)) AS INT) FROM ColNames \
+";
+#else
+  /* Counting on SQLITE_MAX_COLUMN < 100,000 here. (32767 is the hard limit.) */
+  static const char * const zColDigits = "\
+SELECT CASE WHEN (nc < 10) THEN 1 WHEN (nc < 100) THEN 2 \
+ WHEN (nc < 1000) THEN 3 WHEN (nc < 10000) THEN 4 \
+ ELSE 5 FROM (SELECT count(*) AS nc FROM ColNames) \
+";
+#endif
+  static const char * const zRenameRank =
+#ifdef SHELL_COLUMN_RENAME_CLEAN
+    "UPDATE ColNames AS t SET suff="
+    "iif(reps>1, printf('%c%0*d', '"AUTOCOLUMN_SEP"', $1, cpos), '')"
+#else /* ...RENAME_MINIMAL_ONE_PASS */
+"WITH Lzn(nlz) AS (" /* Find minimum extraneous leading 0's for uniqueness */
+"  SELECT 0 AS nlz"
+"  UNION"
+"  SELECT nlz+1 AS nlz FROM Lzn"
+"  WHERE EXISTS("
+"   SELECT 1"
+"   FROM ColNames t, ColNames o"
+"   WHERE"
+"    iif(t.name IN (SELECT * FROM RepeatedNames),"
+"     printf('%s"AUTOCOLUMN_SEP"%s',"
+"      t.name, substring(printf('%.*c%0.*d',nlz+1,'0',$1,t.cpos),2)),"
+"     t.name"
+"    )"
+"    ="
+"    iif(o.name IN (SELECT * FROM RepeatedNames),"
+"     printf('%s"AUTOCOLUMN_SEP"%s',"
+"      o.name, substring(printf('%.*c%0.*d',nlz+1,'0',$1,o.cpos),2)),"
+"     o.name"
+"    )"
+"    COLLATE NOCASE"
+"    AND o.cpos<>t.cpos"
+"   GROUP BY t.cpos"
+"  )"
+") UPDATE Colnames AS t SET"
+" chop = 0," /* No chopping, never touch incoming names. */
+" suff = iif(name IN (SELECT * FROM RepeatedNames),"
+"  printf('"AUTOCOLUMN_SEP"%s', substring("
+"   printf('%.*c%0.*d',(SELECT max(nlz) FROM Lzn)+1,'0',1,t.cpos),2)),"
+"  ''"
+" )"
+#endif
+    ;
+  static const char * const zCollectVar = "\
+SELECT\
+ '('||x'0a'\
+ || group_concat(\
+  cname||' TEXT',\
+  ','||iif((cpos-1)%4>0, ' ', x'0a'||' '))\
+ ||')' AS ColsSpec \
+FROM (\
+ SELECT cpos, printf('\"%w\"',printf('%!.*s%s', nlen-chop,name,suff)) AS cname \
+ FROM ColNames ORDER BY cpos\
+)";
+  static const char * const zRenamesDone =
+    "SELECT group_concat("
+    " printf('\"%w\" to \"%w\"',name,printf('%!.*s%s', nlen-chop, name, suff)),"
+    " ','||x'0a')"
+    "FROM ColNames WHERE suff<>'' OR chop!=0"
+    ;
+  int rc;
+  sqlite3_stmt *pStmt = 0;
+  assert(pDb!=0);
+  if( zColNew ){
+    /* Add initial or additional column. Init db if necessary. */
+    if( *pDb==0 ){
+      if( SQLITE_OK!=sqlite3_open(zCOL_DB, pDb) ) return 0;
+#ifdef SHELL_COLFIX_DB
+      if(*zCOL_DB!=':')
+        sqlite3_exec(*pDb,"drop table if exists ColNames;"
+                     "drop view if exists RepeatedNames;",0,0,0);
+#endif
+      rc = sqlite3_exec(*pDb, zTabMake, 0, 0, 0);
+      rc_err_oom_die(rc);
+    }
+    assert(*pDb!=0);
+    rc = sqlite3_prepare_v2(*pDb, zTabFill, -1, &pStmt, 0);
+    rc_err_oom_die(rc);
+    rc = sqlite3_bind_text(pStmt, 1, zColNew, -1, 0);
+    rc_err_oom_die(rc);
+    rc = sqlite3_step(pStmt);
+    rc_err_oom_die(rc);
+    sqlite3_finalize(pStmt);
+    return 0;
+  }else if( *pDb==0 ){
+    return 0;
+  }else{
+    /* Formulate the columns spec, close the DB, zero *pDb. */
+    char *zColsSpec = 0;
+    int hasDupes = db_int(*pDb, zHasDupes);
+    int nDigits = (hasDupes)? db_int(*pDb, zColDigits) : 0;
+    if( hasDupes ){
+#ifdef SHELL_COLUMN_RENAME_CLEAN
+      rc = sqlite3_exec(*pDb, zDedoctor, 0, 0, 0);
+      rc_err_oom_die(rc);
+#endif
+      rc = sqlite3_exec(*pDb, zSetReps, 0, 0, 0);
+      rc_err_oom_die(rc);
+      rc = sqlite3_prepare_v2(*pDb, zRenameRank, -1, &pStmt, 0);
+      rc_err_oom_die(rc);
+      sqlite3_bind_int(pStmt, 1, nDigits);
+      rc = sqlite3_step(pStmt);
+      sqlite3_finalize(pStmt);
+      assert(rc==SQLITE_DONE);
+    }
+    assert(db_int(*pDb, zHasDupes)==0); /* Consider: remove this */
+    rc = sqlite3_prepare_v2(*pDb, zCollectVar, -1, &pStmt, 0);
+    rc_err_oom_die(rc);
+    rc = sqlite3_step(pStmt);
+    if( rc==SQLITE_ROW ){
+      zColsSpec = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
+    }else{
+      zColsSpec = 0;
+    }
+    if( pzRenamed!=0 ){
+      if( !hasDupes ) *pzRenamed = 0;
+      else{
+        sqlite3_finalize(pStmt);
+        if( SQLITE_OK==sqlite3_prepare_v2(*pDb, zRenamesDone, -1, &pStmt, 0)
+            && SQLITE_ROW==sqlite3_step(pStmt) ){
+          *pzRenamed = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
+        }else
+          *pzRenamed = 0;
+      }
+    }
+    sqlite3_finalize(pStmt);
+    sqlite3_close(*pDb);
+    *pDb = 0;
+    return zColsSpec;
+  }
+}
+
+/*
 ** If an input line begins with "." then invoke this routine to
 ** process that line.
 **
@@ -18385,19 +19265,24 @@
     open_db(p, 0);
     if( booleanValue(azArg[1]) ){
       sqlite3_set_authorizer(p->db, shellAuth, p);
+    }else if( p->bSafeModePersist ){
+      sqlite3_set_authorizer(p->db, safeModeAuth, p);
     }else{
       sqlite3_set_authorizer(p->db, 0, 0);
     }
   }else
 #endif
 
-#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
+#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) \
+  && !defined(SQLITE_SHELL_WASM_MODE)
   if( c=='a' && strncmp(azArg[0], "archive", n)==0 ){
     open_db(p, 0);
+    failIfSafeMode(p, "cannot run .archive in safe mode");
     rc = arDotCommand(p, 0, azArg, nArg);
   }else
 #endif
 
+#ifndef SQLITE_SHELL_WASM_MODE
   if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0)
    || (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0)
   ){
@@ -18408,6 +19293,7 @@
     int j;
     int bAsync = 0;
     const char *zVfs = 0;
+    failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
     for(j=1; j<nArg; j++){
       const char *z = azArg[j];
       if( z[0]=='-' ){
@@ -18465,6 +19351,7 @@
     }
     close_db(pDest);
   }else
+#endif /* !defined(SQLITE_SHELL_WASM_MODE) */
 
   if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){
     if( nArg==2 ){
@@ -18488,7 +19375,16 @@
     }
   }else
 
+  /* The undocumented ".breakpoint" command causes a call to the no-op
+  ** routine named test_breakpoint().
+  */
+  if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){
+    test_breakpoint();
+  }else
+
+#ifndef SQLITE_SHELL_WASM_MODE
   if( c=='c' && strcmp(azArg[0],"cd")==0 ){
+    failIfSafeMode(p, "cannot run .cd in safe mode");
     if( nArg==2 ){
 #if defined(_WIN32) || defined(WIN32)
       wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]);
@@ -18506,14 +19402,8 @@
       rc = 1;
     }
   }else
+#endif /* !defined(SQLITE_SHELL_WASM_MODE) */
 
-  /* The undocumented ".breakpoint" command causes a call to the no-op
-  ** routine named test_breakpoint().
-  */
-  if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){
-    test_breakpoint();
-  }else
-
   if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){
     if( nArg==2 ){
       setOrClearFlag(p, SHFLG_CountChanges, azArg[1]);
@@ -18523,6 +19413,7 @@
     }
   }else
 
+#ifndef SQLITE_SHELL_WASM_MODE
   /* 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.
@@ -18547,16 +19438,66 @@
     }
     sqlite3_free(zRes);
   }else
+#endif /* !defined(SQLITE_SHELL_WASM_MODE) */
 
+#ifndef SQLITE_SHELL_WASM_MODE
   if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){
+    failIfSafeMode(p, "cannot run .clone in safe mode");
     if( nArg==2 ){
       tryToClone(p, azArg[1]);
     }else{
       raw_printf(stderr, "Usage: .clone FILENAME\n");
       rc = 1;
     }
   }else
+#endif /* !defined(SQLITE_SHELL_WASM_MODE) */
 
+  if( c=='c' && strncmp(azArg[0], "connection", n)==0 ){
+    if( nArg==1 ){
+      /* List available connections */
+      int i;
+      for(i=0; i<ArraySize(p->aAuxDb); i++){
+        const char *zFile = p->aAuxDb[i].zDbFilename;
+        if( p->aAuxDb[i].db==0 && p->pAuxDb!=&p->aAuxDb[i] ){
+          zFile = "(not open)";
+        }else if( zFile==0 ){
+          zFile = "(memory)";
+        }else if( zFile[0]==0 ){
+          zFile = "(temporary-file)";
+        }
+        if( p->pAuxDb == &p->aAuxDb[i] ){
+          utf8_printf(stdout, "ACTIVE %d: %s\n", i, zFile);
+        }else if( p->aAuxDb[i].db!=0 ){
+          utf8_printf(stdout, "       %d: %s\n", i, zFile);
+        }
+      }
+    }else if( nArg==2 && IsDigit(azArg[1][0]) && azArg[1][1]==0 ){
+      int i = azArg[1][0] - '0';
+      if( p->pAuxDb != &p->aAuxDb[i] && i>=0 && i<ArraySize(p->aAuxDb) ){
+        p->pAuxDb->db = p->db;
+        p->pAuxDb = &p->aAuxDb[i];
+        globalDb = p->db = p->pAuxDb->db;
+        p->pAuxDb->db = 0;
+      }
+    }else if( nArg==3 && strcmp(azArg[1], "close")==0
+           && IsDigit(azArg[2][0]) && azArg[2][1]==0 ){
+      int i = azArg[2][0] - '0';
+      if( i<0 || i>=ArraySize(p->aAuxDb) ){
+        /* No-op */
+      }else if( p->pAuxDb == &p->aAuxDb[i] ){
+        raw_printf(stderr, "cannot close the active database connection\n");
+        rc = 1;
+      }else if( p->aAuxDb[i].db ){
+        session_close_all(p, i);
+        close_db(p->aAuxDb[i].db);
+        p->aAuxDb[i].db = 0;
+      }
+    }else{
+      raw_printf(stderr, "Usage: .connection [close] [CONNECTION-NUMBER]\n");
+      rc = 1;
+    }
+  }else
+
   if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
     char **azName = 0;
     int nName = 0;
@@ -18571,8 +19512,9 @@
       while( sqlite3_step(pStmt)==SQLITE_ROW ){
         const char *zSchema = (const char *)sqlite3_column_text(pStmt,1);
         const char *zFile = (const char*)sqlite3_column_text(pStmt,2);
+        if( zSchema==0 || zFile==0 ) continue;
         azName = sqlite3_realloc(azName, (nName+1)*2*sizeof(char*));
-        if( azName==0 ){ shell_out_of_memory();  /* Does not return */ }
+        shell_check_oom(azName);
         azName[nName*2] = strdup(zSchema);
         azName[nName*2+1] = strdup(zFile);
         nName++;
@@ -18634,11 +19576,11 @@
     }   
   }else
 
+#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
   if( c=='d' && n>=3 && strncmp(azArg[0], "dbinfo", n)==0 ){
     rc = shell_dbinfo_command(p, nArg, azArg);
   }else
 
-#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
   if( c=='r' && strncmp(azArg[0], "recover", n)==0 ){
     open_db(p, 0);
     rc = recoverDatabaseCmd(p, nArg, azArg);
@@ -18651,7 +19593,7 @@
     int i;
     int savedShowHeader = p->showHeader;
     int savedShellFlags = p->shellFlgs;
-    ShellClearFlag(p, 
+    ShellClearFlag(p,
        SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo
        |SHFLG_DumpDataOnly|SHFLG_DumpNoSys);
     for(i=1; i<nArg; i++){
@@ -18797,10 +19739,12 @@
     }
   }else
 
+#ifndef SQLITE_SHELL_WASM_MODE
   if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
     if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
     rc = 2;
   }else
+#endif
 
   /* The ".explain" command is automatic now.  It is largely pointless.  It
   ** retained purely for backwards compatibility */
@@ -18828,8 +19772,15 @@
 
 #ifndef SQLITE_OMIT_VIRTUALTABLE
   if( c=='e' && strncmp(azArg[0], "expert", n)==0 ){
-    open_db(p, 0);
-    expertDotCommand(p, azArg, nArg);
+    if( p->bSafeMode ){
+      raw_printf(stderr, 
+        "Cannot run experimental commands such as \"%s\" in safe mode\n",
+        azArg[0]);
+      rc = 1;
+    }else{
+      open_db(p, 0);
+      expertDotCommand(p, azArg, nArg);
+    }
   }else
 #endif
 
@@ -19002,7 +19953,7 @@
        "     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 rowid",
+       "ORDER BY x",
        callback, &data, 0
     );
     if( rc==SQLITE_OK ){
@@ -19018,8 +19969,6 @@
       raw_printf(p->out, "/* No STAT tables available */\n");
     }else{
       raw_printf(p->out, "ANALYZE sqlite_schema;\n");
-      sqlite3_exec(p->db, "SELECT 'ANALYZE sqlite_schema'",
-                   callback, &data, 0);
       data.cMode = data.mode = MODE_Insert;
       data.zDestTable = "sqlite_stat1";
       shell_exec(&data, "SELECT * FROM sqlite_stat1", 0);
@@ -19050,8 +19999,10 @@
     }
   }else
 
+#ifndef SQLITE_SHELL_WASM_MODE
   if( c=='i' && strncmp(azArg[0], "import", n)==0 ){
     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 */
@@ -19060,18 +20011,22 @@
     int needCommit;             /* True to COMMIT or ROLLBACK at end */
     int nSep;                   /* Number of bytes in p->colSeparator[] */
     char *zSql;                 /* An SQL statement */
+    char *zFullTabName;         /* Table name with schema if applicable */
     ImportCtx sCtx;             /* Reader context */
     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 */
+    char *zCreate = 0;          /* CREATE TABLE statement text */
 
+    failIfSafeMode(p, "cannot run .import in safe mode");
     memset(&sCtx, 0, sizeof(sCtx));
     if( p->mode==MODE_Ascii ){
       xRead = ascii_read_one_field;
     }else{
       xRead = csv_read_one_field;
     }
+    rc = 1;
     for(i=1; i<nArg; i++){
       char *z = azArg[i];
       if( z[0]=='-' && z[1]=='-' ) z++;
@@ -19083,11 +20038,12 @@
         }else{
           utf8_printf(p->out, "ERROR: extra argument: \"%s\".  Usage:\n", z);
           showHelp(p->out, "import");
-          rc = 1;
           goto meta_command_exit;
         }
       }else if( strcmp(z,"-v")==0 ){
         eVerbose++;
+      }else if( strcmp(z,"-schema")==0 && i<nArg-1 ){
+        zSchema = azArg[++i];
       }else if( strcmp(z,"-skip")==0 && i<nArg-1 ){
         nSkip = integerValue(azArg[++i]);
       }else if( strcmp(z,"-ascii")==0 ){
@@ -19103,15 +20059,13 @@
       }else{
         utf8_printf(p->out, "ERROR: unknown option: \"%s\".  Usage:\n", z);
         showHelp(p->out, "import");
-        rc = 1;
         goto meta_command_exit;
       }
     }
     if( zTable==0 ){
       utf8_printf(p->out, "ERROR: missing %s argument. Usage:\n",
                   zFile==0 ? "FILE" : "TABLE");
       showHelp(p->out, "import");
-      rc = 1;
       goto meta_command_exit;
     }
     seenInterrupt = 0;
@@ -19123,21 +20077,18 @@
       if( nSep==0 ){
         raw_printf(stderr,
                    "Error: non-null column separator required for import\n");
-        rc = 1;
         goto meta_command_exit;
       }
       if( nSep>1 ){
-        raw_printf(stderr, 
+        raw_printf(stderr,
               "Error: multi-character column separators not allowed"
               " for import\n");
-        rc = 1;
         goto meta_command_exit;
       }
       nSep = strlen30(p->rowSeparator);
       if( nSep==0 ){
         raw_printf(stderr,
             "Error: non-null row separator required for import\n");
-        rc = 1;
         goto meta_command_exit;
       }
       if( nSep==2 && p->mode==MODE_Csv && strcmp(p->rowSeparator,SEP_CrLf)==0 ){
@@ -19151,7 +20102,6 @@
       if( nSep>1 ){
         raw_printf(stderr, "Error: multi-character row separators not allowed"
                            " for import\n");
-        rc = 1;
         goto meta_command_exit;
       }
       sCtx.cColSep = p->colSeparator[0];
@@ -19162,7 +20112,6 @@
     if( sCtx.zFile[0]=='|' ){
 #ifdef SQLITE_OMIT_POPEN
       raw_printf(stderr, "Error: pipes are not supported in this OS\n");
-      rc = 1;
       goto meta_command_exit;
 #else
       sCtx.in = popen(sCtx.zFile+1, "r");
@@ -19175,7 +20124,6 @@
     }
     if( sCtx.in==0 ){
       utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
-      rc = 1;
       goto meta_command_exit;
     }
     if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){
@@ -19189,55 +20137,74 @@
       output_c_string(p->out, zSep);
       utf8_printf(p->out, "\n");
     }
+    sCtx.z = sqlite3_malloc64(120);
+    if( sCtx.z==0 ){
+      import_cleanup(&sCtx);
+      shell_out_of_memory();
+    }
+    /* Below, resources must be freed before exit. */
     while( (nSkip--)>0 ){
       while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
     }
-    zSql = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
-    if( zSql==0 ){
+    if( zSchema!=0 ){
+      zFullTabName = sqlite3_mprintf("\"%w\".\"%w\"", zSchema, zTable);
+    }else{
+      zFullTabName = sqlite3_mprintf("\"%w\"", zTable);
+    }
+    zSql = sqlite3_mprintf("SELECT * FROM %s", zFullTabName);
+    if( zSql==0 || zFullTabName==0 ){
       import_cleanup(&sCtx);
       shell_out_of_memory();
     }
     nByte = strlen30(zSql);
     rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
     import_append_char(&sCtx, 0);    /* To ensure sCtx.z is allocated */
     if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
-      char *zCreate = sqlite3_mprintf("CREATE TABLE \"%w\"", zTable);
-      char cSep = '(';
+      sqlite3 *dbCols = 0;
+      char *zRenames = 0;
+      char *zColDefs;
+      zCreate = sqlite3_mprintf("CREATE TABLE %s", zFullTabName);
       while( xRead(&sCtx) ){
-        zCreate = sqlite3_mprintf("%z%c\n  \"%w\" TEXT", zCreate, cSep, sCtx.z);
-        cSep = ',';
+        zAutoColumn(sCtx.z, &dbCols, 0);
         if( sCtx.cTerm!=sCtx.cColSep ) break;
       }
-      if( cSep=='(' ){
+      zColDefs = zAutoColumn(0, &dbCols, &zRenames);
+      if( zRenames!=0 ){
+        utf8_printf((stdin_is_interactive && p->in==stdin)? p->out : stderr,
+                    "Columns renamed during .import %s due to duplicates:\n"
+                    "%s\n", sCtx.zFile, zRenames);
+        sqlite3_free(zRenames);
+      }
+      assert(dbCols==0);
+      if( zColDefs==0 ){
+        utf8_printf(stderr,"%s: empty file\n", sCtx.zFile);
+      import_fail:
         sqlite3_free(zCreate);
+        sqlite3_free(zSql);
+        sqlite3_free(zFullTabName);
         import_cleanup(&sCtx);
-        utf8_printf(stderr,"%s: empty file\n", sCtx.zFile);
         rc = 1;
         goto meta_command_exit;
       }
-      zCreate = sqlite3_mprintf("%z\n)", zCreate);
+      zCreate = sqlite3_mprintf("%z%z\n", zCreate, zColDefs);
       if( eVerbose>=1 ){
         utf8_printf(p->out, "%s\n", zCreate);
       }
       rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
-      sqlite3_free(zCreate);
       if( rc ){
-        utf8_printf(stderr, "CREATE TABLE \"%s\"(...) failed: %s\n", zTable,
-                sqlite3_errmsg(p->db));
-        import_cleanup(&sCtx);
-        rc = 1;
-        goto meta_command_exit;
+        utf8_printf(stderr, "%s failed:\n%s\n", zCreate, sqlite3_errmsg(p->db));
+        goto import_fail;
       }
+      sqlite3_free(zCreate);
+      zCreate = 0;
       rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
     }
-    sqlite3_free(zSql);
     if( rc ){
       if (pStmt) sqlite3_finalize(pStmt);
       utf8_printf(stderr,"Error: %s\n", sqlite3_errmsg(p->db));
-      import_cleanup(&sCtx);
-      rc = 1;
-      goto meta_command_exit;
+      goto import_fail;
     }
+    sqlite3_free(zSql);
     nCol = sqlite3_column_count(pStmt);
     sqlite3_finalize(pStmt);
     pStmt = 0;
@@ -19247,7 +20214,7 @@
       import_cleanup(&sCtx);
       shell_out_of_memory();
     }
-    sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);
+    sqlite3_snprintf(nByte+20, zSql, "INSERT INTO %s VALUES(?", zFullTabName);
     j = strlen30(zSql);
     for(i=1; i<nCol; i++){
       zSql[j++] = ',';
@@ -19259,14 +20226,13 @@
       utf8_printf(p->out, "Insert using: %s\n", zSql);
     }
     rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
-    sqlite3_free(zSql);
     if( rc ){
       utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
       if (pStmt) sqlite3_finalize(pStmt);
-      import_cleanup(&sCtx);
-      rc = 1;
-      goto meta_command_exit;
+      goto import_fail;
     }
+    sqlite3_free(zSql);
+    sqlite3_free(zFullTabName);
     needCommit = sqlite3_get_autocommit(p->db);
     if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
     do{
@@ -19324,6 +20290,7 @@
           sCtx.nRow, sCtx.nErr, sCtx.nLine-1);
     }
   }else
+#endif /* !defined(SQLITE_SHELL_WASM_MODE) */
 
 #ifndef SQLITE_UNTESTABLE
   if( c=='i' && strncmp(azArg[0], "imposter", n)==0 ){
@@ -19372,7 +20339,7 @@
     rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
     sqlite3_free(zSql);
     i = 0;
-    while( sqlite3_step(pStmt)==SQLITE_ROW ){
+    while( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
       char zLabel[20];
       const char *zCol = (const char*)sqlite3_column_text(pStmt,2);
       i++;
@@ -19513,10 +20480,11 @@
     lintDotCommand(p, azArg, nArg);
   }else
 
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
+#if !defined(SQLITE_OMIT_LOAD_EXTENSION) && !defined(SQLITE_SHELL_WASM_MODE)
   if( c=='l' && strncmp(azArg[0], "load", n)==0 ){
     const char *zFile, *zProc;
     char *zErrMsg = 0;
+    failIfSafeMode(p, "cannot run .load in safe mode");
     if( nArg<2 ){
       raw_printf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n");
       rc = 1;
@@ -19534,7 +20502,9 @@
   }else
 #endif
 
+#ifndef SQLITE_SHELL_WASM_MODE
   if( c=='l' && strncmp(azArg[0], "log", n)==0 ){
+    failIfSafeMode(p, "cannot run .log in safe mode");
     if( nArg!=2 ){
       raw_printf(stderr, "Usage: .log FILENAME\n");
       rc = 1;
@@ -19544,67 +20514,148 @@
       p->pLog = output_file_open(zFile, 0);
     }
   }else
+#endif
 
   if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){
-    const char *zMode = nArg>=2 ? azArg[1] : "";
-    int n2 = strlen30(zMode);
-    int c2 = zMode[0];
-    if( c2=='l' && n2>2 && strncmp(azArg[1],"lines",n2)==0 ){
+    const char *zMode = 0;
+    const char *zTabname = 0;
+    int i, n2;
+    ColModeOpts cmOpts = ColModeOpts_default;
+    for(i=1; i<nArg; i++){
+      const char *z = azArg[i];
+      if( optionMatch(z,"wrap") && i+1<nArg ){
+        cmOpts.iWrap = integerValue(azArg[++i]);
+      }else if( optionMatch(z,"ww") ){
+        cmOpts.bWordWrap = 1;
+      }else if( optionMatch(z,"wordwrap") && i+1<nArg ){
+        cmOpts.bWordWrap = (u8)booleanValue(azArg[++i]);
+      }else if( optionMatch(z,"quote") ){
+        cmOpts.bQuote = 1;
+      }else if( optionMatch(z,"noquote") ){
+        cmOpts.bQuote = 0;
+      }else if( zMode==0 ){
+        zMode = z;
+        /* Apply defaults for qbox pseudo-mods. If that
+         * overwrites already-set values, user was informed of this.
+         */
+        if( strcmp(z, "qbox")==0 ){
+          ColModeOpts cmo = ColModeOpts_default_qbox;
+          zMode = "box";
+          cmOpts = cmo;
+        }
+      }else if( zTabname==0 ){
+        zTabname = z;
+      }else if( z[0]=='-' ){
+        utf8_printf(stderr, "unknown option: %s\n", z);
+        utf8_printf(stderr, "options:\n"
+                            "  --noquote\n"
+                            "  --quote\n"
+                            "  --wordwrap on/off\n"
+                            "  --wrap N\n"
+                            "  --ww\n");
+        rc = 1;
+        goto meta_command_exit;
+      }else{
+        utf8_printf(stderr, "extra argument: \"%s\"\n", z);
+        rc = 1;
+        goto meta_command_exit;
+      }
+    }
+    if( zMode==0 ){
+      if( p->mode==MODE_Column
+       || (p->mode>=MODE_Markdown && p->mode<=MODE_Box)
+      ){
+        raw_printf
+          (p->out,
+           "current output mode: %s --wrap %d --wordwrap %s --%squote\n",
+           modeDescr[p->mode], p->cmOpts.iWrap,
+           p->cmOpts.bWordWrap ? "on" : "off",
+           p->cmOpts.bQuote ? "" : "no");
+      }else{
+        raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]);
+      }
+      zMode = modeDescr[p->mode];
+    }
+    n2 = strlen30(zMode);
+    if( strncmp(zMode,"lines",n2)==0 ){
       p->mode = MODE_Line;
       sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
-    }else if( c2=='c' && strncmp(azArg[1],"columns",n2)==0 ){
+    }else if( strncmp(zMode,"columns",n2)==0 ){
       p->mode = MODE_Column;
       if( (p->shellFlgs & SHFLG_HeaderSet)==0 ){
         p->showHeader = 1;
       }
       sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
-    }else if( c2=='l' && n2>2 && strncmp(azArg[1],"list",n2)==0 ){
+      p->cmOpts = cmOpts;
+    }else if( strncmp(zMode,"list",n2)==0 ){
       p->mode = MODE_List;
       sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Column);
       sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
-    }else if( c2=='h' && strncmp(azArg[1],"html",n2)==0 ){
+    }else if( strncmp(zMode,"html",n2)==0 ){
       p->mode = MODE_Html;
-    }else if( c2=='t' && strncmp(azArg[1],"tcl",n2)==0 ){
+    }else if( strncmp(zMode,"tcl",n2)==0 ){
       p->mode = MODE_Tcl;
       sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Space);
       sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
-    }else if( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){
+    }else if( strncmp(zMode,"csv",n2)==0 ){
       p->mode = MODE_Csv;
       sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
       sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
-    }else if( c2=='t' && strncmp(azArg[1],"tabs",n2)==0 ){
+    }else if( strncmp(zMode,"tabs",n2)==0 ){
       p->mode = MODE_List;
       sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab);
-    }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){
+    }else if( strncmp(zMode,"insert",n2)==0 ){
       p->mode = MODE_Insert;
-      set_table_name(p, nArg>=3 ? azArg[2] : "table");
-    }else if( c2=='q' && strncmp(azArg[1],"quote",n2)==0 ){
+      set_table_name(p, zTabname ? zTabname : "table");
+    }else if( strncmp(zMode,"quote",n2)==0 ){
       p->mode = MODE_Quote;
       sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
       sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
-    }else if( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){
+    }else if( strncmp(zMode,"ascii",n2)==0 ){
       p->mode = MODE_Ascii;
       sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit);
       sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
-    }else if( c2=='m' && strncmp(azArg[1],"markdown",n2)==0 ){
+    }else if( strncmp(zMode,"markdown",n2)==0 ){
       p->mode = MODE_Markdown;
-    }else if( c2=='t' && strncmp(azArg[1],"table",n2)==0 ){
+      p->cmOpts = cmOpts;
+    }else if( strncmp(zMode,"table",n2)==0 ){
       p->mode = MODE_Table;
-    }else if( c2=='b' && strncmp(azArg[1],"box",n2)==0 ){
+      p->cmOpts = cmOpts;
+    }else if( strncmp(zMode,"box",n2)==0 ){
       p->mode = MODE_Box;
-    }else if( c2=='j' && strncmp(azArg[1],"json",n2)==0 ){
+      p->cmOpts = cmOpts;
+    }else if( strncmp(zMode,"count",n2)==0 ){
+      p->mode = MODE_Count;
+    }else if( strncmp(zMode,"off",n2)==0 ){
+      p->mode = MODE_Off;
+    }else if( strncmp(zMode,"json",n2)==0 ){
       p->mode = MODE_Json;
-    }else if( nArg==1 ){
-      raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]);
     }else{
       raw_printf(stderr, "Error: mode should be one of: "
          "ascii box column csv html insert json line list markdown "
-         "quote table tabs tcl\n");
+         "qbox quote table tabs tcl\n");
       rc = 1;
     }
     p->cMode = p->mode;
   }else
 
+#ifndef SQLITE_SHELL_WASM_MODE
+  if( c=='n' && strcmp(azArg[0], "nonce")==0 ){
+    if( nArg!=2 ){
+      raw_printf(stderr, "Usage: .nonce NONCE\n");
+      rc = 1;
+    }else if( p->zNonce==0 || strcmp(azArg[1],p->zNonce)!=0 ){
+      raw_printf(stderr, "line %d: incorrect nonce: \"%s\"\n",
+                 p->lineno, azArg[1]);
+      exit(1);
+    }else{
+      p->bSafeMode = 0;
+      return 0;  /* Return immediately to bypass the safe mode reset
+                 ** at the end of this procedure */
+    }
+  }else
+#endif /* !defined(SQLITE_SHELL_WASM_MODE) */
+
   if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){
     if( nArg==2 ){
       sqlite3_snprintf(sizeof(p->nullValue), p->nullValue,
@@ -19615,102 +20666,100 @@
     }
   }else
 
-#ifdef SQLITE_DEBUG
-  if( c=='o' && strcmp(azArg[0],"oom")==0 ){
-    int i;
-    for(i=1; i<nArg; i++){
-      const char *z = azArg[i];
-      if( z[0]=='-' && z[1]=='-' ) z++;
-      if( strcmp(z,"-repeat")==0 ){
-        if( i==nArg-1 ){
-          raw_printf(p->out, "missing argument on \"%s\"\n", azArg[i]);
-          rc = 1;
-        }else{
-          oomRepeat = (int)integerValue(azArg[++i]);
-        }
-      }else if( IsDigit(z[0]) ){
-        oomCounter = (int)integerValue(azArg[i]);
-      }else{
-        raw_printf(p->out, "unknown argument: \"%s\"\n", azArg[i]);
-        raw_printf(p->out, "Usage: .oom [--repeat N] [M]\n");
-        rc = 1;
-      }
-    }
-    if( rc==0 ){
-      raw_printf(p->out, "oomCounter = %d\n", oomCounter);
-      raw_printf(p->out, "oomRepeat  = %d\n", oomRepeat);
-    }
-  }else
-#endif /* SQLITE_DEBUG */
-
   if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
+    const char *zFN = 0;     /* Pointer to constant filename */
     char *zNewFilename = 0;  /* Name of the database file to open */
     int iName = 1;           /* Index in azArg[] of the filename */
     int newFlag = 0;         /* True to delete file before opening */
-    /* Close the existing database */
-    session_close_all(p);
-    close_db(p->db);
-    p->db = 0;
-    p->zDbFilename = 0;
-    sqlite3_free(p->zFreeOnClose);
-    p->zFreeOnClose = 0;
-    p->openMode = SHELL_OPEN_UNSPEC;
-    p->openFlags = 0;
-    p->szMax = 0;
+    int openMode = SHELL_OPEN_UNSPEC;
+
     /* Check for command-line arguments */
     for(iName=1; iName<nArg; iName++){
       const char *z = azArg[iName];
+#ifndef SQLITE_SHELL_WASM_MODE
       if( optionMatch(z,"new") ){
         newFlag = 1;
 #ifdef SQLITE_HAVE_ZLIB
       }else if( optionMatch(z, "zip") ){
-        p->openMode = SHELL_OPEN_ZIPFILE;
+        openMode = SHELL_OPEN_ZIPFILE;
 #endif
       }else if( optionMatch(z, "append") ){
-        p->openMode = SHELL_OPEN_APPENDVFS;
+        openMode = SHELL_OPEN_APPENDVFS;
       }else if( optionMatch(z, "readonly") ){
-        p->openMode = SHELL_OPEN_READONLY;
+        openMode = SHELL_OPEN_READONLY;
       }else if( optionMatch(z, "nofollow") ){
         p->openFlags |= SQLITE_OPEN_NOFOLLOW;
 #ifndef SQLITE_OMIT_DESERIALIZE
       }else if( optionMatch(z, "deserialize") ){
-        p->openMode = SHELL_OPEN_DESERIALIZE;
+        openMode = SHELL_OPEN_DESERIALIZE;
       }else if( optionMatch(z, "hexdb") ){
-        p->openMode = SHELL_OPEN_HEXDB;
+        openMode = SHELL_OPEN_HEXDB;
       }else if( optionMatch(z, "maxsize") && iName+1<nArg ){
         p->szMax = integerValue(azArg[++iName]);
 #endif /* SQLITE_OMIT_DESERIALIZE */
-      }else if( z[0]=='-' ){
+      }else
+#endif /* !SQLITE_SHELL_WASM_MODE */
+      if( z[0]=='-' ){
         utf8_printf(stderr, "unknown option: %s\n", z);
         rc = 1;
         goto meta_command_exit;
-      }else if( zNewFilename ){
+      }else if( zFN ){
         utf8_printf(stderr, "extra argument: \"%s\"\n", z);
         rc = 1;
         goto meta_command_exit;
       }else{
-        zNewFilename = sqlite3_mprintf("%s", z);
+        zFN = z;
       }
     }
+
+    /* Close the existing database */
+    session_close_all(p, -1);
+    close_db(p->db);
+    p->db = 0;
+    p->pAuxDb->zDbFilename = 0;
+    sqlite3_free(p->pAuxDb->zFreeOnClose);
+    p->pAuxDb->zFreeOnClose = 0;
+    p->openMode = openMode;
+    p->openFlags = 0;
+    p->szMax = 0;
+
     /* If a filename is specified, try to open it first */
-    if( zNewFilename || p->openMode==SHELL_OPEN_HEXDB ){
-      if( newFlag ) shellDeleteFile(zNewFilename);
-      p->zDbFilename = zNewFilename;
+    if( zFN || p->openMode==SHELL_OPEN_HEXDB ){
+      if( newFlag && zFN && !p->bSafeMode ) shellDeleteFile(zFN);
+#ifndef SQLITE_SHELL_WASM_MODE
+      if( p->bSafeMode
+       && p->openMode!=SHELL_OPEN_HEXDB
+       && zFN
+       && strcmp(zFN,":memory:")!=0
+      ){
+        failIfSafeMode(p, "cannot open disk-based database files in safe mode");
+      }
+#else
+      /* WASM mode has its own sandboxed pseudo-filesystem. */
+#endif
+      if( zFN ){
+        zNewFilename = sqlite3_mprintf("%s", zFN);
+        shell_check_oom(zNewFilename);
+      }else{
+        zNewFilename = 0;
+      }
+      p->pAuxDb->zDbFilename = zNewFilename;
       open_db(p, OPEN_DB_KEEPALIVE);
       if( p->db==0 ){
         utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename);
         sqlite3_free(zNewFilename);
       }else{
-        p->zFreeOnClose = zNewFilename;
+        p->pAuxDb->zFreeOnClose = zNewFilename;
       }
     }
     if( p->db==0 ){
       /* As a fall-back open a TEMP database */
-      p->zDbFilename = 0;
+      p->pAuxDb->zDbFilename = 0;
       open_db(p, 0);
     }
   }else
 
+#ifndef SQLITE_SHELL_WASM_MODE
   if( (c=='o'
         && (strncmp(azArg[0], "output", n)==0||strncmp(azArg[0], "once", n)==0))
    || (c=='e' && n==5 && strcmp(azArg[0],"excel")==0)
@@ -19719,9 +20768,11 @@
     int bTxtMode = 0;
     int i;
     int eMode = 0;
-    int bBOM = 0;
-    int bOnce = 0;  /* 0: .output, 1: .once, 2: .excel */
+    int bOnce = 0;            /* 0: .output, 1: .once, 2: .excel */
+    unsigned char zBOM[4];    /* Byte-order mark to using if --bom is present */
 
+    zBOM[0] = 0;
+    failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
     if( c=='e' ){
       eMode = 'x';
       bOnce = 2;
@@ -19733,7 +20784,10 @@
       if( z[0]=='-' ){
         if( z[1]=='-' ) z++;
         if( strcmp(z,"-bom")==0 ){
-          bBOM = 1;
+          zBOM[0] = 0xef;
+          zBOM[1] = 0xbb;
+          zBOM[2] = 0xbf;
+          zBOM[3] = 0;
         }else if( c!='e' && strcmp(z,"-x")==0 ){
           eMode = 'x';  /* spreadsheet */
         }else if( c!='e' && strcmp(z,"-e")==0 ){
@@ -19747,7 +20801,7 @@
         }
       }else if( zFile==0 && eMode!='e' && eMode!='x' ){
         zFile = sqlite3_mprintf("%s", z);
-        if( zFile[0]=='|' ){
+        if( zFile && zFile[0]=='|' ){
           while( i+1<nArg ) zFile = sqlite3_mprintf("%z %s", zFile, azArg[++i]);
           break;
         }
@@ -19760,7 +20814,9 @@
         goto meta_command_exit;
       }
     }
-    if( zFile==0 ) zFile = sqlite3_mprintf("stdout");
+    if( zFile==0 ){
+      zFile = sqlite3_mprintf("stdout");
+    }
     if( bOnce ){
       p->outCount = 2;
     }else{
@@ -19787,6 +20843,7 @@
       zFile = sqlite3_mprintf("%s", p->zTempFile);
     }
 #endif /* SQLITE_NOHAVE_SYSTEM */
+    shell_check_oom(zFile);
     if( zFile[0]=='|' ){
 #ifdef SQLITE_OMIT_POPEN
       raw_printf(stderr, "Error: pipes are not supported in this OS\n");
@@ -19799,7 +20856,7 @@
         p->out = stdout;
         rc = 1;
       }else{
-        if( bBOM ) fprintf(p->out,"\357\273\277");
+        if( zBOM[0] ) fwrite(zBOM, 1, 3, p->out);
         sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
       }
 #endif
@@ -19812,12 +20869,13 @@
         p->out = stdout;
         rc = 1;
       } else {
-        if( bBOM ) fprintf(p->out,"\357\273\277");
+        if( zBOM[0] ) fwrite(zBOM, 1, 3, p->out);
         sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
       }
     }
     sqlite3_free(zFile);
   }else
+#endif /* !defined(SQLITE_SHELL_WASM_MODE) */
 
   if( c=='p' && n>=3 && strncmp(azArg[0], "parameter", n)==0 ){
     open_db(p,0);
@@ -19851,7 +20909,7 @@
         rx = sqlite3_prepare_v2(p->db,
              "SELECT key, quote(value) "
              "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
-        while( sqlite3_step(pStmt)==SQLITE_ROW ){
+        while( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
           utf8_printf(p->out, "%-*s %s\n", len, sqlite3_column_text(pStmt,0),
                       sqlite3_column_text(pStmt,1));
         }
@@ -19883,7 +20941,7 @@
       zSql = sqlite3_mprintf(
                   "REPLACE INTO temp.sqlite_parameters(key,value)"
                   "VALUES(%Q,%s);", zKey, zValue);
-      if( zSql==0 ) shell_out_of_memory();
+      shell_check_oom(zSql);
       pStmt = 0;
       rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
       sqlite3_free(zSql);
@@ -19893,7 +20951,7 @@
         zSql = sqlite3_mprintf(
                    "REPLACE INTO temp.sqlite_parameters(key,value)"
                    "VALUES(%Q,%Q);", zKey, zValue);
-        if( zSql==0 ) shell_out_of_memory();
+        shell_check_oom(zSql);
         rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
         sqlite3_free(zSql);
         if( rx!=SQLITE_OK ){
@@ -19914,7 +20972,7 @@
     if( nArg==3 && strcmp(azArg[1],"unset")==0 ){
       char *zSql = sqlite3_mprintf(
           "DELETE FROM temp.sqlite_parameters WHERE key=%Q", azArg[2]);
-      if( zSql==0 ) shell_out_of_memory();
+      shell_check_oom(zSql);
       sqlite3_exec(p->db, zSql, 0, 0, 0);
       sqlite3_free(zSql);
     }else
@@ -19987,13 +21045,17 @@
     }
   }else
 
+#ifndef SQLITE_SHELL_WASM_MODE
   if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){
     rc = 2;
   }else
+#endif
 
+#ifndef SQLITE_SHELL_WASM_MODE
   if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){
     FILE *inSaved = p->in;
     int savedLineno = p->lineno;
+    failIfSafeMode(p, "cannot run .read in safe mode");
     if( nArg!=2 ){
       raw_printf(stderr, "Usage: .read FILE\n");
       rc = 1;
@@ -20014,7 +21076,7 @@
         pclose(p->in);
       }
 #endif
-    }else if( notNormalFile(azArg[1]) || (p->in = fopen(azArg[1], "rb"))==0 ){
+    }else if( (p->in = openChrSource(azArg[1]))==0 ){
       utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
       rc = 1;
     }else{
@@ -20024,14 +21086,17 @@
     p->in = inSaved;
     p->lineno = savedLineno;
   }else
+#endif /* !defined(SQLITE_SHELL_WASM_MODE) */
 
+#ifndef SQLITE_SHELL_WASM_MODE
   if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 ){
     const char *zSrcFile;
     const char *zDb;
     sqlite3 *pSrc;
     sqlite3_backup *pBackup;
     int nTimeout = 0;
 
+    failIfSafeMode(p, "cannot run .restore in safe mode");
     if( nArg==2 ){
       zSrcFile = azArg[1];
       zDb = "main";
@@ -20075,6 +21140,7 @@
     }
     close_db(pSrc);
   }else
+#endif /* !defined(SQLITE_SHELL_WASM_MODE) */
 
   if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){
     if( nArg==2 ){
@@ -20138,6 +21204,7 @@
                       "  rootpage integer,\n"
                       "  sql text\n"
                       ")", zName);
+        shell_check_oom(new_argv[0]);
         new_argv[1] = 0;
         new_colv[0] = "sql";
         new_colv[1] = 0;
@@ -20189,8 +21256,10 @@
       appendText(&sSelect, ") WHERE ", 0);
       if( zName ){
         char *zQarg = sqlite3_mprintf("%Q", zName);
-        int bGlob = strchr(zName, '*') != 0 || strchr(zName, '?') != 0 ||
-                    strchr(zName, '[') != 0;
+        int bGlob;
+        shell_check_oom(zQarg);
+        bGlob = strchr(zName, '*') != 0 || strchr(zName, '?') != 0 ||
+                strchr(zName, '[') != 0;
         if( strchr(zName, '.') ){
           appendText(&sSelect, "lower(printf('%s.%s',sname,tbl_name))", 0);
         }else{
@@ -20228,30 +21297,33 @@
     }
   }else
 
-  if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){
+  if( (c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0)
+   || (c=='t' && n==9  && strncmp(azArg[0], "treetrace", n)==0)
+  ){
     unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
     sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &x);
   }else
 
 #if defined(SQLITE_ENABLE_SESSION)
   if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){
-    OpenSession *pSession = &p->aSession[0];
+    struct AuxDb *pAuxDb = p->pAuxDb;
+    OpenSession *pSession = &pAuxDb->aSession[0];
     char **azCmd = &azArg[1];
     int iSes = 0;
     int nCmd = nArg - 1;
     int i;
     if( nArg<=1 ) goto session_syntax_error;
     open_db(p, 0);
     if( nArg>=3 ){
-      for(iSes=0; iSes<p->nSession; iSes++){
-        if( strcmp(p->aSession[iSes].zName, azArg[1])==0 ) break;
+      for(iSes=0; iSes<pAuxDb->nSession; iSes++){
+        if( strcmp(pAuxDb->aSession[iSes].zName, azArg[1])==0 ) break;
       }
-      if( iSes<p->nSession ){
-        pSession = &p->aSession[iSes];
+      if( iSes<pAuxDb->nSession ){
+        pSession = &pAuxDb->aSession[iSes];
         azCmd++;
         nCmd--;
       }else{
-        pSession = &p->aSession[0];
+        pSession = &pAuxDb->aSession[0];
         iSes = 0;
       }
     }
@@ -20280,6 +21352,7 @@
     */
     if( strcmp(azCmd[0],"changeset")==0 || strcmp(azCmd[0],"patchset")==0 ){
       FILE *out = 0;
+      failIfSafeMode(p, "cannot run \".session %s\" in safe mode", azCmd[0]);
       if( nCmd!=2 ) goto session_syntax_error;
       if( pSession->p==0 ) goto session_not_open;
       out = fopen(azCmd[1], "wb");
@@ -20313,9 +21386,9 @@
     */
     if( strcmp(azCmd[0], "close")==0 ){
       if( nCmd!=1 ) goto session_syntax_error;
-      if( p->nSession ){
+      if( pAuxDb->nSession ){
         session_close(pSession);
-        p->aSession[iSes] = p->aSession[--p->nSession];
+        pAuxDb->aSession[iSes] = pAuxDb->aSession[--pAuxDb->nSession];
       }
     }else
 
@@ -20326,7 +21399,7 @@
       int ii;
       if( nCmd>2 ) goto session_syntax_error;
       ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
-      if( p->nSession ){
+      if( pAuxDb->nSession ){
         ii = sqlite3session_enable(pSession->p, ii);
         utf8_printf(p->out, "session %s enable flag = %d\n",
                     pSession->zName, ii);
@@ -20339,7 +21412,7 @@
     if( strcmp(azCmd[0], "filter")==0 ){
       int ii, nByte;
       if( nCmd<2 ) goto session_syntax_error;
-      if( p->nSession ){
+      if( pAuxDb->nSession ){
         for(ii=0; ii<pSession->nFilter; ii++){
           sqlite3_free(pSession->azFilter[ii]);
         }
@@ -20351,7 +21424,8 @@
           exit(1);
         }
         for(ii=1; ii<nCmd; ii++){
-          pSession->azFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]);
+          char *x = pSession->azFilter[ii-1] = sqlite3_mprintf("%s", azCmd[ii]);
+          shell_check_oom(x);
         }
         pSession->nFilter = ii-1;
       }
@@ -20364,7 +21438,7 @@
       int ii;
       if( nCmd>2 ) goto session_syntax_error;
       ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
-      if( p->nSession ){
+      if( pAuxDb->nSession ){
         ii = sqlite3session_indirect(pSession->p, ii);
         utf8_printf(p->out, "session %s indirect flag = %d\n",
                     pSession->zName, ii);
@@ -20377,7 +21451,7 @@
     if( strcmp(azCmd[0], "isempty")==0 ){
       int ii;
       if( nCmd!=1 ) goto session_syntax_error;
-      if( p->nSession ){
+      if( pAuxDb->nSession ){
         ii = sqlite3session_isempty(pSession->p);
         utf8_printf(p->out, "session %s isempty flag = %d\n",
                     pSession->zName, ii);
@@ -20388,8 +21462,8 @@
     ** List all currently open sessions
     */
     if( strcmp(azCmd[0],"list")==0 ){
-      for(i=0; i<p->nSession; i++){
-        utf8_printf(p->out, "%d %s\n", i, p->aSession[i].zName);
+      for(i=0; i<pAuxDb->nSession; i++){
+        utf8_printf(p->out, "%d %s\n", i, pAuxDb->aSession[i].zName);
       }
     }else
 
@@ -20402,17 +21476,17 @@
       if( nCmd!=3 ) goto session_syntax_error;
       zName = azCmd[2];
       if( zName[0]==0 ) goto session_syntax_error;
-      for(i=0; i<p->nSession; i++){
-        if( strcmp(p->aSession[i].zName,zName)==0 ){
+      for(i=0; i<pAuxDb->nSession; i++){
+        if( strcmp(pAuxDb->aSession[i].zName,zName)==0 ){
           utf8_printf(stderr, "Session \"%s\" already exists\n", zName);
           goto meta_command_exit;
         }
       }
-      if( p->nSession>=ArraySize(p->aSession) ){
-        raw_printf(stderr, "Maximum of %d sessions\n", ArraySize(p->aSession));
+      if( pAuxDb->nSession>=ArraySize(pAuxDb->aSession) ){
+        raw_printf(stderr, "Maximum of %d sessions\n", ArraySize(pAuxDb->aSession));
         goto meta_command_exit;
       }
-      pSession = &p->aSession[p->nSession];
+      pSession = &pAuxDb->aSession[pAuxDb->nSession];
       rc = sqlite3session_create(p->db, azCmd[1], &pSession->p);
       if( rc ){
         raw_printf(stderr, "Cannot open session: error code=%d\n", rc);
@@ -20421,8 +21495,9 @@
       }
       pSession->nFilter = 0;
       sqlite3session_table_filter(pSession->p, session_filter, pSession);
-      p->nSession++;
+      pAuxDb->nSession++;
       pSession->zName = sqlite3_mprintf("%s", zName);
+      shell_check_oom(pSession->zName);
     }else
     /* If no command name matches, show a syntax error */
     session_syntax_error:
@@ -20516,11 +21591,12 @@
         const char *zSql = (const char*)sqlite3_column_text(pStmt, 2);
         const char *zAns = (const char*)sqlite3_column_text(pStmt, 3);
 
+        if( zOp==0 ) continue;
+        if( zSql==0 ) continue;
+        if( zAns==0 ) continue;
         k = 0;
         if( bVerbose>0 ){
-          char *zQuote = sqlite3_mprintf("%q", zSql);
           printf("%d: %s %s\n", tno, zOp, zSql);
-          sqlite3_free(zQuote);
         }
         if( strcmp(zOp,"memo")==0 ){
           utf8_printf(p->out, "%s\n", zSql);
@@ -20638,6 +21714,7 @@
     zSep = "VALUES(";
     while( SQLITE_ROW==sqlite3_step(pStmt) ){
       const char *zTab = (const char*)sqlite3_column_text(pStmt,0);
+      if( zTab==0 ) continue;
       if( zLike && sqlite3_strlike(zLike, zTab, 0)!=0 ) continue;
       if( strncmp(zTab, "sqlite_",7)!=0 ){
         appendText(&sQuery,"SELECT * FROM ", 0);
@@ -20678,6 +21755,7 @@
           "   FROM [sha3sum$query]",
           sSql.z, iSize);
     }
+    shell_check_oom(zSql);
     freeText(&sQuery);
     freeText(&sSql);
     if( bDebug ){
@@ -20688,27 +21766,28 @@
     sqlite3_free(zSql);
   }else
 
-#ifndef SQLITE_NOHAVE_SYSTEM
+#if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_WASM_MODE)
   if( c=='s'
    && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
   ){
     char *zCmd;
     int i, x;
+    failIfSafeMode(p, "cannot run .%s in safe mode", azArg[0]);
     if( nArg<2 ){
       raw_printf(stderr, "Usage: .system COMMAND\n");
       rc = 1;
       goto meta_command_exit;
     }
     zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
-    for(i=2; i<nArg; i++){
+    for(i=2; i<nArg && zCmd!=0; i++){
       zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
                              zCmd, azArg[i]);
     }
-    x = system(zCmd);
+    x = zCmd!=0 ? system(zCmd) : 1;
     sqlite3_free(zCmd);
     if( x ) raw_printf(stderr, "System command returns %d\n", x);
   }else
-#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
+#endif /* !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_WASM_MODE) */
 
   if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
     static const char *azBool[] = { "off", "on", "trigger", "full"};
@@ -20720,12 +21799,22 @@
       goto meta_command_exit;
     }
     utf8_printf(p->out, "%12.12s: %s\n","echo",
-                                  azBool[ShellHasFlag(p, SHFLG_Echo)]);
+                azBool[ShellHasFlag(p, SHFLG_Echo)]);
     utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]);
     utf8_printf(p->out, "%12.12s: %s\n","explain",
          p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off");
     utf8_printf(p->out,"%12.12s: %s\n","headers", azBool[p->showHeader!=0]);
-    utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]);
+    if( p->mode==MODE_Column
+     || (p->mode>=MODE_Markdown && p->mode<=MODE_Box)
+    ){
+      utf8_printf
+        (p->out, "%12.12s: %s --wrap %d --wordwrap %s --%squote\n", "mode",
+         modeDescr[p->mode], p->cmOpts.iWrap,
+         p->cmOpts.bWordWrap ? "on" : "off",
+         p->cmOpts.bQuote ? "" : "no");
+    }else{
+      utf8_printf(p->out, "%12.12s: %s\n","mode", modeDescr[p->mode]);
+    }
     utf8_printf(p->out, "%12.12s: ", "nullvalue");
       output_c_string(p->out, p->nullValue);
       raw_printf(p->out, "\n");
@@ -20750,7 +21839,7 @@
     }
     raw_printf(p->out, "\n");
     utf8_printf(p->out, "%12.12s: %s\n", "filename",
-                p->zDbFilename ? p->zDbFilename : "");
+                p->pAuxDb->zDbFilename ? p->pAuxDb->zDbFilename : "");
   }else
 
   if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){
@@ -20819,8 +21908,10 @@
       }
     }
     rc = sqlite3_finalize(pStmt);
-    appendText(&s, " ORDER BY 1", 0);
-    rc = sqlite3_prepare_v2(p->db, s.z, -1, &pStmt, 0);
+    if( rc==SQLITE_OK ){
+      appendText(&s, " ORDER BY 1", 0);
+      rc = sqlite3_prepare_v2(p->db, s.z, -1, &pStmt, 0);
+    }
     freeText(&s);
     if( rc ) return shellDatabaseError(p->db);
 
@@ -20838,12 +21929,12 @@
         char **azNew;
         int n2 = nAlloc*2 + 10;
         azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2);
-        if( azNew==0 ) shell_out_of_memory();
+        shell_check_oom(azNew);
         nAlloc = n2;
         azResult = azNew;
       }
       azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
-      if( 0==azResult[nRow] ) shell_out_of_memory();
+      shell_check_oom(azResult[nRow]);
       nRow++;
     }
     if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
@@ -20876,6 +21967,7 @@
     sqlite3_free(azResult);
   }else
 
+#ifndef SQLITE_SHELL_WASM_MODE
   /* Begin redirecting output to the file "testcase-out.txt" */
   if( c=='t' && strcmp(azArg[0],"testcase")==0 ){
     output_reset(p);
@@ -20889,35 +21981,38 @@
       sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?");
     }
   }else
+#endif /* !defined(SQLITE_SHELL_WASM_MODE) */
 
 #ifndef SQLITE_UNTESTABLE
   if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 ){
     static const struct {
        const char *zCtrlName;   /* Name of a test-control option */
        int ctrlCode;            /* Integer code for that option */
+       int unSafe;              /* Not valid for --safe mode */
        const char *zUsage;      /* Usage notes */
     } aCtrl[] = {
-      { "always",             SQLITE_TESTCTRL_ALWAYS,        "BOOLEAN"        },
-      { "assert",             SQLITE_TESTCTRL_ASSERT,        "BOOLEAN"        },
-    /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, ""       },*/
-    /*{ "bitvec_test",        SQLITE_TESTCTRL_BITVEC_TEST,   ""             },*/
-      { "byteorder",          SQLITE_TESTCTRL_BYTEORDER,     ""               },
-      { "extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,"BOOLEAN"   },
-    /*{ "fault_install",      SQLITE_TESTCTRL_FAULT_INSTALL, ""             },*/
-      { "imposter",         SQLITE_TESTCTRL_IMPOSTER, "SCHEMA ON/OFF ROOTPAGE"},
-      { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, "" },
-      { "localtime_fault",    SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN"       },
-      { "never_corrupt",      SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN"        },
-      { "optimizations",      SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK"   },
+      { "always",             SQLITE_TESTCTRL_ALWAYS, 1,     "BOOLEAN"         },
+      { "assert",             SQLITE_TESTCTRL_ASSERT, 1,     "BOOLEAN"         },
+    /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,1, ""        },*/
+    /*{ "bitvec_test",        SQLITE_TESTCTRL_BITVEC_TEST, 1,  ""              },*/
+      { "byteorder",          SQLITE_TESTCTRL_BYTEORDER, 0,  ""                },
+      { "extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,0,"BOOLEAN"  },
+    /*{ "fault_install",      SQLITE_TESTCTRL_FAULT_INSTALL, 1,""              },*/
+      { "imposter",         SQLITE_TESTCTRL_IMPOSTER,1,"SCHEMA ON/OFF ROOTPAGE"},
+      { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS,0,""          },
+      { "localtime_fault",    SQLITE_TESTCTRL_LOCALTIME_FAULT,0,"BOOLEAN"      },
+      { "never_corrupt",      SQLITE_TESTCTRL_NEVER_CORRUPT,1, "BOOLEAN"       },
+      { "optimizations",      SQLITE_TESTCTRL_OPTIMIZATIONS,0,"DISABLE-MASK"   },
 #ifdef YYCOVERAGE
-      { "parser_coverage",    SQLITE_TESTCTRL_PARSER_COVERAGE, ""             },
+      { "parser_coverage",    SQLITE_TESTCTRL_PARSER_COVERAGE,0,""             },
 #endif
-      { "pending_byte",       SQLITE_TESTCTRL_PENDING_BYTE,  "OFFSET  "       },
-      { "prng_restore",       SQLITE_TESTCTRL_PRNG_RESTORE,  ""               },
-      { "prng_save",          SQLITE_TESTCTRL_PRNG_SAVE,     ""               },
-      { "prng_seed",          SQLITE_TESTCTRL_PRNG_SEED,     "SEED ?db?"      },
-      { "seek_count",         SQLITE_TESTCTRL_SEEK_COUNT,    ""               },
-      { "tune",               SQLITE_TESTCTRL_TUNE,          "ID VALUE"       },
+      { "pending_byte",       SQLITE_TESTCTRL_PENDING_BYTE,0, "OFFSET  "       },
+      { "prng_restore",       SQLITE_TESTCTRL_PRNG_RESTORE,0, ""               },
+      { "prng_save",          SQLITE_TESTCTRL_PRNG_SAVE,   0, ""               },
+      { "prng_seed",          SQLITE_TESTCTRL_PRNG_SEED,   0, "SEED ?db?"      },
+      { "seek_count",         SQLITE_TESTCTRL_SEEK_COUNT,  0, ""               },
+      { "sorter_mmap",        SQLITE_TESTCTRL_SORTER_MMAP, 0, "NMAX"           },
+      { "tune",               SQLITE_TESTCTRL_TUNE,        1, "ID VALUE"       },
     };
     int testctrl = -1;
     int iCtrl = -1;
@@ -20965,6 +22060,11 @@
     if( testctrl<0 ){
       utf8_printf(stderr,"Error: unknown test-control: %s\n"
                          "Use \".testctrl --help\" for help\n", zCmd);
+    }else if( aCtrl[iCtrl].unSafe && p->bSafeMode ){
+      utf8_printf(stderr,
+         "line %d: \".testctrl %s\" may not be used in safe mode\n",
+         p->lineno, aCtrl[iCtrl].zCtrlName);
+      exit(1);
     }else{
       switch(testctrl){
 
@@ -21097,6 +22197,13 @@
           break;
         }
 #endif
+        case SQLITE_TESTCTRL_SORTER_MMAP:
+          if( nArg==3 ){
+            int opt = (unsigned int)integerValue(azArg[2]);
+            rc2 = sqlite3_test_control(testctrl, p->db, opt);
+            isOk = 3;
+          }
+          break;
       }
     }
     if( isOk==0 && iCtrl>=0 ){
@@ -21338,7 +22445,7 @@
     int j;
     assert( nArg<=ArraySize(azArg) );
     p->nWidth = nArg-1;
-    p->colWidth = realloc(p->colWidth, p->nWidth*sizeof(int)*2);
+    p->colWidth = realloc(p->colWidth, (p->nWidth+1)*sizeof(int)*2);
     if( p->colWidth==0 && p->nWidth>0 ) shell_out_of_memory();
     if( p->nWidth ) p->actualWidth = &p->colWidth[p->nWidth];
     for(j=1; j<nArg; j++){
@@ -21357,58 +22464,115 @@
     p->outCount--;
     if( p->outCount==0 ) output_reset(p);
   }
+  p->bSafeMode = p->bSafeModePersist;
   return rc;
 }
 
-/*
-** Return TRUE if a semicolon occurs anywhere in the first N characters
-** of string z[].
+/* Line scan result and intermediate states (supporting scan resumption)
 */
-static int line_contains_semicolon(const char *z, int N){
-  int i;
-  for(i=0; i<N; i++){  if( z[i]==';' ) return 1; }
-  return 0;
-}
+#ifndef CHAR_BIT
+# define CHAR_BIT 8
+#endif
+typedef enum {
+  QSS_HasDark = 1<<CHAR_BIT, QSS_EndingSemi = 2<<CHAR_BIT,
+  QSS_CharMask = (1<<CHAR_BIT)-1, QSS_ScanMask = 3<<CHAR_BIT,
+  QSS_Start = 0
+} QuickScanState;
+#define QSS_SETV(qss, newst) ((newst) | ((qss) & QSS_ScanMask))
+#define QSS_INPLAIN(qss) (((qss)&QSS_CharMask)==QSS_Start)
+#define QSS_PLAINWHITE(qss) (((qss)&~QSS_EndingSemi)==QSS_Start)
+#define QSS_PLAINDARK(qss) (((qss)&~QSS_EndingSemi)==QSS_HasDark)
+#define QSS_SEMITERM(qss) (((qss)&~QSS_HasDark)==QSS_EndingSemi)
 
 /*
-** Test to see if a line consists entirely of whitespace.
+** Scan line for classification to guide shell's handling.
+** The scan is resumable for subsequent lines when prior
+** return values are passed as the 2nd argument.
 */
-static int _all_whitespace(const char *z){
-  for(; *z; z++){
-    if( IsSpace(z[0]) ) continue;
-    if( *z=='/' && z[1]=='*' ){
-      z += 2;
-      while( *z && (*z!='*' || z[1]!='/') ){ z++; }
-      if( *z==0 ) return 0;
-      z++;
-      continue;
+static QuickScanState quickscan(char *zLine, QuickScanState qss){
+  char cin;
+  char cWait = (char)qss; /* intentional narrowing loss */
+  if( cWait==0 ){
+  PlainScan:
+    assert( cWait==0 );
+    while( (cin = *zLine++)!=0 ){
+      if( IsSpace(cin) )
+        continue;
+      switch (cin){
+      case '-':
+        if( *zLine!='-' )
+          break;
+        while((cin = *++zLine)!=0 )
+          if( cin=='\n')
+            goto PlainScan;
+        return qss;
+      case ';':
+        qss |= QSS_EndingSemi;
+        continue;
+      case '/':
+        if( *zLine=='*' ){
+          ++zLine;
+          cWait = '*';
+          qss = QSS_SETV(qss, cWait);
+          goto TermScan;
+        }
+        break;
+      case '[':
+        cin = ']';
+        /* fall thru */
+      case '`': case '\'': case '"':
+        cWait = cin;
+        qss = QSS_HasDark | cWait;
+        goto TermScan;
+      default:
+        break;
+      }
+      qss = (qss & ~QSS_EndingSemi) | QSS_HasDark;
     }
-    if( *z=='-' && z[1]=='-' ){
-      z += 2;
-      while( *z && *z!='\n' ){ z++; }
-      if( *z==0 ) return 1;
-      continue;
+  }else{
+  TermScan:
+    while( (cin = *zLine++)!=0 ){
+      if( cin==cWait ){
+        switch( cWait ){
+        case '*':
+          if( *zLine != '/' )
+            continue;
+          ++zLine;
+          cWait = 0;
+          qss = QSS_SETV(qss, 0);
+          goto PlainScan;
+        case '`': case '\'': case '"':
+          if(*zLine==cWait){
+            ++zLine;
+            continue;
+          }
+          /* fall thru */
+        case ']':
+          cWait = 0;
+          qss = QSS_SETV(qss, 0);
+          goto PlainScan;
+        default: assert(0);
+        }
+      }
     }
-    return 0;
   }
-  return 1;
+  return qss;
 }
 
 /*
 ** Return TRUE if the line typed in is an SQL command terminator other
 ** than a semi-colon.  The SQL Server style "go" command is understood
 ** as is the Oracle "/".
 */
-static int line_is_command_terminator(const char *zLine){
+static int line_is_command_terminator(char *zLine){
   while( IsSpace(zLine[0]) ){ zLine++; };
-  if( zLine[0]=='/' && _all_whitespace(&zLine[1]) ){
-    return 1;  /* Oracle */
-  }
-  if( ToLower(zLine[0])=='g' && ToLower(zLine[1])=='o'
-         && _all_whitespace(&zLine[2]) ){
-    return 1;  /* SQL Server */
-  }
-  return 0;
+  if( zLine[0]=='/' )
+    zLine += 1; /* Oracle */
+  else if ( ToLower(zLine[0])=='g' && ToLower(zLine[1])=='o' )
+    zLine += 2; /* SQL Server */
+  else
+    return 0;
+  return quickscan(zLine, QSS_Start)==QSS_Start;
 }
 
 /*
@@ -21450,29 +22614,79 @@
   END_TIMER;
   if( rc || zErrMsg ){
     char zPrefix[100];
+    const char *zErrorTail;
+    const char *zErrorType;
+    if( zErrMsg==0 ){
+      zErrorType = "Error";
+      zErrorTail = sqlite3_errmsg(p->db);
+    }else if( strncmp(zErrMsg, "in prepare, ",12)==0 ){
+      zErrorType = "Parse error";
+      zErrorTail = &zErrMsg[12];
+    }else if( strncmp(zErrMsg, "stepping, ", 10)==0 ){
+      zErrorType = "Runtime error";
+      zErrorTail = &zErrMsg[10];
+    }else{
+      zErrorType = "Error";
+      zErrorTail = zErrMsg;
+    }
     if( in!=0 || !stdin_is_interactive ){
       sqlite3_snprintf(sizeof(zPrefix), zPrefix,
-                       "Error: near line %d:", startline);
+                       "%s near line %d:", zErrorType, startline);
     }else{
-      sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error:");
+      sqlite3_snprintf(sizeof(zPrefix), zPrefix, "%s:", zErrorType);
     }
-    if( zErrMsg!=0 ){
-      utf8_printf(stderr, "%s %s\n", zPrefix, zErrMsg);
-      sqlite3_free(zErrMsg);
-      zErrMsg = 0;
-    }else{
-      utf8_printf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db));
-    }
+    utf8_printf(stderr, "%s %s\n", zPrefix, zErrorTail);
+    sqlite3_free(zErrMsg);
+    zErrMsg = 0;
     return 1;
   }else if( ShellHasFlag(p, SHFLG_CountChanges) ){
-    raw_printf(p->out, "changes: %3d   total_changes: %d\n",
-            sqlite3_changes(p->db), sqlite3_total_changes(p->db));
+    char zLineBuf[2000];
+    sqlite3_snprintf(sizeof(zLineBuf), zLineBuf,
+            "changes: %lld   total_changes: %lld",
+            sqlite3_changes64(p->db), sqlite3_total_changes64(p->db));
+    raw_printf(p->out, "%s\n", zLineBuf);
   }
   return 0;
 }
 
+static void echo_group_input(ShellState *p, const char *zDo){
+  if( ShellHasFlag(p, SHFLG_Echo) ) utf8_printf(p->out, "%s\n", zDo);
+}
 
+#ifdef SQLITE_SHELL_WASM_MODE
 /*
+** Alternate one_input_line() impl for wasm mode. This is not in the primary impl
+** because we need the global shellState and cannot access it from that function
+** without moving lots of code around (creating a larger/messier diff).
+*/
+static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
+  /* Parse the next line from shellState.wasm.zInput. */
+  const char *zBegin = shellState.wasm.zPos;
+  const char *z = zBegin;
+  char *zLine = 0;
+  int nZ = 0;
+
+  UNUSED_PARAMETER(in);
+  UNUSED_PARAMETER(isContinuation);
+  if(!z || !*z){
+    return 0;
+  }
+  while(*z && isspace(*z)) ++z;
+  zBegin = z;
+  for(; *z && '\n'!=*z; ++nZ, ++z){}
+  if(nZ>0 && '\r'==zBegin[nZ-1]){
+    --nZ;
+  }
+  shellState.wasm.zPos = z;
+  zLine = realloc(zPrior, nZ+1);
+  shell_check_oom(zLine);
+  memcpy(zLine, zBegin, (size_t)nZ);
+  zLine[nZ] = 0;
+  return zLine;
+}
+#endif /* SQLITE_SHELL_WASM_MODE */
+
+/*
 ** Read input from *in and process it.  If *in==0 then input
 ** is interactive - the user is typing it it.  Otherwise, input
 ** is coming from a file or device.  A prompt is issued and history
@@ -21487,11 +22701,18 @@
   int nLine;                /* Length of current line */
   int nSql = 0;             /* Bytes of zSql[] used */
   int nAlloc = 0;           /* Allocated zSql[] space */
-  int nSqlPrior = 0;        /* Bytes of zSql[] used by prior line */
   int rc;                   /* Error code */
   int errCnt = 0;           /* Number of errors seen */
   int startline = 0;        /* Line number for start of current input */
+  QuickScanState qss = QSS_Start; /* Accumulated line status (so far) */
 
+  if( p->inputNesting==MAX_INPUT_NESTING ){
+    /* This will be more informative in a later version. */
+    utf8_printf(stderr,"Input nesting limit (%d) reached at line %d."
+                " Check recursion.\n", MAX_INPUT_NESTING, p->lineno);
+    return 1;
+  }
+  ++p->inputNesting;
   p->lineno = 0;
   while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){
     fflush(p->out);
@@ -21506,12 +22727,20 @@
       seenInterrupt = 0;
     }
     p->lineno++;
-    if( nSql==0 && _all_whitespace(zLine) ){
-      if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine);
+    if( QSS_INPLAIN(qss)
+        && line_is_command_terminator(zLine)
+        && line_is_complete(zSql, nSql) ){
+      memcpy(zLine,";",2);
+    }
+    qss = quickscan(zLine, qss);
+    if( QSS_PLAINWHITE(qss) && nSql==0 ){
+      /* Just swallow single-line whitespace */
+      echo_group_input(p, zLine);
+      qss = QSS_Start;
       continue;
     }
     if( zLine && (zLine[0]=='.' || zLine[0]=='#') && nSql==0 ){
-      if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine);
+      echo_group_input(p, zLine);
       if( zLine[0]=='.' ){
         rc = do_meta_command(zLine, p);
         if( rc==2 ){ /* exit requested */
@@ -21520,18 +22749,17 @@
           errCnt++;
         }
       }
+      qss = QSS_Start;
       continue;
     }
-    if( line_is_command_terminator(zLine) && line_is_complete(zSql, nSql) ){
-      memcpy(zLine,";",2);
-    }
+    /* No single-line dispositions remain; accumulate line(s). */
     nLine = strlen30(zLine);
     if( nSql+nLine+2>=nAlloc ){
-      nAlloc = nSql+nLine+100;
+      /* Grow buffer by half-again increments when big. */
+      nAlloc = nSql+(nSql>>1)+nLine+100;
       zSql = realloc(zSql, nAlloc);
-      if( zSql==0 ) shell_out_of_memory();
+      shell_check_oom(zSql);
     }
-    nSqlPrior = nSql;
     if( nSql==0 ){
       int i;
       for(i=0; zLine[i] && IsSpace(zLine[i]); i++){}
@@ -21544,8 +22772,8 @@
       memcpy(zSql+nSql, zLine, nLine+1);
       nSql += nLine;
     }
-    if( nSql && line_contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior)
-                && sqlite3_complete(zSql) ){
+    if( nSql && QSS_SEMITERM(qss) && sqlite3_complete(zSql) ){
+      echo_group_input(p, zSql);
       errCnt += runOneSqlLine(p, zSql, p->in, startline);
       nSql = 0;
       if( p->outCount ){
@@ -21554,16 +22782,22 @@
       }else{
         clearTempFile(p);
       }
-    }else if( nSql && _all_whitespace(zSql) ){
-      if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zSql);
+      p->bSafeMode = p->bSafeModePersist;
+      qss = QSS_Start;
+    }else if( nSql && QSS_PLAINWHITE(qss) ){
+      echo_group_input(p, zSql);
       nSql = 0;
+      qss = QSS_Start;
     }
   }
-  if( nSql && !_all_whitespace(zSql) ){
+  if( nSql ){
+    /* This may be incomplete. Let the SQL parser deal with that. */
+    echo_group_input(p, zSql);
     errCnt += runOneSqlLine(p, zSql, p->in, startline);
   }
   free(zSql);
   free(zLine);
+  --p->inputNesting;
   return errCnt>0;
 }
 
@@ -21660,6 +22894,7 @@
       return;
     }
     zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
+    shell_check_oom(zBuf);
     sqliterc = zBuf;
   }
   p->in = fopen(sqliterc,"rb");
@@ -21696,7 +22931,7 @@
 #if !defined(SQLITE_OMIT_DESERIALIZE)
   "   -deserialize         open the database using sqlite3_deserialize()\n"
 #endif
-  "   -echo                print commands before execution\n"
+  "   -echo                print inputs before execution\n"
   "   -init FILENAME       read/process named file\n"
   "   -[no]header          turn headers on or off\n"
 #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
@@ -21720,10 +22955,12 @@
 #endif
   "   -newline SEP         set output row separator. Default: '\\n'\n"
   "   -nofollow            refuse to open symbolic links to database files\n"
+  "   -nonce STRING        set the safe-mode escape nonce\n"
   "   -nullvalue TEXT      set text string for NULL values. Default ''\n"
   "   -pagecache SIZE N    use N slots of SZ bytes each for page cache memory\n"
   "   -quote               set output mode to 'quote'\n"
   "   -readonly            open the database read-only\n"
+  "   -safe                enable safe-mode\n"
   "   -separator SEP       set output column separator. Default: '|'\n"
 #ifdef SQLITE_ENABLE_SORTER_REFERENCES
   "   -sorterref SIZE      sorter references threshold size\n"
@@ -21771,6 +23008,7 @@
   memset(data, 0, sizeof(*data));
   data->normalMode = data->cMode = data->mode = MODE_List;
   data->autoExplain = 1;
+  data->pAuxDb = &data->aAuxDb[0];
   memcpy(data->colSeparator,SEP_Column, 2);
   memcpy(data->rowSeparator,SEP_Row, 2);
   data->showHeader = 0;
@@ -21829,14 +23067,25 @@
 #  endif
 #endif
 
+#ifdef SQLITE_SHELL_WASM_MODE
+#  define main fiddle_main
+#endif
+
 #if SQLITE_SHELL_IS_UTF8
 int SQLITE_CDECL main(int argc, char **argv){
 #else
 int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
   char **argv;
 #endif
+#ifdef SQLITE_DEBUG
+  sqlite3_int64 mem_main_enter = sqlite3_memory_used();
+#endif
   char *zErrMsg = 0;
+#ifdef SQLITE_SHELL_WASM_MODE
+#  define data shellState
+#else
   ShellState data;
+#endif
   const char *zInitFile = 0;
   int i;
   int rc = 0;
@@ -21852,11 +23101,12 @@
 
   setBinaryMode(stdin, 0);
   setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
+#ifdef SQLITE_SHELL_WASM_MODE
+  stdin_is_interactive = 0;
+  stdout_is_console = 1;
+#else
   stdin_is_interactive = isatty(0);
   stdout_is_console = isatty(1);
-
-#ifdef SQLITE_DEBUG
-  registerOomSimulator();
 #endif
 
 #if !defined(_WIN32_WCE)
@@ -21898,16 +23148,16 @@
 #if !SQLITE_SHELL_IS_UTF8
   sqlite3_initialize();
   argvToFree = malloc(sizeof(argv[0])*argc*2);
+  shell_check_oom(argvToFree);
   argcToFree = argc;
   argv = argvToFree + argc;
-  if( argv==0 ) shell_out_of_memory();
   for(i=0; i<argc; i++){
     char *z = sqlite3_win32_unicode_to_utf8(wargv[i]);
     int n;
-    if( z==0 ) shell_out_of_memory();
+    shell_check_oom(z);
     n = (int)strlen(z);
     argv[i] = malloc( n+1 );
-    if( argv[i]==0 ) shell_out_of_memory();
+    shell_check_oom(argv[i]);
     memcpy(argv[i], z, n+1);
     argvToFree[i] = argv[i];
     sqlite3_free(z);
@@ -21934,7 +23184,7 @@
     ** this compile-time option to embed this shell program in larger
     ** applications. */
     extern void SQLITE_SHELL_DBNAME_PROC(const char**);
-    SQLITE_SHELL_DBNAME_PROC(&data.zDbFilename);
+    SQLITE_SHELL_DBNAME_PROC(&data.pAuxDb->zDbFilename);
     warnInmemoryDb = 0;
   }
 #endif
@@ -21949,15 +23199,15 @@
     char *z;
     z = argv[i];
     if( z[0]!='-' ){
-      if( data.zDbFilename==0 ){
-        data.zDbFilename = z;
+      if( data.aAuxDb->zDbFilename==0 ){
+        data.aAuxDb->zDbFilename = z;
       }else{
         /* Excesss arguments are interpreted as SQL (or dot-commands) and
         ** mean that nothing is read from stdin */
         readStdin = 0;
         nCmd++;
         azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd);
-        if( azCmd==0 ) shell_out_of_memory();
+        shell_check_oom(azCmd);
         azCmd[nCmd-1] = z;
       }
     }
@@ -22008,6 +23258,14 @@
       if( n<0 ) n = 0;
       sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, n);
       if( sz*n==0 ) data.shellFlgs &= ~SHFLG_Lookaside;
+    }else if( strcmp(z,"-threadsafe")==0 ){
+      int n;
+      n = (int)integerValue(cmdline_option_value(argc,argv,++i));
+      switch( n ){
+         case 0:  sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);  break;
+         case 2:  sqlite3_config(SQLITE_CONFIG_MULTITHREAD);   break;
+         default: sqlite3_config(SQLITE_CONFIG_SERIALIZED);    break;
+      }
 #ifdef SQLITE_ENABLE_VFSTRACE
     }else if( strcmp(z,"-vfstrace")==0 ){
       extern int vfstrace_register(
@@ -22060,6 +23318,11 @@
       sqlite3MemTraceActivate(stderr);
     }else if( strcmp(z,"-bail")==0 ){
       bail_on_error = 1;
+    }else if( strcmp(z,"-nonce")==0 ){
+      free(data.zNonce);
+      data.zNonce = strdup(argv[++i]);
+    }else if( strcmp(z,"-safe")==0 ){
+      /* no-op - catch this on the second pass */
     }
   }
   verify_uninitialized();
@@ -22090,24 +23353,26 @@
     }
   }
 
-  if( data.zDbFilename==0 ){
+  if( data.pAuxDb->zDbFilename==0 ){
 #ifndef SQLITE_OMIT_MEMORYDB
-    data.zDbFilename = ":memory:";
+    data.pAuxDb->zDbFilename = ":memory:";
     warnInmemoryDb = argc==1;
 #else
     utf8_printf(stderr,"%s: Error: no database filename specified\n", Argv0);
     return 1;
 #endif
   }
   data.out = stdout;
+#ifndef SQLITE_SHELL_WASM_MODE
   sqlite3_appendvfs_init(0,0,0);
+#endif
 
   /* Go ahead and open the database file if it already exists.  If the
   ** file does not exist, delay opening it.  This prevents empty database
   ** files from being created if a user mistypes the database name argument
   ** to the sqlite command-line tool.
   */
-  if( access(data.zDbFilename, 0)==0 ){
+  if( access(data.pAuxDb->zDbFilename, 0)==0 ){
     open_db(&data, 0);
   }
 
@@ -22186,8 +23451,10 @@
                        "%s",cmdline_option_value(argc,argv,++i));
     }else if( strcmp(z,"-header")==0 ){
       data.showHeader = 1;
-    }else if( strcmp(z,"-noheader")==0 ){
+      ShellSetFlag(&data, SHFLG_HeaderSet);
+     }else if( strcmp(z,"-noheader")==0 ){
       data.showHeader = 0;
+      ShellSetFlag(&data, SHFLG_HeaderSet);
     }else if( strcmp(z,"-echo")==0 ){
       ShellSetFlag(&data, SHFLG_Echo);
     }else if( strcmp(z,"-eqp")==0 ){
@@ -22220,6 +23487,10 @@
       i+=2;
     }else if( strcmp(z,"-lookaside")==0 ){
       i+=2;
+    }else if( strcmp(z,"-threadsafe")==0 ){
+      i+=2;
+    }else if( strcmp(z,"-nonce")==0 ){
+      i += 2;
     }else if( strcmp(z,"-mmap")==0 ){
       i++;
     }else if( strcmp(z,"-memtrace")==0 ){
@@ -22278,6 +23549,8 @@
       readStdin = 0;
       break;
 #endif
+    }else if( strcmp(z,"-safe")==0 ){
+      data.bSafeMode = data.bSafeModePersist = 1;
     }else{
       utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
       raw_printf(stderr,"Use -help for a list of options.\n");
@@ -22358,13 +23631,22 @@
       rc = process_input(&data);
     }
   }
+#ifndef SQLITE_SHELL_WASM_MODE
+  /* In WASM mode we have to leave the db state in place so that
+  ** client code can "push" SQL into it after this call returns. */
   free(azCmd);
   set_table_name(&data, 0);
   if( data.db ){
-    session_close_all(&data);
+    session_close_all(&data, -1);
     close_db(data.db);
   }
-  sqlite3_free(data.zFreeOnClose);
+  for(i=0; i<ArraySize(data.aAuxDb); i++){
+    sqlite3_free(data.aAuxDb[i].zFreeOnClose);
+    if( data.aAuxDb[i].db ){
+      session_close_all(&data, i);
+      close_db(data.aAuxDb[i].db);
+    }
+  }
   find_home_dir(1);
   output_reset(&data);
   data.doXdgOpen = 0;
@@ -22374,8 +23656,140 @@
   free(argvToFree);
 #endif
   free(data.colWidth);
+  free(data.zNonce);
   /* Clear the global data structure so that valgrind will detect memory
   ** leaks */
   memset(&data, 0, sizeof(data));
+#ifdef SQLITE_DEBUG
+  if( sqlite3_memory_used()>mem_main_enter ){
+    utf8_printf(stderr, "Memory leaked: %u bytes\n",
+                (unsigned int)(sqlite3_memory_used()-mem_main_enter));
+  }
+#endif
+#endif /* !SQLITE_SHELL_WASM_MODE */
   return rc;
 }
+
+
+#ifdef SQLITE_SHELL_WASM_MODE
+/* Only for emcc experimentation purposes. */
+int fiddle_experiment(int a,int b){
+   return a + b;
+}
+
+/* Only for emcc experimentation purposes.
+
+  Define this function in JS using:
+
+  emcc ... --js-library somefile.js
+
+  containing:
+
+mergeInto(LibraryManager.library, {
+    my_foo: function(){
+        console.debug("my_foo()",arguments);
+    }
+});
+*/
+/*extern void my_foo(sqlite3 *);*/
+/* Only for emcc experimentation purposes. */
+sqlite3 * fiddle_the_db(){
+    printf("fiddle_the_db(%p)\n", (const void*)globalDb);
+    /*my_foo(globalDb);*/
+    return globalDb;
+}
+/* Only for emcc experimentation purposes. */
+sqlite3 * fiddle_db_arg(sqlite3 *arg){
+    printf("fiddle_db_arg(%p)\n", (const void*)arg);
+    return arg;
+}
+
+/*
+** Intended to be called via a SharedWorker() while a separate
+** SharedWorker() (which manages the wasm module) is performing work
+** which should be interrupted. Unfortunately, SharedWorker is not
+** portable enough to make real use of.
+*/
+void fiddle_interrupt(void){
+  if(globalDb) sqlite3_interrupt(globalDb);
+}
+
+/*
+** Returns the filename of the given db name, assuming "main" if
+** zDbName is NULL. Returns NULL if globalDb is not opened.
+*/
+const char * fiddle_db_filename(const char * zDbName){
+    return globalDb
+      ? sqlite3_db_filename(globalDb, zDbName ? zDbName : "main")
+      : NULL;
+}
+
+/*
+** Closes, unlinks, and reopens the db using its current filename (or
+** the default if the db is currently closed). It is assumed, for
+** purposes of the fiddle build, that the file is in a transient
+** virtual filesystem within the browser.
+*/
+void fiddle_reset_db(void){
+  char *zFilename = 0;
+  if(0==globalDb){
+    shellState.pAuxDb->zDbFilename = "/fiddle.sqlite3";
+  }else{
+    zFilename =
+      sqlite3_mprintf("%s", sqlite3_db_filename(globalDb, "main"));
+    shell_check_oom(zFilename);
+    close_db(globalDb);
+    shellDeleteFile(zFilename);
+    shellState.db = 0;
+    shellState.pAuxDb->zDbFilename = zFilename;
+  }
+  open_db(&shellState, 0);
+  sqlite3_free(zFilename);
+}
+
+/*
+** Trivial exportable function for emscripten. Needs to be exported using:
+**
+** emcc ..flags... -sEXPORTED_FUNCTIONS=_fiddle_exec -sEXPORTED_RUNTIME_METHODS=ccall,cwrap
+**
+** (Note the underscore before the function name.) It processes zSql
+** as if it were input to the sqlite3 shell and redirects all output
+** to the wasm binding.
+*/
+void fiddle_exec(const char * zSql){
+  static int once = 0;
+  int rc = 0;
+  if(!once){
+    /* Simulate an argv array for main() */
+    static char * argv[] = {"fiddle",
+                            "-bail",
+                            "-safe"};
+    rc = fiddle_main((int)(sizeof(argv)/sizeof(argv[0])), argv);
+    once = rc ? -1 : 1;
+    memset(&shellState.wasm, 0, sizeof(shellState.wasm));
+    printf(
+        "SQLite version %s %.19s\n" /*extra-version-info*/,
+        sqlite3_libversion(), sqlite3_sourceid()
+    );
+    puts("WASM shell");
+    puts("Enter \".help\" for usage hints.");
+    if(once>0){
+      fiddle_reset_db();
+    }
+    if(shellState.db){
+      printf("Connected to %s.\n", fiddle_db_filename(NULL));
+    }else{
+      fprintf(stderr,"ERROR initializing db!\n");
+      return;
+    }
+  }
+  if(once<0){
+    puts("DB init failed. Not executing SQL.");
+  }else if(zSql && *zSql){
+    shellState.wasm.zInput = zSql;
+    shellState.wasm.zPos = zSql;
+    process_input(&shellState);
+    memset(&shellState.wasm, 0, sizeof(shellState.wasm));
+  }
+}
+#endif /* SQLITE_SHELL_WASM_MODE */