Diff for /elwix/files/sqlite/dist/shell.c between versions 1.4 and 1.6

version 1.4, 2017/02/13 16:52:48 version 1.6, 2021/07/16 18:35:51
Line 1 Line 1
   /* DO NOT EDIT!
   ** This file is automatically generated by the script in the canonical
   ** SQLite source tree at tool/mkshellc.tcl.  That script combines source
   ** code from various constituent source files of SQLite into this single
   ** "shell.c" file used to implement the SQLite command-line shell.
   **
   ** Most of the code found below comes from the "src/shell.c.in" file in
   ** the canonical SQLite source tree.  That main file contains "INCLUDE"
   ** lines that specify other files in the canonical source tree that are
   ** inserted to getnerate this complete program source file.
   **
   ** The code from multiple files is combined into this single "shell.c"
   ** source file to help make the command-line program easier to compile.
   **
   ** To modify this program, get a copy of the canonical SQLite source tree,
   ** edit the src/shell.c.in" and/or some of the other files that are included
   ** by "src/shell.c.in", then rerun the tool/mkshellc.tcl script.
   */
 /*  /*
 ** 2001 September 15  ** 2001 September 15
 **  **
Line 18 Line 36
 #endif  #endif
   
 /*  /*
** If requested, include the SQLite compiler options file for MSVC.** Determine if we are dealing with WinRT, which provides only a subset of
 ** the full Win32 API.
 */  */
#if defined(INCLUDE_MSVC_H)#if !defined(SQLITE_OS_WINRT)
#include "msvc.h"# define SQLITE_OS_WINRT 0
 #endif  #endif
   
 /*  /*
   ** Warning pragmas copied from msvc.h in the core.
   */
   #if defined(_MSC_VER)
   #pragma warning(disable : 4054)
   #pragma warning(disable : 4055)
   #pragma warning(disable : 4100)
   #pragma warning(disable : 4127)
   #pragma warning(disable : 4130)
   #pragma warning(disable : 4152)
   #pragma warning(disable : 4189)
   #pragma warning(disable : 4206)
   #pragma warning(disable : 4210)
   #pragma warning(disable : 4232)
   #pragma warning(disable : 4244)
   #pragma warning(disable : 4305)
   #pragma warning(disable : 4306)
   #pragma warning(disable : 4702)
   #pragma warning(disable : 4706)
   #endif /* defined(_MSC_VER) */
   
   /*
 ** No support for loadable extensions in VxWorks.  ** No support for loadable extensions in VxWorks.
 */  */
 #if (defined(__RTP__) || defined(_WRS_KERNEL)) && !SQLITE_OMIT_LOAD_EXTENSION  #if (defined(__RTP__) || defined(_WRS_KERNEL)) && !SQLITE_OMIT_LOAD_EXTENSION
Line 47 Line 87
 #include <stdio.h>  #include <stdio.h>
 #include <assert.h>  #include <assert.h>
 #include "sqlite3.h"  #include "sqlite3.h"
   typedef sqlite3_int64 i64;
   typedef sqlite3_uint64 u64;
   typedef unsigned char u8;
 #if SQLITE_USER_AUTHENTICATION  #if SQLITE_USER_AUTHENTICATION
 # include "sqlite3userauth.h"  # include "sqlite3userauth.h"
 #endif  #endif
Line 58 Line 101
 # if !defined(__RTP__) && !defined(_WRS_KERNEL)  # if !defined(__RTP__) && !defined(_WRS_KERNEL)
 #  include <pwd.h>  #  include <pwd.h>
 # endif  # endif
   #endif
   #if (!defined(_WIN32) && !defined(WIN32)) || defined(__MINGW32__)
 # include <unistd.h>  # include <unistd.h>
# include <sys/types.h># include <dirent.h>
 # define GETPID getpid
 # if defined(__MINGW32__)
 #  define DIRENT dirent
 #  ifndef S_ISLNK
 #   define S_ISLNK(mode) (0)
 #  endif
 # endif
 #else
 # define GETPID (int)GetCurrentProcessId
 #endif  #endif
   #include <sys/types.h>
   #include <sys/stat.h>
   
 #if HAVE_READLINE  #if HAVE_READLINE
 # include <readline/readline.h>  # include <readline/readline.h>
Line 99 Line 155
   
   
 #if defined(_WIN32) || defined(WIN32)  #if defined(_WIN32) || defined(WIN32)
# include <io.h># if SQLITE_OS_WINRT
include <fcntl.h>#  define SQLITE_OMIT_POPEN 1
define isatty(h) _isatty(h)# else
ifndef access#  include <io.h>
#  define access(f,m) _access((f),(m))#  inclu#  include <fcntl.h>
 #  define isatty(h) _isatty(h)
 #  ifndef access
 #   define access(f,m) _access((f),(m))
 #  endif
 #  ifndef unlink
 #   define unlink _unlink
 #  endif
 #  ifndef strdup
 #   define strdup _strdup
 #  endif
 #  undef popen
 #  define popen _popen
 #  undef pclose
 #  define pclose _pclose
 # endif  # endif
 # undef popen  
 # define popen _popen  
 # undef pclose  
 # define pclose _pclose  
 #else  #else
  /* Make sure isatty() has a prototype. */   /* Make sure isatty() has a prototype. */
  extern int isatty(int);   extern int isatty(int);
Line 137 Line 203
 #define ToLower(X)  (char)tolower((unsigned char)X)  #define ToLower(X)  (char)tolower((unsigned char)X)
   
 #if defined(_WIN32) || defined(WIN32)  #if defined(_WIN32) || defined(WIN32)
   #if SQLITE_OS_WINRT
   #include <intrin.h>
   #endif
 #include <windows.h>  #include <windows.h>
   
 /* string conversion routines only needed on Win32 */  /* string conversion routines only needed on Win32 */
 extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR);  extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR);
 extern char *sqlite3_win32_mbcs_to_utf8_v2(const char *, int);  extern char *sqlite3_win32_mbcs_to_utf8_v2(const char *, int);
 extern char *sqlite3_win32_utf8_to_mbcs_v2(const char *, int);  extern char *sqlite3_win32_utf8_to_mbcs_v2(const char *, int);
   extern LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText);
 #endif  #endif
   
 /* On Windows, we normally run with output mode of TEXT so that \n characters  /* On Windows, we normally run with output mode of TEXT so that \n characters
Line 151  extern char *sqlite3_win32_utf8_to_mbcs_v2(const char  Line 221  extern char *sqlite3_win32_utf8_to_mbcs_v2(const char 
 ** rendering quoted strings that contain \n characters).  The following  ** rendering quoted strings that contain \n characters).  The following
 ** routines take care of that.  ** routines take care of that.
 */  */
#if defined(_WIN32) || defined(WIN32)#if (defined(_WIN32) || defined(WIN32)) && !SQLITE_OS_WINRT
 static void setBinaryMode(FILE *file, int isOutput){  static void setBinaryMode(FILE *file, int isOutput){
   if( isOutput ) fflush(file);    if( isOutput ) fflush(file);
   _setmode(_fileno(file), _O_BINARY);    _setmode(_fileno(file), _O_BINARY);
Line 255  static int hasTimer(void){ Line 325  static int hasTimer(void){
   if( getProcessTimesAddr ){    if( getProcessTimesAddr ){
     return 1;      return 1;
   } else {    } else {
   #if !SQLITE_OS_WINRT
     /* GetProcessTimes() isn't supported in WIN95 and some other Windows      /* GetProcessTimes() isn't supported in WIN95 and some other Windows
     ** versions. See if the version we are running on has it, and if it      ** versions. See if the version we are running on has it, and if it
     ** does, save off a pointer to it and the current process handle.      ** does, save off a pointer to it and the current process handle.
Line 271  static int hasTimer(void){ Line 342  static int hasTimer(void){
         FreeLibrary(hinstLib);          FreeLibrary(hinstLib);
       }        }
     }      }
   #endif
   }    }
   return 0;    return 0;
 }  }
Line 325  static void endTimer(void){ Line 397  static void endTimer(void){
 #define UNUSED_PARAMETER(x) (void)(x)  #define UNUSED_PARAMETER(x) (void)(x)
   
 /*  /*
   ** Number of elements in an array
   */
   #define ArraySize(X)  (int)(sizeof(X)/sizeof(X[0]))
   
   /*
 ** If the following flag is set, then command execution stops  ** If the following flag is set, then command execution stops
 ** at an error if we are not interactive.  ** at an error if we are not interactive.
 */  */
Line 355  static sqlite3 *globalDb = 0; Line 432  static sqlite3 *globalDb = 0;
 */  */
 static volatile int seenInterrupt = 0;  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  ** This is the name of our program. It is set in main(), used
 ** in a number of other places, mostly for error messages.  ** in a number of other places, mostly for error messages.
 */  */
Line 400  void utf8_printf(FILE *out, const char *zFormat, ...){ Line 486  void utf8_printf(FILE *out, const char *zFormat, ...){
 # define raw_printf fprintf  # define raw_printf fprintf
 #endif  #endif
   
   /* Indicate out-of-memory and exit. */
   static void shell_out_of_memory(void){
     raw_printf(stderr,"Error: out of memory\n");
     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
   */
   void shellOomFault(void){
     if( oomRepeat>0 ){
       oomRepeat--;
     }else{
       oomCounter--;
     }
   }
   #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.  ** Write I/O traces to the following stream.
 */  */
Line 426  static void SQLITE_CDECL iotracePrintf(const char *zFo Line 561  static void SQLITE_CDECL iotracePrintf(const char *zFo
 }  }
 #endif  #endif
   
   /*
   ** Output string zUtf to stream pOut as w characters.  If w is negative,
   ** then right-justify the text.  W is the width in UTF-8 characters, not
   ** in bytes.  This is different from the %*.*s specification in printf
   ** since with %*.*s the width is measured in bytes, not characters.
   */
   static void utf8_width_print(FILE *pOut, int w, const char *zUtf){
     int i;
     int n;
     int aw = w<0 ? -w : w;
     for(i=n=0; zUtf[i]; i++){
       if( (zUtf[i]&0xc0)!=0x80 ){
         n++;
         if( n==aw ){
           do{ i++; }while( (zUtf[i]&0xc0)==0x80 );
           break;
         }
       }
     }
     if( n>=aw ){
       utf8_printf(pOut, "%.*s", i, zUtf);
     }else if( w<0 ){
       utf8_printf(pOut, "%*s%s", aw-n, "", zUtf);
     }else{
       utf8_printf(pOut, "%s%*s", zUtf, aw-n, "");
     }
   }
   
   
 /*  /*
 ** Determines if a string is a number of not.  ** Determines if a string is a number of not.
 */  */
Line 455  static int isNumber(const char *z, int *realnum){ Line 618  static int isNumber(const char *z, int *realnum){
 }  }
   
 /*  /*
 ** A global char* and an SQL function to access its current value  
 ** from within an SQL statement. This program used to use the  
 ** sqlite_exec_printf() API to substitue a string into an SQL statement.  
 ** The correct way to do this with sqlite3 is to use the bind API, but  
 ** since the shell is built around the callback paradigm it would be a lot  
 ** of work. Instead just use this hack, which is quite harmless.  
 */  
 static const char *zShellStatic = 0;  
 static void shellstaticFunc(  
   sqlite3_context *context,  
   int argc,  
   sqlite3_value **argv  
 ){  
   assert( 0==argc );  
   assert( zShellStatic );  
   UNUSED_PARAMETER(argc);  
   UNUSED_PARAMETER(argv);  
   sqlite3_result_text(context, zShellStatic, -1, SQLITE_STATIC);  
 }  
   
   
 /*  
 ** Compute a string length that is limited to what can be stored in  ** Compute a string length that is limited to what can be stored in
 ** lower 30 bits of a 32-bit signed integer.  ** lower 30 bits of a 32-bit signed integer.
 */  */
Line 487  static int strlen30(const char *z){ Line 628  static int strlen30(const char *z){
 }  }
   
 /*  /*
   ** Return the length of a string in characters.  Multibyte UTF8 characters
   ** count as a single character.
   */
   static int strlenChar(const char *z){
     int n = 0;
     while( *z ){
       if( (0xc0&*(z++))!=0x80 ) n++;
     }
     return n;
   }
   
   /*
   ** Return true if zFile does not exist or if it is not an ordinary file.
   */
   #ifdef _WIN32
   # define notNormalFile(X) 0
   #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);
   }
   #endif
   
   /*
 ** This routine reads a line of text from FILE in, stores  ** This routine reads a line of text from FILE in, stores
 ** the text in memory obtained from malloc() and returns a pointer  ** the text in memory obtained from malloc() and returns a pointer
 ** to the text.  NULL is returned at end of file, or if malloc()  ** to the text.  NULL is returned at end of file, or if malloc()
Line 503  static char *local_getline(char *zLine, FILE *in){ Line 671  static char *local_getline(char *zLine, FILE *in){
     if( n+100>nLine ){      if( n+100>nLine ){
       nLine = nLine*2 + 100;        nLine = nLine*2 + 100;
       zLine = realloc(zLine, nLine);        zLine = realloc(zLine, nLine);
      if( zLine==0 ) return 0;      if( zLine==0 ) shell_out_of_memory();
     }      }
     if( fgets(&zLine[n], nLine - n, in)==0 ){      if( fgets(&zLine[n], nLine - n, in)==0 ){
       if( n==0 ){        if( n==0 ){
Line 530  static char *local_getline(char *zLine, FILE *in){ Line 698  static char *local_getline(char *zLine, FILE *in){
       int nTrans = strlen30(zTrans)+1;        int nTrans = strlen30(zTrans)+1;
       if( nTrans>nLine ){        if( nTrans>nLine ){
         zLine = realloc(zLine, nTrans);          zLine = realloc(zLine, nTrans);
        if( zLine==0 ){        if( zLine==0 ) shell_out_of_memory();
          sqlite3_free(zTrans); 
          return 0; 
        } 
       }        }
       memcpy(zLine, zTrans, nTrans);        memcpy(zLine, zTrans, nTrans);
       sqlite3_free(zTrans);        sqlite3_free(zTrans);
Line 577  static char *one_input_line(FILE *in, char *zPrior, in Line 742  static char *one_input_line(FILE *in, char *zPrior, in
   return zResult;    return zResult;
 }  }
   
   
   /*
   ** Return the value of a hexadecimal digit.  Return -1 if the input
   ** is not a hex digit.
   */
   static int hexDigitValue(char c){
     if( c>='0' && c<='9' ) return c - '0';
     if( c>='a' && c<='f' ) return c - 'a' + 10;
     if( c>='A' && c<='F' ) return c - 'A' + 10;
     return -1;
   }
   
   /*
   ** Interpret zArg as an integer value, possibly with suffixes.
   */
   static sqlite3_int64 integerValue(const char *zArg){
     sqlite3_int64 v = 0;
     static const struct { char *zSuffix; int iMult; } aMult[] = {
       { "KiB", 1024 },
       { "MiB", 1024*1024 },
       { "GiB", 1024*1024*1024 },
       { "KB",  1000 },
       { "MB",  1000000 },
       { "GB",  1000000000 },
       { "K",   1000 },
       { "M",   1000000 },
       { "G",   1000000000 },
     };
     int i;
     int isNeg = 0;
     if( zArg[0]=='-' ){
       isNeg = 1;
       zArg++;
     }else if( zArg[0]=='+' ){
       zArg++;
     }
     if( zArg[0]=='0' && zArg[1]=='x' ){
       int x;
       zArg += 2;
       while( (x = hexDigitValue(zArg[0]))>=0 ){
         v = (v<<4) + x;
         zArg++;
       }
     }else{
       while( IsDigit(zArg[0]) ){
         v = v*10 + zArg[0] - '0';
         zArg++;
       }
     }
     for(i=0; i<ArraySize(aMult); i++){
       if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
         v *= aMult[i].iMult;
         break;
       }
     }
     return isNeg? -v : v;
   }
   
   /*
   ** A variable length string to which one can append text.
   */
   typedef struct ShellText ShellText;
   struct ShellText {
     char *z;
     int n;
     int nAlloc;
   };
   
   /*
   ** Initialize and destroy a ShellText object
   */
   static void initText(ShellText *p){
     memset(p, 0, sizeof(*p));
   }
   static void freeText(ShellText *p){
     free(p->z);
     initText(p);
   }
   
   /* zIn is either a pointer to a NULL-terminated string in memory obtained
   ** from malloc(), or a NULL pointer. The string pointed to by zAppend is
   ** added to zIn, and the result returned in memory obtained from malloc().
   ** zIn, if it was not NULL, is freed.
   **
   ** If the third argument, quote, is not '\0', then it is used as a
   ** quote character for zAppend.
   */
   static void appendText(ShellText *p, char const *zAppend, char quote){
     int len;
     int i;
     int nAppend = strlen30(zAppend);
   
     len = nAppend+p->n+1;
     if( quote ){
       len += 2;
       for(i=0; i<nAppend; i++){
         if( zAppend[i]==quote ) len++;
       }
     }
   
     if( p->n+len>=p->nAlloc ){
       p->nAlloc = p->nAlloc*2 + len + 20;
       p->z = realloc(p->z, p->nAlloc);
       if( p->z==0 ) shell_out_of_memory();
     }
   
     if( quote ){
       char *zCsr = p->z+p->n;
       *zCsr++ = quote;
       for(i=0; i<nAppend; i++){
         *zCsr++ = zAppend[i];
         if( zAppend[i]==quote ) *zCsr++ = quote;
       }
       *zCsr++ = quote;
       p->n = (int)(zCsr - p->z);
       *zCsr = '\0';
     }else{
       memcpy(p->z+p->n, zAppend, nAppend);
       p->n += nAppend;
       p->z[p->n] = '\0';
     }
   }
   
   /*
   ** Attempt to determine if identifier zName needs to be quoted, either
   ** because it contains non-alphanumeric characters, or because it is an
   ** SQLite keyword.  Be conservative in this estimate:  When in doubt assume
   ** that quoting is required.
   **
   ** Return '"' if quoting is required.  Return 0 if no quoting is required.
   */
   static char quoteChar(const char *zName){
     int i;
     if( !isalpha((unsigned char)zName[0]) && zName[0]!='_' ) return '"';
     for(i=0; zName[i]; i++){
       if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ) return '"';
     }
     return sqlite3_keyword_check(zName, i) ? '"' : 0;
   }
   
   /*
   ** Construct a fake object name and column list to describe the structure
   ** of the view, virtual table, or table valued function zSchema.zName.
   */
   static char *shellFakeSchema(
     sqlite3 *db,            /* The database connection containing the vtab */
     const char *zSchema,    /* Schema of the database holding the vtab */
     const char *zName       /* The name of the virtual table */
   ){
     sqlite3_stmt *pStmt = 0;
     char *zSql;
     ShellText s;
     char cQuote;
     char *zDiv = "(";
     int nRow = 0;
   
     zSql = sqlite3_mprintf("PRAGMA \"%w\".table_info=%Q;",
                            zSchema ? zSchema : "main", zName);
     sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
     sqlite3_free(zSql);
     initText(&s);
     if( zSchema ){
       cQuote = quoteChar(zSchema);
       if( cQuote && sqlite3_stricmp(zSchema,"temp")==0 ) cQuote = 0;
       appendText(&s, zSchema, cQuote);
       appendText(&s, ".", 0);
     }
     cQuote = quoteChar(zName);
     appendText(&s, zName, cQuote);
     while( sqlite3_step(pStmt)==SQLITE_ROW ){
       const char *zCol = (const char*)sqlite3_column_text(pStmt, 1);
       nRow++;
       appendText(&s, zDiv, 0);
       zDiv = ",";
       cQuote = quoteChar(zCol);
       appendText(&s, zCol, cQuote);
     }
     appendText(&s, ")", 0);
     sqlite3_finalize(pStmt);
     if( nRow==0 ){
       freeText(&s);
       s.z = 0;
     }
     return s.z;
   }
   
   /*
   ** SQL function:  shell_module_schema(X)
   **
   ** Return a fake schema for the table-valued function or eponymous virtual
   ** table X.
   */
   static void shellModuleSchema(
     sqlite3_context *pCtx,
     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);
     UNUSED_PARAMETER(nVal);
     if( zFake ){
       sqlite3_result_text(pCtx, sqlite3_mprintf("/* %s */", zFake),
                           -1, sqlite3_free);
       free(zFake);
     }
   }
   
   /*
   ** SQL function:  shell_add_schema(S,X)
   **
   ** Add the schema name X to the CREATE statement in S and return the result.
   ** Examples:
   **
   **    CREATE TABLE t1(x)   ->   CREATE TABLE xyz.t1(x);
   **
   ** Also works on
   **
   **    CREATE INDEX
   **    CREATE UNIQUE INDEX
   **    CREATE VIEW
   **    CREATE TRIGGER
   **    CREATE VIRTUAL TABLE
   **
   ** This UDF is used by the .schema command to insert the schema name of
   ** attached databases into the middle of the sqlite_schema.sql field.
   */
   static void shellAddSchemaName(
     sqlite3_context *pCtx,
     int nVal,
     sqlite3_value **apVal
   ){
     static const char *aPrefix[] = {
        "TABLE",
        "INDEX",
        "UNIQUE INDEX",
        "VIEW",
        "TRIGGER",
        "VIRTUAL TABLE"
     };
     int i = 0;
     const char *zIn = (const char*)sqlite3_value_text(apVal[0]);
     const char *zSchema = (const char*)sqlite3_value_text(apVal[1]);
     const char *zName = (const char*)sqlite3_value_text(apVal[2]);
     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++){
         int n = strlen30(aPrefix[i]);
         if( strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){
           char *z = 0;
           char *zFake = 0;
           if( zSchema ){
             char cQuote = quoteChar(zSchema);
             if( cQuote && sqlite3_stricmp(zSchema,"temp")!=0 ){
               z = sqlite3_mprintf("%.*s \"%w\".%s", n+7, zIn, zSchema, zIn+n+8);
             }else{
               z = sqlite3_mprintf("%.*s %s.%s", n+7, zIn, zSchema, zIn+n+8);
             }
           }
           if( zName
            && aPrefix[i][0]=='V'
            && (zFake = shellFakeSchema(db, zSchema, zName))!=0
           ){
             if( z==0 ){
               z = sqlite3_mprintf("%s\n/* %s */", zIn, zFake);
             }else{
               z = sqlite3_mprintf("%z\n/* %s */", z, zFake);
             }
             free(zFake);
           }
           if( z ){
             sqlite3_result_text(pCtx, z, -1, sqlite3_free);
             return;
           }
         }
       }
     }
     sqlite3_result_value(pCtx, apVal[0]);
   }
   
   /*
   ** The source code for several run-time loadable extensions is inserted
   ** below by the ../tool/mkshellc.tcl script.  Before processing that included
   ** code, we need to override some macros to make the included program code
   ** work here in the middle of this regular program.
   */
   #define SQLITE_EXTENSION_INIT1
   #define SQLITE_EXTENSION_INIT2(X) (void)(X)
   
   #if defined(_WIN32) && defined(_MSC_VER)
   /************************* Begin test_windirent.h ******************/
   /*
   ** 2015 November 30
   **
   ** The author disclaims copyright to this source code.  In place of
   ** a legal notice, here is a blessing:
   **
   **    May you do good and not evil.
   **    May you find forgiveness for yourself and forgive others.
   **    May you share freely, never taking more than you give.
   **
   *************************************************************************
   ** This file contains declarations for most of the opendir() family of
   ** POSIX functions on Win32 using the MSVCRT.
   */
   
   #if defined(_WIN32) && defined(_MSC_VER) && !defined(SQLITE_WINDIRENT_H)
   #define SQLITE_WINDIRENT_H
   
   /*
   ** We need several data types from the Windows SDK header.
   */
   
   #ifndef WIN32_LEAN_AND_MEAN
   #define WIN32_LEAN_AND_MEAN
   #endif
   
   #include "windows.h"
   
   /*
   ** We need several support functions from the SQLite core.
   */
   
   /* #include "sqlite3.h" */
   
   /*
   ** We need several things from the ANSI and MSVCRT headers.
   */
   
   #include <stdio.h>
   #include <stdlib.h>
   #include <errno.h>
   #include <io.h>
   #include <limits.h>
   #include <sys/types.h>
   #include <sys/stat.h>
   
   /*
   ** We may need several defines that should have been in "sys/stat.h".
   */
   
   #ifndef S_ISREG
   #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
   #endif
   
   #ifndef S_ISDIR
   #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
   #endif
   
   #ifndef S_ISLNK
   #define S_ISLNK(mode) (0)
   #endif
   
   /*
   ** We may need to provide the "mode_t" type.
   */
   
   #ifndef MODE_T_DEFINED
     #define MODE_T_DEFINED
     typedef unsigned short mode_t;
   #endif
   
   /*
   ** We may need to provide the "ino_t" type.
   */
   
   #ifndef INO_T_DEFINED
     #define INO_T_DEFINED
     typedef unsigned short ino_t;
   #endif
   
   /*
   ** We need to define "NAME_MAX" if it was not present in "limits.h".
   */
   
   #ifndef NAME_MAX
   #  ifdef FILENAME_MAX
   #    define NAME_MAX (FILENAME_MAX)
   #  else
   #    define NAME_MAX (260)
   #  endif
   #endif
   
   /*
   ** We need to define "NULL_INTPTR_T" and "BAD_INTPTR_T".
   */
   
   #ifndef NULL_INTPTR_T
   #  define NULL_INTPTR_T ((intptr_t)(0))
   #endif
   
   #ifndef BAD_INTPTR_T
   #  define BAD_INTPTR_T ((intptr_t)(-1))
   #endif
   
   /*
   ** We need to provide the necessary structures and related types.
   */
   
   #ifndef DIRENT_DEFINED
   #define DIRENT_DEFINED
   typedef struct DIRENT DIRENT;
   typedef DIRENT *LPDIRENT;
   struct DIRENT {
     ino_t d_ino;               /* Sequence number, do not use. */
     unsigned d_attributes;     /* Win32 file attributes. */
     char d_name[NAME_MAX + 1]; /* Name within the directory. */
   };
   #endif
   
   #ifndef DIR_DEFINED
   #define DIR_DEFINED
   typedef struct DIR DIR;
   typedef DIR *LPDIR;
   struct DIR {
     intptr_t d_handle; /* Value returned by "_findfirst". */
     DIRENT d_first;    /* DIRENT constructed based on "_findfirst". */
     DIRENT d_next;     /* DIRENT constructed based on "_findnext". */
   };
   #endif
   
   /*
   ** Provide a macro, for use by the implementation, to determine if a
   ** particular directory entry should be skipped over when searching for
   ** the next directory entry that should be returned by the readdir() or
   ** readdir_r() functions.
   */
   
   #ifndef is_filtered
   #  define is_filtered(a) ((((a).attrib)&_A_HIDDEN) || (((a).attrib)&_A_SYSTEM))
   #endif
   
   /*
   ** Provide the function prototype for the POSIX compatiable getenv()
   ** function.  This function is not thread-safe.
   */
   
   extern const char *windirent_getenv(const char *name);
   
   /*
   ** Finally, we can provide the function prototypes for the opendir(),
   ** readdir(), readdir_r(), and closedir() POSIX functions.
   */
   
   extern LPDIR opendir(const char *dirname);
   extern LPDIRENT readdir(LPDIR dirp);
   extern INT readdir_r(LPDIR dirp, LPDIRENT entry, LPDIRENT *result);
   extern INT closedir(LPDIR dirp);
   
   #endif /* defined(WIN32) && defined(_MSC_VER) */
   
   /************************* End test_windirent.h ********************/
   /************************* Begin test_windirent.c ******************/
   /*
   ** 2015 November 30
   **
   ** The author disclaims copyright to this source code.  In place of
   ** a legal notice, here is a blessing:
   **
   **    May you do good and not evil.
   **    May you find forgiveness for yourself and forgive others.
   **    May you share freely, never taking more than you give.
   **
   *************************************************************************
   ** This file contains code to implement most of the opendir() family of
   ** POSIX functions on Win32 using the MSVCRT.
   */
   
   #if defined(_WIN32) && defined(_MSC_VER)
   /* #include "test_windirent.h" */
   
   /*
   ** Implementation of the POSIX getenv() function using the Win32 API.
   ** This function is not thread-safe.
   */
   const char *windirent_getenv(
     const char *name
   ){
     static char value[32768]; /* Maximum length, per MSDN */
     DWORD dwSize = sizeof(value) / sizeof(char); /* Size in chars */
     DWORD dwRet; /* Value returned by GetEnvironmentVariableA() */
   
     memset(value, 0, sizeof(value));
     dwRet = GetEnvironmentVariableA(name, value, dwSize);
     if( dwRet==0 || dwRet>dwSize ){
       /*
       ** The function call to GetEnvironmentVariableA() failed -OR-
       ** the buffer is not large enough.  Either way, return NULL.
       */
       return 0;
     }else{
       /*
       ** The function call to GetEnvironmentVariableA() succeeded
       ** -AND- the buffer contains the entire value.
       */
       return value;
     }
   }
   
   /*
   ** Implementation of the POSIX opendir() function using the MSVCRT.
   */
   LPDIR opendir(
     const char *dirname
   ){
     struct _finddata_t data;
     LPDIR dirp = (LPDIR)sqlite3_malloc(sizeof(DIR));
     SIZE_T namesize = sizeof(data.name) / sizeof(data.name[0]);
   
     if( dirp==NULL ) return NULL;
     memset(dirp, 0, sizeof(DIR));
   
     /* TODO: Remove this if Unix-style root paths are not used. */
     if( sqlite3_stricmp(dirname, "/")==0 ){
       dirname = windirent_getenv("SystemDrive");
     }
   
     memset(&data, 0, sizeof(struct _finddata_t));
     _snprintf(data.name, namesize, "%s\\*", dirname);
     dirp->d_handle = _findfirst(data.name, &data);
   
     if( dirp->d_handle==BAD_INTPTR_T ){
       closedir(dirp);
       return NULL;
     }
   
     /* TODO: Remove this block to allow hidden and/or system files. */
     if( is_filtered(data) ){
   next:
   
       memset(&data, 0, sizeof(struct _finddata_t));
       if( _findnext(dirp->d_handle, &data)==-1 ){
         closedir(dirp);
         return NULL;
       }
   
       /* TODO: Remove this block to allow hidden and/or system files. */
       if( is_filtered(data) ) goto next;
     }
   
     dirp->d_first.d_attributes = data.attrib;
     strncpy(dirp->d_first.d_name, data.name, NAME_MAX);
     dirp->d_first.d_name[NAME_MAX] = '\0';
   
     return dirp;
   }
   
   /*
   ** Implementation of the POSIX readdir() function using the MSVCRT.
   */
   LPDIRENT readdir(
     LPDIR dirp
   ){
     struct _finddata_t data;
   
     if( dirp==NULL ) return NULL;
   
     if( dirp->d_first.d_ino==0 ){
       dirp->d_first.d_ino++;
       dirp->d_next.d_ino++;
   
       return &dirp->d_first;
     }
   
   next:
   
     memset(&data, 0, sizeof(struct _finddata_t));
     if( _findnext(dirp->d_handle, &data)==-1 ) return NULL;
   
     /* TODO: Remove this block to allow hidden and/or system files. */
     if( is_filtered(data) ) goto next;
   
     dirp->d_next.d_ino++;
     dirp->d_next.d_attributes = data.attrib;
     strncpy(dirp->d_next.d_name, data.name, NAME_MAX);
     dirp->d_next.d_name[NAME_MAX] = '\0';
   
     return &dirp->d_next;
   }
   
   /*
   ** Implementation of the POSIX readdir_r() function using the MSVCRT.
   */
   INT readdir_r(
     LPDIR dirp,
     LPDIRENT entry,
     LPDIRENT *result
   ){
     struct _finddata_t data;
   
     if( dirp==NULL ) return EBADF;
   
     if( dirp->d_first.d_ino==0 ){
       dirp->d_first.d_ino++;
       dirp->d_next.d_ino++;
   
       entry->d_ino = dirp->d_first.d_ino;
       entry->d_attributes = dirp->d_first.d_attributes;
       strncpy(entry->d_name, dirp->d_first.d_name, NAME_MAX);
       entry->d_name[NAME_MAX] = '\0';
   
       *result = entry;
       return 0;
     }
   
   next:
   
     memset(&data, 0, sizeof(struct _finddata_t));
     if( _findnext(dirp->d_handle, &data)==-1 ){
       *result = NULL;
       return ENOENT;
     }
   
     /* TODO: Remove this block to allow hidden and/or system files. */
     if( is_filtered(data) ) goto next;
   
     entry->d_ino = (ino_t)-1; /* not available */
     entry->d_attributes = data.attrib;
     strncpy(entry->d_name, data.name, NAME_MAX);
     entry->d_name[NAME_MAX] = '\0';
   
     *result = entry;
     return 0;
   }
   
   /*
   ** Implementation of the POSIX closedir() function using the MSVCRT.
   */
   INT closedir(
     LPDIR dirp
   ){
     INT result = 0;
   
     if( dirp==NULL ) return EINVAL;
   
     if( dirp->d_handle!=NULL_INTPTR_T && dirp->d_handle!=BAD_INTPTR_T ){
       result = _findclose(dirp->d_handle);
     }
   
     sqlite3_free(dirp);
     return result;
   }
   
   #endif /* defined(WIN32) && defined(_MSC_VER) */
   
   /************************* End test_windirent.c ********************/
   #define dirent DIRENT
   #endif
   /************************* Begin ../ext/misc/shathree.c ******************/
   /*
   ** 2017-03-08
   **
   ** The author disclaims copyright to this source code.  In place of
   ** a legal notice, here is a blessing:
   **
   **    May you do good and not evil.
   **    May you find forgiveness for yourself and forgive others.
   **    May you share freely, never taking more than you give.
   **
   ******************************************************************************
   **
   ** This SQLite extension implements functions that compute SHA3 hashes.
   ** Two SQL functions are implemented:
   **
   **     sha3(X,SIZE)
   **     sha3_query(Y,SIZE)
   **
   ** The sha3(X) function computes the SHA3 hash of the input X, or NULL if
   ** X is NULL.
   **
   ** The sha3_query(Y) function evalutes all queries in the SQL statements of Y
   ** and returns a hash of their results.
   **
   ** The SIZE argument is optional.  If omitted, the SHA3-256 hash algorithm
   ** is used.  If SIZE is included it must be one of the integers 224, 256,
   ** 384, or 512, to determine SHA3 hash variant that is computed.
   */
   /* #include "sqlite3ext.h" */
   SQLITE_EXTENSION_INIT1
   #include <assert.h>
   #include <string.h>
   #include <stdarg.h>
   
   #ifndef SQLITE_AMALGAMATION
   /* typedef sqlite3_uint64 u64; */
   #endif /* SQLITE_AMALGAMATION */
   
   /******************************************************************************
   ** The Hash Engine
   */
   /*
   ** Macros to determine whether the machine is big or little endian,
   ** and whether or not that determination is run-time or compile-time.
   **
   ** For best performance, an attempt is made to guess at the byte-order
   ** using C-preprocessor macros.  If that is unsuccessful, or if
   ** -DSHA3_BYTEORDER=0 is set, then byte-order is determined
   ** at run-time.
   */
   #ifndef SHA3_BYTEORDER
   # if defined(i386)     || defined(__i386__)   || defined(_M_IX86) ||    \
        defined(__x86_64) || defined(__x86_64__) || defined(_M_X64)  ||    \
        defined(_M_AMD64) || defined(_M_ARM)     || defined(__x86)   ||    \
        defined(__arm__)
   #   define SHA3_BYTEORDER    1234
   # elif defined(sparc)    || defined(__ppc__)
   #   define SHA3_BYTEORDER    4321
   # else
   #   define SHA3_BYTEORDER 0
   # endif
   #endif
   
   
   /*
   ** State structure for a SHA3 hash in progress
   */
   typedef struct SHA3Context SHA3Context;
   struct SHA3Context {
     union {
       u64 s[25];                /* Keccak state. 5x5 lines of 64 bits each */
       unsigned char x[1600];    /* ... or 1600 bytes */
     } u;
     unsigned nRate;        /* Bytes of input accepted per Keccak iteration */
     unsigned nLoaded;      /* Input bytes loaded into u.x[] so far this cycle */
     unsigned ixMask;       /* Insert next input into u.x[nLoaded^ixMask]. */
   };
   
   /*
   ** A single step of the Keccak mixing function for a 1600-bit state
   */
   static void KeccakF1600Step(SHA3Context *p){
     int i;
     u64 b0, b1, b2, b3, b4;
     u64 c0, c1, c2, c3, c4;
     u64 d0, d1, d2, d3, d4;
     static const u64 RC[] = {
       0x0000000000000001ULL,  0x0000000000008082ULL,
       0x800000000000808aULL,  0x8000000080008000ULL,
       0x000000000000808bULL,  0x0000000080000001ULL,
       0x8000000080008081ULL,  0x8000000000008009ULL,
       0x000000000000008aULL,  0x0000000000000088ULL,
       0x0000000080008009ULL,  0x000000008000000aULL,
       0x000000008000808bULL,  0x800000000000008bULL,
       0x8000000000008089ULL,  0x8000000000008003ULL,
       0x8000000000008002ULL,  0x8000000000000080ULL,
       0x000000000000800aULL,  0x800000008000000aULL,
       0x8000000080008081ULL,  0x8000000000008080ULL,
       0x0000000080000001ULL,  0x8000000080008008ULL
     };
   # define a00 (p->u.s[0])
   # define a01 (p->u.s[1])
   # define a02 (p->u.s[2])
   # define a03 (p->u.s[3])
   # define a04 (p->u.s[4])
   # define a10 (p->u.s[5])
   # define a11 (p->u.s[6])
   # define a12 (p->u.s[7])
   # define a13 (p->u.s[8])
   # define a14 (p->u.s[9])
   # define a20 (p->u.s[10])
   # define a21 (p->u.s[11])
   # define a22 (p->u.s[12])
   # define a23 (p->u.s[13])
   # define a24 (p->u.s[14])
   # define a30 (p->u.s[15])
   # define a31 (p->u.s[16])
   # define a32 (p->u.s[17])
   # define a33 (p->u.s[18])
   # define a34 (p->u.s[19])
   # define a40 (p->u.s[20])
   # define a41 (p->u.s[21])
   # define a42 (p->u.s[22])
   # define a43 (p->u.s[23])
   # define a44 (p->u.s[24])
   # define ROL64(a,x) ((a<<x)|(a>>(64-x)))
   
     for(i=0; i<24; i+=4){
       c0 = a00^a10^a20^a30^a40;
       c1 = a01^a11^a21^a31^a41;
       c2 = a02^a12^a22^a32^a42;
       c3 = a03^a13^a23^a33^a43;
       c4 = a04^a14^a24^a34^a44;
       d0 = c4^ROL64(c1, 1);
       d1 = c0^ROL64(c2, 1);
       d2 = c1^ROL64(c3, 1);
       d3 = c2^ROL64(c4, 1);
       d4 = c3^ROL64(c0, 1);
   
       b0 = (a00^d0);
       b1 = ROL64((a11^d1), 44);
       b2 = ROL64((a22^d2), 43);
       b3 = ROL64((a33^d3), 21);
       b4 = ROL64((a44^d4), 14);
       a00 =   b0 ^((~b1)&  b2 );
       a00 ^= RC[i];
       a11 =   b1 ^((~b2)&  b3 );
       a22 =   b2 ^((~b3)&  b4 );
       a33 =   b3 ^((~b4)&  b0 );
       a44 =   b4 ^((~b0)&  b1 );
   
       b2 = ROL64((a20^d0), 3);
       b3 = ROL64((a31^d1), 45);
       b4 = ROL64((a42^d2), 61);
       b0 = ROL64((a03^d3), 28);
       b1 = ROL64((a14^d4), 20);
       a20 =   b0 ^((~b1)&  b2 );
       a31 =   b1 ^((~b2)&  b3 );
       a42 =   b2 ^((~b3)&  b4 );
       a03 =   b3 ^((~b4)&  b0 );
       a14 =   b4 ^((~b0)&  b1 );
   
       b4 = ROL64((a40^d0), 18);
       b0 = ROL64((a01^d1), 1);
       b1 = ROL64((a12^d2), 6);
       b2 = ROL64((a23^d3), 25);
       b3 = ROL64((a34^d4), 8);
       a40 =   b0 ^((~b1)&  b2 );
       a01 =   b1 ^((~b2)&  b3 );
       a12 =   b2 ^((~b3)&  b4 );
       a23 =   b3 ^((~b4)&  b0 );
       a34 =   b4 ^((~b0)&  b1 );
   
       b1 = ROL64((a10^d0), 36);
       b2 = ROL64((a21^d1), 10);
       b3 = ROL64((a32^d2), 15);
       b4 = ROL64((a43^d3), 56);
       b0 = ROL64((a04^d4), 27);
       a10 =   b0 ^((~b1)&  b2 );
       a21 =   b1 ^((~b2)&  b3 );
       a32 =   b2 ^((~b3)&  b4 );
       a43 =   b3 ^((~b4)&  b0 );
       a04 =   b4 ^((~b0)&  b1 );
   
       b3 = ROL64((a30^d0), 41);
       b4 = ROL64((a41^d1), 2);
       b0 = ROL64((a02^d2), 62);
       b1 = ROL64((a13^d3), 55);
       b2 = ROL64((a24^d4), 39);
       a30 =   b0 ^((~b1)&  b2 );
       a41 =   b1 ^((~b2)&  b3 );
       a02 =   b2 ^((~b3)&  b4 );
       a13 =   b3 ^((~b4)&  b0 );
       a24 =   b4 ^((~b0)&  b1 );
   
       c0 = a00^a20^a40^a10^a30;
       c1 = a11^a31^a01^a21^a41;
       c2 = a22^a42^a12^a32^a02;
       c3 = a33^a03^a23^a43^a13;
       c4 = a44^a14^a34^a04^a24;
       d0 = c4^ROL64(c1, 1);
       d1 = c0^ROL64(c2, 1);
       d2 = c1^ROL64(c3, 1);
       d3 = c2^ROL64(c4, 1);
       d4 = c3^ROL64(c0, 1);
   
       b0 = (a00^d0);
       b1 = ROL64((a31^d1), 44);
       b2 = ROL64((a12^d2), 43);
       b3 = ROL64((a43^d3), 21);
       b4 = ROL64((a24^d4), 14);
       a00 =   b0 ^((~b1)&  b2 );
       a00 ^= RC[i+1];
       a31 =   b1 ^((~b2)&  b3 );
       a12 =   b2 ^((~b3)&  b4 );
       a43 =   b3 ^((~b4)&  b0 );
       a24 =   b4 ^((~b0)&  b1 );
   
       b2 = ROL64((a40^d0), 3);
       b3 = ROL64((a21^d1), 45);
       b4 = ROL64((a02^d2), 61);
       b0 = ROL64((a33^d3), 28);
       b1 = ROL64((a14^d4), 20);
       a40 =   b0 ^((~b1)&  b2 );
       a21 =   b1 ^((~b2)&  b3 );
       a02 =   b2 ^((~b3)&  b4 );
       a33 =   b3 ^((~b4)&  b0 );
       a14 =   b4 ^((~b0)&  b1 );
   
       b4 = ROL64((a30^d0), 18);
       b0 = ROL64((a11^d1), 1);
       b1 = ROL64((a42^d2), 6);
       b2 = ROL64((a23^d3), 25);
       b3 = ROL64((a04^d4), 8);
       a30 =   b0 ^((~b1)&  b2 );
       a11 =   b1 ^((~b2)&  b3 );
       a42 =   b2 ^((~b3)&  b4 );
       a23 =   b3 ^((~b4)&  b0 );
       a04 =   b4 ^((~b0)&  b1 );
   
       b1 = ROL64((a20^d0), 36);
       b2 = ROL64((a01^d1), 10);
       b3 = ROL64((a32^d2), 15);
       b4 = ROL64((a13^d3), 56);
       b0 = ROL64((a44^d4), 27);
       a20 =   b0 ^((~b1)&  b2 );
       a01 =   b1 ^((~b2)&  b3 );
       a32 =   b2 ^((~b3)&  b4 );
       a13 =   b3 ^((~b4)&  b0 );
       a44 =   b4 ^((~b0)&  b1 );
   
       b3 = ROL64((a10^d0), 41);
       b4 = ROL64((a41^d1), 2);
       b0 = ROL64((a22^d2), 62);
       b1 = ROL64((a03^d3), 55);
       b2 = ROL64((a34^d4), 39);
       a10 =   b0 ^((~b1)&  b2 );
       a41 =   b1 ^((~b2)&  b3 );
       a22 =   b2 ^((~b3)&  b4 );
       a03 =   b3 ^((~b4)&  b0 );
       a34 =   b4 ^((~b0)&  b1 );
   
       c0 = a00^a40^a30^a20^a10;
       c1 = a31^a21^a11^a01^a41;
       c2 = a12^a02^a42^a32^a22;
       c3 = a43^a33^a23^a13^a03;
       c4 = a24^a14^a04^a44^a34;
       d0 = c4^ROL64(c1, 1);
       d1 = c0^ROL64(c2, 1);
       d2 = c1^ROL64(c3, 1);
       d3 = c2^ROL64(c4, 1);
       d4 = c3^ROL64(c0, 1);
   
       b0 = (a00^d0);
       b1 = ROL64((a21^d1), 44);
       b2 = ROL64((a42^d2), 43);
       b3 = ROL64((a13^d3), 21);
       b4 = ROL64((a34^d4), 14);
       a00 =   b0 ^((~b1)&  b2 );
       a00 ^= RC[i+2];
       a21 =   b1 ^((~b2)&  b3 );
       a42 =   b2 ^((~b3)&  b4 );
       a13 =   b3 ^((~b4)&  b0 );
       a34 =   b4 ^((~b0)&  b1 );
   
       b2 = ROL64((a30^d0), 3);
       b3 = ROL64((a01^d1), 45);
       b4 = ROL64((a22^d2), 61);
       b0 = ROL64((a43^d3), 28);
       b1 = ROL64((a14^d4), 20);
       a30 =   b0 ^((~b1)&  b2 );
       a01 =   b1 ^((~b2)&  b3 );
       a22 =   b2 ^((~b3)&  b4 );
       a43 =   b3 ^((~b4)&  b0 );
       a14 =   b4 ^((~b0)&  b1 );
   
       b4 = ROL64((a10^d0), 18);
       b0 = ROL64((a31^d1), 1);
       b1 = ROL64((a02^d2), 6);
       b2 = ROL64((a23^d3), 25);
       b3 = ROL64((a44^d4), 8);
       a10 =   b0 ^((~b1)&  b2 );
       a31 =   b1 ^((~b2)&  b3 );
       a02 =   b2 ^((~b3)&  b4 );
       a23 =   b3 ^((~b4)&  b0 );
       a44 =   b4 ^((~b0)&  b1 );
   
       b1 = ROL64((a40^d0), 36);
       b2 = ROL64((a11^d1), 10);
       b3 = ROL64((a32^d2), 15);
       b4 = ROL64((a03^d3), 56);
       b0 = ROL64((a24^d4), 27);
       a40 =   b0 ^((~b1)&  b2 );
       a11 =   b1 ^((~b2)&  b3 );
       a32 =   b2 ^((~b3)&  b4 );
       a03 =   b3 ^((~b4)&  b0 );
       a24 =   b4 ^((~b0)&  b1 );
   
       b3 = ROL64((a20^d0), 41);
       b4 = ROL64((a41^d1), 2);
       b0 = ROL64((a12^d2), 62);
       b1 = ROL64((a33^d3), 55);
       b2 = ROL64((a04^d4), 39);
       a20 =   b0 ^((~b1)&  b2 );
       a41 =   b1 ^((~b2)&  b3 );
       a12 =   b2 ^((~b3)&  b4 );
       a33 =   b3 ^((~b4)&  b0 );
       a04 =   b4 ^((~b0)&  b1 );
   
       c0 = a00^a30^a10^a40^a20;
       c1 = a21^a01^a31^a11^a41;
       c2 = a42^a22^a02^a32^a12;
       c3 = a13^a43^a23^a03^a33;
       c4 = a34^a14^a44^a24^a04;
       d0 = c4^ROL64(c1, 1);
       d1 = c0^ROL64(c2, 1);
       d2 = c1^ROL64(c3, 1);
       d3 = c2^ROL64(c4, 1);
       d4 = c3^ROL64(c0, 1);
   
       b0 = (a00^d0);
       b1 = ROL64((a01^d1), 44);
       b2 = ROL64((a02^d2), 43);
       b3 = ROL64((a03^d3), 21);
       b4 = ROL64((a04^d4), 14);
       a00 =   b0 ^((~b1)&  b2 );
       a00 ^= RC[i+3];
       a01 =   b1 ^((~b2)&  b3 );
       a02 =   b2 ^((~b3)&  b4 );
       a03 =   b3 ^((~b4)&  b0 );
       a04 =   b4 ^((~b0)&  b1 );
   
       b2 = ROL64((a10^d0), 3);
       b3 = ROL64((a11^d1), 45);
       b4 = ROL64((a12^d2), 61);
       b0 = ROL64((a13^d3), 28);
       b1 = ROL64((a14^d4), 20);
       a10 =   b0 ^((~b1)&  b2 );
       a11 =   b1 ^((~b2)&  b3 );
       a12 =   b2 ^((~b3)&  b4 );
       a13 =   b3 ^((~b4)&  b0 );
       a14 =   b4 ^((~b0)&  b1 );
   
       b4 = ROL64((a20^d0), 18);
       b0 = ROL64((a21^d1), 1);
       b1 = ROL64((a22^d2), 6);
       b2 = ROL64((a23^d3), 25);
       b3 = ROL64((a24^d4), 8);
       a20 =   b0 ^((~b1)&  b2 );
       a21 =   b1 ^((~b2)&  b3 );
       a22 =   b2 ^((~b3)&  b4 );
       a23 =   b3 ^((~b4)&  b0 );
       a24 =   b4 ^((~b0)&  b1 );
   
       b1 = ROL64((a30^d0), 36);
       b2 = ROL64((a31^d1), 10);
       b3 = ROL64((a32^d2), 15);
       b4 = ROL64((a33^d3), 56);
       b0 = ROL64((a34^d4), 27);
       a30 =   b0 ^((~b1)&  b2 );
       a31 =   b1 ^((~b2)&  b3 );
       a32 =   b2 ^((~b3)&  b4 );
       a33 =   b3 ^((~b4)&  b0 );
       a34 =   b4 ^((~b0)&  b1 );
   
       b3 = ROL64((a40^d0), 41);
       b4 = ROL64((a41^d1), 2);
       b0 = ROL64((a42^d2), 62);
       b1 = ROL64((a43^d3), 55);
       b2 = ROL64((a44^d4), 39);
       a40 =   b0 ^((~b1)&  b2 );
       a41 =   b1 ^((~b2)&  b3 );
       a42 =   b2 ^((~b3)&  b4 );
       a43 =   b3 ^((~b4)&  b0 );
       a44 =   b4 ^((~b0)&  b1 );
     }
   }
   
   /*
   ** Initialize a new hash.  iSize determines the size of the hash
   ** in bits and should be one of 224, 256, 384, or 512.  Or iSize
   ** can be zero to use the default hash size of 256 bits.
   */
   static void SHA3Init(SHA3Context *p, int iSize){
     memset(p, 0, sizeof(*p));
     if( iSize>=128 && iSize<=512 ){
       p->nRate = (1600 - ((iSize + 31)&~31)*2)/8;
     }else{
       p->nRate = (1600 - 2*256)/8;
     }
   #if SHA3_BYTEORDER==1234
     /* Known to be little-endian at compile-time. No-op */
   #elif SHA3_BYTEORDER==4321
     p->ixMask = 7;  /* Big-endian */
   #else
     {
       static unsigned int one = 1;
       if( 1==*(unsigned char*)&one ){
         /* Little endian.  No byte swapping. */
         p->ixMask = 0;
       }else{
         /* Big endian.  Byte swap. */
         p->ixMask = 7;
       }
     }
   #endif
   }
   
   /*
   ** Make consecutive calls to the SHA3Update function to add new content
   ** to the hash
   */
   static void SHA3Update(
     SHA3Context *p,
     const unsigned char *aData,
     unsigned int nData
   ){
     unsigned int i = 0;
   #if SHA3_BYTEORDER==1234
     if( (p->nLoaded % 8)==0 && ((aData - (const unsigned char*)0)&7)==0 ){
       for(; i+7<nData; i+=8){
         p->u.s[p->nLoaded/8] ^= *(u64*)&aData[i];
         p->nLoaded += 8;
         if( p->nLoaded>=p->nRate ){
           KeccakF1600Step(p);
           p->nLoaded = 0;
         }
       }
     }
   #endif
     for(; i<nData; i++){
   #if SHA3_BYTEORDER==1234
       p->u.x[p->nLoaded] ^= aData[i];
   #elif SHA3_BYTEORDER==4321
       p->u.x[p->nLoaded^0x07] ^= aData[i];
   #else
       p->u.x[p->nLoaded^p->ixMask] ^= aData[i];
   #endif
       p->nLoaded++;
       if( p->nLoaded==p->nRate ){
         KeccakF1600Step(p);
         p->nLoaded = 0;
       }
     }
   }
   
   /*
   ** After all content has been added, invoke SHA3Final() to compute
   ** the final hash.  The function returns a pointer to the binary
   ** hash value.
   */
   static unsigned char *SHA3Final(SHA3Context *p){
     unsigned int i;
     if( p->nLoaded==p->nRate-1 ){
       const unsigned char c1 = 0x86;
       SHA3Update(p, &c1, 1);
     }else{
       const unsigned char c2 = 0x06;
       const unsigned char c3 = 0x80;
       SHA3Update(p, &c2, 1);
       p->nLoaded = p->nRate - 1;
       SHA3Update(p, &c3, 1);
     }
     for(i=0; i<p->nRate; i++){
       p->u.x[i+p->nRate] = p->u.x[i^p->ixMask];
     }
     return &p->u.x[p->nRate];
   }
   /* End of the hashing logic
   *****************************************************************************/
   
   /*
   ** Implementation of the sha3(X,SIZE) function.
   **
   ** Return a BLOB which is the SIZE-bit SHA3 hash of X.  The default
   ** size is 256.  If X is a BLOB, it is hashed as is.  
   ** For all other non-NULL types of input, X is converted into a UTF-8 string
   ** and the string is hashed without the trailing 0x00 terminator.  The hash
   ** of a NULL value is NULL.
   */
   static void sha3Func(
     sqlite3_context *context,
     int argc,
     sqlite3_value **argv
   ){
     SHA3Context cx;
     int eType = sqlite3_value_type(argv[0]);
     int nByte = sqlite3_value_bytes(argv[0]);
     int iSize;
     if( argc==1 ){
       iSize = 256;
     }else{
       iSize = sqlite3_value_int(argv[1]);
       if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){
         sqlite3_result_error(context, "SHA3 size should be one of: 224 256 "
                                       "384 512", -1);
         return;
       }
     }
     if( eType==SQLITE_NULL ) return;
     SHA3Init(&cx, iSize);
     if( eType==SQLITE_BLOB ){
       SHA3Update(&cx, sqlite3_value_blob(argv[0]), nByte);
     }else{
       SHA3Update(&cx, sqlite3_value_text(argv[0]), nByte);
     }
     sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT);
   }
   
   /* Compute a string using sqlite3_vsnprintf() with a maximum length
   ** of 50 bytes and add it to the hash.
   */
   static void hash_step_vformat(
     SHA3Context *p,                 /* Add content to this context */
     const char *zFormat,
     ...
   ){
     va_list ap;
     int n;
     char zBuf[50];
     va_start(ap, zFormat);
     sqlite3_vsnprintf(sizeof(zBuf),zBuf,zFormat,ap);
     va_end(ap);
     n = (int)strlen(zBuf);
     SHA3Update(p, (unsigned char*)zBuf, n);
   }
   
   /*
   ** Implementation of the sha3_query(SQL,SIZE) function.
   **
   ** This function compiles and runs the SQL statement(s) given in the
   ** argument. The results are hashed using a SIZE-bit SHA3.  The default
   ** size is 256.
   **
   ** The format of the byte stream that is hashed is summarized as follows:
   **
   **       S<n>:<sql>
   **       R
   **       N
   **       I<int>
   **       F<ieee-float>
   **       B<size>:<bytes>
   **       T<size>:<text>
   **
   ** <sql> is the original SQL text for each statement run and <n> is
   ** the size of that text.  The SQL text is UTF-8.  A single R character
   ** occurs before the start of each row.  N means a NULL value.
   ** I mean an 8-byte little-endian integer <int>.  F is a floating point
   ** number with an 8-byte little-endian IEEE floating point value <ieee-float>.
   ** B means blobs of <size> bytes.  T means text rendered as <size>
   ** bytes of UTF-8.  The <n> and <size> values are expressed as an ASCII
   ** text integers.
   **
   ** For each SQL statement in the X input, there is one S segment.  Each
   ** S segment is followed by zero or more R segments, one for each row in the
   ** result set.  After each R, there are one or more N, I, F, B, or T segments,
   ** one for each column in the result set.  Segments are concatentated directly
   ** with no delimiters of any kind.
   */
   static void sha3QueryFunc(
     sqlite3_context *context,
     int argc,
     sqlite3_value **argv
   ){
     sqlite3 *db = sqlite3_context_db_handle(context);
     const char *zSql = (const char*)sqlite3_value_text(argv[0]);
     sqlite3_stmt *pStmt = 0;
     int nCol;                   /* Number of columns in the result set */
     int i;                      /* Loop counter */
     int rc;
     int n;
     const char *z;
     SHA3Context cx;
     int iSize;
   
     if( argc==1 ){
       iSize = 256;
     }else{
       iSize = sqlite3_value_int(argv[1]);
       if( iSize!=224 && iSize!=256 && iSize!=384 && iSize!=512 ){
         sqlite3_result_error(context, "SHA3 size should be one of: 224 256 "
                                       "384 512", -1);
         return;
       }
     }
     if( zSql==0 ) return;
     SHA3Init(&cx, iSize);
     while( zSql[0] ){
       rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zSql);
       if( rc ){
         char *zMsg = sqlite3_mprintf("error SQL statement [%s]: %s",
                                      zSql, sqlite3_errmsg(db));
         sqlite3_finalize(pStmt);
         sqlite3_result_error(context, zMsg, -1);
         sqlite3_free(zMsg);
         return;
       }
       if( !sqlite3_stmt_readonly(pStmt) ){
         char *zMsg = sqlite3_mprintf("non-query: [%s]", sqlite3_sql(pStmt));
         sqlite3_finalize(pStmt);
         sqlite3_result_error(context, zMsg, -1);
         sqlite3_free(zMsg);
         return;
       }
       nCol = sqlite3_column_count(pStmt);
       z = sqlite3_sql(pStmt);
       if( z ){
         n = (int)strlen(z);
         hash_step_vformat(&cx,"S%d:",n);
         SHA3Update(&cx,(unsigned char*)z,n);
       }
   
       /* Compute a hash over the result of the query */
       while( SQLITE_ROW==sqlite3_step(pStmt) ){
         SHA3Update(&cx,(const unsigned char*)"R",1);
         for(i=0; i<nCol; i++){
           switch( sqlite3_column_type(pStmt,i) ){
             case SQLITE_NULL: {
               SHA3Update(&cx, (const unsigned char*)"N",1);
               break;
             }
             case SQLITE_INTEGER: {
               sqlite3_uint64 u;
               int j;
               unsigned char x[9];
               sqlite3_int64 v = sqlite3_column_int64(pStmt,i);
               memcpy(&u, &v, 8);
               for(j=8; j>=1; j--){
                 x[j] = u & 0xff;
                 u >>= 8;
               }
               x[0] = 'I';
               SHA3Update(&cx, x, 9);
               break;
             }
             case SQLITE_FLOAT: {
               sqlite3_uint64 u;
               int j;
               unsigned char x[9];
               double r = sqlite3_column_double(pStmt,i);
               memcpy(&u, &r, 8);
               for(j=8; j>=1; j--){
                 x[j] = u & 0xff;
                 u >>= 8;
               }
               x[0] = 'F';
               SHA3Update(&cx,x,9);
               break;
             }
             case SQLITE_TEXT: {
               int n2 = sqlite3_column_bytes(pStmt, i);
               const unsigned char *z2 = sqlite3_column_text(pStmt, i);
               hash_step_vformat(&cx,"T%d:",n2);
               SHA3Update(&cx, z2, n2);
               break;
             }
             case SQLITE_BLOB: {
               int n2 = sqlite3_column_bytes(pStmt, i);
               const unsigned char *z2 = sqlite3_column_blob(pStmt, i);
               hash_step_vformat(&cx,"B%d:",n2);
               SHA3Update(&cx, z2, n2);
               break;
             }
           }
         }
       }
       sqlite3_finalize(pStmt);
     }
     sqlite3_result_blob(context, SHA3Final(&cx), iSize/8, SQLITE_TRANSIENT);
   }
   
   
   #ifdef _WIN32
   
   #endif
   int sqlite3_shathree_init(
     sqlite3 *db,
     char **pzErrMsg,
     const sqlite3_api_routines *pApi
   ){
     int rc = SQLITE_OK;
     SQLITE_EXTENSION_INIT2(pApi);
     (void)pzErrMsg;  /* Unused parameter */
     rc = sqlite3_create_function(db, "sha3", 1,
                         SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC,
                         0, sha3Func, 0, 0);
     if( rc==SQLITE_OK ){
       rc = sqlite3_create_function(db, "sha3", 2,
                         SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC,
                         0, sha3Func, 0, 0);
     }
     if( rc==SQLITE_OK ){
       rc = sqlite3_create_function(db, "sha3_query", 1,
                         SQLITE_UTF8 | SQLITE_DIRECTONLY,
                         0, sha3QueryFunc, 0, 0);
     }
     if( rc==SQLITE_OK ){
       rc = sqlite3_create_function(db, "sha3_query", 2,
                         SQLITE_UTF8 | SQLITE_DIRECTONLY,
                         0, sha3QueryFunc, 0, 0);
     }
     return rc;
   }
   
   /************************* End ../ext/misc/shathree.c ********************/
   /************************* Begin ../ext/misc/fileio.c ******************/
   /*
   ** 2014-06-13
   **
   ** The author disclaims copyright to this source code.  In place of
   ** a legal notice, here is a blessing:
   **
   **    May you do good and not evil.
   **    May you find forgiveness for yourself and forgive others.
   **    May you share freely, never taking more than you give.
   **
   ******************************************************************************
   **
   ** This SQLite extension implements SQL functions readfile() and
   ** writefile(), 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 1GB. (1000013824 bytes)
   ** This VFS will not read or write past the 1GB 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  (65536*15259)
   
   /*
   ** Size of storage page upon which to align appendvfs portion.
   */
   #ifndef APND_ROUNDUP_BITS
   #define APND_ROUNDUP_BITS 12
   #endif
   
   /*
   ** 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))
   
   /* Invariants for an open appendvfs file:
    * Once an appendvfs file is opened, it will be in one of three states:
    * State 0: Never written. Underlying file (if any) is unaltered.
    * State 1: Append mark is persisted, content write is in progress.
    * State 2: Append mark is persisted, content writes are complete.
    * 
    * State 0 is persistent in the sense that nothing will have been done
    * to the underlying file, including any attempt to convert it to an
    * appendvfs file.
    *
    * State 1 is normally transitory. However, if a write operation ends
    * abnormally (disk full, power loss, process kill, etc.), then State 1
    * may be persistent on disk with an incomplete content write-out. This
    * is logically equivalent to an interrupted write to an ordinary file,
    * where some unknown portion of to-be-written data is persisted while
    * the remainder is not. Database integrity in such cases is maintained
    * (or not) by the same measures available for ordinary file access.
    *
    * State 2 is persistent under normal circumstances (when there is no
    * abnormal termination of a write operation such that data provided
    * to the underlying VFS write method has not yet reached storage.)
    *
    * In order to maintain the state invariant, the append mark is written
    * in advance of content writes where any part of such content would
    * overwrite an existing (or yet to be written) append mark.
    */
   struct ApndFile {
     /* Access to IO methods of the underlying file */
     sqlite3_file base;
     /* File offset to beginning of appended content (unchanging) */
     sqlite3_int64 iPgOne;
     /* File offset of written append-mark, or -1 if unwritten */
     sqlite3_int64 iMark;
   };
   
   /*
   ** 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 right end-marker, the expected odd size, and the
        * SQLite DB type marker where the end-marker puts it, then it
        * is an appendvfs database (to be treated as such.)
        */
       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;
     }
   }
   
   /* Round-up used to get appendvfs portion to begin at a page boundary. */
   #define APND_ALIGN_MASK(nbits) ((1<<nbits)-1)
   #define APND_START_ROUNDUP(fsz, nbits) \
    ( ((fsz)+APND_ALIGN_MASK(nbits)) & ~(sqlite3_int64)APND_ALIGN_MASK(nbits) )
   
   /*
   ** Open an apnd file handle.
   */
   static int apndOpen(
     sqlite3_vfs *pVfs,
     const char *zName,
     sqlite3_file *pFile,
     int flags,
     int *pOutFlags
   ){
     ApndFile *p;
     sqlite3_file *pSubFile;
     sqlite3_vfs *pSubVfs;
     int rc;
     sqlite3_int64 sz;
     pSubVfs = ORIGVFS(pVfs);
     if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){
       /* The appendvfs is not to be used for transient or temporary databases. */
       return pSubVfs->xOpen(pSubVfs, zName, pFile, flags, pOutFlags);
     }
     p = (ApndFile*)pFile;
     memset(p, 0, sizeof(*p));
     pSubFile = ORIGFILE(pFile);
     pFile->pMethods = &apnd_io_methods;
     rc = pSubVfs->xOpen(pSubVfs, zName, pSubFile, flags, pOutFlags);
     if( rc ) goto apnd_open_done;
     rc = pSubFile->pMethods->xFileSize(pSubFile, &sz);
     if( rc ){
       pSubFile->pMethods->xClose(pSubFile);
       goto apnd_open_done;
     }
     if( apndIsOrdinaryDatabaseFile(sz, pSubFile) ){
       memmove(pFile, pSubFile, pSubVfs->szOsFile);
       return SQLITE_OK;
     }
     /* Record that append mark has not been written until seen otherwise. */
     p->iMark = -1;
     p->iPgOne = apndReadMark(sz, pFile);
     if( p->iPgOne>=0 ){
       /* Append mark was found, infer its offset */
       p->iMark = sz - p->iPgOne - APND_MARK_SIZE;
       return SQLITE_OK;
     }
     if( (flags & SQLITE_OPEN_CREATE)==0 ){
       pSubFile->pMethods->xClose(pSubFile);
       rc = SQLITE_CANTOPEN;
     }
     /* 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, the p->iMark value indicates it is not yet written.
      */
     p->iPgOne = APND_START_ROUNDUP(sz, APND_ROUNDUP_BITS);
   apnd_open_done:
     if( rc ) pFile->pMethods = 0;
     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);
     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
   **
   ** 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 the UINT collating sequence.
   **
   ** UINT works like BINARY for text, except that embedded strings
   ** of digits compare in numeric order.
   **
   **     *   Leading zeros are handled properly, in the sense that
   **         they do not mess of the maginitude comparison of embedded
   **         strings of digits.  "x00123y" is equal to "x123y".
   **
   **     *   Only unsigned integers are recognized.  Plus and minus
   **         signs are ignored.  Decimal points and exponential notation
   **         are ignored.
   **
   **     *   Embedded integers can be of arbitrary length.  Comparison
   **         is *not* limited integers that can be expressed as a
   **         64-bit machine integer.
   */
   /* #include "sqlite3ext.h" */
   SQLITE_EXTENSION_INIT1
   #include <assert.h>
   #include <string.h>
   #include <ctype.h>
   
   /*
   ** Compare text in lexicographic order, except strings of digits
   ** compare in numeric order.
   */
   static int uintCollFunc(
     void *notUsed,
     int nKey1, const void *pKey1,
     int nKey2, const void *pKey2
   ){
     const unsigned char *zA = (const unsigned char*)pKey1;
     const unsigned char *zB = (const unsigned char*)pKey2;
     int i=0, j=0, x;
     (void)notUsed;
     while( i<nKey1 && j<nKey2 ){
       x = zA[i] - zB[j];
       if( isdigit(zA[i]) ){
         int k;
         if( !isdigit(zB[j]) ) return x;
         while( i<nKey1 && zA[i]=='0' ){ i++; }
         while( j<nKey2 && zB[j]=='0' ){ j++; }
         k = 0;
         while( i+k<nKey1 && isdigit(zA[i+k])
                && j+k<nKey2 && isdigit(zB[j+k]) ){
           k++;
         }
         if( i+k<nKey1 && isdigit(zA[i+k]) ){
           return +1;
         }else if( j+k<nKey2 && isdigit(zB[j+k]) ){
           return -1;
         }else{
           x = memcmp(zA+i, zB+j, k);
           if( x ) return x;
           i += k;
           j += k;
         }
       }else if( x ){
         return x;
       }else{
         i++;
         j++;
       }
     }
     return (nKey1 - i) - (nKey2 - j);
   }
   
   #ifdef _WIN32
   
   #endif
   int sqlite3_uint_init(
     sqlite3 *db, 
     char **pzErrMsg, 
     const sqlite3_api_routines *pApi
   ){
     SQLITE_EXTENSION_INIT2(pApi);
     (void)pzErrMsg;  /* Unused parameter */
     return sqlite3_create_collation(db, "uint", SQLITE_UTF8, 0, uintCollFunc);
   }
   
   /************************* End ../ext/misc/uint.c ********************/
   /************************* Begin ../ext/misc/decimal.c ******************/
   /*
   ** 2020-06-22
   **
   ** 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.
   **
   ******************************************************************************
   **
   ** Routines to implement arbitrary-precision decimal math.
   **
   ** The focus here is on simplicity and correctness, not performance.
   */
   /* #include "sqlite3ext.h" */
   SQLITE_EXTENSION_INIT1
   #include <assert.h>
   #include <string.h>
   #include <ctype.h>
   #include <stdlib.h>
   
   /* Mark a function parameter as unused, to suppress nuisance compiler
   ** warnings. */
   #ifndef UNUSED_PARAMETER
   # define UNUSED_PARAMETER(X)  (void)(X)
   #endif
   
   
   /* A decimal object */
   typedef struct Decimal Decimal;
   struct Decimal {
     char sign;        /* 0 for positive, 1 for negative */
     char oom;         /* True if an OOM is encountered */
     char isNull;      /* True if holds a NULL rather than a number */
     char isInit;      /* True upon initialization */
     int nDigit;       /* Total number of digits */
     int nFrac;        /* Number of digits to the right of the decimal point */
     signed char *a;   /* Array of digits.  Most significant first. */
   };
   
   /*
   ** Release memory held by a Decimal, but do not free the object itself.
   */
   static void decimal_clear(Decimal *p){
     sqlite3_free(p->a);
   }
   
   /*
   ** Destroy a Decimal object
   */
   static void decimal_free(Decimal *p){
     if( p ){
       decimal_clear(p);
       sqlite3_free(p);
     }
   }
   
   /*
   ** Allocate a new Decimal object.  Initialize it to the number given
   ** by the input string.
   */
   static Decimal *decimal_new(
     sqlite3_context *pCtx,
     sqlite3_value *pIn,
     int nAlt,
     const unsigned char *zAlt
   ){
     Decimal *p;
     int n, i;
     const unsigned char *zIn;
     int iExp = 0;
     p = sqlite3_malloc( sizeof(*p) );
     if( p==0 ) goto new_no_mem;
     p->sign = 0;
     p->oom = 0;
     p->isInit = 1;
     p->isNull = 0;
     p->nDigit = 0;
     p->nFrac = 0;
     if( zAlt ){
       n = nAlt,
       zIn = zAlt;
     }else{
       if( sqlite3_value_type(pIn)==SQLITE_NULL ){
         p->a = 0;
         p->isNull = 1;
         return p;
       }
       n = sqlite3_value_bytes(pIn);
       zIn = sqlite3_value_text(pIn);
     }
     p->a = sqlite3_malloc64( n+1 );
     if( p->a==0 ) goto new_no_mem;
     for(i=0; isspace(zIn[i]); i++){}
     if( zIn[i]=='-' ){
       p->sign = 1;
       i++;
     }else if( zIn[i]=='+' ){
       i++;
     }
     while( i<n && zIn[i]=='0' ) i++;
     while( i<n ){
       char c = zIn[i];
       if( c>='0' && c<='9' ){
         p->a[p->nDigit++] = c - '0';
       }else if( c=='.' ){
         p->nFrac = p->nDigit + 1;
       }else if( c=='e' || c=='E' ){
         int j = i+1;
         int neg = 0;
         if( j>=n ) break;
         if( zIn[j]=='-' ){
           neg = 1;
           j++;
         }else if( zIn[j]=='+' ){
           j++;
         }
         while( j<n && iExp<1000000 ){
           if( zIn[j]>='0' && zIn[j]<='9' ){
             iExp = iExp*10 + zIn[j] - '0';
           }
           j++;
         }
         if( neg ) iExp = -iExp;
         break;
       }
       i++;
     }
     if( p->nFrac ){
       p->nFrac = p->nDigit - (p->nFrac - 1);
     }
     if( iExp>0 ){
       if( p->nFrac>0 ){
         if( iExp<=p->nFrac ){
           p->nFrac -= iExp;
           iExp = 0;
         }else{
           iExp -= p->nFrac;
           p->nFrac = 0;
         }
       }
       if( iExp>0 ){   
         p->a = sqlite3_realloc64(p->a, p->nDigit + iExp + 1 );
         if( p->a==0 ) goto new_no_mem;
         memset(p->a+p->nDigit, 0, iExp);
         p->nDigit += iExp;
       }
     }else if( iExp<0 ){
       int nExtra;
       iExp = -iExp;
       nExtra = p->nDigit - p->nFrac - 1;
       if( nExtra ){
         if( nExtra>=iExp ){
           p->nFrac += iExp;
           iExp  = 0;
         }else{
           iExp -= nExtra;
           p->nFrac = p->nDigit - 1;
         }
       }
       if( iExp>0 ){
         p->a = sqlite3_realloc64(p->a, p->nDigit + iExp + 1 );
         if( p->a==0 ) goto new_no_mem;
         memmove(p->a+iExp, p->a, p->nDigit);
         memset(p->a, 0, iExp);
         p->nDigit += iExp;
         p->nFrac += iExp;
       }
     }
     return p;
   
   new_no_mem:
     if( pCtx ) sqlite3_result_error_nomem(pCtx);
     sqlite3_free(p);
     return 0;
   }
   
   /*
   ** Make the given Decimal the result.
   */
   static void decimal_result(sqlite3_context *pCtx, Decimal *p){
     char *z;
     int i, j;
     int n;
     if( p==0 || p->oom ){
       sqlite3_result_error_nomem(pCtx);
       return;
     }
     if( p->isNull ){
       sqlite3_result_null(pCtx);
       return;
     }
     z = sqlite3_malloc( p->nDigit+4 );
     if( z==0 ){
       sqlite3_result_error_nomem(pCtx);
       return;
     }
     i = 0;
     if( p->nDigit==0 || (p->nDigit==1 && p->a[0]==0) ){
       p->sign = 0;
     }
     if( p->sign ){
       z[0] = '-';
       i = 1;
     }
     n = p->nDigit - p->nFrac;
     if( n<=0 ){
       z[i++] = '0';
     }
     j = 0;
     while( n>1 && p->a[j]==0 ){
       j++;
       n--;
     }
     while( n>0  ){
       z[i++] = p->a[j] + '0';
       j++;
       n--;
     }
     if( p->nFrac ){
       z[i++] = '.';
       do{
         z[i++] = p->a[j] + '0';
         j++;
       }while( j<p->nDigit );
     }
     z[i] = 0;
     sqlite3_result_text(pCtx, z, i, sqlite3_free);
   }
   
   /*
   ** SQL Function:   decimal(X)
   **
   ** Convert input X into decimal and then back into text
   */
   static void decimalFunc(
     sqlite3_context *context,
     int argc,
     sqlite3_value **argv
   ){
     Decimal *p = decimal_new(context, argv[0], 0, 0);
     UNUSED_PARAMETER(argc);
     decimal_result(context, p);
     decimal_free(p);
   }
   
   /*
   ** Compare to Decimal objects.  Return negative, 0, or positive if the
   ** first object is less than, equal to, or greater than the second.
   **
   ** Preconditions for this routine:
   **
   **    pA!=0
   **    pA->isNull==0
   **    pB!=0
   **    pB->isNull==0
   */
   static int decimal_cmp(const Decimal *pA, const Decimal *pB){
     int nASig, nBSig, rc, n;
     if( pA->sign!=pB->sign ){
       return pA->sign ? -1 : +1;
     }
     if( pA->sign ){
       const Decimal *pTemp = pA;
       pA = pB;
       pB = pTemp;
     }
     nASig = pA->nDigit - pA->nFrac;
     nBSig = pB->nDigit - pB->nFrac;
     if( nASig!=nBSig ){
       return nASig - nBSig;
     }
     n = pA->nDigit;
     if( n>pB->nDigit ) n = pB->nDigit;
     rc = memcmp(pA->a, pB->a, n);
     if( rc==0 ){
       rc = pA->nDigit - pB->nDigit;
     }
     return rc;
   }
   
   /*
   ** SQL Function:   decimal_cmp(X, Y)
   **
   ** Return negative, zero, or positive if X is less then, equal to, or
   ** greater than Y.
   */
   static void decimalCmpFunc(
     sqlite3_context *context,
     int argc,
     sqlite3_value **argv
   ){
     Decimal *pA = 0, *pB = 0;
     int rc;
   
     UNUSED_PARAMETER(argc);
     pA = decimal_new(context, argv[0], 0, 0);
     if( pA==0 || pA->isNull ) goto cmp_done;
     pB = decimal_new(context, argv[1], 0, 0);
     if( pB==0 || pB->isNull ) goto cmp_done;
     rc = decimal_cmp(pA, pB);
     if( rc<0 ) rc = -1;
     else if( rc>0 ) rc = +1;
     sqlite3_result_int(context, rc);
   cmp_done:
     decimal_free(pA);
     decimal_free(pB);
   }
   
   /*
   ** Expand the Decimal so that it has a least nDigit digits and nFrac
   ** digits to the right of the decimal point.
   */
   static void decimal_expand(Decimal *p, int nDigit, int nFrac){
     int nAddSig;
     int nAddFrac;
     if( p==0 ) return;
     nAddFrac = nFrac - p->nFrac;
     nAddSig = (nDigit - p->nDigit) - nAddFrac;
     if( nAddFrac==0 && nAddSig==0 ) return;
     p->a = sqlite3_realloc64(p->a, nDigit+1);
     if( p->a==0 ){
       p->oom = 1;
       return;
     }
     if( nAddSig ){
       memmove(p->a+nAddSig, p->a, p->nDigit);
       memset(p->a, 0, nAddSig);
       p->nDigit += nAddSig;
     }
     if( nAddFrac ){
       memset(p->a+p->nDigit, 0, nAddFrac);
       p->nDigit += nAddFrac;
       p->nFrac += nAddFrac;
     }
   }
   
   /*
   ** Add the value pB into pA.
   **
   ** Both pA and pB might become denormalized by this routine.
   */
   static void decimal_add(Decimal *pA, Decimal *pB){
     int nSig, nFrac, nDigit;
     int i, rc;
     if( pA==0 ){
       return;
     }
     if( pA->oom || pB==0 || pB->oom ){
       pA->oom = 1;
       return;
     }
     if( pA->isNull || pB->isNull ){
       pA->isNull = 1;
       return;
     }
     nSig = pA->nDigit - pA->nFrac;
     if( nSig && pA->a[0]==0 ) nSig--;
     if( nSig<pB->nDigit-pB->nFrac ){
       nSig = pB->nDigit - pB->nFrac;
     }
     nFrac = pA->nFrac;
     if( nFrac<pB->nFrac ) nFrac = pB->nFrac;
     nDigit = nSig + nFrac + 1;
     decimal_expand(pA, nDigit, nFrac);
     decimal_expand(pB, nDigit, nFrac);
     if( pA->oom || pB->oom ){
       pA->oom = 1;
     }else{
       if( pA->sign==pB->sign ){
         int carry = 0;
         for(i=nDigit-1; i>=0; i--){
           int x = pA->a[i] + pB->a[i] + carry;
           if( x>=10 ){
             carry = 1;
             pA->a[i] = x - 10;
           }else{
             carry = 0;
             pA->a[i] = x;
           }
         }
       }else{
         signed char *aA, *aB;
         int borrow = 0;
         rc = memcmp(pA->a, pB->a, nDigit);
         if( rc<0 ){
           aA = pB->a;
           aB = pA->a;
           pA->sign = !pA->sign;
         }else{
           aA = pA->a;
           aB = pB->a;
         }
         for(i=nDigit-1; i>=0; i--){
           int x = aA[i] - aB[i] - borrow;
           if( x<0 ){
             pA->a[i] = x+10;
             borrow = 1;
           }else{
             pA->a[i] = x;
             borrow = 0;
           }
         }
       }
     }
   }
   
   /*
   ** Compare text in decimal order.
   */
   static int decimalCollFunc(
     void *notUsed,
     int nKey1, const void *pKey1,
     int nKey2, const void *pKey2
   ){
     const unsigned char *zA = (const unsigned char*)pKey1;
     const unsigned char *zB = (const unsigned char*)pKey2;
     Decimal *pA = decimal_new(0, 0, nKey1, zA);
     Decimal *pB = decimal_new(0, 0, nKey2, zB);
     int rc;
     UNUSED_PARAMETER(notUsed);
     if( pA==0 || pB==0 ){
       rc = 0;
     }else{
       rc = decimal_cmp(pA, pB);
     }
     decimal_free(pA);
     decimal_free(pB);
     return rc;
   }
   
   
   /*
   ** SQL Function:   decimal_add(X, Y)
   **                 decimal_sub(X, Y)
   **
   ** Return the sum or difference of X and Y.
   */
   static void decimalAddFunc(
     sqlite3_context *context,
     int argc,
     sqlite3_value **argv
   ){
     Decimal *pA = decimal_new(context, argv[0], 0, 0);
     Decimal *pB = decimal_new(context, argv[1], 0, 0);
     UNUSED_PARAMETER(argc);
     decimal_add(pA, pB);
     decimal_result(context, pA);
     decimal_free(pA);
     decimal_free(pB);
   }
   static void decimalSubFunc(
     sqlite3_context *context,
     int argc,
     sqlite3_value **argv
   ){
     Decimal *pA = decimal_new(context, argv[0], 0, 0);
     Decimal *pB = decimal_new(context, argv[1], 0, 0);
     UNUSED_PARAMETER(argc);
     if( pB==0 ) return;
     pB->sign = !pB->sign;
     decimal_add(pA, pB);
     decimal_result(context, pA);
     decimal_free(pA);
     decimal_free(pB);
   }
   
   /* Aggregate funcion:   decimal_sum(X)
   **
   ** Works like sum() except that it uses decimal arithmetic for unlimited
   ** precision.
   */
   static void decimalSumStep(
     sqlite3_context *context,
     int argc,
     sqlite3_value **argv
   ){
     Decimal *p;
     Decimal *pArg;
     UNUSED_PARAMETER(argc);
     p = sqlite3_aggregate_context(context, sizeof(*p));
     if( p==0 ) return;
     if( !p->isInit ){
       p->isInit = 1;
       p->a = sqlite3_malloc(2);
       if( p->a==0 ){
         p->oom = 1;
       }else{
         p->a[0] = 0;
       }
       p->nDigit = 1;
       p->nFrac = 0;
     }
     if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
     pArg = decimal_new(context, argv[0], 0, 0);
     decimal_add(p, pArg);
     decimal_free(pArg);
   }
   static void decimalSumInverse(
     sqlite3_context *context,
     int argc,
     sqlite3_value **argv
   ){
     Decimal *p;
     Decimal *pArg;
     UNUSED_PARAMETER(argc);
     p = sqlite3_aggregate_context(context, sizeof(*p));
     if( p==0 ) return;
     if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
     pArg = decimal_new(context, argv[0], 0, 0);
     if( pArg ) pArg->sign = !pArg->sign;
     decimal_add(p, pArg);
     decimal_free(pArg);
   }
   static void decimalSumValue(sqlite3_context *context){
     Decimal *p = sqlite3_aggregate_context(context, 0);
     if( p==0 ) return;
     decimal_result(context, p);
   }
   static void decimalSumFinalize(sqlite3_context *context){
     Decimal *p = sqlite3_aggregate_context(context, 0);
     if( p==0 ) return;
     decimal_result(context, p);
     decimal_clear(p);
   }
   
   /*
   ** SQL Function:   decimal_mul(X, Y)
   **
   ** Return the product of X and Y.
   **
   ** All significant digits after the decimal point are retained.
   ** Trailing zeros after the decimal point are omitted as long as
   ** the number of digits after the decimal point is no less than
   ** either the number of digits in either input.
   */
   static void decimalMulFunc(
     sqlite3_context *context,
     int argc,
     sqlite3_value **argv
   ){
     Decimal *pA = decimal_new(context, argv[0], 0, 0);
     Decimal *pB = decimal_new(context, argv[1], 0, 0);
     signed char *acc = 0;
     int i, j, k;
     int minFrac;
     UNUSED_PARAMETER(argc);
     if( pA==0 || pA->oom || pA->isNull
      || pB==0 || pB->oom || pB->isNull 
     ){
       goto mul_end;
     }
     acc = sqlite3_malloc64( pA->nDigit + pB->nDigit + 2 );
     if( acc==0 ){
       sqlite3_result_error_nomem(context);
       goto mul_end;
     }
     memset(acc, 0, pA->nDigit + pB->nDigit + 2);
     minFrac = pA->nFrac;
     if( pB->nFrac<minFrac ) minFrac = pB->nFrac;
     for(i=pA->nDigit-1; i>=0; i--){
       signed char f = pA->a[i];
       int carry = 0, x;
       for(j=pB->nDigit-1, k=i+j+3; j>=0; j--, k--){
         x = acc[k] + f*pB->a[j] + carry;
         acc[k] = x%10;
         carry = x/10;
       }
       x = acc[k] + carry;
       acc[k] = x%10;
       acc[k-1] += x/10;
     }
     sqlite3_free(pA->a);
     pA->a = acc;
     acc = 0;
     pA->nDigit += pB->nDigit + 2;
     pA->nFrac += pB->nFrac;
     pA->sign ^= pB->sign;
     while( pA->nFrac>minFrac && pA->a[pA->nDigit-1]==0 ){
       pA->nFrac--;
       pA->nDigit--;
     }
     decimal_result(context, pA);
   
   mul_end:
     sqlite3_free(acc);
     decimal_free(pA);
     decimal_free(pB);
   }
   
   #ifdef _WIN32
   
   #endif
   int sqlite3_decimal_init(
     sqlite3 *db, 
     char **pzErrMsg, 
     const sqlite3_api_routines *pApi
   ){
     int rc = SQLITE_OK;
     static const struct {
       const char *zFuncName;
       int nArg;
       void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
     } aFunc[] = {
       { "decimal",       1,   decimalFunc        },
       { "decimal_cmp",   2,   decimalCmpFunc     },
       { "decimal_add",   2,   decimalAddFunc     },
       { "decimal_sub",   2,   decimalSubFunc     },
       { "decimal_mul",   2,   decimalMulFunc     },
     };
     unsigned int i;
     (void)pzErrMsg;  /* Unused parameter */
   
     SQLITE_EXTENSION_INIT2(pApi);
   
     for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
       rc = sqlite3_create_function(db, aFunc[i].zFuncName, aFunc[i].nArg,
                      SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
                      0, aFunc[i].xFunc, 0, 0);
     }
     if( rc==SQLITE_OK ){
       rc = sqlite3_create_window_function(db, "decimal_sum", 1,
                      SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC, 0,
                      decimalSumStep, decimalSumFinalize,
                      decimalSumValue, decimalSumInverse, 0);
     }
     if( rc==SQLITE_OK ){
       rc = sqlite3_create_collation(db, "decimal", SQLITE_UTF8,
                                     0, decimalCollFunc);
     }
     return rc;
   }
   
   /************************* End ../ext/misc/decimal.c ********************/
   /************************* Begin ../ext/misc/ieee754.c ******************/
   /*
   ** 2013-04-17
   **
   ** The author disclaims copyright to this source code.  In place of
   ** a legal notice, here is a blessing:
   **
   **    May you do good and not evil.
   **    May you find forgiveness for yourself and forgive others.
   **    May you share freely, never taking more than you give.
   **
   ******************************************************************************
   **
   ** This SQLite extension implements functions for the exact display
   ** and input of IEEE754 Binary64 floating-point numbers.
   **
   **   ieee754(X)
   **   ieee754(Y,Z)
   **
   ** In the first form, the value X should be a floating-point number.
   ** The function will return a string of the form 'ieee754(Y,Z)' where
   ** Y and Z are integers such that X==Y*pow(2,Z).
   **
   ** In the second form, Y and Z are integers which are the mantissa and
   ** base-2 exponent of a new floating point number.  The function returns
   ** a floating-point value equal to Y*pow(2,Z).
   **
   ** Examples:
   **
   **     ieee754(2.0)             ->     'ieee754(2,0)'
   **     ieee754(45.25)           ->     'ieee754(181,-2)'
   **     ieee754(2, 0)            ->     2.0
   **     ieee754(181, -2)         ->     45.25
   **
   ** Two additional functions break apart the one-argument ieee754()
   ** result into separate integer values:
   **
   **     ieee754_mantissa(45.25)  ->     181
   **     ieee754_exponent(45.25)  ->     -2
   **
   ** These functions convert binary64 numbers into blobs and back again.
   **
   **     ieee754_from_blob(x'3ff0000000000000')  ->  1.0
   **     ieee754_to_blob(1.0)                    ->  x'3ff0000000000000'
   **
   ** In all single-argument functions, if the argument is an 8-byte blob
   ** then that blob is interpreted as a big-endian binary64 value.
   **
   **
   ** EXACT DECIMAL REPRESENTATION OF BINARY64 VALUES
   ** -----------------------------------------------
   **
   ** This extension in combination with the separate 'decimal' extension
   ** can be used to compute the exact decimal representation of binary64
   ** values.  To begin, first compute a table of exponent values:
   **
   **    CREATE TABLE pow2(x INTEGER PRIMARY KEY, v TEXT);
   **    WITH RECURSIVE c(x,v) AS (
   **      VALUES(0,'1')
   **      UNION ALL
   **      SELECT x+1, decimal_mul(v,'2') FROM c WHERE x+1<=971
   **    ) INSERT INTO pow2(x,v) SELECT x, v FROM c;
   **    WITH RECURSIVE c(x,v) AS (
   **      VALUES(-1,'0.5')
   **      UNION ALL
   **      SELECT x-1, decimal_mul(v,'0.5') FROM c WHERE x-1>=-1075
   **    ) INSERT INTO pow2(x,v) SELECT x, v FROM c;
   **
   ** Then, to compute the exact decimal representation of a floating
   ** point value (the value 47.49 is used in the example) do:
   **
   **    WITH c(n) AS (VALUES(47.49))
   **          ---------------^^^^^---- Replace with whatever you want
   **    SELECT decimal_mul(ieee754_mantissa(c.n),pow2.v)
   **      FROM pow2, c WHERE pow2.x=ieee754_exponent(c.n);
   **
   ** Here is a query to show various boundry values for the binary64
   ** number format:
   **
   **    WITH c(name,bin) AS (VALUES
   **       ('minimum positive value',        x'0000000000000001'),
   **       ('maximum subnormal value',       x'000fffffffffffff'),
   **       ('mininum positive nornal value', x'0010000000000000'),
   **       ('maximum value',                 x'7fefffffffffffff'))
   **    SELECT c.name, decimal_mul(ieee754_mantissa(c.bin),pow2.v)
   **      FROM pow2, c WHERE pow2.x=ieee754_exponent(c.bin);
   **
   */
   /* #include "sqlite3ext.h" */
   SQLITE_EXTENSION_INIT1
   #include <assert.h>
   #include <string.h>
   
   /* Mark a function parameter as unused, to suppress nuisance compiler
   ** warnings. */
   #ifndef UNUSED_PARAMETER
   # define UNUSED_PARAMETER(X)  (void)(X)
   #endif
   
   /*
   ** Implementation of the ieee754() function
   */
   static void ieee754func(
     sqlite3_context *context,
     int argc,
     sqlite3_value **argv
   ){
     if( argc==1 ){
       sqlite3_int64 m, a;
       double r;
       int e;
       int isNeg;
       char zResult[100];
       assert( sizeof(m)==sizeof(r) );
       if( sqlite3_value_type(argv[0])==SQLITE_BLOB
        && sqlite3_value_bytes(argv[0])==sizeof(r)
       ){
         const unsigned char *x = sqlite3_value_blob(argv[0]);
         unsigned int i;
         sqlite3_uint64 v = 0;
         for(i=0; i<sizeof(r); i++){
           v = (v<<8) | x[i];
         }
         memcpy(&r, &v, sizeof(r));
       }else{
         r = sqlite3_value_double(argv[0]);
       }
       if( r<0.0 ){
         isNeg = 1;
         r = -r;
       }else{
         isNeg = 0;
       }
       memcpy(&a,&r,sizeof(a));
       if( a==0 ){
         e = 0;
         m = 0;
       }else{
         e = a>>52;
         m = a & ((((sqlite3_int64)1)<<52)-1);
         if( e==0 ){
           m <<= 1;
         }else{
           m |= ((sqlite3_int64)1)<<52;
         }
         while( e<1075 && m>0 && (m&1)==0 ){
           m >>= 1;
           e++;
         }
         if( isNeg ) m = -m;
       }
       switch( *(int*)sqlite3_user_data(context) ){
         case 0:
           sqlite3_snprintf(sizeof(zResult), zResult, "ieee754(%lld,%d)",
                            m, e-1075);
           sqlite3_result_text(context, zResult, -1, SQLITE_TRANSIENT);
           break;
         case 1:
           sqlite3_result_int64(context, m);
           break;
         case 2:
           sqlite3_result_int(context, e-1075);
           break;
       }
     }else{
       sqlite3_int64 m, e, a;
       double r;
       int isNeg = 0;
       m = sqlite3_value_int64(argv[0]);
       e = sqlite3_value_int64(argv[1]);
   
       /* Limit the range of e.  Ticket 22dea1cfdb9151e4 2021-03-02 */
       if( e>10000 ){
         e = 10000;
       }else if( e<-10000 ){
         e = -10000;
       }
   
       if( m<0 ){
         isNeg = 1;
         m = -m;
         if( m<0 ) return;
       }else if( m==0 && e>-1000 && e<1000 ){
         sqlite3_result_double(context, 0.0);
         return;
       }
       while( (m>>32)&0xffe00000 ){
         m >>= 1;
         e++;
       }
       while( m!=0 && ((m>>32)&0xfff00000)==0 ){
         m <<= 1;
         e--;
       }
       e += 1075;
       if( e<=0 ){
         /* Subnormal */
         m >>= 1-e;
         e = 0;
       }else if( e>0x7ff ){
         e = 0x7ff;
       }
       a = m & ((((sqlite3_int64)1)<<52)-1);
       a |= e<<52;
       if( isNeg ) a |= ((sqlite3_uint64)1)<<63;
       memcpy(&r, &a, sizeof(r));
       sqlite3_result_double(context, r);
     }
   }
   
   /*
   ** Functions to convert between blobs and floats.
   */
   static void ieee754func_from_blob(
     sqlite3_context *context,
     int argc,
     sqlite3_value **argv
   ){
     UNUSED_PARAMETER(argc);
     if( sqlite3_value_type(argv[0])==SQLITE_BLOB
      && sqlite3_value_bytes(argv[0])==sizeof(double)
     ){
       double r;
       const unsigned char *x = sqlite3_value_blob(argv[0]);
       unsigned int i;
       sqlite3_uint64 v = 0;
       for(i=0; i<sizeof(r); i++){
         v = (v<<8) | x[i];
       }
       memcpy(&r, &v, sizeof(r));
       sqlite3_result_double(context, r);
     }
   }
   static void ieee754func_to_blob(
     sqlite3_context *context,
     int argc,
     sqlite3_value **argv
   ){
     UNUSED_PARAMETER(argc);
     if( sqlite3_value_type(argv[0])==SQLITE_FLOAT
      || sqlite3_value_type(argv[0])==SQLITE_INTEGER
     ){
       double r = sqlite3_value_double(argv[0]);
       sqlite3_uint64 v;
       unsigned char a[sizeof(r)];
       unsigned int i;
       memcpy(&v, &r, sizeof(r));
       for(i=1; i<=sizeof(r); i++){
         a[sizeof(r)-i] = v&0xff;
         v >>= 8;
       }
       sqlite3_result_blob(context, a, sizeof(r), SQLITE_TRANSIENT);
     }
   }
   
   
   #ifdef _WIN32
   
   #endif
   int sqlite3_ieee_init(
     sqlite3 *db, 
     char **pzErrMsg, 
     const sqlite3_api_routines *pApi
   ){
     static const struct {
       char *zFName;
       int nArg;
       int iAux;
       void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
     } aFunc[] = {
       { "ieee754",           1,   0, ieee754func },
       { "ieee754",           2,   0, ieee754func },
       { "ieee754_mantissa",  1,   1, ieee754func },
       { "ieee754_exponent",  1,   2, ieee754func },
       { "ieee754_to_blob",   1,   0, ieee754func_to_blob },
       { "ieee754_from_blob", 1,   0, ieee754func_from_blob },
   
     };
     unsigned int i;
     int rc = SQLITE_OK;
     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,    
                                  SQLITE_UTF8|SQLITE_INNOCUOUS,
                                  (void*)&aFunc[i].iAux,
                                  aFunc[i].xFunc, 0, 0);
     }
     return rc;
   }
   
   /************************* End ../ext/misc/ieee754.c ********************/
   /************************* Begin ../ext/misc/series.c ******************/
   /*
   ** 2015-08-18
   **
   ** The author disclaims copyright to this source code.  In place of
   ** a legal notice, here is a blessing:
   **
   **    May you do good and not evil.
   **    May you find forgiveness for yourself and forgive others.
   **    May you share freely, never taking more than you give.
   **
   *************************************************************************
   **
   ** This file demonstrates how to create a table-valued-function using
   ** a virtual table.  This demo implements the generate_series() function
   ** which gives similar results to the eponymous function in PostgreSQL.
   ** Examples:
   **
   **      SELECT * FROM generate_series(0,100,5);
   **
   ** The query above returns integers from 0 through 100 counting by steps
   ** of 5.
   **
   **      SELECT * FROM generate_series(0,100);
   **
   ** Integers from 0 through 100 with a step size of 1.
   **
   **      SELECT * FROM generate_series(20) LIMIT 10;
   **
   ** Integers 20 through 29.
   **
   ** HOW IT WORKS
   **
   ** The generate_series "function" is really a virtual table with the
   ** following schema:
   **
   **     CREATE TABLE generate_series(
   **       value,
   **       start HIDDEN,
   **       stop HIDDEN,
   **       step HIDDEN
   **     );
   **
   ** Function arguments in queries against this virtual table are translated
   ** into equality constraints against successive hidden columns.  In other
   ** words, the following pairs of queries are equivalent to each other:
   **
   **    SELECT * FROM generate_series(0,100,5);
   **    SELECT * FROM generate_series WHERE start=0 AND stop=100 AND step=5;
   **
   **    SELECT * FROM generate_series(0,100);
   **    SELECT * FROM generate_series WHERE start=0 AND stop=100;
   **
   **    SELECT * FROM generate_series(20) LIMIT 10;
   **    SELECT * FROM generate_series WHERE start=20 LIMIT 10;
   **
   ** The generate_series virtual table implementation leaves the xCreate method
   ** set to NULL.  This means that it is not possible to do a CREATE VIRTUAL
   ** TABLE command with "generate_series" as the USING argument.  Instead, there
   ** is a single generate_series virtual table that is always available without
   ** having to be created first.
   **
   ** The xBestIndex method looks for equality constraints against the hidden
   ** start, stop, and step columns, and if present, it uses those constraints
   ** to bound the sequence of generated values.  If the equality constraints
   ** are missing, it uses 0 for start, 4294967295 for stop, and 1 for step.
   ** xBestIndex returns a small cost when both start and stop are available,
   ** and a very large cost if either start or stop are unavailable.  This
   ** encourages the query planner to order joins such that the bounds of the
   ** series are well-defined.
   */
   /* #include "sqlite3ext.h" */
   SQLITE_EXTENSION_INIT1
   #include <assert.h>
   #include <string.h>
   
   #ifndef SQLITE_OMIT_VIRTUALTABLE
   
   
   /* series_cursor is a subclass of sqlite3_vtab_cursor which will
   ** serve as the underlying representation of a cursor that scans
   ** over rows of the result
   */
   typedef struct series_cursor series_cursor;
   struct series_cursor {
     sqlite3_vtab_cursor base;  /* Base class - must be first */
     int isDesc;                /* True to count down rather than up */
     sqlite3_int64 iRowid;      /* The rowid */
     sqlite3_int64 iValue;      /* Current value ("value") */
     sqlite3_int64 mnValue;     /* Mimimum value ("start") */
     sqlite3_int64 mxValue;     /* Maximum value ("stop") */
     sqlite3_int64 iStep;       /* Increment ("step") */
   };
   
   /*
   ** The seriesConnect() method is invoked to create a new
   ** series_vtab that describes the generate_series virtual table.
   **
   ** Think of this routine as the constructor for series_vtab objects.
   **
   ** All this routine needs to do is:
   **
   **    (1) Allocate the series_vtab object and initialize all fields.
   **
   **    (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
   **        result set of queries against generate_series will look like.
   */
   static int seriesConnect(
     sqlite3 *db,
     void *pUnused,
     int argcUnused, const char *const*argvUnused,
     sqlite3_vtab **ppVtab,
     char **pzErrUnused
   ){
     sqlite3_vtab *pNew;
     int rc;
   
   /* Column numbers */
   #define SERIES_COLUMN_VALUE 0
   #define SERIES_COLUMN_START 1
   #define SERIES_COLUMN_STOP  2
   #define SERIES_COLUMN_STEP  3
   
     (void)pUnused;
     (void)argcUnused;
     (void)argvUnused;
     (void)pzErrUnused;
     rc = sqlite3_declare_vtab(db,
        "CREATE TABLE x(value,start hidden,stop hidden,step hidden)");
     if( rc==SQLITE_OK ){
       pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) );
       if( pNew==0 ) return SQLITE_NOMEM;
       memset(pNew, 0, sizeof(*pNew));
       sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
     }
     return rc;
   }
   
   /*
   ** This method is the destructor for series_cursor objects.
   */
   static int seriesDisconnect(sqlite3_vtab *pVtab){
     sqlite3_free(pVtab);
     return SQLITE_OK;
   }
   
   /*
   ** Constructor for a new series_cursor object.
   */
   static int seriesOpen(sqlite3_vtab *pUnused, sqlite3_vtab_cursor **ppCursor){
     series_cursor *pCur;
     (void)pUnused;
     pCur = sqlite3_malloc( sizeof(*pCur) );
     if( pCur==0 ) return SQLITE_NOMEM;
     memset(pCur, 0, sizeof(*pCur));
     *ppCursor = &pCur->base;
     return SQLITE_OK;
   }
   
   /*
   ** Destructor for a series_cursor.
   */
   static int seriesClose(sqlite3_vtab_cursor *cur){
     sqlite3_free(cur);
     return SQLITE_OK;
   }
   
   
   /*
   ** Advance a series_cursor to its next row of output.
   */
   static int seriesNext(sqlite3_vtab_cursor *cur){
     series_cursor *pCur = (series_cursor*)cur;
     if( pCur->isDesc ){
       pCur->iValue -= pCur->iStep;
     }else{
       pCur->iValue += pCur->iStep;
     }
     pCur->iRowid++;
     return SQLITE_OK;
   }
   
   /*
   ** Return values of columns for the row at which the series_cursor
   ** is currently pointing.
   */
   static int seriesColumn(
     sqlite3_vtab_cursor *cur,   /* The cursor */
     sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
     int i                       /* Which column to return */
   ){
     series_cursor *pCur = (series_cursor*)cur;
     sqlite3_int64 x = 0;
     switch( i ){
       case SERIES_COLUMN_START:  x = pCur->mnValue; break;
       case SERIES_COLUMN_STOP:   x = pCur->mxValue; break;
       case SERIES_COLUMN_STEP:   x = pCur->iStep;   break;
       default:                   x = pCur->iValue;  break;
     }
     sqlite3_result_int64(ctx, x);
     return SQLITE_OK;
   }
   
   /*
   ** Return the rowid for the current row. In this implementation, the
   ** first row returned is assigned rowid value 1, and each subsequent
   ** row a value 1 more than that of the previous.
   */
   static int seriesRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
     series_cursor *pCur = (series_cursor*)cur;
     *pRowid = pCur->iRowid;
     return SQLITE_OK;
   }
   
   /*
   ** Return TRUE if the cursor has been moved off of the last
   ** row of output.
   */
   static int seriesEof(sqlite3_vtab_cursor *cur){
     series_cursor *pCur = (series_cursor*)cur;
     if( pCur->isDesc ){
       return pCur->iValue < pCur->mnValue;
     }else{
       return pCur->iValue > pCur->mxValue;
     }
   }
   
   /* True to cause run-time checking of the start=, stop=, and/or step= 
   ** parameters.  The only reason to do this is for testing the
   ** constraint checking logic for virtual tables in the SQLite core.
   */
   #ifndef SQLITE_SERIES_CONSTRAINT_VERIFY
   # define SQLITE_SERIES_CONSTRAINT_VERIFY 0
   #endif
   
   /*
   ** This method is called to "rewind" the series_cursor object back
   ** to the first row of output.  This method is always called at least
   ** once prior to any call to seriesColumn() or seriesRowid() or 
   ** seriesEof().
   **
   ** The query plan selected by seriesBestIndex is passed in the idxNum
   ** parameter.  (idxStr is not used in this implementation.)  idxNum
   ** is a bitmask showing which constraints are available:
   **
   **    1:    start=VALUE
   **    2:    stop=VALUE
   **    4:    step=VALUE
   **
   ** Also, if bit 8 is set, that means that the series should be output
   ** in descending order rather than in ascending order.  If bit 16 is
   ** set, then output must appear in ascending order.
   **
   ** This routine should initialize the cursor and position it so that it
   ** is pointing at the first row, or pointing off the end of the table
   ** (so that seriesEof() will return true) if the table is empty.
   */
   static int seriesFilter(
     sqlite3_vtab_cursor *pVtabCursor, 
     int idxNum, const char *idxStrUnused,
     int argc, sqlite3_value **argv
   ){
     series_cursor *pCur = (series_cursor *)pVtabCursor;
     int i = 0;
     (void)idxStrUnused;
     if( idxNum & 1 ){
       pCur->mnValue = sqlite3_value_int64(argv[i++]);
     }else{
       pCur->mnValue = 0;
     }
     if( idxNum & 2 ){
       pCur->mxValue = sqlite3_value_int64(argv[i++]);
     }else{
       pCur->mxValue = 0xffffffff;
     }
     if( idxNum & 4 ){
       pCur->iStep = sqlite3_value_int64(argv[i++]);
       if( pCur->iStep==0 ){
         pCur->iStep = 1;
       }else if( pCur->iStep<0 ){
         pCur->iStep = -pCur->iStep;
         if( (idxNum & 16)==0 ) idxNum |= 8;
       }
     }else{
       pCur->iStep = 1;
     }
     for(i=0; i<argc; i++){
       if( sqlite3_value_type(argv[i])==SQLITE_NULL ){
         /* If any of the constraints have a NULL value, then return no rows.
         ** See ticket https://www.sqlite.org/src/info/fac496b61722daf2 */
         pCur->mnValue = 1;
         pCur->mxValue = 0;
         break;
       }
     }
     if( idxNum & 8 ){
       pCur->isDesc = 1;
       pCur->iValue = pCur->mxValue;
       if( pCur->iStep>0 ){
         pCur->iValue -= (pCur->mxValue - pCur->mnValue)%pCur->iStep;
       }
     }else{
       pCur->isDesc = 0;
       pCur->iValue = pCur->mnValue;
     }
     pCur->iRowid = 1;
     return SQLITE_OK;
   }
   
   /*
   ** SQLite will invoke this method one or more times while planning a query
   ** that uses the generate_series virtual table.  This routine needs to create
   ** a query plan for each invocation and compute an estimated cost for that
   ** plan.
   **
   ** In this implementation idxNum is used to represent the
   ** query plan.  idxStr is unused.
   **
   ** The query plan is represented by bits in idxNum:
   **
   **  (1)  start = $value  -- constraint exists
   **  (2)  stop = $value   -- constraint exists
   **  (4)  step = $value   -- constraint exists
   **  (8)  output in descending order
   */
   static int seriesBestIndex(
     sqlite3_vtab *tabUnused,
     sqlite3_index_info *pIdxInfo
   ){
     int i, j;              /* Loop over constraints */
     int idxNum = 0;        /* The query plan bitmask */
     int unusableMask = 0;  /* Mask of unusable constraints */
     int nArg = 0;          /* Number of arguments that seriesFilter() expects */
     int aIdx[3];           /* Constraints on start, stop, and step */
     const struct sqlite3_index_constraint *pConstraint;
   
     /* This implementation assumes that the start, stop, and step columns
     ** are the last three columns in the virtual table. */
     assert( SERIES_COLUMN_STOP == SERIES_COLUMN_START+1 );
     assert( SERIES_COLUMN_STEP == SERIES_COLUMN_START+2 );
     (void)tabUnused;
     aIdx[0] = aIdx[1] = aIdx[2] = -1;
     pConstraint = pIdxInfo->aConstraint;
     for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
       int iCol;    /* 0 for start, 1 for stop, 2 for step */
       int iMask;   /* bitmask for those column */
       if( pConstraint->iColumn<SERIES_COLUMN_START ) continue;
       iCol = pConstraint->iColumn - SERIES_COLUMN_START;
       assert( iCol>=0 && iCol<=2 );
       iMask = 1 << iCol;
       if( pConstraint->usable==0 ){
         unusableMask |=  iMask;
         continue;
       }else if( pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
         idxNum |= iMask;
         aIdx[iCol] = i;
       }
     }
     for(i=0; i<3; i++){
       if( (j = aIdx[i])>=0 ){
         pIdxInfo->aConstraintUsage[j].argvIndex = ++nArg;
         pIdxInfo->aConstraintUsage[j].omit = !SQLITE_SERIES_CONSTRAINT_VERIFY;
       }
     }
     if( (unusableMask & ~idxNum)!=0 ){
       /* The start, stop, and step columns are inputs.  Therefore if there
       ** are unusable constraints on any of start, stop, or step then
       ** this plan is unusable */
       return SQLITE_CONSTRAINT;
     }
     if( (idxNum & 3)==3 ){
       /* Both start= and stop= boundaries are available.  This is the 
       ** the preferred case */
       pIdxInfo->estimatedCost = (double)(2 - ((idxNum&4)!=0));
       pIdxInfo->estimatedRows = 1000;
       if( pIdxInfo->nOrderBy==1 ){
         if( pIdxInfo->aOrderBy[0].desc ){
           idxNum |= 8;
         }else{
           idxNum |= 16;
         }
         pIdxInfo->orderByConsumed = 1;
       }
     }else{
       /* If either boundary is missing, we have to generate a huge span
       ** of numbers.  Make this case very expensive so that the query
       ** planner will work hard to avoid it. */
       pIdxInfo->estimatedRows = 2147483647;
     }
     pIdxInfo->idxNum = idxNum;
     return SQLITE_OK;
   }
   
   /*
   ** This following structure defines all the methods for the 
   ** generate_series virtual table.
   */
   static sqlite3_module seriesModule = {
     0,                         /* iVersion */
     0,                         /* xCreate */
     seriesConnect,             /* xConnect */
     seriesBestIndex,           /* xBestIndex */
     seriesDisconnect,          /* xDisconnect */
     0,                         /* xDestroy */
     seriesOpen,                /* xOpen - open a cursor */
     seriesClose,               /* xClose - close a cursor */
     seriesFilter,              /* xFilter - configure scan constraints */
     seriesNext,                /* xNext - advance a cursor */
     seriesEof,                 /* xEof - check for end of scan */
     seriesColumn,              /* xColumn - read data */
     seriesRowid,               /* xRowid - read data */
     0,                         /* xUpdate */
     0,                         /* xBegin */
     0,                         /* xSync */
     0,                         /* xCommit */
     0,                         /* xRollback */
     0,                         /* xFindMethod */
     0,                         /* xRename */
     0,                         /* xSavepoint */
     0,                         /* xRelease */
     0,                         /* xRollbackTo */
     0                          /* xShadowName */
   };
   
   #endif /* SQLITE_OMIT_VIRTUALTABLE */
   
   #ifdef _WIN32
   
   #endif
   int sqlite3_series_init(
     sqlite3 *db, 
     char **pzErrMsg, 
     const sqlite3_api_routines *pApi
   ){
     int rc = SQLITE_OK;
     SQLITE_EXTENSION_INIT2(pApi);
   #ifndef SQLITE_OMIT_VIRTUALTABLE
     if( sqlite3_libversion_number()<3008012 ){
       *pzErrMsg = sqlite3_mprintf(
           "generate_series() requires SQLite 3.8.12 or later");
       return SQLITE_ERROR;
     }
     rc = sqlite3_create_module(db, "generate_series", &seriesModule, 0);
   #endif
     return rc;
   }
   
   /************************* End ../ext/misc/series.c ********************/
   #ifdef SQLITE_HAVE_ZLIB
   /************************* Begin ../ext/misc/zipfile.c ******************/
   /*
   ** 2017-12-26
   **
   ** The author disclaims copyright to this source code.  In place of
   ** a legal notice, here is a blessing:
   **
   **    May you do good and not evil.
   **    May you find forgiveness for yourself and forgive others.
   **    May you share freely, never taking more than you give.
   **
   ******************************************************************************
   **
   ** This file implements a virtual table for reading and writing ZIP archive
   ** files.
   **
   ** Usage example:
   **
   **     SELECT name, sz, datetime(mtime,'unixepoch') FROM zipfile($filename);
   **
   ** Current limitations:
   **
   **    *  No support for encryption
   **    *  No support for ZIP archives spanning multiple files
   **    *  No support for zip64 extensions
   **    *  Only the "inflate/deflate" (zlib) compression method is supported
   */
   /* #include "sqlite3ext.h" */
   SQLITE_EXTENSION_INIT1
   #include <stdio.h>
   #include <string.h>
   #include <assert.h>
   
   #include <zlib.h>
   
   #ifndef SQLITE_OMIT_VIRTUALTABLE
   
   #ifndef SQLITE_AMALGAMATION
   
   /* typedef sqlite3_int64 i64; */
   /* typedef unsigned char u8; */
   typedef unsigned short u16;
   typedef unsigned long u32;
   #define MIN(a,b) ((a)<(b) ? (a) : (b))
   
   #if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
   # define ALWAYS(X)      (1)
   # define NEVER(X)       (0)
   #elif !defined(NDEBUG)
   # define ALWAYS(X)      ((X)?1:(assert(0),0))
   # define NEVER(X)       ((X)?(assert(0),1):0)
   #else
   # define ALWAYS(X)      (X)
   # define NEVER(X)       (X)
   #endif
   
   #endif   /* SQLITE_AMALGAMATION */
   
   /*
   ** Definitions for mode bitmasks S_IFDIR, S_IFREG and S_IFLNK.
   **
   ** In some ways it would be better to obtain these values from system 
   ** header files. But, the dependency is undesirable and (a) these
   ** have been stable for decades, (b) the values are part of POSIX and
   ** are also made explicit in [man stat], and (c) are part of the 
   ** file format for zip archives.
   */
   #ifndef S_IFDIR
   # define S_IFDIR 0040000
   #endif
   #ifndef S_IFREG
   # define S_IFREG 0100000
   #endif
   #ifndef S_IFLNK
   # define S_IFLNK 0120000
   #endif
   
   static const char ZIPFILE_SCHEMA[] = 
     "CREATE TABLE y("
       "name PRIMARY KEY,"  /* 0: Name of file in zip archive */
       "mode,"              /* 1: POSIX mode for file */
       "mtime,"             /* 2: Last modification time (secs since 1970)*/
       "sz,"                /* 3: Size of object */
       "rawdata,"           /* 4: Raw data */
       "data,"              /* 5: Uncompressed data */
       "method,"            /* 6: Compression method (integer) */
       "z HIDDEN"           /* 7: Name of zip file */
     ") WITHOUT ROWID;";
   
   #define ZIPFILE_F_COLUMN_IDX 7    /* Index of column "file" in the above */
   #define ZIPFILE_BUFFER_SIZE (64*1024)
   
   
   /*
   ** Magic numbers used to read and write zip files.
   **
   ** ZIPFILE_NEWENTRY_MADEBY:
   **   Use this value for the "version-made-by" field in new zip file
   **   entries. The upper byte indicates "unix", and the lower byte 
   **   indicates that the zip file matches pkzip specification 3.0. 
   **   This is what info-zip seems to do.
   **
   ** ZIPFILE_NEWENTRY_REQUIRED:
   **   Value for "version-required-to-extract" field of new entries.
   **   Version 2.0 is required to support folders and deflate compression.
   **
   ** ZIPFILE_NEWENTRY_FLAGS:
   **   Value for "general-purpose-bit-flags" field of new entries. Bit
   **   11 means "utf-8 filename and comment".
   **
   ** ZIPFILE_SIGNATURE_CDS:
   **   First 4 bytes of a valid CDS record.
   **
   ** ZIPFILE_SIGNATURE_LFH:
   **   First 4 bytes of a valid LFH record.
   **
   ** ZIPFILE_SIGNATURE_EOCD
   **   First 4 bytes of a valid EOCD record.
   */
   #define ZIPFILE_EXTRA_TIMESTAMP   0x5455
   #define ZIPFILE_NEWENTRY_MADEBY   ((3<<8) + 30)
   #define ZIPFILE_NEWENTRY_REQUIRED 20
   #define ZIPFILE_NEWENTRY_FLAGS    0x800
   #define ZIPFILE_SIGNATURE_CDS     0x02014b50
   #define ZIPFILE_SIGNATURE_LFH     0x04034b50
   #define ZIPFILE_SIGNATURE_EOCD    0x06054b50
   
   /*
   ** The sizes of the fixed-size part of each of the three main data 
   ** structures in a zip archive.
   */
   #define ZIPFILE_LFH_FIXED_SZ      30
   #define ZIPFILE_EOCD_FIXED_SZ     22
   #define ZIPFILE_CDS_FIXED_SZ      46
   
   /*
   *** 4.3.16  End of central directory record:
   ***
   ***   end of central dir signature    4 bytes  (0x06054b50)
   ***   number of this disk             2 bytes
   ***   number of the disk with the
   ***   start of the central directory  2 bytes
   ***   total number of entries in the
   ***   central directory on this disk  2 bytes
   ***   total number of entries in
   ***   the central directory           2 bytes
   ***   size of the central directory   4 bytes
   ***   offset of start of central
   ***   directory with respect to
   ***   the starting disk number        4 bytes
   ***   .ZIP file comment length        2 bytes
   ***   .ZIP file comment       (variable size)
   */
   typedef struct ZipfileEOCD ZipfileEOCD;
   struct ZipfileEOCD {
     u16 iDisk;
     u16 iFirstDisk;
     u16 nEntry;
     u16 nEntryTotal;
     u32 nSize;
     u32 iOffset;
   };
   
   /*
   *** 4.3.12  Central directory structure:
   ***
   *** ...
   ***
   ***   central file header signature   4 bytes  (0x02014b50)
   ***   version made by                 2 bytes
   ***   version needed to extract       2 bytes
   ***   general purpose bit flag        2 bytes
   ***   compression method              2 bytes
   ***   last mod file time              2 bytes
   ***   last mod file date              2 bytes
   ***   crc-32                          4 bytes
   ***   compressed size                 4 bytes
   ***   uncompressed size               4 bytes
   ***   file name length                2 bytes
   ***   extra field length              2 bytes
   ***   file comment length             2 bytes
   ***   disk number start               2 bytes
   ***   internal file attributes        2 bytes
   ***   external file attributes        4 bytes
   ***   relative offset of local header 4 bytes
   */
   typedef struct ZipfileCDS ZipfileCDS;
   struct ZipfileCDS {
     u16 iVersionMadeBy;
     u16 iVersionExtract;
     u16 flags;
     u16 iCompression;
     u16 mTime;
     u16 mDate;
     u32 crc32;
     u32 szCompressed;
     u32 szUncompressed;
     u16 nFile;
     u16 nExtra;
     u16 nComment;
     u16 iDiskStart;
     u16 iInternalAttr;
     u32 iExternalAttr;
     u32 iOffset;
     char *zFile;                    /* Filename (sqlite3_malloc()) */
   };
   
   /*
   *** 4.3.7  Local file header:
   ***
   ***   local file header signature     4 bytes  (0x04034b50)
   ***   version needed to extract       2 bytes
   ***   general purpose bit flag        2 bytes
   ***   compression method              2 bytes
   ***   last mod file time              2 bytes
   ***   last mod file date              2 bytes
   ***   crc-32                          4 bytes
   ***   compressed size                 4 bytes
   ***   uncompressed size               4 bytes
   ***   file name length                2 bytes
   ***   extra field length              2 bytes
   ***   
   */
   typedef struct ZipfileLFH ZipfileLFH;
   struct ZipfileLFH {
     u16 iVersionExtract;
     u16 flags;
     u16 iCompression;
     u16 mTime;
     u16 mDate;
     u32 crc32;
     u32 szCompressed;
     u32 szUncompressed;
     u16 nFile;
     u16 nExtra;
   };
   
   typedef struct ZipfileEntry ZipfileEntry;
   struct ZipfileEntry {
     ZipfileCDS cds;            /* Parsed CDS record */
     u32 mUnixTime;             /* Modification time, in UNIX format */
     u8 *aExtra;                /* cds.nExtra+cds.nComment bytes of extra data */
     i64 iDataOff;              /* Offset to data in file (if aData==0) */
     u8 *aData;                 /* cds.szCompressed bytes of compressed data */
     ZipfileEntry *pNext;       /* Next element in in-memory CDS */
   };
   
   /* 
   ** Cursor type for zipfile tables.
   */
   typedef struct ZipfileCsr ZipfileCsr;
   struct ZipfileCsr {
     sqlite3_vtab_cursor base;  /* Base class - must be first */
     i64 iId;                   /* Cursor ID */
     u8 bEof;                   /* True when at EOF */
     u8 bNoop;                  /* If next xNext() call is no-op */
   
     /* Used outside of write transactions */
     FILE *pFile;               /* Zip file */
     i64 iNextOff;              /* Offset of next record in central directory */
     ZipfileEOCD eocd;          /* Parse of central directory record */
   
     ZipfileEntry *pFreeEntry;  /* Free this list when cursor is closed or reset */
     ZipfileEntry *pCurrent;    /* Current entry */
     ZipfileCsr *pCsrNext;      /* Next cursor on same virtual table */
   };
   
   typedef struct ZipfileTab ZipfileTab;
   struct ZipfileTab {
     sqlite3_vtab base;         /* Base class - must be first */
     char *zFile;               /* Zip file this table accesses (may be NULL) */
     sqlite3 *db;               /* Host database connection */
     u8 *aBuffer;               /* Temporary buffer used for various tasks */
   
     ZipfileCsr *pCsrList;      /* List of cursors */
     i64 iNextCsrid;
   
     /* The following are used by write transactions only */
     ZipfileEntry *pFirstEntry; /* Linked list of all files (if pWriteFd!=0) */
     ZipfileEntry *pLastEntry;  /* Last element in pFirstEntry list */
     FILE *pWriteFd;            /* File handle open on zip archive */
     i64 szCurrent;             /* Current size of zip archive */
     i64 szOrig;                /* Size of archive at start of transaction */
   };
   
   /*
   ** Set the error message contained in context ctx to the results of
   ** vprintf(zFmt, ...).
   */
   static void zipfileCtxErrorMsg(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 string zIn is quoted, dequote it in place. Otherwise, if the string
   ** is not quoted, do nothing.
   */
   static void zipfileDequote(char *zIn){
     char q = zIn[0];
     if( q=='"' || q=='\'' || q=='`' || q=='[' ){
       int iIn = 1;
       int iOut = 0;
       if( q=='[' ) q = ']';
       while( ALWAYS(zIn[iIn]) ){
         char c = zIn[iIn++];
         if( c==q && zIn[iIn++]!=q ) break;
         zIn[iOut++] = c;
       }
       zIn[iOut] = '\0';
     }
   }
   
   /*
   ** Construct a new ZipfileTab virtual table object.
   ** 
   **   argv[0]   -> module name  ("zipfile")
   **   argv[1]   -> database name
   **   argv[2]   -> table name
   **   argv[...] -> "column name" and other module argument fields.
   */
   static int zipfileConnect(
     sqlite3 *db,
     void *pAux,
     int argc, const char *const*argv,
     sqlite3_vtab **ppVtab,
     char **pzErr
   ){
     int nByte = sizeof(ZipfileTab) + ZIPFILE_BUFFER_SIZE;
     int nFile = 0;
     const char *zFile = 0;
     ZipfileTab *pNew = 0;
     int rc;
   
     /* If the table name is not "zipfile", require that the argument be
     ** specified. This stops zipfile tables from being created as:
     **
     **   CREATE VIRTUAL TABLE zzz USING zipfile();
     **
     ** It does not prevent:
     **
     **   CREATE VIRTUAL TABLE zipfile USING zipfile();
     */
     assert( 0==sqlite3_stricmp(argv[0], "zipfile") );
     if( (0!=sqlite3_stricmp(argv[2], "zipfile") && argc<4) || argc>4 ){
       *pzErr = sqlite3_mprintf("zipfile constructor requires one argument");
       return SQLITE_ERROR;
     }
   
     if( argc>3 ){
       zFile = argv[3];
       nFile = (int)strlen(zFile)+1;
     }
   
     rc = sqlite3_declare_vtab(db, ZIPFILE_SCHEMA);
     if( rc==SQLITE_OK ){
       pNew = (ZipfileTab*)sqlite3_malloc64((sqlite3_int64)nByte+nFile);
       if( pNew==0 ) return SQLITE_NOMEM;
       memset(pNew, 0, nByte+nFile);
       pNew->db = db;
       pNew->aBuffer = (u8*)&pNew[1];
       if( zFile ){
         pNew->zFile = (char*)&pNew->aBuffer[ZIPFILE_BUFFER_SIZE];
         memcpy(pNew->zFile, zFile, nFile);
         zipfileDequote(pNew->zFile);
       }
     }
     sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY);
     *ppVtab = (sqlite3_vtab*)pNew;
     return rc;
   }
   
   /*
   ** Free the ZipfileEntry structure indicated by the only argument.
   */
   static void zipfileEntryFree(ZipfileEntry *p){
     if( p ){
       sqlite3_free(p->cds.zFile);
       sqlite3_free(p);
     }
   }
   
   /*
   ** Release resources that should be freed at the end of a write 
   ** transaction.
   */
   static void zipfileCleanupTransaction(ZipfileTab *pTab){
     ZipfileEntry *pEntry;
     ZipfileEntry *pNext;
   
     if( pTab->pWriteFd ){
       fclose(pTab->pWriteFd);
       pTab->pWriteFd = 0;
     }
     for(pEntry=pTab->pFirstEntry; pEntry; pEntry=pNext){
       pNext = pEntry->pNext;
       zipfileEntryFree(pEntry);
     }
     pTab->pFirstEntry = 0;
     pTab->pLastEntry = 0;
     pTab->szCurrent = 0;
     pTab->szOrig = 0;
   }
   
   /*
   ** This method is the destructor for zipfile vtab objects.
   */
   static int zipfileDisconnect(sqlite3_vtab *pVtab){
     zipfileCleanupTransaction((ZipfileTab*)pVtab);
     sqlite3_free(pVtab);
     return SQLITE_OK;
   }
   
   /*
   ** Constructor for a new ZipfileCsr object.
   */
   static int zipfileOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCsr){
     ZipfileTab *pTab = (ZipfileTab*)p;
     ZipfileCsr *pCsr;
     pCsr = sqlite3_malloc(sizeof(*pCsr));
     *ppCsr = (sqlite3_vtab_cursor*)pCsr;
     if( pCsr==0 ){
       return SQLITE_NOMEM;
     }
     memset(pCsr, 0, sizeof(*pCsr));
     pCsr->iId = ++pTab->iNextCsrid;
     pCsr->pCsrNext = pTab->pCsrList;
     pTab->pCsrList = pCsr;
     return SQLITE_OK;
   }
   
   /*
   ** Reset a cursor back to the state it was in when first returned
   ** by zipfileOpen().
   */
   static void zipfileResetCursor(ZipfileCsr *pCsr){
     ZipfileEntry *p;
     ZipfileEntry *pNext;
   
     pCsr->bEof = 0;
     if( pCsr->pFile ){
       fclose(pCsr->pFile);
       pCsr->pFile = 0;
       zipfileEntryFree(pCsr->pCurrent);
       pCsr->pCurrent = 0;
     }
   
     for(p=pCsr->pFreeEntry; p; p=pNext){
       pNext = p->pNext;
       zipfileEntryFree(p);
     }
   }
   
   /*
   ** Destructor for an ZipfileCsr.
   */
   static int zipfileClose(sqlite3_vtab_cursor *cur){
     ZipfileCsr *pCsr = (ZipfileCsr*)cur;
     ZipfileTab *pTab = (ZipfileTab*)(pCsr->base.pVtab);
     ZipfileCsr **pp;
     zipfileResetCursor(pCsr);
   
     /* Remove this cursor from the ZipfileTab.pCsrList list. */
     for(pp=&pTab->pCsrList; *pp!=pCsr; pp=&((*pp)->pCsrNext));
     *pp = pCsr->pCsrNext;
   
     sqlite3_free(pCsr);
     return SQLITE_OK;
   }
   
   /*
   ** Set the error message for the virtual table associated with cursor
   ** pCsr to the results of vprintf(zFmt, ...).
   */
   static void zipfileTableErr(ZipfileTab *pTab, const char *zFmt, ...){
     va_list ap;
     va_start(ap, zFmt);
     sqlite3_free(pTab->base.zErrMsg);
     pTab->base.zErrMsg = sqlite3_vmprintf(zFmt, ap);
     va_end(ap);
   }
   static void zipfileCursorErr(ZipfileCsr *pCsr, const char *zFmt, ...){
     va_list ap;
     va_start(ap, zFmt);
     sqlite3_free(pCsr->base.pVtab->zErrMsg);
     pCsr->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap);
     va_end(ap);
   }
   
   /*
   ** Read nRead bytes of data from offset iOff of file pFile into buffer
   ** aRead[]. Return SQLITE_OK if successful, or an SQLite error code
   ** otherwise. 
   **
   ** If an error does occur, output variable (*pzErrmsg) may be set to point
   ** to an English language error message. It is the responsibility of the
   ** caller to eventually free this buffer using
   ** sqlite3_free().
   */
   static int zipfileReadData(
     FILE *pFile,                    /* Read from this file */
     u8 *aRead,                      /* Read into this buffer */
     int nRead,                      /* Number of bytes to read */
     i64 iOff,                       /* Offset to read from */
     char **pzErrmsg                 /* OUT: Error message (from sqlite3_malloc) */
   ){
     size_t n;
     fseek(pFile, (long)iOff, SEEK_SET);
     n = fread(aRead, 1, nRead, pFile);
     if( (int)n!=nRead ){
       *pzErrmsg = sqlite3_mprintf("error in fread()");
       return SQLITE_ERROR;
     }
     return SQLITE_OK;
   }
   
   static int zipfileAppendData(
     ZipfileTab *pTab,
     const u8 *aWrite,
     int nWrite
   ){
     if( nWrite>0 ){
       size_t n = nWrite;
       fseek(pTab->pWriteFd, (long)pTab->szCurrent, SEEK_SET);
       n = fwrite(aWrite, 1, nWrite, pTab->pWriteFd);
       if( (int)n!=nWrite ){
         pTab->base.zErrMsg = sqlite3_mprintf("error in fwrite()");
         return SQLITE_ERROR;
       }
       pTab->szCurrent += nWrite;
     }
     return SQLITE_OK;
   }
   
   /*
   ** Read and return a 16-bit little-endian unsigned integer from buffer aBuf.
   */
   static u16 zipfileGetU16(const u8 *aBuf){
     return (aBuf[1] << 8) + aBuf[0];
   }
   
   /*
   ** Read and return a 32-bit little-endian unsigned integer from buffer aBuf.
   */
   static u32 zipfileGetU32(const u8 *aBuf){
     return ((u32)(aBuf[3]) << 24)
          + ((u32)(aBuf[2]) << 16)
          + ((u32)(aBuf[1]) <<  8)
          + ((u32)(aBuf[0]) <<  0);
   }
   
   /*
   ** Write a 16-bit little endiate integer into buffer aBuf.
   */
   static void zipfilePutU16(u8 *aBuf, u16 val){
     aBuf[0] = val & 0xFF;
     aBuf[1] = (val>>8) & 0xFF;
   }
   
   /*
   ** Write a 32-bit little endiate integer into buffer aBuf.
   */
   static void zipfilePutU32(u8 *aBuf, u32 val){
     aBuf[0] = val & 0xFF;
     aBuf[1] = (val>>8) & 0xFF;
     aBuf[2] = (val>>16) & 0xFF;
     aBuf[3] = (val>>24) & 0xFF;
   }
   
   #define zipfileRead32(aBuf) ( aBuf+=4, zipfileGetU32(aBuf-4) )
   #define zipfileRead16(aBuf) ( aBuf+=2, zipfileGetU16(aBuf-2) )
   
   #define zipfileWrite32(aBuf,val) { zipfilePutU32(aBuf,val); aBuf+=4; }
   #define zipfileWrite16(aBuf,val) { zipfilePutU16(aBuf,val); aBuf+=2; }
   
   /*
   ** Magic numbers used to read CDS records.
   */
   #define ZIPFILE_CDS_NFILE_OFF        28
   #define ZIPFILE_CDS_SZCOMPRESSED_OFF 20
   
   /*
   ** Decode the CDS record in buffer aBuf into (*pCDS). Return SQLITE_ERROR
   ** if the record is not well-formed, or SQLITE_OK otherwise.
   */
   static int zipfileReadCDS(u8 *aBuf, ZipfileCDS *pCDS){
     u8 *aRead = aBuf;
     u32 sig = zipfileRead32(aRead);
     int rc = SQLITE_OK;
     if( sig!=ZIPFILE_SIGNATURE_CDS ){
       rc = SQLITE_ERROR;
     }else{
       pCDS->iVersionMadeBy = zipfileRead16(aRead);
       pCDS->iVersionExtract = zipfileRead16(aRead);
       pCDS->flags = zipfileRead16(aRead);
       pCDS->iCompression = zipfileRead16(aRead);
       pCDS->mTime = zipfileRead16(aRead);
       pCDS->mDate = zipfileRead16(aRead);
       pCDS->crc32 = zipfileRead32(aRead);
       pCDS->szCompressed = zipfileRead32(aRead);
       pCDS->szUncompressed = zipfileRead32(aRead);
       assert( aRead==&aBuf[ZIPFILE_CDS_NFILE_OFF] );
       pCDS->nFile = zipfileRead16(aRead);
       pCDS->nExtra = zipfileRead16(aRead);
       pCDS->nComment = zipfileRead16(aRead);
       pCDS->iDiskStart = zipfileRead16(aRead);
       pCDS->iInternalAttr = zipfileRead16(aRead);
       pCDS->iExternalAttr = zipfileRead32(aRead);
       pCDS->iOffset = zipfileRead32(aRead);
       assert( aRead==&aBuf[ZIPFILE_CDS_FIXED_SZ] );
     }
   
     return rc;
   }
   
   /*
   ** Decode the LFH record in buffer aBuf into (*pLFH). Return SQLITE_ERROR
   ** if the record is not well-formed, or SQLITE_OK otherwise.
   */
   static int zipfileReadLFH(
     u8 *aBuffer,
     ZipfileLFH *pLFH
   ){
     u8 *aRead = aBuffer;
     int rc = SQLITE_OK;
   
     u32 sig = zipfileRead32(aRead);
     if( sig!=ZIPFILE_SIGNATURE_LFH ){
       rc = SQLITE_ERROR;
     }else{
       pLFH->iVersionExtract = zipfileRead16(aRead);
       pLFH->flags = zipfileRead16(aRead);
       pLFH->iCompression = zipfileRead16(aRead);
       pLFH->mTime = zipfileRead16(aRead);
       pLFH->mDate = zipfileRead16(aRead);
       pLFH->crc32 = zipfileRead32(aRead);
       pLFH->szCompressed = zipfileRead32(aRead);
       pLFH->szUncompressed = zipfileRead32(aRead);
       pLFH->nFile = zipfileRead16(aRead);
       pLFH->nExtra = zipfileRead16(aRead);
     }
     return rc;
   }
   
   
   /*
   ** Buffer aExtra (size nExtra bytes) contains zip archive "extra" fields.
   ** Scan through this buffer to find an "extra-timestamp" field. If one
   ** exists, extract the 32-bit modification-timestamp from it and store
   ** the value in output parameter *pmTime.
   **
   ** Zero is returned if no extra-timestamp record could be found (and so
   ** *pmTime is left unchanged), or non-zero otherwise.
   **
   ** The general format of an extra field is:
   **
   **   Header ID    2 bytes
   **   Data Size    2 bytes
   **   Data         N bytes
   */
   static int zipfileScanExtra(u8 *aExtra, int nExtra, u32 *pmTime){
     int ret = 0;
     u8 *p = aExtra;
     u8 *pEnd = &aExtra[nExtra];
   
     while( p<pEnd ){
       u16 id = zipfileRead16(p);
       u16 nByte = zipfileRead16(p);
   
       switch( id ){
         case ZIPFILE_EXTRA_TIMESTAMP: {
           u8 b = p[0];
           if( b & 0x01 ){     /* 0x01 -> modtime is present */
             *pmTime = zipfileGetU32(&p[1]);
             ret = 1;
           }
           break;
         }
       }
   
       p += nByte;
     }
     return ret;
   }
   
   /*
   ** Convert the standard MS-DOS timestamp stored in the mTime and mDate
   ** fields of the CDS structure passed as the only argument to a 32-bit
   ** UNIX seconds-since-the-epoch timestamp. Return the result.
   **
   ** "Standard" MS-DOS time format:
   **
   **   File modification time:
   **     Bits 00-04: seconds divided by 2
   **     Bits 05-10: minute
   **     Bits 11-15: hour
   **   File modification date:
   **     Bits 00-04: day
   **     Bits 05-08: month (1-12)
   **     Bits 09-15: years from 1980 
   **
   ** https://msdn.microsoft.com/en-us/library/9kkf9tah.aspx
   */
   static u32 zipfileMtime(ZipfileCDS *pCDS){
     int Y = (1980 + ((pCDS->mDate >> 9) & 0x7F));
     int M = ((pCDS->mDate >> 5) & 0x0F);
     int D = (pCDS->mDate & 0x1F);
     int B = -13;
   
     int sec = (pCDS->mTime & 0x1F)*2;
     int min = (pCDS->mTime >> 5) & 0x3F;
     int hr = (pCDS->mTime >> 11) & 0x1F;
     i64 JD;
   
     /* JD = INT(365.25 * (Y+4716)) + INT(30.6001 * (M+1)) + D + B - 1524.5 */
   
     /* Calculate the JD in seconds for noon on the day in question */
     if( M<3 ){
       Y = Y-1;
       M = M+12;
     }
     JD = (i64)(24*60*60) * (
         (int)(365.25 * (Y + 4716))
       + (int)(30.6001 * (M + 1))
       + D + B - 1524
     );
   
     /* Correct the JD for the time within the day */
     JD += (hr-12) * 3600 + min * 60 + sec;
   
     /* Convert JD to unix timestamp (the JD epoch is 2440587.5) */
     return (u32)(JD - (i64)(24405875) * 24*60*6);
   }
   
   /*
   ** The opposite of zipfileMtime(). This function populates the mTime and
   ** mDate fields of the CDS structure passed as the first argument according
   ** to the UNIX timestamp value passed as the second.
   */
   static void zipfileMtimeToDos(ZipfileCDS *pCds, u32 mUnixTime){
     /* Convert unix timestamp to JD (2440588 is noon on 1/1/1970) */
     i64 JD = (i64)2440588 + mUnixTime / (24*60*60);
   
     int A, B, C, D, E;
     int yr, mon, day;
     int hr, min, sec;
   
     A = (int)((JD - 1867216.25)/36524.25);
     A = (int)(JD + 1 + A - (A/4));
     B = A + 1524;
     C = (int)((B - 122.1)/365.25);
     D = (36525*(C&32767))/100;
     E = (int)((B-D)/30.6001);
   
     day = B - D - (int)(30.6001*E);
     mon = (E<14 ? E-1 : E-13);
     yr = mon>2 ? C-4716 : C-4715;
   
     hr = (mUnixTime % (24*60*60)) / (60*60);
     min = (mUnixTime % (60*60)) / 60;
     sec = (mUnixTime % 60);
   
     if( yr>=1980 ){
       pCds->mDate = (u16)(day + (mon << 5) + ((yr-1980) << 9));
       pCds->mTime = (u16)(sec/2 + (min<<5) + (hr<<11));
     }else{
       pCds->mDate = pCds->mTime = 0;
     }
   
     assert( mUnixTime<315507600 
          || mUnixTime==zipfileMtime(pCds) 
          || ((mUnixTime % 2) && mUnixTime-1==zipfileMtime(pCds)) 
          /* || (mUnixTime % 2) */
     );
   }
   
   /*
   ** If aBlob is not NULL, then it is a pointer to a buffer (nBlob bytes in
   ** size) containing an entire zip archive image. Or, if aBlob is NULL,
   ** then pFile is a file-handle open on a zip file. In either case, this
   ** function creates a ZipfileEntry object based on the zip archive entry
   ** for which the CDS record is at offset iOff.
   **
   ** If successful, SQLITE_OK is returned and (*ppEntry) set to point to
   ** the new object. Otherwise, an SQLite error code is returned and the
   ** final value of (*ppEntry) undefined.
   */
   static int zipfileGetEntry(
     ZipfileTab *pTab,               /* Store any error message here */
     const u8 *aBlob,                /* Pointer to in-memory file image */
     int nBlob,                      /* Size of aBlob[] in bytes */
     FILE *pFile,                    /* If aBlob==0, read from this file */
     i64 iOff,                       /* Offset of CDS record */
     ZipfileEntry **ppEntry          /* OUT: Pointer to new object */
   ){
     u8 *aRead;
     char **pzErr = &pTab->base.zErrMsg;
     int rc = SQLITE_OK;
   
     if( aBlob==0 ){
       aRead = pTab->aBuffer;
       rc = zipfileReadData(pFile, aRead, ZIPFILE_CDS_FIXED_SZ, iOff, pzErr);
     }else{
       aRead = (u8*)&aBlob[iOff];
     }
   
     if( rc==SQLITE_OK ){
       sqlite3_int64 nAlloc;
       ZipfileEntry *pNew;
   
       int nFile = zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF]);
       int nExtra = zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF+2]);
       nExtra += zipfileGetU16(&aRead[ZIPFILE_CDS_NFILE_OFF+4]);
   
       nAlloc = sizeof(ZipfileEntry) + nExtra;
       if( aBlob ){
         nAlloc += zipfileGetU32(&aRead[ZIPFILE_CDS_SZCOMPRESSED_OFF]);
       }
   
       pNew = (ZipfileEntry*)sqlite3_malloc64(nAlloc);
       if( pNew==0 ){
         rc = SQLITE_NOMEM;
       }else{
         memset(pNew, 0, sizeof(ZipfileEntry));
         rc = zipfileReadCDS(aRead, &pNew->cds);
         if( rc!=SQLITE_OK ){
           *pzErr = sqlite3_mprintf("failed to read CDS at offset %lld", iOff);
         }else if( aBlob==0 ){
           rc = zipfileReadData(
               pFile, aRead, nExtra+nFile, iOff+ZIPFILE_CDS_FIXED_SZ, pzErr
           );
         }else{
           aRead = (u8*)&aBlob[iOff + ZIPFILE_CDS_FIXED_SZ];
         }
       }
   
       if( rc==SQLITE_OK ){
         u32 *pt = &pNew->mUnixTime;
         pNew->cds.zFile = sqlite3_mprintf("%.*s", nFile, aRead); 
         pNew->aExtra = (u8*)&pNew[1];
         memcpy(pNew->aExtra, &aRead[nFile], nExtra);
         if( pNew->cds.zFile==0 ){
           rc = SQLITE_NOMEM;
         }else if( 0==zipfileScanExtra(&aRead[nFile], pNew->cds.nExtra, pt) ){
           pNew->mUnixTime = zipfileMtime(&pNew->cds);
         }
       }
   
       if( rc==SQLITE_OK ){
         static const int szFix = ZIPFILE_LFH_FIXED_SZ;
         ZipfileLFH lfh;
         if( pFile ){
           rc = zipfileReadData(pFile, aRead, szFix, pNew->cds.iOffset, pzErr);
         }else{
           aRead = (u8*)&aBlob[pNew->cds.iOffset];
         }
   
         rc = zipfileReadLFH(aRead, &lfh);
         if( rc==SQLITE_OK ){
           pNew->iDataOff =  pNew->cds.iOffset + ZIPFILE_LFH_FIXED_SZ;
           pNew->iDataOff += lfh.nFile + lfh.nExtra;
           if( aBlob && pNew->cds.szCompressed ){
             pNew->aData = &pNew->aExtra[nExtra];
             memcpy(pNew->aData, &aBlob[pNew->iDataOff], pNew->cds.szCompressed);
           }
         }else{
           *pzErr = sqlite3_mprintf("failed to read LFH at offset %d", 
               (int)pNew->cds.iOffset
           );
         }
       }
   
       if( rc!=SQLITE_OK ){
         zipfileEntryFree(pNew);
       }else{
         *ppEntry = pNew;
       }
     }
   
     return rc;
   }
   
   /*
   ** Advance an ZipfileCsr to its next row of output.
   */
   static int zipfileNext(sqlite3_vtab_cursor *cur){
     ZipfileCsr *pCsr = (ZipfileCsr*)cur;
     int rc = SQLITE_OK;
   
     if( pCsr->pFile ){
       i64 iEof = pCsr->eocd.iOffset + pCsr->eocd.nSize;
       zipfileEntryFree(pCsr->pCurrent);
       pCsr->pCurrent = 0;
       if( pCsr->iNextOff>=iEof ){
         pCsr->bEof = 1;
       }else{
         ZipfileEntry *p = 0;
         ZipfileTab *pTab = (ZipfileTab*)(cur->pVtab);
         rc = zipfileGetEntry(pTab, 0, 0, pCsr->pFile, pCsr->iNextOff, &p);
         if( rc==SQLITE_OK ){
           pCsr->iNextOff += ZIPFILE_CDS_FIXED_SZ;
           pCsr->iNextOff += (int)p->cds.nExtra + p->cds.nFile + p->cds.nComment;
         }
         pCsr->pCurrent = p;
       }
     }else{
       if( !pCsr->bNoop ){
         pCsr->pCurrent = pCsr->pCurrent->pNext;
       }
       if( pCsr->pCurrent==0 ){
         pCsr->bEof = 1;
       }
     }
   
     pCsr->bNoop = 0;
     return rc;
   }
   
   static void zipfileFree(void *p) { 
     sqlite3_free(p); 
   }
   
   /*
   ** Buffer aIn (size nIn bytes) contains compressed data. Uncompressed, the
   ** size is nOut bytes. This function uncompresses the data and sets the
   ** return value in context pCtx to the result (a blob).
   **
   ** If an error occurs, an error code is left in pCtx instead.
   */
   static void zipfileInflate(
     sqlite3_context *pCtx,          /* Store result here */
     const u8 *aIn,                  /* Compressed data */
     int nIn,                        /* Size of buffer aIn[] in bytes */
     int nOut                        /* Expected output size */
   ){
     u8 *aRes = sqlite3_malloc(nOut);
     if( aRes==0 ){
       sqlite3_result_error_nomem(pCtx);
     }else{
       int err;
       z_stream str;
       memset(&str, 0, sizeof(str));
   
       str.next_in = (Byte*)aIn;
       str.avail_in = nIn;
       str.next_out = (Byte*)aRes;
       str.avail_out = nOut;
   
       err = inflateInit2(&str, -15);
       if( err!=Z_OK ){
         zipfileCtxErrorMsg(pCtx, "inflateInit2() failed (%d)", err);
       }else{
         err = inflate(&str, Z_NO_FLUSH);
         if( err!=Z_STREAM_END ){
           zipfileCtxErrorMsg(pCtx, "inflate() failed (%d)", err);
         }else{
           sqlite3_result_blob(pCtx, aRes, nOut, zipfileFree);
           aRes = 0;
         }
       }
       sqlite3_free(aRes);
       inflateEnd(&str);
     }
   }
   
   /*
   ** Buffer aIn (size nIn bytes) contains uncompressed data. This function
   ** compresses it and sets (*ppOut) to point to a buffer containing the
   ** compressed data. The caller is responsible for eventually calling
   ** sqlite3_free() to release buffer (*ppOut). Before returning, (*pnOut) 
   ** is set to the size of buffer (*ppOut) in bytes.
   **
   ** If no error occurs, SQLITE_OK is returned. Otherwise, an SQLite error
   ** code is returned and an error message left in virtual-table handle
   ** pTab. The values of (*ppOut) and (*pnOut) are left unchanged in this
   ** case.
   */
   static int zipfileDeflate(
     const u8 *aIn, int nIn,         /* Input */
     u8 **ppOut, int *pnOut,         /* Output */
     char **pzErr                    /* OUT: Error message */
   ){
     int rc = SQLITE_OK;
     sqlite3_int64 nAlloc;
     z_stream str;
     u8 *aOut;
   
     memset(&str, 0, sizeof(str));
     str.next_in = (Bytef*)aIn;
     str.avail_in = nIn;
     deflateInit2(&str, 9, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);
   
     nAlloc = deflateBound(&str, nIn);
     aOut = (u8*)sqlite3_malloc64(nAlloc);
     if( aOut==0 ){
       rc = SQLITE_NOMEM;
     }else{
       int res;
       str.next_out = aOut;
       str.avail_out = nAlloc;
       res = deflate(&str, Z_FINISH);
       if( res==Z_STREAM_END ){
         *ppOut = aOut;
         *pnOut = (int)str.total_out;
       }else{
         sqlite3_free(aOut);
         *pzErr = sqlite3_mprintf("zipfile: deflate() error");
         rc = SQLITE_ERROR;
       }
       deflateEnd(&str);
     }
   
     return rc;
   }
   
   
   /*
   ** Return values of columns for the row at which the series_cursor
   ** is currently pointing.
   */
   static int zipfileColumn(
     sqlite3_vtab_cursor *cur,   /* The cursor */
     sqlite3_context *ctx,       /* First argument to sqlite3_result_...() */
     int i                       /* Which column to return */
   ){
     ZipfileCsr *pCsr = (ZipfileCsr*)cur;
     ZipfileCDS *pCDS = &pCsr->pCurrent->cds;
     int rc = SQLITE_OK;
     switch( i ){
       case 0:   /* name */
         sqlite3_result_text(ctx, pCDS->zFile, -1, SQLITE_TRANSIENT);
         break;
       case 1:   /* mode */
         /* TODO: Whether or not the following is correct surely depends on
         ** the platform on which the archive was created.  */
         sqlite3_result_int(ctx, pCDS->iExternalAttr >> 16);
         break;
       case 2: { /* mtime */
         sqlite3_result_int64(ctx, pCsr->pCurrent->mUnixTime);
         break;
       }
       case 3: { /* sz */
         if( sqlite3_vtab_nochange(ctx)==0 ){
           sqlite3_result_int64(ctx, pCDS->szUncompressed);
         }
         break;
       }
       case 4:   /* rawdata */
         if( sqlite3_vtab_nochange(ctx) ) break;
       case 5: { /* data */
         if( i==4 || pCDS->iCompression==0 || pCDS->iCompression==8 ){
           int sz = pCDS->szCompressed;
           int szFinal = pCDS->szUncompressed;
           if( szFinal>0 ){
             u8 *aBuf;
             u8 *aFree = 0;
             if( pCsr->pCurrent->aData ){
               aBuf = pCsr->pCurrent->aData;
             }else{
               aBuf = aFree = sqlite3_malloc64(sz);
               if( aBuf==0 ){
                 rc = SQLITE_NOMEM;
               }else{
                 FILE *pFile = pCsr->pFile;
                 if( pFile==0 ){
                   pFile = ((ZipfileTab*)(pCsr->base.pVtab))->pWriteFd;
                 }
                 rc = zipfileReadData(pFile, aBuf, sz, pCsr->pCurrent->iDataOff,
                     &pCsr->base.pVtab->zErrMsg
                 );
               }
             }
             if( rc==SQLITE_OK ){
               if( i==5 && pCDS->iCompression ){
                 zipfileInflate(ctx, aBuf, sz, szFinal);
               }else{
                 sqlite3_result_blob(ctx, aBuf, sz, SQLITE_TRANSIENT);
               }
             }
             sqlite3_free(aFree);
           }else{
             /* Figure out if this is a directory or a zero-sized file. Consider
             ** it to be a directory either if the mode suggests so, or if
             ** the final character in the name is '/'.  */
             u32 mode = pCDS->iExternalAttr >> 16;
             if( !(mode & S_IFDIR) && pCDS->zFile[pCDS->nFile-1]!='/' ){
               sqlite3_result_blob(ctx, "", 0, SQLITE_STATIC);
             }
           }
         }
         break;
       }
       case 6:   /* method */
         sqlite3_result_int(ctx, pCDS->iCompression);
         break;
       default:  /* z */
         assert( i==7 );
         sqlite3_result_int64(ctx, pCsr->iId);
         break;
     }
   
     return rc;
   }
   
   /*
   ** Return TRUE if the cursor is at EOF.
   */
   static int zipfileEof(sqlite3_vtab_cursor *cur){
     ZipfileCsr *pCsr = (ZipfileCsr*)cur;
     return pCsr->bEof;
   }
   
   /*
   ** If aBlob is not NULL, then it points to a buffer nBlob bytes in size
   ** containing an entire zip archive image. Or, if aBlob is NULL, then pFile
   ** is guaranteed to be a file-handle open on a zip file.
   **
   ** This function attempts to locate the EOCD record within the zip archive
   ** and populate *pEOCD with the results of decoding it. SQLITE_OK is
   ** returned if successful. Otherwise, an SQLite error code is returned and
   ** an English language error message may be left in virtual-table pTab.
   */
   static int zipfileReadEOCD(
     ZipfileTab *pTab,               /* Return errors here */
     const u8 *aBlob,                /* Pointer to in-memory file image */
     int nBlob,                      /* Size of aBlob[] in bytes */
     FILE *pFile,                    /* Read from this file if aBlob==0 */
     ZipfileEOCD *pEOCD              /* Object to populate */
   ){
     u8 *aRead = pTab->aBuffer;      /* Temporary buffer */
     int nRead;                      /* Bytes to read from file */
     int rc = SQLITE_OK;
   
     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));
       iOff = szFile - nRead;
       rc = zipfileReadData(pFile, aRead, nRead, iOff, &pTab->base.zErrMsg);
     }else{
       nRead = (int)(MIN(nBlob, ZIPFILE_BUFFER_SIZE));
       aRead = (u8*)&aBlob[nBlob-nRead];
     }
   
     if( rc==SQLITE_OK ){
       int i;
   
       /* Scan backwards looking for the signature bytes */
       for(i=nRead-20; i>=0; i--){
         if( aRead[i]==0x50 && aRead[i+1]==0x4b 
          && aRead[i+2]==0x05 && aRead[i+3]==0x06 
         ){
           break;
         }
       }
       if( i<0 ){
         pTab->base.zErrMsg = sqlite3_mprintf(
             "cannot find end of central directory record"
         );
         return SQLITE_ERROR;
       }
   
       aRead += i+4;
       pEOCD->iDisk = zipfileRead16(aRead);
       pEOCD->iFirstDisk = zipfileRead16(aRead);
       pEOCD->nEntry = zipfileRead16(aRead);
       pEOCD->nEntryTotal = zipfileRead16(aRead);
       pEOCD->nSize = zipfileRead32(aRead);
       pEOCD->iOffset = zipfileRead32(aRead);
     }
   
     return rc;
   }
   
   /*
   ** Add object pNew to the linked list that begins at ZipfileTab.pFirstEntry 
   ** and ends with pLastEntry. If argument pBefore is NULL, then pNew is added
   ** to the end of the list. Otherwise, it is added to the list immediately
   ** before pBefore (which is guaranteed to be a part of said list).
   */
   static void zipfileAddEntry(
     ZipfileTab *pTab, 
     ZipfileEntry *pBefore, 
     ZipfileEntry *pNew
   ){
     assert( (pTab->pFirstEntry==0)==(pTab->pLastEntry==0) );
     assert( pNew->pNext==0 );
     if( pBefore==0 ){
       if( pTab->pFirstEntry==0 ){
         pTab->pFirstEntry = pTab->pLastEntry = pNew;
       }else{
         assert( pTab->pLastEntry->pNext==0 );
         pTab->pLastEntry->pNext = pNew;
         pTab->pLastEntry = pNew;
       }
     }else{
       ZipfileEntry **pp;
       for(pp=&pTab->pFirstEntry; *pp!=pBefore; pp=&((*pp)->pNext));
       pNew->pNext = pBefore;
       *pp = pNew;
     }
   }
   
   static int zipfileLoadDirectory(ZipfileTab *pTab, const u8 *aBlob, int nBlob){
     ZipfileEOCD eocd;
     int rc;
     int i;
     i64 iOff;
   
     rc = zipfileReadEOCD(pTab, aBlob, nBlob, pTab->pWriteFd, &eocd);
     iOff = eocd.iOffset;
     for(i=0; rc==SQLITE_OK && i<eocd.nEntry; i++){
       ZipfileEntry *pNew = 0;
       rc = zipfileGetEntry(pTab, aBlob, nBlob, pTab->pWriteFd, iOff, &pNew);
   
       if( rc==SQLITE_OK ){
         zipfileAddEntry(pTab, 0, pNew);
         iOff += ZIPFILE_CDS_FIXED_SZ;
         iOff += (int)pNew->cds.nExtra + pNew->cds.nFile + pNew->cds.nComment;
       }
     }
     return rc;
   }
   
   /*
   ** xFilter callback.
   */
   static int zipfileFilter(
     sqlite3_vtab_cursor *cur, 
     int idxNum, const char *idxStr,
     int argc, sqlite3_value **argv
   ){
     ZipfileTab *pTab = (ZipfileTab*)cur->pVtab;
     ZipfileCsr *pCsr = (ZipfileCsr*)cur;
     const char *zFile = 0;          /* Zip file to scan */
     int rc = SQLITE_OK;             /* Return Code */
     int bInMemory = 0;              /* True for an in-memory zipfile */
   
     zipfileResetCursor(pCsr);
   
     if( pTab->zFile ){
       zFile = pTab->zFile;
     }else if( idxNum==0 ){
       zipfileCursorErr(pCsr, "zipfile() function requires an argument");
       return SQLITE_ERROR;
     }else if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
       const u8 *aBlob = (const u8*)sqlite3_value_blob(argv[0]);
       int nBlob = sqlite3_value_bytes(argv[0]);
       assert( pTab->pFirstEntry==0 );
       rc = zipfileLoadDirectory(pTab, aBlob, nBlob);
       pCsr->pFreeEntry = pTab->pFirstEntry;
       pTab->pFirstEntry = pTab->pLastEntry = 0;
       if( rc!=SQLITE_OK ) return rc;
       bInMemory = 1;
     }else{
       zFile = (const char*)sqlite3_value_text(argv[0]);
     }
   
     if( 0==pTab->pWriteFd && 0==bInMemory ){
       pCsr->pFile = fopen(zFile, "rb");
       if( pCsr->pFile==0 ){
         zipfileCursorErr(pCsr, "cannot open file: %s", zFile);
         rc = SQLITE_ERROR;
       }else{
         rc = zipfileReadEOCD(pTab, 0, 0, pCsr->pFile, &pCsr->eocd);
         if( rc==SQLITE_OK ){
           if( pCsr->eocd.nEntry==0 ){
             pCsr->bEof = 1;
           }else{
             pCsr->iNextOff = pCsr->eocd.iOffset;
             rc = zipfileNext(cur);
           }
         }
       }
     }else{
       pCsr->bNoop = 1;
       pCsr->pCurrent = pCsr->pFreeEntry ? pCsr->pFreeEntry : pTab->pFirstEntry;
       rc = zipfileNext(cur);
     }
   
     return rc;
   }
   
   /*
   ** xBestIndex callback.
   */
   static int zipfileBestIndex(
     sqlite3_vtab *tab,
     sqlite3_index_info *pIdxInfo
   ){
     int i;
     int idx = -1;
     int unusable = 0;
   
     for(i=0; i<pIdxInfo->nConstraint; i++){
       const struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i];
       if( pCons->iColumn!=ZIPFILE_F_COLUMN_IDX ) continue;
       if( pCons->usable==0 ){
         unusable = 1;
       }else if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){
         idx = i;
       }
     }
     pIdxInfo->estimatedCost = 1000.0;
     if( idx>=0 ){
       pIdxInfo->aConstraintUsage[idx].argvIndex = 1;
       pIdxInfo->aConstraintUsage[idx].omit = 1;
       pIdxInfo->idxNum = 1;
     }else if( unusable ){
       return SQLITE_CONSTRAINT;
     }
     return SQLITE_OK;
   }
   
   static ZipfileEntry *zipfileNewEntry(const char *zPath){
     ZipfileEntry *pNew;
     pNew = sqlite3_malloc(sizeof(ZipfileEntry));
     if( pNew ){
       memset(pNew, 0, sizeof(ZipfileEntry));
       pNew->cds.zFile = sqlite3_mprintf("%s", zPath);
       if( pNew->cds.zFile==0 ){
         sqlite3_free(pNew);
         pNew = 0;
       }
     }
     return pNew;
   }
   
   static int zipfileSerializeLFH(ZipfileEntry *pEntry, u8 *aBuf){
     ZipfileCDS *pCds = &pEntry->cds;
     u8 *a = aBuf;
   
     pCds->nExtra = 9;
   
     /* Write the LFH itself */
     zipfileWrite32(a, ZIPFILE_SIGNATURE_LFH);
     zipfileWrite16(a, pCds->iVersionExtract);
     zipfileWrite16(a, pCds->flags);
     zipfileWrite16(a, pCds->iCompression);
     zipfileWrite16(a, pCds->mTime);
     zipfileWrite16(a, pCds->mDate);
     zipfileWrite32(a, pCds->crc32);
     zipfileWrite32(a, pCds->szCompressed);
     zipfileWrite32(a, pCds->szUncompressed);
     zipfileWrite16(a, (u16)pCds->nFile);
     zipfileWrite16(a, pCds->nExtra);
     assert( a==&aBuf[ZIPFILE_LFH_FIXED_SZ] );
   
     /* Add the file name */
     memcpy(a, pCds->zFile, (int)pCds->nFile);
     a += (int)pCds->nFile;
   
     /* The "extra" data */
     zipfileWrite16(a, ZIPFILE_EXTRA_TIMESTAMP);
     zipfileWrite16(a, 5);
     *a++ = 0x01;
     zipfileWrite32(a, pEntry->mUnixTime);
   
     return a-aBuf;
   }
   
   static int zipfileAppendEntry(
     ZipfileTab *pTab,
     ZipfileEntry *pEntry,
     const u8 *pData,
     int nData
   ){
     u8 *aBuf = pTab->aBuffer;
     int nBuf;
     int rc;
   
     nBuf = zipfileSerializeLFH(pEntry, aBuf);
     rc = zipfileAppendData(pTab, aBuf, nBuf);
     if( rc==SQLITE_OK ){
       pEntry->iDataOff = pTab->szCurrent;
       rc = zipfileAppendData(pTab, pData, nData);
     }
   
     return rc;
   }
   
   static int zipfileGetMode(
     sqlite3_value *pVal, 
     int bIsDir,                     /* If true, default to directory */
     u32 *pMode,                     /* OUT: Mode value */
     char **pzErr                    /* OUT: Error message */
   ){
     const char *z = (const char*)sqlite3_value_text(pVal);
     u32 mode = 0;
     if( z==0 ){
       mode = (bIsDir ? (S_IFDIR + 0755) : (S_IFREG + 0644));
     }else if( z[0]>='0' && z[0]<='9' ){
       mode = (unsigned int)sqlite3_value_int(pVal);
     }else{
       const char zTemplate[11] = "-rwxrwxrwx";
       int i;
       if( strlen(z)!=10 ) goto parse_error;
       switch( z[0] ){
         case '-': mode |= S_IFREG; break;
         case 'd': mode |= S_IFDIR; break;
         case 'l': mode |= S_IFLNK; break;
         default: goto parse_error;
       }
       for(i=1; i<10; i++){
         if( z[i]==zTemplate[i] ) mode |= 1 << (9-i);
         else if( z[i]!='-' ) goto parse_error;
       }
     }
     if( ((mode & S_IFDIR)==0)==bIsDir ){
       /* The "mode" attribute is a directory, but data has been specified.
       ** Or vice-versa - no data but "mode" is a file or symlink.  */
       *pzErr = sqlite3_mprintf("zipfile: mode does not match data");
       return SQLITE_CONSTRAINT;
     }
     *pMode = mode;
     return SQLITE_OK;
   
    parse_error:
     *pzErr = sqlite3_mprintf("zipfile: parse error in mode: %s", z);
     return SQLITE_ERROR;
   }
   
   /*
   ** Both (const char*) arguments point to nul-terminated strings. Argument
   ** nB is the value of strlen(zB). This function returns 0 if the strings are
   ** identical, ignoring any trailing '/' character in either path.  */
   static int zipfileComparePath(const char *zA, const char *zB, int nB){
     int nA = (int)strlen(zA);
     if( nA>0 && zA[nA-1]=='/' ) nA--;
     if( nB>0 && zB[nB-1]=='/' ) nB--;
     if( nA==nB && memcmp(zA, zB, nA)==0 ) return 0;
     return 1;
   }
   
   static int zipfileBegin(sqlite3_vtab *pVtab){
     ZipfileTab *pTab = (ZipfileTab*)pVtab;
     int rc = SQLITE_OK;
   
     assert( pTab->pWriteFd==0 );
     if( pTab->zFile==0 || pTab->zFile[0]==0 ){
       pTab->base.zErrMsg = sqlite3_mprintf("zipfile: missing filename");
       return SQLITE_ERROR;
     }
   
     /* Open a write fd on the file. Also load the entire central directory
     ** structure into memory. During the transaction any new file data is 
     ** appended to the archive file, but the central directory is accumulated
     ** in main-memory until the transaction is committed.  */
     pTab->pWriteFd = fopen(pTab->zFile, "ab+");
     if( pTab->pWriteFd==0 ){
       pTab->base.zErrMsg = sqlite3_mprintf(
           "zipfile: failed to open file %s for writing", pTab->zFile
           );
       rc = SQLITE_ERROR;
     }else{
       fseek(pTab->pWriteFd, 0, SEEK_END);
       pTab->szCurrent = pTab->szOrig = (i64)ftell(pTab->pWriteFd);
       rc = zipfileLoadDirectory(pTab, 0, 0);
     }
   
     if( rc!=SQLITE_OK ){
       zipfileCleanupTransaction(pTab);
     }
   
     return rc;
   }
   
   /*
   ** Return the current time as a 32-bit timestamp in UNIX epoch format (like
   ** time(2)).
   */
   static u32 zipfileTime(void){
     sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
     u32 ret;
     if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){
       i64 ms;
       pVfs->xCurrentTimeInt64(pVfs, &ms);
       ret = (u32)((ms/1000) - ((i64)24405875 * 8640));
     }else{
       double day;
       pVfs->xCurrentTime(pVfs, &day);
       ret = (u32)((day - 2440587.5) * 86400);
     }
     return ret;
   }
   
   /*
   ** Return a 32-bit timestamp in UNIX epoch format.
   **
   ** If the value passed as the only argument is either NULL or an SQL NULL,
   ** return the current time. Otherwise, return the value stored in (*pVal)
   ** cast to a 32-bit unsigned integer.
   */
   static u32 zipfileGetTime(sqlite3_value *pVal){
     if( pVal==0 || sqlite3_value_type(pVal)==SQLITE_NULL ){
       return zipfileTime();
     }
     return (u32)sqlite3_value_int64(pVal);
   }
   
   /*
   ** Unless it is NULL, entry pOld is currently part of the pTab->pFirstEntry
   ** linked list.  Remove it from the list and free the object.
   */
   static void zipfileRemoveEntryFromList(ZipfileTab *pTab, ZipfileEntry *pOld){
     if( pOld ){
       ZipfileEntry **pp;
       for(pp=&pTab->pFirstEntry; (*pp)!=pOld; pp=&((*pp)->pNext));
       *pp = (*pp)->pNext;
       zipfileEntryFree(pOld);
     }
   }
   
   /*
   ** xUpdate method.
   */
   static int zipfileUpdate(
     sqlite3_vtab *pVtab, 
     int nVal, 
     sqlite3_value **apVal, 
     sqlite_int64 *pRowid
   ){
     ZipfileTab *pTab = (ZipfileTab*)pVtab;
     int rc = SQLITE_OK;             /* Return Code */
     ZipfileEntry *pNew = 0;         /* New in-memory CDS entry */
   
     u32 mode = 0;                   /* Mode for new entry */
     u32 mTime = 0;                  /* Modification time for new entry */
     i64 sz = 0;                     /* Uncompressed size */
     const char *zPath = 0;          /* Path for new entry */
     int nPath = 0;                  /* strlen(zPath) */
     const u8 *pData = 0;            /* Pointer to buffer containing content */
     int nData = 0;                  /* Size of pData buffer in bytes */
     int iMethod = 0;                /* Compression method for new entry */
     u8 *pFree = 0;                  /* Free this */
     char *zFree = 0;                /* Also free this */
     ZipfileEntry *pOld = 0;
     ZipfileEntry *pOld2 = 0;
     int bUpdate = 0;                /* True for an update that modifies "name" */
     int bIsDir = 0;
     u32 iCrc32 = 0;
   
     if( pTab->pWriteFd==0 ){
       rc = zipfileBegin(pVtab);
       if( rc!=SQLITE_OK ) return rc;
     }
   
     /* If this is a DELETE or UPDATE, find the archive entry to delete. */
     if( sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
       const char *zDelete = (const char*)sqlite3_value_text(apVal[0]);
       int nDelete = (int)strlen(zDelete);
       if( nVal>1 ){
         const char *zUpdate = (const char*)sqlite3_value_text(apVal[1]);
         if( zUpdate && zipfileComparePath(zUpdate, zDelete, nDelete)!=0 ){
           bUpdate = 1;
         }
       }
       for(pOld=pTab->pFirstEntry; 1; pOld=pOld->pNext){
         if( zipfileComparePath(pOld->cds.zFile, zDelete, nDelete)==0 ){
           break;
         }
         assert( pOld->pNext );
       }
     }
   
     if( nVal>1 ){
       /* Check that "sz" and "rawdata" are both NULL: */
       if( sqlite3_value_type(apVal[5])!=SQLITE_NULL ){
         zipfileTableErr(pTab, "sz must be NULL");
         rc = SQLITE_CONSTRAINT;
       }
       if( sqlite3_value_type(apVal[6])!=SQLITE_NULL ){
         zipfileTableErr(pTab, "rawdata must be NULL"); 
         rc = SQLITE_CONSTRAINT;
       }
   
       if( rc==SQLITE_OK ){
         if( sqlite3_value_type(apVal[7])==SQLITE_NULL ){
           /* data=NULL. A directory */
           bIsDir = 1;
         }else{
           /* Value specified for "data", and possibly "method". This must be
           ** a regular file or a symlink. */
           const u8 *aIn = sqlite3_value_blob(apVal[7]);
           int nIn = sqlite3_value_bytes(apVal[7]);
           int bAuto = sqlite3_value_type(apVal[8])==SQLITE_NULL;
   
           iMethod = sqlite3_value_int(apVal[8]);
           sz = nIn;
           pData = aIn;
           nData = nIn;
           if( iMethod!=0 && iMethod!=8 ){
             zipfileTableErr(pTab, "unknown compression method: %d", iMethod);
             rc = SQLITE_CONSTRAINT;
           }else{
             if( bAuto || iMethod ){
               int nCmp;
               rc = zipfileDeflate(aIn, nIn, &pFree, &nCmp, &pTab->base.zErrMsg);
               if( rc==SQLITE_OK ){
                 if( iMethod || nCmp<nIn ){
                   iMethod = 8;
                   pData = pFree;
                   nData = nCmp;
                 }
               }
             }
             iCrc32 = crc32(0, aIn, nIn);
           }
         }
       }
   
       if( rc==SQLITE_OK ){
         rc = zipfileGetMode(apVal[3], bIsDir, &mode, &pTab->base.zErrMsg);
       }
   
       if( rc==SQLITE_OK ){
         zPath = (const char*)sqlite3_value_text(apVal[2]);
         if( zPath==0 ) zPath = "";
         nPath = (int)strlen(zPath);
         mTime = zipfileGetTime(apVal[4]);
       }
   
       if( rc==SQLITE_OK && bIsDir ){
         /* For a directory, check that the last character in the path is a
         ** '/'. This appears to be required for compatibility with info-zip
         ** (the unzip command on unix). It does not create directories
         ** otherwise.  */
         if( nPath<=0 || zPath[nPath-1]!='/' ){
           zFree = sqlite3_mprintf("%s/", zPath);
           zPath = (const char*)zFree;
           if( zFree==0 ){
             rc = SQLITE_NOMEM;
             nPath = 0;
           }else{
             nPath = (int)strlen(zPath);
           }
         }
       }
   
       /* Check that we're not inserting a duplicate entry -OR- updating an
       ** entry with a path, thereby making it into a duplicate. */
       if( (pOld==0 || bUpdate) && rc==SQLITE_OK ){
         ZipfileEntry *p;
         for(p=pTab->pFirstEntry; p; p=p->pNext){
           if( zipfileComparePath(p->cds.zFile, zPath, nPath)==0 ){
             switch( sqlite3_vtab_on_conflict(pTab->db) ){
               case SQLITE_IGNORE: {
                 goto zipfile_update_done;
               }
               case SQLITE_REPLACE: {
                 pOld2 = p;
                 break;
               }
               default: {
                 zipfileTableErr(pTab, "duplicate name: \"%s\"", zPath);
                 rc = SQLITE_CONSTRAINT;
                 break;
               }
             }
             break;
           }
         }
       }
   
       if( rc==SQLITE_OK ){
         /* Create the new CDS record. */
         pNew = zipfileNewEntry(zPath);
         if( pNew==0 ){
           rc = SQLITE_NOMEM;
         }else{
           pNew->cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY;
           pNew->cds.iVersionExtract = ZIPFILE_NEWENTRY_REQUIRED;
           pNew->cds.flags = ZIPFILE_NEWENTRY_FLAGS;
           pNew->cds.iCompression = (u16)iMethod;
           zipfileMtimeToDos(&pNew->cds, mTime);
           pNew->cds.crc32 = iCrc32;
           pNew->cds.szCompressed = nData;
           pNew->cds.szUncompressed = (u32)sz;
           pNew->cds.iExternalAttr = (mode<<16);
           pNew->cds.iOffset = (u32)pTab->szCurrent;
           pNew->cds.nFile = (u16)nPath;
           pNew->mUnixTime = (u32)mTime;
           rc = zipfileAppendEntry(pTab, pNew, pData, nData);
           zipfileAddEntry(pTab, pOld, pNew);
         }
       }
     }
   
     if( rc==SQLITE_OK && (pOld || pOld2) ){
       ZipfileCsr *pCsr;
       for(pCsr=pTab->pCsrList; pCsr; pCsr=pCsr->pCsrNext){
         if( pCsr->pCurrent && (pCsr->pCurrent==pOld || pCsr->pCurrent==pOld2) ){
           pCsr->pCurrent = pCsr->pCurrent->pNext;
           pCsr->bNoop = 1;
         }
       }
   
       zipfileRemoveEntryFromList(pTab, pOld);
       zipfileRemoveEntryFromList(pTab, pOld2);
     }
   
   zipfile_update_done:
     sqlite3_free(pFree);
     sqlite3_free(zFree);
     return rc;
   }
   
   static int zipfileSerializeEOCD(ZipfileEOCD *p, u8 *aBuf){
     u8 *a = aBuf;
     zipfileWrite32(a, ZIPFILE_SIGNATURE_EOCD);
     zipfileWrite16(a, p->iDisk);
     zipfileWrite16(a, p->iFirstDisk);
     zipfileWrite16(a, p->nEntry);
     zipfileWrite16(a, p->nEntryTotal);
     zipfileWrite32(a, p->nSize);
     zipfileWrite32(a, p->iOffset);
     zipfileWrite16(a, 0);        /* Size of trailing comment in bytes*/
   
     return a-aBuf;
   }
   
   static int zipfileAppendEOCD(ZipfileTab *pTab, ZipfileEOCD *p){
     int nBuf = zipfileSerializeEOCD(p, pTab->aBuffer);
     assert( nBuf==ZIPFILE_EOCD_FIXED_SZ );
     return zipfileAppendData(pTab, pTab->aBuffer, nBuf);
   }
   
   /*
   ** Serialize the CDS structure into buffer aBuf[]. Return the number
   ** of bytes written.
   */
   static int zipfileSerializeCDS(ZipfileEntry *pEntry, u8 *aBuf){
     u8 *a = aBuf;
     ZipfileCDS *pCDS = &pEntry->cds;
   
     if( pEntry->aExtra==0 ){
       pCDS->nExtra = 9;
     }
   
     zipfileWrite32(a, ZIPFILE_SIGNATURE_CDS);
     zipfileWrite16(a, pCDS->iVersionMadeBy);
     zipfileWrite16(a, pCDS->iVersionExtract);
     zipfileWrite16(a, pCDS->flags);
     zipfileWrite16(a, pCDS->iCompression);
     zipfileWrite16(a, pCDS->mTime);
     zipfileWrite16(a, pCDS->mDate);
     zipfileWrite32(a, pCDS->crc32);
     zipfileWrite32(a, pCDS->szCompressed);
     zipfileWrite32(a, pCDS->szUncompressed);
     assert( a==&aBuf[ZIPFILE_CDS_NFILE_OFF] );
     zipfileWrite16(a, pCDS->nFile);
     zipfileWrite16(a, pCDS->nExtra);
     zipfileWrite16(a, pCDS->nComment);
     zipfileWrite16(a, pCDS->iDiskStart);
     zipfileWrite16(a, pCDS->iInternalAttr);
     zipfileWrite32(a, pCDS->iExternalAttr);
     zipfileWrite32(a, pCDS->iOffset);
   
     memcpy(a, pCDS->zFile, pCDS->nFile);
     a += pCDS->nFile;
   
     if( pEntry->aExtra ){
       int n = (int)pCDS->nExtra + (int)pCDS->nComment;
       memcpy(a, pEntry->aExtra, n);
       a += n;
     }else{
       assert( pCDS->nExtra==9 );
       zipfileWrite16(a, ZIPFILE_EXTRA_TIMESTAMP);
       zipfileWrite16(a, 5);
       *a++ = 0x01;
       zipfileWrite32(a, pEntry->mUnixTime);
     }
   
     return a-aBuf;
   }
   
   static int zipfileCommit(sqlite3_vtab *pVtab){
     ZipfileTab *pTab = (ZipfileTab*)pVtab;
     int rc = SQLITE_OK;
     if( pTab->pWriteFd ){
       i64 iOffset = pTab->szCurrent;
       ZipfileEntry *p;
       ZipfileEOCD eocd;
       int nEntry = 0;
   
       /* Write out all entries */
       for(p=pTab->pFirstEntry; rc==SQLITE_OK && p; p=p->pNext){
         int n = zipfileSerializeCDS(p, pTab->aBuffer);
         rc = zipfileAppendData(pTab, pTab->aBuffer, n);
         nEntry++;
       }
   
       /* Write out the EOCD record */
       eocd.iDisk = 0;
       eocd.iFirstDisk = 0;
       eocd.nEntry = (u16)nEntry;
       eocd.nEntryTotal = (u16)nEntry;
       eocd.nSize = (u32)(pTab->szCurrent - iOffset);
       eocd.iOffset = (u32)iOffset;
       rc = zipfileAppendEOCD(pTab, &eocd);
   
       zipfileCleanupTransaction(pTab);
     }
     return rc;
   }
   
   static int zipfileRollback(sqlite3_vtab *pVtab){
     return zipfileCommit(pVtab);
   }
   
   static ZipfileCsr *zipfileFindCursor(ZipfileTab *pTab, i64 iId){
     ZipfileCsr *pCsr;
     for(pCsr=pTab->pCsrList; pCsr; pCsr=pCsr->pCsrNext){
       if( iId==pCsr->iId ) break;
     }
     return pCsr;
   }
   
   static void zipfileFunctionCds(
     sqlite3_context *context,
     int argc,
     sqlite3_value **argv
   ){
     ZipfileCsr *pCsr;
     ZipfileTab *pTab = (ZipfileTab*)sqlite3_user_data(context);
     assert( argc>0 );
   
     pCsr = zipfileFindCursor(pTab, sqlite3_value_int64(argv[0]));
     if( pCsr ){
       ZipfileCDS *p = &pCsr->pCurrent->cds;
       char *zRes = sqlite3_mprintf("{"
           "\"version-made-by\" : %u, "
           "\"version-to-extract\" : %u, "
           "\"flags\" : %u, "
           "\"compression\" : %u, "
           "\"time\" : %u, "
           "\"date\" : %u, "
           "\"crc32\" : %u, "
           "\"compressed-size\" : %u, "
           "\"uncompressed-size\" : %u, "
           "\"file-name-length\" : %u, "
           "\"extra-field-length\" : %u, "
           "\"file-comment-length\" : %u, "
           "\"disk-number-start\" : %u, "
           "\"internal-attr\" : %u, "
           "\"external-attr\" : %u, "
           "\"offset\" : %u }",
           (u32)p->iVersionMadeBy, (u32)p->iVersionExtract,
           (u32)p->flags, (u32)p->iCompression,
           (u32)p->mTime, (u32)p->mDate,
           (u32)p->crc32, (u32)p->szCompressed,
           (u32)p->szUncompressed, (u32)p->nFile,
           (u32)p->nExtra, (u32)p->nComment,
           (u32)p->iDiskStart, (u32)p->iInternalAttr,
           (u32)p->iExternalAttr, (u32)p->iOffset
       );
   
       if( zRes==0 ){
         sqlite3_result_error_nomem(context);
       }else{
         sqlite3_result_text(context, zRes, -1, SQLITE_TRANSIENT);
         sqlite3_free(zRes);
       }
     }
   }
   
   /*
   ** xFindFunction method.
   */
   static int zipfileFindFunction(
     sqlite3_vtab *pVtab,            /* Virtual table handle */
     int nArg,                       /* Number of SQL function arguments */
     const char *zName,              /* Name of SQL function */
     void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), /* OUT: Result */
     void **ppArg                    /* OUT: User data for *pxFunc */
   ){
     if( sqlite3_stricmp("zipfile_cds", zName)==0 ){
       *pxFunc = zipfileFunctionCds;
       *ppArg = (void*)pVtab;
       return 1;
     }
     return 0;
   }
   
   typedef struct ZipfileBuffer ZipfileBuffer;
   struct ZipfileBuffer {
     u8 *a;                          /* Pointer to buffer */
     int n;                          /* Size of buffer in bytes */
     int nAlloc;                     /* Byte allocated at a[] */
   };
   
   typedef struct ZipfileCtx ZipfileCtx;
   struct ZipfileCtx {
     int nEntry;
     ZipfileBuffer body;
     ZipfileBuffer cds;
   };
   
   static int zipfileBufferGrow(ZipfileBuffer *pBuf, int nByte){
     if( pBuf->n+nByte>pBuf->nAlloc ){
       u8 *aNew;
       sqlite3_int64 nNew = pBuf->n ? pBuf->n*2 : 512;
       int nReq = pBuf->n + nByte;
   
       while( nNew<nReq ) nNew = nNew*2;
       aNew = sqlite3_realloc64(pBuf->a, nNew);
       if( aNew==0 ) return SQLITE_NOMEM;
       pBuf->a = aNew;
       pBuf->nAlloc = (int)nNew;
     }
     return SQLITE_OK;
   }
   
   /*
   ** xStep() callback for the zipfile() aggregate. This can be called in
   ** any of the following ways:
   **
   **   SELECT zipfile(name,data) ...
   **   SELECT zipfile(name,mode,mtime,data) ...
   **   SELECT zipfile(name,mode,mtime,data,method) ...
   */
   void zipfileStep(sqlite3_context *pCtx, int nVal, sqlite3_value **apVal){
     ZipfileCtx *p;                  /* Aggregate function context */
     ZipfileEntry e;                 /* New entry to add to zip archive */
   
     sqlite3_value *pName = 0;
     sqlite3_value *pMode = 0;
     sqlite3_value *pMtime = 0;
     sqlite3_value *pData = 0;
     sqlite3_value *pMethod = 0;
   
     int bIsDir = 0;
     u32 mode;
     int rc = SQLITE_OK;
     char *zErr = 0;
   
     int iMethod = -1;               /* Compression method to use (0 or 8) */
   
     const u8 *aData = 0;            /* Possibly compressed data for new entry */
     int nData = 0;                  /* Size of aData[] in bytes */
     int szUncompressed = 0;         /* Size of data before compression */
     u8 *aFree = 0;                  /* Free this before returning */
     u32 iCrc32 = 0;                 /* crc32 of uncompressed data */
   
     char *zName = 0;                /* Path (name) of new entry */
     int nName = 0;                  /* Size of zName in bytes */
     char *zFree = 0;                /* Free this before returning */
     int nByte;
   
     memset(&e, 0, sizeof(e));
     p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx));
     if( p==0 ) return;
   
     /* Martial the arguments into stack variables */
     if( nVal!=2 && nVal!=4 && nVal!=5 ){
       zErr = sqlite3_mprintf("wrong number of arguments to function zipfile()");
       rc = SQLITE_ERROR;
       goto zipfile_step_out;
     }
     pName = apVal[0];
     if( nVal==2 ){
       pData = apVal[1];
     }else{
       pMode = apVal[1];
       pMtime = apVal[2];
       pData = apVal[3];
       if( nVal==5 ){
         pMethod = apVal[4];
       }
     }
   
     /* Check that the 'name' parameter looks ok. */
     zName = (char*)sqlite3_value_text(pName);
     nName = sqlite3_value_bytes(pName);
     if( zName==0 ){
       zErr = sqlite3_mprintf("first argument to zipfile() must be non-NULL");
       rc = SQLITE_ERROR;
       goto zipfile_step_out;
     }
   
     /* Inspect the 'method' parameter. This must be either 0 (store), 8 (use
     ** deflate compression) or NULL (choose automatically).  */
     if( pMethod && SQLITE_NULL!=sqlite3_value_type(pMethod) ){
       iMethod = (int)sqlite3_value_int64(pMethod);
       if( iMethod!=0 && iMethod!=8 ){
         zErr = sqlite3_mprintf("illegal method value: %d", iMethod);
         rc = SQLITE_ERROR;
         goto zipfile_step_out;
       }
     }
   
     /* Now inspect the data. If this is NULL, then the new entry must be a
     ** directory.  Otherwise, figure out whether or not the data should
     ** be deflated or simply stored in the zip archive. */
     if( sqlite3_value_type(pData)==SQLITE_NULL ){
       bIsDir = 1;
       iMethod = 0;
     }else{
       aData = sqlite3_value_blob(pData);
       szUncompressed = nData = sqlite3_value_bytes(pData);
       iCrc32 = crc32(0, aData, nData);
       if( iMethod<0 || iMethod==8 ){
         int nOut = 0;
         rc = zipfileDeflate(aData, nData, &aFree, &nOut, &zErr);
         if( rc!=SQLITE_OK ){
           goto zipfile_step_out;
         }
         if( iMethod==8 || nOut<nData ){
           aData = aFree;
           nData = nOut;
           iMethod = 8;
         }else{
           iMethod = 0;
         }
       }
     }
   
     /* Decode the "mode" argument. */
     rc = zipfileGetMode(pMode, bIsDir, &mode, &zErr);
     if( rc ) goto zipfile_step_out;
   
     /* Decode the "mtime" argument. */
     e.mUnixTime = zipfileGetTime(pMtime);
   
     /* If this is a directory entry, ensure that there is exactly one '/'
     ** at the end of the path. Or, if this is not a directory and the path
     ** ends in '/' it is an error. */
     if( bIsDir==0 ){
       if( nName>0 && zName[nName-1]=='/' ){
         zErr = sqlite3_mprintf("non-directory name must not end with /");
         rc = SQLITE_ERROR;
         goto zipfile_step_out;
       }
     }else{
       if( nName==0 || zName[nName-1]!='/' ){
         zName = zFree = sqlite3_mprintf("%s/", zName);
         if( zName==0 ){
           rc = SQLITE_NOMEM;
           goto zipfile_step_out;
         }
         nName = (int)strlen(zName);
       }else{
         while( nName>1 && zName[nName-2]=='/' ) nName--;
       }
     }
   
     /* Assemble the ZipfileEntry object for the new zip archive entry */
     e.cds.iVersionMadeBy = ZIPFILE_NEWENTRY_MADEBY;
     e.cds.iVersionExtract = ZIPFILE_NEWENTRY_REQUIRED;
     e.cds.flags = ZIPFILE_NEWENTRY_FLAGS;
     e.cds.iCompression = (u16)iMethod;
     zipfileMtimeToDos(&e.cds, (u32)e.mUnixTime);
     e.cds.crc32 = iCrc32;
     e.cds.szCompressed = nData;
     e.cds.szUncompressed = szUncompressed;
     e.cds.iExternalAttr = (mode<<16);
     e.cds.iOffset = p->body.n;
     e.cds.nFile = (u16)nName;
     e.cds.zFile = zName;
   
     /* Append the LFH to the body of the new archive */
     nByte = ZIPFILE_LFH_FIXED_SZ + e.cds.nFile + 9;
     if( (rc = zipfileBufferGrow(&p->body, nByte)) ) goto zipfile_step_out;
     p->body.n += zipfileSerializeLFH(&e, &p->body.a[p->body.n]);
   
     /* Append the data to the body of the new archive */
     if( nData>0 ){
       if( (rc = zipfileBufferGrow(&p->body, nData)) ) goto zipfile_step_out;
       memcpy(&p->body.a[p->body.n], aData, nData);
       p->body.n += nData;
     }
   
     /* Append the CDS record to the directory of the new archive */
     nByte = ZIPFILE_CDS_FIXED_SZ + e.cds.nFile + 9;
     if( (rc = zipfileBufferGrow(&p->cds, nByte)) ) goto zipfile_step_out;
     p->cds.n += zipfileSerializeCDS(&e, &p->cds.a[p->cds.n]);
   
     /* Increment the count of entries in the archive */
     p->nEntry++;
   
    zipfile_step_out:
     sqlite3_free(aFree);
     sqlite3_free(zFree);
     if( rc ){
       if( zErr ){
         sqlite3_result_error(pCtx, zErr, -1);
       }else{
         sqlite3_result_error_code(pCtx, rc);
       }
     }
     sqlite3_free(zErr);
   }
   
   /*
   ** xFinalize() callback for zipfile aggregate function.
   */
   void zipfileFinal(sqlite3_context *pCtx){
     ZipfileCtx *p;
     ZipfileEOCD eocd;
     sqlite3_int64 nZip;
     u8 *aZip;
   
     p = (ZipfileCtx*)sqlite3_aggregate_context(pCtx, sizeof(ZipfileCtx));
     if( p==0 ) return;
     if( p->nEntry>0 ){
       memset(&eocd, 0, sizeof(eocd));
       eocd.nEntry = (u16)p->nEntry;
       eocd.nEntryTotal = (u16)p->nEntry;
       eocd.nSize = p->cds.n;
       eocd.iOffset = p->body.n;
   
       nZip = p->body.n + p->cds.n + ZIPFILE_EOCD_FIXED_SZ;
       aZip = (u8*)sqlite3_malloc64(nZip);
       if( aZip==0 ){
         sqlite3_result_error_nomem(pCtx);
       }else{
         memcpy(aZip, p->body.a, p->body.n);
         memcpy(&aZip[p->body.n], p->cds.a, p->cds.n);
         zipfileSerializeEOCD(&eocd, &aZip[p->body.n + p->cds.n]);
         sqlite3_result_blob(pCtx, aZip, (int)nZip, zipfileFree);
       }
     }
   
     sqlite3_free(p->body.a);
     sqlite3_free(p->cds.a);
   }
   
   
   /*
   ** Register the "zipfile" virtual table.
   */
   static int zipfileRegister(sqlite3 *db){
     static sqlite3_module zipfileModule = {
       1,                         /* iVersion */
       zipfileConnect,            /* xCreate */
       zipfileConnect,            /* xConnect */
       zipfileBestIndex,          /* xBestIndex */
       zipfileDisconnect,         /* xDisconnect */
       zipfileDisconnect,         /* xDestroy */
       zipfileOpen,               /* xOpen - open a cursor */
       zipfileClose,              /* xClose - close a cursor */
       zipfileFilter,             /* xFilter - configure scan constraints */
       zipfileNext,               /* xNext - advance a cursor */
       zipfileEof,                /* xEof - check for end of scan */
       zipfileColumn,             /* xColumn - read data */
       0,                         /* xRowid - read data */
       zipfileUpdate,             /* xUpdate */
       zipfileBegin,              /* xBegin */
       0,                         /* xSync */
       zipfileCommit,             /* xCommit */
       zipfileRollback,           /* xRollback */
       zipfileFindFunction,       /* xFindMethod */
       0,                         /* xRename */
     };
   
     int rc = sqlite3_create_module(db, "zipfile"  , &zipfileModule, 0);
     if( rc==SQLITE_OK ) rc = sqlite3_overload_function(db, "zipfile_cds", -1);
     if( rc==SQLITE_OK ){
       rc = sqlite3_create_function(db, "zipfile", -1, SQLITE_UTF8, 0, 0, 
           zipfileStep, zipfileFinal
       );
     }
     return rc;
   }
   #else         /* SQLITE_OMIT_VIRTUALTABLE */
   # define zipfileRegister(x) SQLITE_OK
   #endif
   
   #ifdef _WIN32
   
   #endif
   int sqlite3_zipfile_init(
     sqlite3 *db, 
     char **pzErrMsg, 
     const sqlite3_api_routines *pApi
   ){
     SQLITE_EXTENSION_INIT2(pApi);
     (void)pzErrMsg;  /* Unused parameter */
     return zipfileRegister(db);
   }
   
   /************************* End ../ext/misc/zipfile.c ********************/
   /************************* Begin ../ext/misc/sqlar.c ******************/
   /*
   ** 2017-12-17
   **
   ** The author disclaims copyright to this source code.  In place of
   ** a legal notice, here is a blessing:
   **
   **    May you do good and not evil.
   **    May you find forgiveness for yourself and forgive others.
   **    May you share freely, never taking more than you give.
   **
   ******************************************************************************
   **
   ** Utility functions sqlar_compress() and sqlar_uncompress(). Useful
   ** for working with sqlar archives and used by the shell tool's built-in
   ** sqlar support.
   */
   /* #include "sqlite3ext.h" */
   SQLITE_EXTENSION_INIT1
   #include <zlib.h>
   #include <assert.h>
   
   /*
   ** Implementation of the "sqlar_compress(X)" SQL function.
   **
   ** If the type of X is SQLITE_BLOB, and compressing that blob using
   ** zlib utility function compress() yields a smaller blob, return the
   ** compressed blob. Otherwise, return a copy of X.
   **
   ** SQLar uses the "zlib format" for compressed content.  The zlib format
   ** contains a two-byte identification header and a four-byte checksum at
   ** the end.  This is different from ZIP which uses the raw deflate format.
   **
   ** Future enhancements to SQLar might add support for new compression formats.
   ** If so, those new formats will be identified by alternative headers in the
   ** compressed data.
   */
   static void sqlarCompressFunc(
     sqlite3_context *context,
     int argc,
     sqlite3_value **argv
   ){
     assert( argc==1 );
     if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){
       const Bytef *pData = sqlite3_value_blob(argv[0]);
       uLong nData = sqlite3_value_bytes(argv[0]);
       uLongf nOut = compressBound(nData);
       Bytef *pOut;
   
       pOut = (Bytef*)sqlite3_malloc(nOut);
       if( pOut==0 ){
         sqlite3_result_error_nomem(context);
         return;
       }else{
         if( Z_OK!=compress(pOut, &nOut, pData, nData) ){
           sqlite3_result_error(context, "error in compress()", -1);
         }else if( nOut<nData ){
           sqlite3_result_blob(context, pOut, nOut, SQLITE_TRANSIENT);
         }else{
           sqlite3_result_value(context, argv[0]);
         }
         sqlite3_free(pOut);
       }
     }else{
       sqlite3_result_value(context, argv[0]);
     }
   }
   
   /*
   ** Implementation of the "sqlar_uncompress(X,SZ)" SQL function
   **
   ** Parameter SZ is interpreted as an integer. If it is less than or
   ** equal to zero, then this function returns a copy of X. Or, if
   ** SZ is equal to the size of X when interpreted as a blob, also
   ** return a copy of X. Otherwise, decompress blob X using zlib
   ** utility function uncompress() and return the results (another
   ** blob).
   */
   static void sqlarUncompressFunc(
     sqlite3_context *context,
     int argc,
     sqlite3_value **argv
   ){
     uLong nData;
     uLongf sz;
   
     assert( argc==2 );
     sz = sqlite3_value_int(argv[1]);
   
     if( sz<=0 || sz==(nData = sqlite3_value_bytes(argv[0])) ){
       sqlite3_result_value(context, argv[0]);
     }else{
       const Bytef *pData= sqlite3_value_blob(argv[0]);
       Bytef *pOut = sqlite3_malloc(sz);
       if( Z_OK!=uncompress(pOut, &sz, pData, nData) ){
         sqlite3_result_error(context, "error in uncompress()", -1);
       }else{
         sqlite3_result_blob(context, pOut, sz, SQLITE_TRANSIENT);
       }
       sqlite3_free(pOut);
     }
   }
   
   
   #ifdef _WIN32
   
   #endif
   int sqlite3_sqlar_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, "sqlar_compress", 1, 
                                  SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
                                  sqlarCompressFunc, 0, 0);
     if( rc==SQLITE_OK ){
       rc = sqlite3_create_function(db, "sqlar_uncompress", 2,
                                    SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
                                    sqlarUncompressFunc, 0, 0);
     }
     return rc;
   }
   
   /************************* End ../ext/misc/sqlar.c ********************/
   #endif
   /************************* Begin ../ext/expert/sqlite3expert.h ******************/
   /*
   ** 2017 April 07
   **
   ** The author disclaims copyright to this source code.  In place of
   ** a legal notice, here is a blessing:
   **
   **    May you do good and not evil.
   **    May you find forgiveness for yourself and forgive others.
   **    May you share freely, never taking more than you give.
   **
   *************************************************************************
   */
   #if !defined(SQLITEEXPERT_H)
   #define SQLITEEXPERT_H 1
   /* #include "sqlite3.h" */
   
   typedef struct sqlite3expert sqlite3expert;
   
   /*
   ** Create a new sqlite3expert object.
   **
   ** If successful, a pointer to the new object is returned and (*pzErr) set
   ** to NULL. Or, if an error occurs, NULL is returned and (*pzErr) set to
   ** an English-language error message. In this case it is the responsibility
   ** of the caller to eventually free the error message buffer using
   ** sqlite3_free().
   */
   sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErr);
   
   /*
   ** Configure an sqlite3expert object.
   **
   ** EXPERT_CONFIG_SAMPLE:
   **   By default, sqlite3_expert_analyze() generates sqlite_stat1 data for
   **   each candidate index. This involves scanning and sorting the entire
   **   contents of each user database table once for each candidate index
   **   associated with the table. For large databases, this can be 
   **   prohibitively slow. This option allows the sqlite3expert object to
   **   be configured so that sqlite_stat1 data is instead generated based on a
   **   subset of each table, or so that no sqlite_stat1 data is used at all.
   **
   **   A single integer argument is passed to this option. If the value is less
   **   than or equal to zero, then no sqlite_stat1 data is generated or used by
   **   the analysis - indexes are recommended based on the database schema only.
   **   Or, if the value is 100 or greater, complete sqlite_stat1 data is
   **   generated for each candidate index (this is the default). Finally, if the
   **   value falls between 0 and 100, then it represents the percentage of user
   **   table rows that should be considered when generating sqlite_stat1 data.
   **
   **   Examples:
   **
   **     // Do not generate any sqlite_stat1 data
   **     sqlite3_expert_config(pExpert, EXPERT_CONFIG_SAMPLE, 0);
   **
   **     // Generate sqlite_stat1 data based on 10% of the rows in each table.
   **     sqlite3_expert_config(pExpert, EXPERT_CONFIG_SAMPLE, 10);
   */
   int sqlite3_expert_config(sqlite3expert *p, int op, ...);
   
   #define EXPERT_CONFIG_SAMPLE 1    /* int */
   
   /*
   ** Specify zero or more SQL statements to be included in the analysis.
   **
   ** Buffer zSql must contain zero or more complete SQL statements. This
   ** function parses all statements contained in the buffer and adds them
   ** to the internal list of statements to analyze. If successful, SQLITE_OK
   ** is returned and (*pzErr) set to NULL. Or, if an error occurs - for example
   ** due to a error in the SQL - an SQLite error code is returned and (*pzErr)
   ** may be set to point to an English language error message. In this case
   ** the caller is responsible for eventually freeing the error message buffer
   ** using sqlite3_free().
   **
   ** If an error does occur while processing one of the statements in the
   ** buffer passed as the second argument, none of the statements in the
   ** buffer are added to the analysis.
   **
   ** This function must be called before sqlite3_expert_analyze(). If a call
   ** to this function is made on an sqlite3expert object that has already
   ** been passed to sqlite3_expert_analyze() SQLITE_MISUSE is returned
   ** immediately and no statements are added to the analysis.
   */
   int sqlite3_expert_sql(
     sqlite3expert *p,               /* From a successful sqlite3_expert_new() */
     const char *zSql,               /* SQL statement(s) to add */
     char **pzErr                    /* OUT: Error message (if any) */
   );
   
   
   /*
   ** This function is called after the sqlite3expert object has been configured
   ** with all SQL statements using sqlite3_expert_sql() to actually perform
   ** the analysis. Once this function has been called, it is not possible to
   ** add further SQL statements to the analysis.
   **
   ** If successful, SQLITE_OK is returned and (*pzErr) is set to NULL. Or, if
   ** an error occurs, an SQLite error code is returned and (*pzErr) set to 
   ** point to a buffer containing an English language error message. In this
   ** case it is the responsibility of the caller to eventually free the buffer
   ** using sqlite3_free().
   **
   ** If an error does occur within this function, the sqlite3expert object
   ** is no longer useful for any purpose. At that point it is no longer
   ** possible to add further SQL statements to the object or to re-attempt
   ** the analysis. The sqlite3expert object must still be freed using a call
   ** sqlite3_expert_destroy().
   */
   int sqlite3_expert_analyze(sqlite3expert *p, char **pzErr);
   
   /*
   ** Return the total number of statements loaded using sqlite3_expert_sql().
   ** The total number of SQL statements may be different from the total number
   ** to calls to sqlite3_expert_sql().
   */
   int sqlite3_expert_count(sqlite3expert*);
   
   /*
   ** Return a component of the report.
   **
   ** This function is called after sqlite3_expert_analyze() to extract the
   ** results of the analysis. Each call to this function returns either a
   ** NULL pointer or a pointer to a buffer containing a nul-terminated string.
   ** The value passed as the third argument must be one of the EXPERT_REPORT_*
   ** #define constants defined below.
   **
   ** For some EXPERT_REPORT_* parameters, the buffer returned contains 
   ** information relating to a specific SQL statement. In these cases that
   ** SQL statement is identified by the value passed as the second argument.
   ** SQL statements are numbered from 0 in the order in which they are parsed.
   ** If an out-of-range value (less than zero or equal to or greater than the
   ** value returned by sqlite3_expert_count()) is passed as the second argument
   ** along with such an EXPERT_REPORT_* parameter, NULL is always returned.
   **
   ** EXPERT_REPORT_SQL:
   **   Return the text of SQL statement iStmt.
   **
   ** EXPERT_REPORT_INDEXES:
   **   Return a buffer containing the CREATE INDEX statements for all recommended
   **   indexes for statement iStmt. If there are no new recommeded indexes, NULL 
   **   is returned.
   **
   ** EXPERT_REPORT_PLAN:
   **   Return a buffer containing the EXPLAIN QUERY PLAN output for SQL query
   **   iStmt after the proposed indexes have been added to the database schema.
   **
   ** EXPERT_REPORT_CANDIDATES:
   **   Return a pointer to a buffer containing the CREATE INDEX statements 
   **   for all indexes that were tested (for all SQL statements). The iStmt
   **   parameter is ignored for EXPERT_REPORT_CANDIDATES calls.
   */
   const char *sqlite3_expert_report(sqlite3expert*, int iStmt, int eReport);
   
   /*
   ** Values for the third argument passed to sqlite3_expert_report().
   */
   #define EXPERT_REPORT_SQL        1
   #define EXPERT_REPORT_INDEXES    2
   #define EXPERT_REPORT_PLAN       3
   #define EXPERT_REPORT_CANDIDATES 4
   
   /*
   ** Free an (sqlite3expert*) handle and all associated resources. There 
   ** should be one call to this function for each successful call to 
   ** sqlite3-expert_new().
   */
   void sqlite3_expert_destroy(sqlite3expert*);
   
   #endif  /* !defined(SQLITEEXPERT_H) */
   
   /************************* End ../ext/expert/sqlite3expert.h ********************/
   /************************* Begin ../ext/expert/sqlite3expert.c ******************/
   /*
   ** 2017 April 09
   **
   ** The author disclaims copyright to this source code.  In place of
   ** a legal notice, here is a blessing:
   **
   **    May you do good and not evil.
   **    May you find forgiveness for yourself and forgive others.
   **    May you share freely, never taking more than you give.
   **
   *************************************************************************
   */
   /* #include "sqlite3expert.h" */
   #include <assert.h>
   #include <string.h>
   #include <stdio.h>
   
   #ifndef SQLITE_OMIT_VIRTUALTABLE 
   
   /* typedef sqlite3_int64 i64; */
   /* typedef sqlite3_uint64 u64; */
   
   typedef struct IdxColumn IdxColumn;
   typedef struct IdxConstraint IdxConstraint;
   typedef struct IdxScan IdxScan;
   typedef struct IdxStatement IdxStatement;
   typedef struct IdxTable IdxTable;
   typedef struct IdxWrite IdxWrite;
   
   #define STRLEN  (int)strlen
   
   /*
   ** A temp table name that we assume no user database will actually use.
   ** If this assumption proves incorrect triggers on the table with the
   ** conflicting name will be ignored.
   */
   #define UNIQUE_TABLE_NAME "t592690916721053953805701627921227776"
   
   /*
   ** A single constraint. Equivalent to either "col = ?" or "col < ?" (or
   ** any other type of single-ended range constraint on a column).
   **
   ** pLink:
   **   Used to temporarily link IdxConstraint objects into lists while
   **   creating candidate indexes.
   */
   struct IdxConstraint {
     char *zColl;                    /* Collation sequence */
     int bRange;                     /* True for range, false for eq */
     int iCol;                       /* Constrained table column */
     int bFlag;                      /* Used by idxFindCompatible() */
     int bDesc;                      /* True if ORDER BY <expr> DESC */
     IdxConstraint *pNext;           /* Next constraint in pEq or pRange list */
     IdxConstraint *pLink;           /* See above */
   };
   
   /*
   ** A single scan of a single table.
   */
   struct IdxScan {
     IdxTable *pTab;                 /* Associated table object */
     int iDb;                        /* Database containing table zTable */
     i64 covering;                   /* Mask of columns required for cov. index */
     IdxConstraint *pOrder;          /* ORDER BY columns */
     IdxConstraint *pEq;             /* List of == constraints */
     IdxConstraint *pRange;          /* List of < constraints */
     IdxScan *pNextScan;             /* Next IdxScan object for same analysis */
   };
   
   /*
   ** Information regarding a single database table. Extracted from 
   ** "PRAGMA table_info" by function idxGetTableInfo().
   */
   struct IdxColumn {
     char *zName;
     char *zColl;
     int iPk;
   };
   struct IdxTable {
     int nCol;
     char *zName;                    /* Table name */
     IdxColumn *aCol;
     IdxTable *pNext;                /* Next table in linked list of all tables */
   };
   
   /*
   ** An object of the following type is created for each unique table/write-op
   ** seen. The objects are stored in a singly-linked list beginning at
   ** sqlite3expert.pWrite.
   */
   struct IdxWrite {
     IdxTable *pTab;
     int eOp;                        /* SQLITE_UPDATE, DELETE or INSERT */
     IdxWrite *pNext;
   };
   
   /*
   ** Each statement being analyzed is represented by an instance of this
   ** structure.
   */
   struct IdxStatement {
     int iId;                        /* Statement number */
     char *zSql;                     /* SQL statement */
     char *zIdx;                     /* Indexes */
     char *zEQP;                     /* Plan */
     IdxStatement *pNext;
   };
   
   
   /*
   ** A hash table for storing strings. With space for a payload string
   ** with each entry. Methods are:
   **
   **   idxHashInit()
   **   idxHashClear()
   **   idxHashAdd()
   **   idxHashSearch()
   */
   #define IDX_HASH_SIZE 1023
   typedef struct IdxHashEntry IdxHashEntry;
   typedef struct IdxHash IdxHash;
   struct IdxHashEntry {
     char *zKey;                     /* nul-terminated key */
     char *zVal;                     /* nul-terminated value string */
     char *zVal2;                    /* nul-terminated value string 2 */
     IdxHashEntry *pHashNext;        /* Next entry in same hash bucket */
     IdxHashEntry *pNext;            /* Next entry in hash */
   };
   struct IdxHash {
     IdxHashEntry *pFirst;
     IdxHashEntry *aHash[IDX_HASH_SIZE];
   };
   
   /*
   ** sqlite3expert object.
   */
   struct sqlite3expert {
     int iSample;                    /* Percentage of tables to sample for stat1 */
     sqlite3 *db;                    /* User database */
     sqlite3 *dbm;                   /* In-memory db for this analysis */
     sqlite3 *dbv;                   /* Vtab schema for this analysis */
     IdxTable *pTable;               /* List of all IdxTable objects */
     IdxScan *pScan;                 /* List of scan objects */
     IdxWrite *pWrite;               /* List of write objects */
     IdxStatement *pStatement;       /* List of IdxStatement objects */
     int bRun;                       /* True once analysis has run */
     char **pzErrmsg;
     int rc;                         /* Error code from whereinfo hook */
     IdxHash hIdx;                   /* Hash containing all candidate indexes */
     char *zCandidates;              /* For EXPERT_REPORT_CANDIDATES */
   };
   
   
   /*
   ** Allocate and return nByte bytes of zeroed memory using sqlite3_malloc(). 
   ** If the allocation fails, set *pRc to SQLITE_NOMEM and return NULL.
   */
   static void *idxMalloc(int *pRc, int nByte){
     void *pRet;
     assert( *pRc==SQLITE_OK );
     assert( nByte>0 );
     pRet = sqlite3_malloc(nByte);
     if( pRet ){
       memset(pRet, 0, nByte);
     }else{
       *pRc = SQLITE_NOMEM;
     }
     return pRet;
   }
   
   /*
   ** Initialize an IdxHash hash table.
   */
   static void idxHashInit(IdxHash *pHash){
     memset(pHash, 0, sizeof(IdxHash));
   }
   
   /*
   ** Reset an IdxHash hash table.
   */
   static void idxHashClear(IdxHash *pHash){
     int i;
     for(i=0; i<IDX_HASH_SIZE; i++){
       IdxHashEntry *pEntry;
       IdxHashEntry *pNext;
       for(pEntry=pHash->aHash[i]; pEntry; pEntry=pNext){
         pNext = pEntry->pHashNext;
         sqlite3_free(pEntry->zVal2);
         sqlite3_free(pEntry);
       }
     }
     memset(pHash, 0, sizeof(IdxHash));
   }
   
   /*
   ** Return the index of the hash bucket that the string specified by the
   ** arguments to this function belongs.
   */
   static int idxHashString(const char *z, int n){
     unsigned int ret = 0;
     int i;
     for(i=0; i<n; i++){
       ret += (ret<<3) + (unsigned char)(z[i]);
     }
     return (int)(ret % IDX_HASH_SIZE);
   }
   
   /*
   ** If zKey is already present in the hash table, return non-zero and do
   ** nothing. Otherwise, add an entry with key zKey and payload string zVal to
   ** the hash table passed as the second argument. 
   */
   static int idxHashAdd(
     int *pRc, 
     IdxHash *pHash, 
     const char *zKey,
     const char *zVal
   ){
     int nKey = STRLEN(zKey);
     int iHash = idxHashString(zKey, nKey);
     int nVal = (zVal ? STRLEN(zVal) : 0);
     IdxHashEntry *pEntry;
     assert( iHash>=0 );
     for(pEntry=pHash->aHash[iHash]; pEntry; pEntry=pEntry->pHashNext){
       if( STRLEN(pEntry->zKey)==nKey && 0==memcmp(pEntry->zKey, zKey, nKey) ){
         return 1;
       }
     }
     pEntry = idxMalloc(pRc, sizeof(IdxHashEntry) + nKey+1 + nVal+1);
     if( pEntry ){
       pEntry->zKey = (char*)&pEntry[1];
       memcpy(pEntry->zKey, zKey, nKey);
       if( zVal ){
         pEntry->zVal = &pEntry->zKey[nKey+1];
         memcpy(pEntry->zVal, zVal, nVal);
       }
       pEntry->pHashNext = pHash->aHash[iHash];
       pHash->aHash[iHash] = pEntry;
   
       pEntry->pNext = pHash->pFirst;
       pHash->pFirst = pEntry;
     }
     return 0;
   }
   
   /*
   ** If zKey/nKey is present in the hash table, return a pointer to the 
   ** hash-entry object.
   */
   static IdxHashEntry *idxHashFind(IdxHash *pHash, const char *zKey, int nKey){
     int iHash;
     IdxHashEntry *pEntry;
     if( nKey<0 ) nKey = STRLEN(zKey);
     iHash = idxHashString(zKey, nKey);
     assert( iHash>=0 );
     for(pEntry=pHash->aHash[iHash]; pEntry; pEntry=pEntry->pHashNext){
       if( STRLEN(pEntry->zKey)==nKey && 0==memcmp(pEntry->zKey, zKey, nKey) ){
         return pEntry;
       }
     }
     return 0;
   }
   
   /*
   ** If the hash table contains an entry with a key equal to the string
   ** passed as the final two arguments to this function, return a pointer
   ** to the payload string. Otherwise, if zKey/nKey is not present in the
   ** hash table, return NULL.
   */
   static const char *idxHashSearch(IdxHash *pHash, const char *zKey, int nKey){
     IdxHashEntry *pEntry = idxHashFind(pHash, zKey, nKey);
     if( pEntry ) return pEntry->zVal;
     return 0;
   }
   
   /*
   ** Allocate and return a new IdxConstraint object. Set the IdxConstraint.zColl
   ** variable to point to a copy of nul-terminated string zColl.
   */
   static IdxConstraint *idxNewConstraint(int *pRc, const char *zColl){
     IdxConstraint *pNew;
     int nColl = STRLEN(zColl);
   
     assert( *pRc==SQLITE_OK );
     pNew = (IdxConstraint*)idxMalloc(pRc, sizeof(IdxConstraint) * nColl + 1);
     if( pNew ){
       pNew->zColl = (char*)&pNew[1];
       memcpy(pNew->zColl, zColl, nColl+1);
     }
     return pNew;
   }
   
   /*
   ** An error associated with database handle db has just occurred. Pass
   ** the error message to callback function xOut.
   */
   static void idxDatabaseError(
     sqlite3 *db,                    /* Database handle */
     char **pzErrmsg                 /* Write error here */
   ){
     *pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(db));
   }
   
   /*
   ** Prepare an SQL statement.
   */
   static int idxPrepareStmt(
     sqlite3 *db,                    /* Database handle to compile against */
     sqlite3_stmt **ppStmt,          /* OUT: Compiled SQL statement */
     char **pzErrmsg,                /* OUT: sqlite3_malloc()ed error message */
     const char *zSql                /* SQL statement to compile */
   ){
     int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0);
     if( rc!=SQLITE_OK ){
       *ppStmt = 0;
       idxDatabaseError(db, pzErrmsg);
     }
     return rc;
   }
   
   /*
   ** Prepare an SQL statement using the results of a printf() formatting.
   */
   static int idxPrintfPrepareStmt(
     sqlite3 *db,                    /* Database handle to compile against */
     sqlite3_stmt **ppStmt,          /* OUT: Compiled SQL statement */
     char **pzErrmsg,                /* OUT: sqlite3_malloc()ed error message */
     const char *zFmt,               /* printf() format of SQL statement */
     ...                             /* Trailing printf() arguments */
   ){
     va_list ap;
     int rc;
     char *zSql;
     va_start(ap, zFmt);
     zSql = sqlite3_vmprintf(zFmt, ap);
     if( zSql==0 ){
       rc = SQLITE_NOMEM;
     }else{
       rc = idxPrepareStmt(db, ppStmt, pzErrmsg, zSql);
       sqlite3_free(zSql);
     }
     va_end(ap);
     return rc;
   }
   
   
   /*************************************************************************
   ** Beginning of virtual table implementation.
   */
   typedef struct ExpertVtab ExpertVtab;
   struct ExpertVtab {
     sqlite3_vtab base;
     IdxTable *pTab;
     sqlite3expert *pExpert;
   };
   
   typedef struct ExpertCsr ExpertCsr;
   struct ExpertCsr {
     sqlite3_vtab_cursor base;
     sqlite3_stmt *pData;
   };
   
   static char *expertDequote(const char *zIn){
     int n = STRLEN(zIn);
     char *zRet = sqlite3_malloc(n);
   
     assert( zIn[0]=='\'' );
     assert( zIn[n-1]=='\'' );
   
     if( zRet ){
       int iOut = 0;
       int iIn = 0;
       for(iIn=1; iIn<(n-1); iIn++){
         if( zIn[iIn]=='\'' ){
           assert( zIn[iIn+1]=='\'' );
           iIn++;
         }
         zRet[iOut++] = zIn[iIn];
       }
       zRet[iOut] = '\0';
     }
   
     return zRet;
   }
   
   /* 
   ** This function is the implementation of both the xConnect and xCreate
   ** methods of the r-tree virtual table.
   **
   **   argv[0]   -> module name
   **   argv[1]   -> database name
   **   argv[2]   -> table name
   **   argv[...] -> column names...
   */
   static int expertConnect(
     sqlite3 *db,
     void *pAux,
     int argc, const char *const*argv,
     sqlite3_vtab **ppVtab,
     char **pzErr
   ){
     sqlite3expert *pExpert = (sqlite3expert*)pAux;
     ExpertVtab *p = 0;
     int rc;
   
     if( argc!=4 ){
       *pzErr = sqlite3_mprintf("internal error!");
       rc = SQLITE_ERROR;
     }else{
       char *zCreateTable = expertDequote(argv[3]);
       if( zCreateTable ){
         rc = sqlite3_declare_vtab(db, zCreateTable);
         if( rc==SQLITE_OK ){
           p = idxMalloc(&rc, sizeof(ExpertVtab));
         }
         if( rc==SQLITE_OK ){
           p->pExpert = pExpert;
           p->pTab = pExpert->pTable;
           assert( sqlite3_stricmp(p->pTab->zName, argv[2])==0 );
         }
         sqlite3_free(zCreateTable);
       }else{
         rc = SQLITE_NOMEM;
       }
     }
   
     *ppVtab = (sqlite3_vtab*)p;
     return rc;
   }
   
   static int expertDisconnect(sqlite3_vtab *pVtab){
     ExpertVtab *p = (ExpertVtab*)pVtab;
     sqlite3_free(p);
     return SQLITE_OK;
   }
   
   static int expertBestIndex(sqlite3_vtab *pVtab, sqlite3_index_info *pIdxInfo){
     ExpertVtab *p = (ExpertVtab*)pVtab;
     int rc = SQLITE_OK;
     int n = 0;
     IdxScan *pScan;
     const int opmask = 
       SQLITE_INDEX_CONSTRAINT_EQ | SQLITE_INDEX_CONSTRAINT_GT |
       SQLITE_INDEX_CONSTRAINT_LT | SQLITE_INDEX_CONSTRAINT_GE |
       SQLITE_INDEX_CONSTRAINT_LE;
   
     pScan = idxMalloc(&rc, sizeof(IdxScan));
     if( pScan ){
       int i;
   
       /* Link the new scan object into the list */
       pScan->pTab = p->pTab;
       pScan->pNextScan = p->pExpert->pScan;
       p->pExpert->pScan = pScan;
   
       /* Add the constraints to the IdxScan object */
       for(i=0; i<pIdxInfo->nConstraint; i++){
         struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i];
         if( pCons->usable 
          && pCons->iColumn>=0 
          && p->pTab->aCol[pCons->iColumn].iPk==0
          && (pCons->op & opmask) 
         ){
           IdxConstraint *pNew;
           const char *zColl = sqlite3_vtab_collation(pIdxInfo, i);
           pNew = idxNewConstraint(&rc, zColl);
           if( pNew ){
             pNew->iCol = pCons->iColumn;
             if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){
               pNew->pNext = pScan->pEq;
               pScan->pEq = pNew;
             }else{
               pNew->bRange = 1;
               pNew->pNext = pScan->pRange;
               pScan->pRange = pNew;
             }
           }
           n++;
           pIdxInfo->aConstraintUsage[i].argvIndex = n;
         }
       }
   
       /* Add the ORDER BY to the IdxScan object */
       for(i=pIdxInfo->nOrderBy-1; i>=0; i--){
         int iCol = pIdxInfo->aOrderBy[i].iColumn;
         if( iCol>=0 ){
           IdxConstraint *pNew = idxNewConstraint(&rc, p->pTab->aCol[iCol].zColl);
           if( pNew ){
             pNew->iCol = iCol;
             pNew->bDesc = pIdxInfo->aOrderBy[i].desc;
             pNew->pNext = pScan->pOrder;
             pNew->pLink = pScan->pOrder;
             pScan->pOrder = pNew;
             n++;
           }
         }
       }
     }
   
     pIdxInfo->estimatedCost = 1000000.0 / (n+1);
     return rc;
   }
   
   static int expertUpdate(
     sqlite3_vtab *pVtab, 
     int nData, 
     sqlite3_value **azData, 
     sqlite_int64 *pRowid
   ){
     (void)pVtab;
     (void)nData;
     (void)azData;
     (void)pRowid;
     return SQLITE_OK;
   }
   
   /* 
   ** Virtual table module xOpen method.
   */
   static int expertOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
     int rc = SQLITE_OK;
     ExpertCsr *pCsr;
     (void)pVTab;
     pCsr = idxMalloc(&rc, sizeof(ExpertCsr));
     *ppCursor = (sqlite3_vtab_cursor*)pCsr;
     return rc;
   }
   
   /* 
   ** Virtual table module xClose method.
   */
   static int expertClose(sqlite3_vtab_cursor *cur){
     ExpertCsr *pCsr = (ExpertCsr*)cur;
     sqlite3_finalize(pCsr->pData);
     sqlite3_free(pCsr);
     return SQLITE_OK;
   }
   
   /*
   ** Virtual table module xEof method.
   **
   ** Return non-zero if the cursor does not currently point to a valid 
   ** record (i.e if the scan has finished), or zero otherwise.
   */
   static int expertEof(sqlite3_vtab_cursor *cur){
     ExpertCsr *pCsr = (ExpertCsr*)cur;
     return pCsr->pData==0;
   }
   
   /* 
   ** Virtual table module xNext method.
   */
   static int expertNext(sqlite3_vtab_cursor *cur){
     ExpertCsr *pCsr = (ExpertCsr*)cur;
     int rc = SQLITE_OK;
   
     assert( pCsr->pData );
     rc = sqlite3_step(pCsr->pData);
     if( rc!=SQLITE_ROW ){
       rc = sqlite3_finalize(pCsr->pData);
       pCsr->pData = 0;
     }else{
       rc = SQLITE_OK;
     }
   
     return rc;
   }
   
   /* 
   ** Virtual table module xRowid method.
   */
   static int expertRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
     (void)cur;
     *pRowid = 0;
     return SQLITE_OK;
   }
   
   /* 
   ** Virtual table module xColumn method.
   */
   static int expertColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
     ExpertCsr *pCsr = (ExpertCsr*)cur;
     sqlite3_value *pVal;
     pVal = sqlite3_column_value(pCsr->pData, i);
     if( pVal ){
       sqlite3_result_value(ctx, pVal);
     }
     return SQLITE_OK;
   }
   
   /* 
   ** Virtual table module xFilter method.
   */
   static int expertFilter(
     sqlite3_vtab_cursor *cur, 
     int idxNum, const char *idxStr,
     int argc, sqlite3_value **argv
   ){
     ExpertCsr *pCsr = (ExpertCsr*)cur;
     ExpertVtab *pVtab = (ExpertVtab*)(cur->pVtab);
     sqlite3expert *pExpert = pVtab->pExpert;
     int rc;
   
     (void)idxNum;
     (void)idxStr;
     (void)argc;
     (void)argv;
     rc = sqlite3_finalize(pCsr->pData);
     pCsr->pData = 0;
     if( rc==SQLITE_OK ){
       rc = idxPrintfPrepareStmt(pExpert->db, &pCsr->pData, &pVtab->base.zErrMsg,
           "SELECT * FROM main.%Q WHERE sample()", pVtab->pTab->zName
       );
     }
   
     if( rc==SQLITE_OK ){
       rc = expertNext(cur);
     }
     return rc;
   }
   
   static int idxRegisterVtab(sqlite3expert *p){
     static sqlite3_module expertModule = {
       2,                            /* iVersion */
       expertConnect,                /* xCreate - create a table */
       expertConnect,                /* xConnect - connect to an existing table */
       expertBestIndex,              /* xBestIndex - Determine search strategy */
       expertDisconnect,             /* xDisconnect - Disconnect from a table */
       expertDisconnect,             /* xDestroy - Drop a table */
       expertOpen,                   /* xOpen - open a cursor */
       expertClose,                  /* xClose - close a cursor */
       expertFilter,                 /* xFilter - configure scan constraints */
       expertNext,                   /* xNext - advance a cursor */
       expertEof,                    /* xEof */
       expertColumn,                 /* xColumn - read data */
       expertRowid,                  /* xRowid - read data */
       expertUpdate,                 /* xUpdate - write data */
       0,                            /* xBegin - begin transaction */
       0,                            /* xSync - sync transaction */
       0,                            /* xCommit - commit transaction */
       0,                            /* xRollback - rollback transaction */
       0,                            /* xFindFunction - function overloading */
       0,                            /* xRename - rename the table */
       0,                            /* xSavepoint */
       0,                            /* xRelease */
       0,                            /* xRollbackTo */
       0,                            /* xShadowName */
     };
   
     return sqlite3_create_module(p->dbv, "expert", &expertModule, (void*)p);
   }
   /*
   ** End of virtual table implementation.
   *************************************************************************/
   /*
   ** Finalize SQL statement pStmt. If (*pRc) is SQLITE_OK when this function
   ** is called, set it to the return value of sqlite3_finalize() before
   ** returning. Otherwise, discard the sqlite3_finalize() return value.
   */
   static void idxFinalize(int *pRc, sqlite3_stmt *pStmt){
     int rc = sqlite3_finalize(pStmt);
     if( *pRc==SQLITE_OK ) *pRc = rc;
   }
   
   /*
   ** Attempt to allocate an IdxTable structure corresponding to table zTab
   ** in the main database of connection db. If successful, set (*ppOut) to
   ** point to the new object and return SQLITE_OK. Otherwise, return an
   ** SQLite error code and set (*ppOut) to NULL. In this case *pzErrmsg may be
   ** set to point to an error string.
   **
   ** It is the responsibility of the caller to eventually free either the
   ** IdxTable object or error message using sqlite3_free().
   */
   static int idxGetTableInfo(
     sqlite3 *db,                    /* Database connection to read details from */
     const char *zTab,               /* Table name */
     IdxTable **ppOut,               /* OUT: New object (if successful) */
     char **pzErrmsg                 /* OUT: Error message (if not) */
   ){
     sqlite3_stmt *p1 = 0;
     int nCol = 0;
     int nTab = STRLEN(zTab);
     int nByte = sizeof(IdxTable) + nTab + 1;
     IdxTable *pNew = 0;
     int rc, rc2;
     char *pCsr = 0;
     int nPk = 0;
   
     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);
       nByte += 1 + STRLEN(zCol);
       rc = sqlite3_table_column_metadata(
           db, "main", zTab, zCol, 0, &zCol, 0, 0, 0
       );
       nByte += 1 + STRLEN(zCol);
       nCol++;
       nPk += (sqlite3_column_int(p1, 5)>0);
     }
     rc2 = sqlite3_reset(p1);
     if( rc==SQLITE_OK ) rc = rc2;
   
     nByte += sizeof(IdxColumn) * nCol;
     if( rc==SQLITE_OK ){
       pNew = idxMalloc(&rc, nByte);
     }
     if( rc==SQLITE_OK ){
       pNew->aCol = (IdxColumn*)&pNew[1];
       pNew->nCol = nCol;
       pCsr = (char*)&pNew->aCol[nCol];
     }
   
     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;
       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
       );
       if( rc==SQLITE_OK ){
         nCopy = STRLEN(zCol) + 1;
         pNew->aCol[nCol].zColl = pCsr;
         memcpy(pCsr, zCol, nCopy);
         pCsr += nCopy;
       }
   
       nCol++;
     }
     idxFinalize(&rc, p1);
   
     if( rc!=SQLITE_OK ){
       sqlite3_free(pNew);
       pNew = 0;
     }else{
       pNew->zName = pCsr;
       memcpy(pNew->zName, zTab, nTab+1);
     }
   
     *ppOut = pNew;
     return rc;
   }
   
   /*
   ** This function is a no-op if *pRc is set to anything other than 
   ** SQLITE_OK when it is called.
   **
   ** If *pRc is initially set to SQLITE_OK, then the text specified by
   ** the printf() style arguments is appended to zIn and the result returned
   ** in a buffer allocated by sqlite3_malloc(). sqlite3_free() is called on
   ** zIn before returning.
   */
   static char *idxAppendText(int *pRc, char *zIn, const char *zFmt, ...){
     va_list ap;
     char *zAppend = 0;
     char *zRet = 0;
     int nIn = zIn ? STRLEN(zIn) : 0;
     int nAppend = 0;
     va_start(ap, zFmt);
     if( *pRc==SQLITE_OK ){
       zAppend = sqlite3_vmprintf(zFmt, ap);
       if( zAppend ){
         nAppend = STRLEN(zAppend);
         zRet = (char*)sqlite3_malloc(nIn + nAppend + 1);
       }
       if( zAppend && zRet ){
         if( nIn ) memcpy(zRet, zIn, nIn);
         memcpy(&zRet[nIn], zAppend, nAppend+1);
       }else{
         sqlite3_free(zRet);
         zRet = 0;
         *pRc = SQLITE_NOMEM;
       }
       sqlite3_free(zAppend);
       sqlite3_free(zIn);
     }
     va_end(ap);
     return zRet;
   }
   
   /*
   ** Return true if zId must be quoted in order to use it as an SQL
   ** identifier, or false otherwise.
   */
   static int idxIdentifierRequiresQuotes(const char *zId){
     int i;
     for(i=0; zId[i]; i++){
       if( !(zId[i]=='_')
        && !(zId[i]>='0' && zId[i]<='9')
        && !(zId[i]>='a' && zId[i]<='z')
        && !(zId[i]>='A' && zId[i]<='Z')
       ){
         return 1;
       }
     }
     return 0;
   }
   
   /*
   ** This function appends an index column definition suitable for constraint
   ** pCons to the string passed as zIn and returns the result.
   */
   static char *idxAppendColDefn(
     int *pRc,                       /* IN/OUT: Error code */
     char *zIn,                      /* Column defn accumulated so far */
     IdxTable *pTab,                 /* Table index will be created on */
     IdxConstraint *pCons
   ){
     char *zRet = zIn;
     IdxColumn *p = &pTab->aCol[pCons->iCol];
     if( zRet ) zRet = idxAppendText(pRc, zRet, ", ");
   
     if( idxIdentifierRequiresQuotes(p->zName) ){
       zRet = idxAppendText(pRc, zRet, "%Q", p->zName);
     }else{
       zRet = idxAppendText(pRc, zRet, "%s", p->zName);
     }
   
     if( sqlite3_stricmp(p->zColl, pCons->zColl) ){
       if( idxIdentifierRequiresQuotes(pCons->zColl) ){
         zRet = idxAppendText(pRc, zRet, " COLLATE %Q", pCons->zColl);
       }else{
         zRet = idxAppendText(pRc, zRet, " COLLATE %s", pCons->zColl);
       }
     }
   
     if( pCons->bDesc ){
       zRet = idxAppendText(pRc, zRet, " DESC");
     }
     return zRet;
   }
   
   /*
   ** Search database dbm for an index compatible with the one idxCreateFromCons()
   ** would create from arguments pScan, pEq and pTail. If no error occurs and 
   ** such an index is found, return non-zero. Or, if no such index is found,
   ** return zero.
   **
   ** If an error occurs, set *pRc to an SQLite error code and return zero.
   */
   static int idxFindCompatible(
     int *pRc,                       /* OUT: Error code */
     sqlite3* dbm,                   /* Database to search */
     IdxScan *pScan,                 /* Scan for table to search for index on */
     IdxConstraint *pEq,             /* List of == constraints */
     IdxConstraint *pTail            /* List of range constraints */
   ){
     const char *zTbl = pScan->pTab->zName;
     sqlite3_stmt *pIdxList = 0;
     IdxConstraint *pIter;
     int nEq = 0;                    /* Number of elements in pEq */
     int rc;
   
     /* Count the elements in list pEq */
     for(pIter=pEq; pIter; pIter=pIter->pLink) nEq++;
   
     rc = idxPrintfPrepareStmt(dbm, &pIdxList, 0, "PRAGMA index_list=%Q", zTbl);
     while( rc==SQLITE_OK && sqlite3_step(pIdxList)==SQLITE_ROW ){
       int bMatch = 1;
       IdxConstraint *pT = pTail;
       sqlite3_stmt *pInfo = 0;
       const char *zIdx = (const char*)sqlite3_column_text(pIdxList, 1);
   
       /* Zero the IdxConstraint.bFlag values in the pEq list */
       for(pIter=pEq; pIter; pIter=pIter->pLink) pIter->bFlag = 0;
   
       rc = idxPrintfPrepareStmt(dbm, &pInfo, 0, "PRAGMA index_xInfo=%Q", zIdx);
       while( rc==SQLITE_OK && sqlite3_step(pInfo)==SQLITE_ROW ){
         int iIdx = sqlite3_column_int(pInfo, 0);
         int iCol = sqlite3_column_int(pInfo, 1);
         const char *zColl = (const char*)sqlite3_column_text(pInfo, 4);
   
         if( iIdx<nEq ){
           for(pIter=pEq; pIter; pIter=pIter->pLink){
             if( pIter->bFlag ) continue;
             if( pIter->iCol!=iCol ) continue;
             if( sqlite3_stricmp(pIter->zColl, zColl) ) continue;
             pIter->bFlag = 1;
             break;
           }
           if( pIter==0 ){
             bMatch = 0;
             break;
           }
         }else{
           if( pT ){
             if( pT->iCol!=iCol || sqlite3_stricmp(pT->zColl, zColl) ){
               bMatch = 0;
               break;
             }
             pT = pT->pLink;
           }
         }
       }
       idxFinalize(&rc, pInfo);
   
       if( rc==SQLITE_OK && bMatch ){
         sqlite3_finalize(pIdxList);
         return 1;
       }
     }
     idxFinalize(&rc, pIdxList);
   
     *pRc = rc;
     return 0;
   }
   
   static int idxCreateFromCons(
     sqlite3expert *p,
     IdxScan *pScan,
     IdxConstraint *pEq, 
     IdxConstraint *pTail
   ){
     sqlite3 *dbm = p->dbm;
     int rc = SQLITE_OK;
     if( (pEq || pTail) && 0==idxFindCompatible(&rc, dbm, pScan, pEq, pTail) ){
       IdxTable *pTab = pScan->pTab;
       char *zCols = 0;
       char *zIdx = 0;
       IdxConstraint *pCons;
       unsigned int h = 0;
       const char *zFmt;
   
       for(pCons=pEq; pCons; pCons=pCons->pLink){
         zCols = idxAppendColDefn(&rc, zCols, pTab, pCons);
       }
       for(pCons=pTail; pCons; pCons=pCons->pLink){
         zCols = idxAppendColDefn(&rc, zCols, pTab, pCons);
       }
   
       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 ){ 
           rc = SQLITE_NOMEM;
         }else{
           if( idxIdentifierRequiresQuotes(zTable) ){
             zFmt = "CREATE INDEX '%q' ON %Q(%s)";
           }else{
             zFmt = "CREATE INDEX %s ON %s(%s)";
           }
           zIdx = sqlite3_mprintf(zFmt, zName, zTable, zCols);
           if( !zIdx ){
             rc = SQLITE_NOMEM;
           }else{
             rc = sqlite3_exec(dbm, zIdx, 0, 0, p->pzErrmsg);
             idxHashAdd(&rc, &p->hIdx, zName, zIdx);
           }
           sqlite3_free(zName);
           sqlite3_free(zIdx);
         }
       }
   
       sqlite3_free(zCols);
     }
     return rc;
   }
   
   /*
   ** Return true if list pList (linked by IdxConstraint.pLink) contains
   ** a constraint compatible with *p. Otherwise return false.
   */
   static int idxFindConstraint(IdxConstraint *pList, IdxConstraint *p){
     IdxConstraint *pCmp;
     for(pCmp=pList; pCmp; pCmp=pCmp->pLink){
       if( p->iCol==pCmp->iCol ) return 1;
     }
     return 0;
   }
   
   static int idxCreateFromWhere(
     sqlite3expert *p, 
     IdxScan *pScan,                 /* Create indexes for this scan */
     IdxConstraint *pTail            /* range/ORDER BY constraints for inclusion */
   ){
     IdxConstraint *p1 = 0;
     IdxConstraint *pCon;
     int rc;
   
     /* Gather up all the == constraints. */
     for(pCon=pScan->pEq; pCon; pCon=pCon->pNext){
       if( !idxFindConstraint(p1, pCon) && !idxFindConstraint(pTail, pCon) ){
         pCon->pLink = p1;
         p1 = pCon;
       }
     }
   
     /* Create an index using the == constraints collected above. And the
     ** range constraint/ORDER BY terms passed in by the caller, if any. */
     rc = idxCreateFromCons(p, pScan, p1, pTail);
   
     /* If no range/ORDER BY passed by the caller, create a version of the
     ** index for each range constraint.  */
     if( pTail==0 ){
       for(pCon=pScan->pRange; rc==SQLITE_OK && pCon; pCon=pCon->pNext){
         assert( pCon->pLink==0 );
         if( !idxFindConstraint(p1, pCon) && !idxFindConstraint(pTail, pCon) ){
           rc = idxCreateFromCons(p, pScan, p1, pCon);
         }
       }
     }
   
     return rc;
   }
   
   /*
   ** Create candidate indexes in database [dbm] based on the data in 
   ** linked-list pScan.
   */
   static int idxCreateCandidates(sqlite3expert *p){
     int rc = SQLITE_OK;
     IdxScan *pIter;
   
     for(pIter=p->pScan; pIter && rc==SQLITE_OK; pIter=pIter->pNextScan){
       rc = idxCreateFromWhere(p, pIter, 0);
       if( rc==SQLITE_OK && pIter->pOrder ){
         rc = idxCreateFromWhere(p, pIter, pIter->pOrder);
       }
     }
   
     return rc;
   }
   
   /*
   ** Free all elements of the linked list starting at pConstraint.
   */
   static void idxConstraintFree(IdxConstraint *pConstraint){
     IdxConstraint *pNext;
     IdxConstraint *p;
   
     for(p=pConstraint; p; p=pNext){
       pNext = p->pNext;
       sqlite3_free(p);
     }
   }
   
   /*
   ** Free all elements of the linked list starting from pScan up until pLast
   ** (pLast is not freed).
   */
   static void idxScanFree(IdxScan *pScan, IdxScan *pLast){
     IdxScan *p;
     IdxScan *pNext;
     for(p=pScan; p!=pLast; p=pNext){
       pNext = p->pNextScan;
       idxConstraintFree(p->pOrder);
       idxConstraintFree(p->pEq);
       idxConstraintFree(p->pRange);
       sqlite3_free(p);
     }
   }
   
   /*
   ** Free all elements of the linked list starting from pStatement up 
   ** until pLast (pLast is not freed).
   */
   static void idxStatementFree(IdxStatement *pStatement, IdxStatement *pLast){
     IdxStatement *p;
     IdxStatement *pNext;
     for(p=pStatement; p!=pLast; p=pNext){
       pNext = p->pNext;
       sqlite3_free(p->zEQP);
       sqlite3_free(p->zIdx);
       sqlite3_free(p);
     }
   }
   
   /*
   ** Free the linked list of IdxTable objects starting at pTab.
   */
   static void idxTableFree(IdxTable *pTab){
     IdxTable *pIter;
     IdxTable *pNext;
     for(pIter=pTab; pIter; pIter=pNext){
       pNext = pIter->pNext;
       sqlite3_free(pIter);
     }
   }
   
   /*
   ** Free the linked list of IdxWrite objects starting at pTab.
   */
   static void idxWriteFree(IdxWrite *pTab){
     IdxWrite *pIter;
     IdxWrite *pNext;
     for(pIter=pTab; pIter; pIter=pNext){
       pNext = pIter->pNext;
       sqlite3_free(pIter);
     }
   }
   
   
   
   /*
   ** This function is called after candidate indexes have been created. It
   ** runs all the queries to see which indexes they prefer, and populates
   ** IdxStatement.zIdx and IdxStatement.zEQP with the results.
   */
   int idxFindIndexes(
     sqlite3expert *p,
     char **pzErr                         /* OUT: Error message (sqlite3_malloc) */
   ){
     IdxStatement *pStmt;
     sqlite3 *dbm = p->dbm;
     int rc = SQLITE_OK;
   
     IdxHash hIdx;
     idxHashInit(&hIdx);
   
     for(pStmt=p->pStatement; rc==SQLITE_OK && pStmt; pStmt=pStmt->pNext){
       IdxHashEntry *pEntry;
       sqlite3_stmt *pExplain = 0;
       idxHashClear(&hIdx);
       rc = idxPrintfPrepareStmt(dbm, &pExplain, pzErr,
           "EXPLAIN QUERY PLAN %s", pStmt->zSql
       );
       while( rc==SQLITE_OK && sqlite3_step(pExplain)==SQLITE_ROW ){
         /* int iId = sqlite3_column_int(pExplain, 0); */
         /* int iParent = sqlite3_column_int(pExplain, 1); */
         /* int iNotUsed = sqlite3_column_int(pExplain, 2); */
         const char *zDetail = (const char*)sqlite3_column_text(pExplain, 3);
         int nDetail;
         int i;
   
         if( !zDetail ) continue;
         nDetail = STRLEN(zDetail);
   
         for(i=0; i<nDetail; i++){
           const char *zIdx = 0;
           if( i+13<nDetail && memcmp(&zDetail[i], " USING INDEX ", 13)==0 ){
             zIdx = &zDetail[i+13];
           }else if( i+22<nDetail 
               && memcmp(&zDetail[i], " USING COVERING INDEX ", 22)==0 
           ){
             zIdx = &zDetail[i+22];
           }
           if( zIdx ){
             const char *zSql;
             int nIdx = 0;
             while( zIdx[nIdx]!='\0' && (zIdx[nIdx]!=' ' || zIdx[nIdx+1]!='(') ){
               nIdx++;
             }
             zSql = idxHashSearch(&p->hIdx, zIdx, nIdx);
             if( zSql ){
               idxHashAdd(&rc, &hIdx, zSql, 0);
               if( rc ) goto find_indexes_out;
             }
             break;
           }
         }
   
         if( zDetail[0]!='-' ){
           pStmt->zEQP = idxAppendText(&rc, pStmt->zEQP, "%s\n", zDetail);
         }
       }
   
       for(pEntry=hIdx.pFirst; pEntry; pEntry=pEntry->pNext){
         pStmt->zIdx = idxAppendText(&rc, pStmt->zIdx, "%s;\n", pEntry->zKey);
       }
   
       idxFinalize(&rc, pExplain);
     }
   
    find_indexes_out:
     idxHashClear(&hIdx);
     return rc;
   }
   
   static int idxAuthCallback(
     void *pCtx,
     int eOp,
     const char *z3,
     const char *z4,
     const char *zDb,
     const char *zTrigger
   ){
     int rc = SQLITE_OK;
     (void)z4;
     (void)zTrigger;
     if( eOp==SQLITE_INSERT || eOp==SQLITE_UPDATE || eOp==SQLITE_DELETE ){
       if( sqlite3_stricmp(zDb, "main")==0 ){
         sqlite3expert *p = (sqlite3expert*)pCtx;
         IdxTable *pTab;
         for(pTab=p->pTable; pTab; pTab=pTab->pNext){
           if( 0==sqlite3_stricmp(z3, pTab->zName) ) break;
         }
         if( pTab ){
           IdxWrite *pWrite;
           for(pWrite=p->pWrite; pWrite; pWrite=pWrite->pNext){
             if( pWrite->pTab==pTab && pWrite->eOp==eOp ) break;
           }
           if( pWrite==0 ){
             pWrite = idxMalloc(&rc, sizeof(IdxWrite));
             if( rc==SQLITE_OK ){
               pWrite->pTab = pTab;
               pWrite->eOp = eOp;
               pWrite->pNext = p->pWrite;
               p->pWrite = pWrite;
             }
           }
         }
       }
     }
     return rc;
   }
   
   static int idxProcessOneTrigger(
     sqlite3expert *p, 
     IdxWrite *pWrite, 
     char **pzErr
   ){
     static const char *zInt = UNIQUE_TABLE_NAME;
     static const char *zDrop = "DROP TABLE " UNIQUE_TABLE_NAME;
     IdxTable *pTab = pWrite->pTab;
     const char *zTab = pTab->zName;
     const char *zSql = 
       "SELECT 'CREATE TEMP' || substr(sql, 7) FROM sqlite_schema "
       "WHERE tbl_name = %Q AND type IN ('table', 'trigger') "
       "ORDER BY type;";
     sqlite3_stmt *pSelect = 0;
     int rc = SQLITE_OK;
     char *zWrite = 0;
   
     /* Create the table and its triggers in the temp schema */
     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);
       rc = sqlite3_exec(p->dbv, zCreate, 0, 0, pzErr);
     }
     idxFinalize(&rc, pSelect);
   
     /* Rename the table in the temp schema to zInt */
     if( rc==SQLITE_OK ){
       char *z = sqlite3_mprintf("ALTER TABLE temp.%Q RENAME TO %Q", zTab, zInt);
       if( z==0 ){
         rc = SQLITE_NOMEM;
       }else{
         rc = sqlite3_exec(p->dbv, z, 0, 0, pzErr);
         sqlite3_free(z);
       }
     }
   
     switch( pWrite->eOp ){
       case SQLITE_INSERT: {
         int i;
         zWrite = idxAppendText(&rc, zWrite, "INSERT INTO %Q VALUES(", zInt);
         for(i=0; i<pTab->nCol; i++){
           zWrite = idxAppendText(&rc, zWrite, "%s?", i==0 ? "" : ", ");
         }
         zWrite = idxAppendText(&rc, zWrite, ")");
         break;
       }
       case SQLITE_UPDATE: {
         int i;
         zWrite = idxAppendText(&rc, zWrite, "UPDATE %Q SET ", zInt);
         for(i=0; i<pTab->nCol; i++){
           zWrite = idxAppendText(&rc, zWrite, "%s%Q=?", i==0 ? "" : ", ", 
               pTab->aCol[i].zName
           );
         }
         break;
       }
       default: {
         assert( pWrite->eOp==SQLITE_DELETE );
         if( rc==SQLITE_OK ){
           zWrite = sqlite3_mprintf("DELETE FROM %Q", zInt);
           if( zWrite==0 ) rc = SQLITE_NOMEM;
         }
       }
     }
   
     if( rc==SQLITE_OK ){
       sqlite3_stmt *pX = 0;
       rc = sqlite3_prepare_v2(p->dbv, zWrite, -1, &pX, 0);
       idxFinalize(&rc, pX);
       if( rc!=SQLITE_OK ){
         idxDatabaseError(p->dbv, pzErr);
       }
     }
     sqlite3_free(zWrite);
   
     if( rc==SQLITE_OK ){
       rc = sqlite3_exec(p->dbv, zDrop, 0, 0, pzErr);
     }
   
     return rc;
   }
   
   static int idxProcessTriggers(sqlite3expert *p, char **pzErr){
     int rc = SQLITE_OK;
     IdxWrite *pEnd = 0;
     IdxWrite *pFirst = p->pWrite;
   
     while( rc==SQLITE_OK && pFirst!=pEnd ){
       IdxWrite *pIter;
       for(pIter=pFirst; rc==SQLITE_OK && pIter!=pEnd; pIter=pIter->pNext){
         rc = idxProcessOneTrigger(p, pIter, pzErr);
       }
       pEnd = pFirst;
       pFirst = p->pWrite;
     }
   
     return rc;
   }
   
   
   static int idxCreateVtabSchema(sqlite3expert *p, char **pzErrmsg){
     int rc = idxRegisterVtab(p);
     sqlite3_stmt *pSchema = 0;
   
     /* For each table in the main db schema:
     **
     **   1) Add an entry to the p->pTable list, and
     **   2) Create the equivalent virtual table in dbv.
     */
     rc = idxPrepareStmt(p->db, &pSchema, pzErrmsg,
         "SELECT type, name, sql, 1 FROM sqlite_schema "
         "WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%%' "
         " UNION ALL "
         "SELECT type, name, sql, 2 FROM sqlite_schema "
         "WHERE type = 'trigger'"
         "  AND tbl_name IN(SELECT name FROM sqlite_schema WHERE type = 'view') "
         "ORDER BY 4, 1"
     );
     while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSchema) ){
       const char *zType = (const char*)sqlite3_column_text(pSchema, 0);
       const char *zName = (const char*)sqlite3_column_text(pSchema, 1);
       const char *zSql = (const char*)sqlite3_column_text(pSchema, 2);
   
       if( zType[0]=='v' || zType[1]=='r' ){
         rc = sqlite3_exec(p->dbv, zSql, 0, 0, pzErrmsg);
       }else{
         IdxTable *pTab;
         rc = idxGetTableInfo(p->db, zName, &pTab, pzErrmsg);
         if( rc==SQLITE_OK ){
           int i;
           char *zInner = 0;
           char *zOuter = 0;
           pTab->pNext = p->pTable;
           p->pTable = pTab;
   
           /* The statement the vtab will pass to sqlite3_declare_vtab() */
           zInner = idxAppendText(&rc, 0, "CREATE TABLE x(");
           for(i=0; i<pTab->nCol; i++){
             zInner = idxAppendText(&rc, zInner, "%s%Q COLLATE %s", 
                 (i==0 ? "" : ", "), pTab->aCol[i].zName, pTab->aCol[i].zColl
             );
           }
           zInner = idxAppendText(&rc, zInner, ")");
   
           /* The CVT statement to create the vtab */
           zOuter = idxAppendText(&rc, 0, 
               "CREATE VIRTUAL TABLE %Q USING expert(%Q)", zName, zInner
           );
           if( rc==SQLITE_OK ){
             rc = sqlite3_exec(p->dbv, zOuter, 0, 0, pzErrmsg);
           }
           sqlite3_free(zInner);
           sqlite3_free(zOuter);
         }
       }
     }
     idxFinalize(&rc, pSchema);
     return rc;
   }
   
   struct IdxSampleCtx {
     int iTarget;
     double target;                  /* Target nRet/nRow value */
     double nRow;                    /* Number of rows seen */
     double nRet;                    /* Number of rows returned */
   };
   
   static void idxSampleFunc(
     sqlite3_context *pCtx,
     int argc,
     sqlite3_value **argv
   ){
     struct IdxSampleCtx *p = (struct IdxSampleCtx*)sqlite3_user_data(pCtx);
     int bRet;
   
     (void)argv;
     assert( argc==0 );
     if( p->nRow==0.0 ){
       bRet = 1;
     }else{
       bRet = (p->nRet / p->nRow) <= p->target;
       if( bRet==0 ){
         unsigned short rnd;
         sqlite3_randomness(2, (void*)&rnd);
         bRet = ((int)rnd % 100) <= p->iTarget;
       }
     }
   
     sqlite3_result_int(pCtx, bRet);
     p->nRow += 1.0;
     p->nRet += (double)bRet;
   }
   
   struct IdxRemCtx {
     int nSlot;
     struct IdxRemSlot {
       int eType;                    /* SQLITE_NULL, INTEGER, REAL, TEXT, BLOB */
       i64 iVal;                     /* SQLITE_INTEGER value */
       double rVal;                  /* SQLITE_FLOAT value */
       int nByte;                    /* Bytes of space allocated at z */
       int n;                        /* Size of buffer z */
       char *z;                      /* SQLITE_TEXT/BLOB value */
     } aSlot[1];
   };
   
   /*
   ** Implementation of scalar function rem().
   */
   static void idxRemFunc(
     sqlite3_context *pCtx,
     int argc,
     sqlite3_value **argv
   ){
     struct IdxRemCtx *p = (struct IdxRemCtx*)sqlite3_user_data(pCtx);
     struct IdxRemSlot *pSlot;
     int iSlot;
     assert( argc==2 );
   
     iSlot = sqlite3_value_int(argv[0]);
     assert( iSlot<=p->nSlot );
     pSlot = &p->aSlot[iSlot];
   
     switch( pSlot->eType ){
       case SQLITE_NULL:
         /* no-op */
         break;
   
       case SQLITE_INTEGER:
         sqlite3_result_int64(pCtx, pSlot->iVal);
         break;
   
       case SQLITE_FLOAT:
         sqlite3_result_double(pCtx, pSlot->rVal);
         break;
   
       case SQLITE_BLOB:
         sqlite3_result_blob(pCtx, pSlot->z, pSlot->n, SQLITE_TRANSIENT);
         break;
   
       case SQLITE_TEXT:
         sqlite3_result_text(pCtx, pSlot->z, pSlot->n, SQLITE_TRANSIENT);
         break;
     }
   
     pSlot->eType = sqlite3_value_type(argv[1]);
     switch( pSlot->eType ){
       case SQLITE_NULL:
         /* no-op */
         break;
   
       case SQLITE_INTEGER:
         pSlot->iVal = sqlite3_value_int64(argv[1]);
         break;
   
       case SQLITE_FLOAT:
         pSlot->rVal = sqlite3_value_double(argv[1]);
         break;
   
       case SQLITE_BLOB:
       case SQLITE_TEXT: {
         int nByte = sqlite3_value_bytes(argv[1]);
         if( nByte>pSlot->nByte ){
           char *zNew = (char*)sqlite3_realloc(pSlot->z, nByte*2);
           if( zNew==0 ){
             sqlite3_result_error_nomem(pCtx);
             return;
           }
           pSlot->nByte = nByte*2;
           pSlot->z = zNew;
         }
         pSlot->n = nByte;
         if( pSlot->eType==SQLITE_BLOB ){
           memcpy(pSlot->z, sqlite3_value_blob(argv[1]), nByte);
         }else{
           memcpy(pSlot->z, sqlite3_value_text(argv[1]), nByte);
         }
         break;
       }
     }
   }
   
   static int idxLargestIndex(sqlite3 *db, int *pnMax, char **pzErr){
     int rc = SQLITE_OK;
     const char *zMax = 
       "SELECT max(i.seqno) FROM "
       "  sqlite_schema AS s, "
       "  pragma_index_list(s.name) AS l, "
       "  pragma_index_info(l.name) AS i "
       "WHERE s.type = 'table'";
     sqlite3_stmt *pMax = 0;
   
     *pnMax = 0;
     rc = idxPrepareStmt(db, &pMax, pzErr, zMax);
     if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pMax) ){
       *pnMax = sqlite3_column_int(pMax, 0) + 1;
     }
     idxFinalize(&rc, pMax);
   
     return rc;
   }
   
   static int idxPopulateOneStat1(
     sqlite3expert *p,
     sqlite3_stmt *pIndexXInfo,
     sqlite3_stmt *pWriteStat,
     const char *zTab,
     const char *zIdx,
     char **pzErr
   ){
     char *zCols = 0;
     char *zOrder = 0;
     char *zQuery = 0;
     int nCol = 0;
     int i;
     sqlite3_stmt *pQuery = 0;
     int *aStat = 0;
     int rc = SQLITE_OK;
   
     assert( p->iSample>0 );
   
     /* Formulate the query text */
     sqlite3_bind_text(pIndexXInfo, 1, zIdx, -1, SQLITE_STATIC);
     while( SQLITE_OK==rc && SQLITE_ROW==sqlite3_step(pIndexXInfo) ){
       const char *zComma = zCols==0 ? "" : ", ";
       const char *zName = (const char*)sqlite3_column_text(pIndexXInfo, 0);
       const char *zColl = (const char*)sqlite3_column_text(pIndexXInfo, 1);
       zCols = idxAppendText(&rc, zCols, 
           "%sx.%Q IS rem(%d, x.%Q) COLLATE %s", zComma, zName, nCol, zName, zColl
       );
       zOrder = idxAppendText(&rc, zOrder, "%s%d", zComma, ++nCol);
     }
     sqlite3_reset(pIndexXInfo);
     if( rc==SQLITE_OK ){
       if( p->iSample==100 ){
         zQuery = sqlite3_mprintf(
             "SELECT %s FROM %Q x ORDER BY %s", zCols, zTab, zOrder
         );
       }else{
         zQuery = sqlite3_mprintf(
             "SELECT %s FROM temp."UNIQUE_TABLE_NAME" x ORDER BY %s", zCols, zOrder
         );
       }
     }
     sqlite3_free(zCols);
     sqlite3_free(zOrder);
   
     /* Formulate the query text */
     if( rc==SQLITE_OK ){
       sqlite3 *dbrem = (p->iSample==100 ? p->db : p->dbv);
       rc = idxPrepareStmt(dbrem, &pQuery, pzErr, zQuery);
     }
     sqlite3_free(zQuery);
   
     if( rc==SQLITE_OK ){
       aStat = (int*)idxMalloc(&rc, sizeof(int)*(nCol+1));
     }
     if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pQuery) ){
       IdxHashEntry *pEntry;
       char *zStat = 0;
       for(i=0; i<=nCol; i++) aStat[i] = 1;
       while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pQuery) ){
         aStat[0]++;
         for(i=0; i<nCol; i++){
           if( sqlite3_column_int(pQuery, i)==0 ) break;
         }
         for(/*no-op*/; i<nCol; i++){
           aStat[i+1]++;
         }
       }
   
       if( rc==SQLITE_OK ){
         int s0 = aStat[0];
         zStat = sqlite3_mprintf("%d", s0);
         if( zStat==0 ) rc = SQLITE_NOMEM;
         for(i=1; rc==SQLITE_OK && i<=nCol; i++){
           zStat = idxAppendText(&rc, zStat, " %d", (s0+aStat[i]/2) / aStat[i]);
         }
       }
   
       if( rc==SQLITE_OK ){
         sqlite3_bind_text(pWriteStat, 1, zTab, -1, SQLITE_STATIC);
         sqlite3_bind_text(pWriteStat, 2, zIdx, -1, SQLITE_STATIC);
         sqlite3_bind_text(pWriteStat, 3, zStat, -1, SQLITE_STATIC);
         sqlite3_step(pWriteStat);
         rc = sqlite3_reset(pWriteStat);
       }
   
       pEntry = idxHashFind(&p->hIdx, zIdx, STRLEN(zIdx));
       if( pEntry ){
         assert( pEntry->zVal2==0 );
         pEntry->zVal2 = zStat;
       }else{
         sqlite3_free(zStat);
       }
     }
     sqlite3_free(aStat);
     idxFinalize(&rc, pQuery);
   
     return rc;
   }
   
   static int idxBuildSampleTable(sqlite3expert *p, const char *zTab){
     int rc;
     char *zSql;
   
     rc = sqlite3_exec(p->dbv,"DROP TABLE IF EXISTS temp."UNIQUE_TABLE_NAME,0,0,0);
     if( rc!=SQLITE_OK ) return rc;
   
     zSql = sqlite3_mprintf(
         "CREATE TABLE temp." UNIQUE_TABLE_NAME " AS SELECT * FROM %Q", zTab
     );
     if( zSql==0 ) return SQLITE_NOMEM;
     rc = sqlite3_exec(p->dbv, zSql, 0, 0, 0);
     sqlite3_free(zSql);
   
     return rc;
   }
   
   /*
   ** This function is called as part of sqlite3_expert_analyze(). Candidate
   ** indexes have already been created in database sqlite3expert.dbm, this
   ** function populates sqlite_stat1 table in the same database.
   **
   ** The stat1 data is generated by querying the 
   */
   static int idxPopulateStat1(sqlite3expert *p, char **pzErr){
     int rc = SQLITE_OK;
     int nMax =0;
     struct IdxRemCtx *pCtx = 0;
     struct IdxSampleCtx samplectx; 
     int i;
     i64 iPrev = -100000;
     sqlite3_stmt *pAllIndex = 0;
     sqlite3_stmt *pIndexXInfo = 0;
     sqlite3_stmt *pWrite = 0;
   
     const char *zAllIndex =
       "SELECT s.rowid, s.name, l.name FROM "
       "  sqlite_schema AS s, "
       "  pragma_index_list(s.name) AS l "
       "WHERE s.type = 'table'";
     const char *zIndexXInfo = 
       "SELECT name, coll FROM pragma_index_xinfo(?) WHERE key";
     const char *zWrite = "INSERT INTO sqlite_stat1 VALUES(?, ?, ?)";
   
     /* If iSample==0, no sqlite_stat1 data is required. */
     if( p->iSample==0 ) return SQLITE_OK;
   
     rc = idxLargestIndex(p->dbm, &nMax, pzErr);
     if( nMax<=0 || rc!=SQLITE_OK ) return rc;
   
     rc = sqlite3_exec(p->dbm, "ANALYZE; PRAGMA writable_schema=1", 0, 0, 0);
   
     if( rc==SQLITE_OK ){
       int nByte = sizeof(struct IdxRemCtx) + (sizeof(struct IdxRemSlot) * nMax);
       pCtx = (struct IdxRemCtx*)idxMalloc(&rc, nByte);
     }
   
     if( rc==SQLITE_OK ){
       sqlite3 *dbrem = (p->iSample==100 ? p->db : p->dbv);
       rc = sqlite3_create_function(
           dbrem, "rem", 2, SQLITE_UTF8, (void*)pCtx, idxRemFunc, 0, 0
       );
     }
     if( rc==SQLITE_OK ){
       rc = sqlite3_create_function(
           p->db, "sample", 0, SQLITE_UTF8, (void*)&samplectx, idxSampleFunc, 0, 0
       );
     }
   
     if( rc==SQLITE_OK ){
       pCtx->nSlot = nMax+1;
       rc = idxPrepareStmt(p->dbm, &pAllIndex, pzErr, zAllIndex);
     }
     if( rc==SQLITE_OK ){
       rc = idxPrepareStmt(p->dbm, &pIndexXInfo, pzErr, zIndexXInfo);
     }
     if( rc==SQLITE_OK ){
       rc = idxPrepareStmt(p->dbm, &pWrite, pzErr, zWrite);
     }
   
     while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pAllIndex) ){
       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( p->iSample<100 && iPrev!=iRowid ){
         samplectx.target = (double)p->iSample / 100.0;
         samplectx.iTarget = p->iSample;
         samplectx.nRow = 0.0;
         samplectx.nRet = 0.0;
         rc = idxBuildSampleTable(p, zTab);
         if( rc!=SQLITE_OK ) break;
       }
       rc = idxPopulateOneStat1(p, pIndexXInfo, pWrite, zTab, zIdx, pzErr);
       iPrev = iRowid;
     }
     if( rc==SQLITE_OK && p->iSample<100 ){
       rc = sqlite3_exec(p->dbv, 
           "DROP TABLE IF EXISTS temp." UNIQUE_TABLE_NAME, 0,0,0
       );
     }
   
     idxFinalize(&rc, pAllIndex);
     idxFinalize(&rc, pIndexXInfo);
     idxFinalize(&rc, pWrite);
   
     if( pCtx ){
       for(i=0; i<pCtx->nSlot; i++){
         sqlite3_free(pCtx->aSlot[i].z);
       }
       sqlite3_free(pCtx);
     }
   
     if( rc==SQLITE_OK ){
       rc = sqlite3_exec(p->dbm, "ANALYZE sqlite_schema", 0, 0, 0);
     }
   
     sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp."UNIQUE_TABLE_NAME,0,0,0);
     return rc;
   }
   
   /*
   ** Allocate a new sqlite3expert object.
   */
   sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErrmsg){
     int rc = SQLITE_OK;
     sqlite3expert *pNew;
   
     pNew = (sqlite3expert*)idxMalloc(&rc, sizeof(sqlite3expert));
   
     /* Open two in-memory databases to work with. The "vtab database" (dbv)
     ** will contain a virtual table corresponding to each real table in
     ** the user database schema, and a copy of each view. It is used to
     ** collect information regarding the WHERE, ORDER BY and other clauses
     ** of the user's query.
     */
     if( rc==SQLITE_OK ){
       pNew->db = db;
       pNew->iSample = 100;
       rc = sqlite3_open(":memory:", &pNew->dbv);
     }
     if( rc==SQLITE_OK ){
       rc = sqlite3_open(":memory:", &pNew->dbm);
       if( rc==SQLITE_OK ){
         sqlite3_db_config(pNew->dbm, SQLITE_DBCONFIG_TRIGGER_EQP, 1, (int*)0);
       }
     }
     
   
     /* Copy the entire schema of database [db] into [dbm]. */
     if( rc==SQLITE_OK ){
       sqlite3_stmt *pSql;
       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);
       }
       idxFinalize(&rc, pSql);
     }
   
     /* Create the vtab schema */
     if( rc==SQLITE_OK ){
       rc = idxCreateVtabSchema(pNew, pzErrmsg);
     }
   
     /* Register the auth callback with dbv */
     if( rc==SQLITE_OK ){
       sqlite3_set_authorizer(pNew->dbv, idxAuthCallback, (void*)pNew);
     }
   
     /* If an error has occurred, free the new object and reutrn NULL. Otherwise,
     ** return the new sqlite3expert handle.  */
     if( rc!=SQLITE_OK ){
       sqlite3_expert_destroy(pNew);
       pNew = 0;
     }
     return pNew;
   }
   
   /*
   ** Configure an sqlite3expert object.
   */
   int sqlite3_expert_config(sqlite3expert *p, int op, ...){
     int rc = SQLITE_OK;
     va_list ap;
     va_start(ap, op);
     switch( op ){
       case EXPERT_CONFIG_SAMPLE: {
         int iVal = va_arg(ap, int);
         if( iVal<0 ) iVal = 0;
         if( iVal>100 ) iVal = 100;
         p->iSample = iVal;
         break;
       }
       default:
         rc = SQLITE_NOTFOUND;
         break;
     }
   
     va_end(ap);
     return rc;
   }
   
   /*
   ** Add an SQL statement to the analysis.
   */
   int sqlite3_expert_sql(
     sqlite3expert *p,               /* From sqlite3_expert_new() */
     const char *zSql,               /* SQL statement to add */
     char **pzErr                    /* OUT: Error message (if any) */
   ){
     IdxScan *pScanOrig = p->pScan;
     IdxStatement *pStmtOrig = p->pStatement;
     int rc = SQLITE_OK;
     const char *zStmt = zSql;
   
     if( p->bRun ) return SQLITE_MISUSE;
   
     while( rc==SQLITE_OK && zStmt && zStmt[0] ){
       sqlite3_stmt *pStmt = 0;
       rc = sqlite3_prepare_v2(p->dbv, zStmt, -1, &pStmt, &zStmt);
       if( rc==SQLITE_OK ){
         if( pStmt ){
           IdxStatement *pNew;
           const char *z = sqlite3_sql(pStmt);
           int n = STRLEN(z);
           pNew = (IdxStatement*)idxMalloc(&rc, sizeof(IdxStatement) + n+1);
           if( rc==SQLITE_OK ){
             pNew->zSql = (char*)&pNew[1];
             memcpy(pNew->zSql, z, n+1);
             pNew->pNext = p->pStatement;
             if( p->pStatement ) pNew->iId = p->pStatement->iId+1;
             p->pStatement = pNew;
           }
           sqlite3_finalize(pStmt);
         }
       }else{
         idxDatabaseError(p->dbv, pzErr);
       }
     }
   
     if( rc!=SQLITE_OK ){
       idxScanFree(p->pScan, pScanOrig);
       idxStatementFree(p->pStatement, pStmtOrig);
       p->pScan = pScanOrig;
       p->pStatement = pStmtOrig;
     }
   
     return rc;
   }
   
   int sqlite3_expert_analyze(sqlite3expert *p, char **pzErr){
     int rc;
     IdxHashEntry *pEntry;
   
     /* Do trigger processing to collect any extra IdxScan structures */
     rc = idxProcessTriggers(p, pzErr);
   
     /* Create candidate indexes within the in-memory database file */
     if( rc==SQLITE_OK ){
       rc = idxCreateCandidates(p);
     }
   
     /* Generate the stat1 data */
     if( rc==SQLITE_OK ){
       rc = idxPopulateStat1(p, pzErr);
     }
   
     /* Formulate the EXPERT_REPORT_CANDIDATES text */
     for(pEntry=p->hIdx.pFirst; pEntry; pEntry=pEntry->pNext){
       p->zCandidates = idxAppendText(&rc, p->zCandidates, 
           "%s;%s%s\n", pEntry->zVal, 
           pEntry->zVal2 ? " -- stat1: " : "", pEntry->zVal2
       );
     }
   
     /* Figure out which of the candidate indexes are preferred by the query
     ** planner and report the results to the user.  */
     if( rc==SQLITE_OK ){
       rc = idxFindIndexes(p, pzErr);
     }
   
     if( rc==SQLITE_OK ){
       p->bRun = 1;
     }
     return rc;
   }
   
   /*
   ** Return the total number of statements that have been added to this
   ** sqlite3expert using sqlite3_expert_sql().
   */
   int sqlite3_expert_count(sqlite3expert *p){
     int nRet = 0;
     if( p->pStatement ) nRet = p->pStatement->iId+1;
     return nRet;
   }
   
   /*
   ** Return a component of the report.
   */
   const char *sqlite3_expert_report(sqlite3expert *p, int iStmt, int eReport){
     const char *zRet = 0;
     IdxStatement *pStmt;
   
     if( p->bRun==0 ) return 0;
     for(pStmt=p->pStatement; pStmt && pStmt->iId!=iStmt; pStmt=pStmt->pNext);
     switch( eReport ){
       case EXPERT_REPORT_SQL:
         if( pStmt ) zRet = pStmt->zSql;
         break;
       case EXPERT_REPORT_INDEXES:
         if( pStmt ) zRet = pStmt->zIdx;
         break;
       case EXPERT_REPORT_PLAN:
         if( pStmt ) zRet = pStmt->zEQP;
         break;
       case EXPERT_REPORT_CANDIDATES:
         zRet = p->zCandidates;
         break;
     }
     return zRet;
   }
   
   /*
   ** Free an sqlite3expert object.
   */
   void sqlite3_expert_destroy(sqlite3expert *p){
     if( p ){
       sqlite3_close(p->dbm);
       sqlite3_close(p->dbv);
       idxScanFree(p->pScan, 0);
       idxStatementFree(p->pStatement, 0);
       idxTableFree(p->pTable);
       idxWriteFree(p->pWrite);
       idxHashClear(&p->hIdx);
       sqlite3_free(p->zCandidates);
       sqlite3_free(p);
     }
   }
   
   #endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
   
   /************************* End ../ext/expert/sqlite3expert.c ********************/
   
   #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
   /************************* Begin ../ext/misc/dbdata.c ******************/
   /*
   ** 2019-04-17
   **
   ** The author disclaims copyright to this source code.  In place of
   ** a legal notice, here is a blessing:
   **
   **    May you do good and not evil.
   **    May you find forgiveness for yourself and forgive others.
   **    May you share freely, never taking more than you give.
   **
   ******************************************************************************
   **
   ** This file contains an implementation of two eponymous virtual tables,
   ** "sqlite_dbdata" and "sqlite_dbptr". Both modules require that the
   ** "sqlite_dbpage" eponymous virtual table be available.
   **
   ** SQLITE_DBDATA:
   **   sqlite_dbdata is used to extract data directly from a database b-tree
   **   page and its associated overflow pages, bypassing the b-tree layer.
   **   The table schema is equivalent to:
   **
   **     CREATE TABLE sqlite_dbdata(
   **       pgno INTEGER,
   **       cell INTEGER,
   **       field INTEGER,
   **       value ANY,
   **       schema TEXT HIDDEN
   **     );
   **
   **   IMPORTANT: THE VIRTUAL TABLE SCHEMA ABOVE IS SUBJECT TO CHANGE. IN THE
   **   FUTURE NEW NON-HIDDEN COLUMNS MAY BE ADDED BETWEEN "value" AND
   **   "schema".
   **
   **   Each page of the database is inspected. If it cannot be interpreted as
   **   a b-tree page, or if it is a b-tree page containing 0 entries, the
   **   sqlite_dbdata table contains no rows for that page.  Otherwise, the
   **   table contains one row for each field in the record associated with
   **   each cell on the page. For intkey b-trees, the key value is stored in
   **   field -1.
   **
   **   For example, for the database:
   **
   **     CREATE TABLE t1(a, b);     -- root page is page 2
   **     INSERT INTO t1(rowid, a, b) VALUES(5, 'v', 'five');
   **     INSERT INTO t1(rowid, a, b) VALUES(10, 'x', 'ten');
   **
   **   the sqlite_dbdata table contains, as well as from entries related to 
   **   page 1, content equivalent to:
   **
   **     INSERT INTO sqlite_dbdata(pgno, cell, field, value) VALUES
   **         (2, 0, -1, 5     ),
   **         (2, 0,  0, 'v'   ),
   **         (2, 0,  1, 'five'),
   **         (2, 1, -1, 10    ),
   **         (2, 1,  0, 'x'   ),
   **         (2, 1,  1, 'ten' );
   **
   **   If database corruption is encountered, this module does not report an
   **   error. Instead, it attempts to extract as much data as possible and
   **   ignores the corruption.
   **
   ** SQLITE_DBPTR:
   **   The sqlite_dbptr table has the following schema:
   **
   **     CREATE TABLE sqlite_dbptr(
   **       pgno INTEGER,
   **       child INTEGER,
   **       schema TEXT HIDDEN
   **     );
   **
   **   It contains one entry for each b-tree pointer between a parent and
   **   child page in the database.
   */
   #if !defined(SQLITEINT_H) 
   /* #include "sqlite3ext.h" */
   
   /* typedef unsigned char u8; */
   
   #endif
   SQLITE_EXTENSION_INIT1
   #include <string.h>
   #include <assert.h>
   
   #define DBDATA_PADDING_BYTES 100 
   
   typedef struct DbdataTable DbdataTable;
   typedef struct DbdataCursor DbdataCursor;
   
   /* Cursor object */
   struct DbdataCursor {
     sqlite3_vtab_cursor base;       /* Base class.  Must be first */
     sqlite3_stmt *pStmt;            /* For fetching database pages */
   
     int iPgno;                      /* Current page number */
     u8 *aPage;                      /* Buffer containing page */
     int nPage;                      /* Size of aPage[] in bytes */
     int nCell;                      /* Number of cells on aPage[] */
     int iCell;                      /* Current cell number */
     int bOnePage;                   /* True to stop after one page */
     int szDb;
     sqlite3_int64 iRowid;
   
     /* Only for the sqlite_dbdata table */
     u8 *pRec;                       /* Buffer containing current record */
     int nRec;                       /* Size of pRec[] in bytes */
     int nHdr;                       /* Size of header in bytes */
     int iField;                     /* Current field number */
     u8 *pHdrPtr;
     u8 *pPtr;
     
     sqlite3_int64 iIntkey;          /* Integer key value */
   };
   
   /* Table object */
   struct DbdataTable {
     sqlite3_vtab base;              /* Base class.  Must be first */
     sqlite3 *db;                    /* The database connection */
     sqlite3_stmt *pStmt;            /* For fetching database pages */
     int bPtr;                       /* True for sqlite3_dbptr table */
   };
   
   /* Column and schema definitions for sqlite_dbdata */
   #define DBDATA_COLUMN_PGNO        0
   #define DBDATA_COLUMN_CELL        1
   #define DBDATA_COLUMN_FIELD       2
   #define DBDATA_COLUMN_VALUE       3
   #define DBDATA_COLUMN_SCHEMA      4
   #define DBDATA_SCHEMA             \
         "CREATE TABLE x("           \
         "  pgno INTEGER,"           \
         "  cell INTEGER,"           \
         "  field INTEGER,"          \
         "  value ANY,"              \
         "  schema TEXT HIDDEN"      \
         ")"
   
   /* Column and schema definitions for sqlite_dbptr */
   #define DBPTR_COLUMN_PGNO         0
   #define DBPTR_COLUMN_CHILD        1
   #define DBPTR_COLUMN_SCHEMA       2
   #define DBPTR_SCHEMA              \
         "CREATE TABLE x("           \
         "  pgno INTEGER,"           \
         "  child INTEGER,"          \
         "  schema TEXT HIDDEN"      \
         ")"
   
   /*
   ** Connect to an sqlite_dbdata (pAux==0) or sqlite_dbptr (pAux!=0) virtual 
   ** table.
   */
   static int dbdataConnect(
     sqlite3 *db,
     void *pAux,
     int argc, const char *const*argv,
     sqlite3_vtab **ppVtab,
     char **pzErr
   ){
     DbdataTable *pTab = 0;
     int rc = sqlite3_declare_vtab(db, pAux ? DBPTR_SCHEMA : DBDATA_SCHEMA);
   
     if( rc==SQLITE_OK ){
       pTab = (DbdataTable*)sqlite3_malloc64(sizeof(DbdataTable));
       if( pTab==0 ){
         rc = SQLITE_NOMEM;
       }else{
         memset(pTab, 0, sizeof(DbdataTable));
         pTab->db = db;
         pTab->bPtr = (pAux!=0);
       }
     }
   
     *ppVtab = (sqlite3_vtab*)pTab;
     return rc;
   }
   
   /*
   ** Disconnect from or destroy a sqlite_dbdata or sqlite_dbptr virtual table.
   */
   static int dbdataDisconnect(sqlite3_vtab *pVtab){
     DbdataTable *pTab = (DbdataTable*)pVtab;
     if( pTab ){
       sqlite3_finalize(pTab->pStmt);
       sqlite3_free(pVtab);
     }
     return SQLITE_OK;
   }
   
   /*
   ** This function interprets two types of constraints:
   **
   **       schema=?
   **       pgno=?
   **
   ** If neither are present, idxNum is set to 0. If schema=? is present,
   ** the 0x01 bit in idxNum is set. If pgno=? is present, the 0x02 bit
   ** in idxNum is set.
   **
   ** If both parameters are present, schema is in position 0 and pgno in
   ** position 1.
   */
   static int dbdataBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdx){
     DbdataTable *pTab = (DbdataTable*)tab;
     int i;
     int iSchema = -1;
     int iPgno = -1;
     int colSchema = (pTab->bPtr ? DBPTR_COLUMN_SCHEMA : DBDATA_COLUMN_SCHEMA);
   
     for(i=0; i<pIdx->nConstraint; i++){
       struct sqlite3_index_constraint *p = &pIdx->aConstraint[i];
       if( p->op==SQLITE_INDEX_CONSTRAINT_EQ ){
         if( p->iColumn==colSchema ){
           if( p->usable==0 ) return SQLITE_CONSTRAINT;
           iSchema = i;
         }
         if( p->iColumn==DBDATA_COLUMN_PGNO && p->usable ){
           iPgno = i;
         }
       }
     }
   
     if( iSchema>=0 ){
       pIdx->aConstraintUsage[iSchema].argvIndex = 1;
       pIdx->aConstraintUsage[iSchema].omit = 1;
     }
     if( iPgno>=0 ){
       pIdx->aConstraintUsage[iPgno].argvIndex = 1 + (iSchema>=0);
       pIdx->aConstraintUsage[iPgno].omit = 1;
       pIdx->estimatedCost = 100;
       pIdx->estimatedRows =  50;
   
       if( pTab->bPtr==0 && pIdx->nOrderBy && pIdx->aOrderBy[0].desc==0 ){
         int iCol = pIdx->aOrderBy[0].iColumn;
         if( pIdx->nOrderBy==1 ){
           pIdx->orderByConsumed = (iCol==0 || iCol==1);
         }else if( pIdx->nOrderBy==2 && pIdx->aOrderBy[1].desc==0 && iCol==0 ){
           pIdx->orderByConsumed = (pIdx->aOrderBy[1].iColumn==1);
         }
       }
   
     }else{
       pIdx->estimatedCost = 100000000;
       pIdx->estimatedRows = 1000000000;
     }
     pIdx->idxNum = (iSchema>=0 ? 0x01 : 0x00) | (iPgno>=0 ? 0x02 : 0x00);
     return SQLITE_OK;
   }
   
   /*
   ** Open a new sqlite_dbdata or sqlite_dbptr cursor.
   */
   static int dbdataOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
     DbdataCursor *pCsr;
   
     pCsr = (DbdataCursor*)sqlite3_malloc64(sizeof(DbdataCursor));
     if( pCsr==0 ){
       return SQLITE_NOMEM;
     }else{
       memset(pCsr, 0, sizeof(DbdataCursor));
       pCsr->base.pVtab = pVTab;
     }
   
     *ppCursor = (sqlite3_vtab_cursor *)pCsr;
     return SQLITE_OK;
   }
   
   /*
   ** Restore a cursor object to the state it was in when first allocated 
   ** by dbdataOpen().
   */
   static void dbdataResetCursor(DbdataCursor *pCsr){
     DbdataTable *pTab = (DbdataTable*)(pCsr->base.pVtab);
     if( pTab->pStmt==0 ){
       pTab->pStmt = pCsr->pStmt;
     }else{
       sqlite3_finalize(pCsr->pStmt);
     }
     pCsr->pStmt = 0;
     pCsr->iPgno = 1;
     pCsr->iCell = 0;
     pCsr->iField = 0;
     pCsr->bOnePage = 0;
     sqlite3_free(pCsr->aPage);
     sqlite3_free(pCsr->pRec);
     pCsr->pRec = 0;
     pCsr->aPage = 0;
   }
   
   /*
   ** Close an sqlite_dbdata or sqlite_dbptr cursor.
   */
   static int dbdataClose(sqlite3_vtab_cursor *pCursor){
     DbdataCursor *pCsr = (DbdataCursor*)pCursor;
     dbdataResetCursor(pCsr);
     sqlite3_free(pCsr);
     return SQLITE_OK;
   }
   
   /* 
   ** Utility methods to decode 16 and 32-bit big-endian unsigned integers. 
   */
   static unsigned int get_uint16(unsigned char *a){
     return (a[0]<<8)|a[1];
   }
   static unsigned int get_uint32(unsigned char *a){
     return ((unsigned int)a[0]<<24)
          | ((unsigned int)a[1]<<16)
          | ((unsigned int)a[2]<<8)
          | ((unsigned int)a[3]);
   }
   
   /*
   ** Load page pgno from the database via the sqlite_dbpage virtual table.
   ** If successful, set (*ppPage) to point to a buffer containing the page
   ** data, (*pnPage) to the size of that buffer in bytes and return
   ** SQLITE_OK. In this case it is the responsibility of the caller to
   ** eventually free the buffer using sqlite3_free().
   **
   ** Or, if an error occurs, set both (*ppPage) and (*pnPage) to 0 and
   ** return an SQLite error code.
   */
   static int dbdataLoadPage(
     DbdataCursor *pCsr,             /* Cursor object */
     unsigned int pgno,              /* Page number of page to load */
     u8 **ppPage,                    /* OUT: pointer to page buffer */
     int *pnPage                     /* OUT: Size of (*ppPage) in bytes */
   ){
     int rc2;
     int rc = SQLITE_OK;
     sqlite3_stmt *pStmt = pCsr->pStmt;
   
     *ppPage = 0;
     *pnPage = 0;
     sqlite3_bind_int64(pStmt, 2, pgno);
     if( SQLITE_ROW==sqlite3_step(pStmt) ){
       int nCopy = sqlite3_column_bytes(pStmt, 0);
       if( nCopy>0 ){
         u8 *pPage;
         pPage = (u8*)sqlite3_malloc64(nCopy + DBDATA_PADDING_BYTES);
         if( pPage==0 ){
           rc = SQLITE_NOMEM;
         }else{
           const u8 *pCopy = sqlite3_column_blob(pStmt, 0);
           memcpy(pPage, pCopy, nCopy);
           memset(&pPage[nCopy], 0, DBDATA_PADDING_BYTES);
         }
         *ppPage = pPage;
         *pnPage = nCopy;
       }
     }
     rc2 = sqlite3_reset(pStmt);
     if( rc==SQLITE_OK ) rc = rc2;
   
     return rc;
   }
   
   /*
   ** Read a varint.  Put the value in *pVal and return the number of bytes.
   */
   static int dbdataGetVarint(const u8 *z, sqlite3_int64 *pVal){
     sqlite3_int64 v = 0;
     int i;
     for(i=0; i<8; i++){
       v = (v<<7) + (z[i]&0x7f);
       if( (z[i]&0x80)==0 ){ *pVal = v; return i+1; }
     }
     v = (v<<8) + (z[i]&0xff);
     *pVal = v;
     return 9;
   }
   
   /*
   ** Return the number of bytes of space used by an SQLite value of type
   ** eType.
   */
   static int dbdataValueBytes(int eType){
     switch( eType ){
       case 0: case 8: case 9:
       case 10: case 11:
         return 0;
       case 1:
         return 1;
       case 2:
         return 2;
       case 3:
         return 3;
       case 4:
         return 4;
       case 5:
         return 6;
       case 6:
       case 7:
         return 8;
       default:
         if( eType>0 ){
           return ((eType-12) / 2);
         }
         return 0;
     }
   }
   
   /*
   ** Load a value of type eType from buffer pData and use it to set the
   ** result of context object pCtx.
   */
   static void dbdataValue(
     sqlite3_context *pCtx, 
     int eType, 
     u8 *pData,
     int nData
   ){
     if( eType>=0 && dbdataValueBytes(eType)<=nData ){
       switch( eType ){
         case 0: 
         case 10: 
         case 11: 
           sqlite3_result_null(pCtx);
           break;
         
         case 8: 
           sqlite3_result_int(pCtx, 0);
           break;
         case 9:
           sqlite3_result_int(pCtx, 1);
           break;
     
         case 1: case 2: case 3: case 4: case 5: case 6: case 7: {
           sqlite3_uint64 v = (signed char)pData[0];
           pData++;
           switch( eType ){
             case 7:
             case 6:  v = (v<<16) + (pData[0]<<8) + pData[1];  pData += 2;
             case 5:  v = (v<<16) + (pData[0]<<8) + pData[1];  pData += 2;
             case 4:  v = (v<<8) + pData[0];  pData++;
             case 3:  v = (v<<8) + pData[0];  pData++;
             case 2:  v = (v<<8) + pData[0];  pData++;
           }
     
           if( eType==7 ){
             double r;
             memcpy(&r, &v, sizeof(r));
             sqlite3_result_double(pCtx, r);
           }else{
             sqlite3_result_int64(pCtx, (sqlite3_int64)v);
           }
           break;
         }
     
         default: {
           int n = ((eType-12) / 2);
           if( eType % 2 ){
             sqlite3_result_text(pCtx, (const char*)pData, n, SQLITE_TRANSIENT);
           }else{
             sqlite3_result_blob(pCtx, pData, n, SQLITE_TRANSIENT);
           }
         }
       }
     }
   }
   
   /*
   ** Move an sqlite_dbdata or sqlite_dbptr cursor to the next entry.
   */
   static int dbdataNext(sqlite3_vtab_cursor *pCursor){
     DbdataCursor *pCsr = (DbdataCursor*)pCursor;
     DbdataTable *pTab = (DbdataTable*)pCursor->pVtab;
   
     pCsr->iRowid++;
     while( 1 ){
       int rc;
       int iOff = (pCsr->iPgno==1 ? 100 : 0);
       int bNextPage = 0;
   
       if( pCsr->aPage==0 ){
         while( 1 ){
           if( pCsr->bOnePage==0 && pCsr->iPgno>pCsr->szDb ) return SQLITE_OK;
           rc = dbdataLoadPage(pCsr, pCsr->iPgno, &pCsr->aPage, &pCsr->nPage);
           if( rc!=SQLITE_OK ) return rc;
           if( pCsr->aPage ) break;
           pCsr->iPgno++;
         }
         pCsr->iCell = pTab->bPtr ? -2 : 0;
         pCsr->nCell = get_uint16(&pCsr->aPage[iOff+3]);
       }
   
       if( pTab->bPtr ){
         if( pCsr->aPage[iOff]!=0x02 && pCsr->aPage[iOff]!=0x05 ){
           pCsr->iCell = pCsr->nCell;
         }
         pCsr->iCell++;
         if( pCsr->iCell>=pCsr->nCell ){
           sqlite3_free(pCsr->aPage);
           pCsr->aPage = 0;
           if( pCsr->bOnePage ) return SQLITE_OK;
           pCsr->iPgno++;
         }else{
           return SQLITE_OK;
         }
       }else{
         /* If there is no record loaded, load it now. */
         if( pCsr->pRec==0 ){
           int bHasRowid = 0;
           int nPointer = 0;
           sqlite3_int64 nPayload = 0;
           sqlite3_int64 nHdr = 0;
           int iHdr;
           int U, X;
           int nLocal;
     
           switch( pCsr->aPage[iOff] ){
             case 0x02:
               nPointer = 4;
               break;
             case 0x0a:
               break;
             case 0x0d:
               bHasRowid = 1;
               break;
             default:
               /* This is not a b-tree page with records on it. Continue. */
               pCsr->iCell = pCsr->nCell;
               break;
           }
   
           if( pCsr->iCell>=pCsr->nCell ){
             bNextPage = 1;
           }else{
     
             iOff += 8 + nPointer + pCsr->iCell*2;
             if( iOff>pCsr->nPage ){
               bNextPage = 1;
             }else{
               iOff = get_uint16(&pCsr->aPage[iOff]);
             }
       
             /* For an interior node cell, skip past the child-page number */
             iOff += nPointer;
       
             /* Load the "byte of payload including overflow" field */
             if( bNextPage || iOff>pCsr->nPage ){
               bNextPage = 1;
             }else{
               iOff += dbdataGetVarint(&pCsr->aPage[iOff], &nPayload);
             }
       
             /* If this is a leaf intkey cell, load the rowid */
             if( bHasRowid && !bNextPage && iOff<pCsr->nPage ){
               iOff += dbdataGetVarint(&pCsr->aPage[iOff], &pCsr->iIntkey);
             }
       
             /* Figure out how much data to read from the local page */
             U = pCsr->nPage;
             if( bHasRowid ){
               X = U-35;
             }else{
               X = ((U-12)*64/255)-23;
             }
             if( nPayload<=X ){
               nLocal = nPayload;
             }else{
               int M, K;
               M = ((U-12)*32/255)-23;
               K = M+((nPayload-M)%(U-4));
               if( K<=X ){
                 nLocal = K;
               }else{
                 nLocal = M;
               }
             }
   
             if( bNextPage || nLocal+iOff>pCsr->nPage ){
               bNextPage = 1;
             }else{
   
               /* Allocate space for payload. And a bit more to catch small buffer
               ** overruns caused by attempting to read a varint or similar from 
               ** near the end of a corrupt record.  */
               pCsr->pRec = (u8*)sqlite3_malloc64(nPayload+DBDATA_PADDING_BYTES);
               if( pCsr->pRec==0 ) return SQLITE_NOMEM;
               memset(pCsr->pRec, 0, nPayload+DBDATA_PADDING_BYTES);
               pCsr->nRec = nPayload;
   
               /* Load the nLocal bytes of payload */
               memcpy(pCsr->pRec, &pCsr->aPage[iOff], nLocal);
               iOff += nLocal;
   
               /* Load content from overflow pages */
               if( nPayload>nLocal ){
                 sqlite3_int64 nRem = nPayload - nLocal;
                 unsigned int pgnoOvfl = get_uint32(&pCsr->aPage[iOff]);
                 while( nRem>0 ){
                   u8 *aOvfl = 0;
                   int nOvfl = 0;
                   int nCopy;
                   rc = dbdataLoadPage(pCsr, pgnoOvfl, &aOvfl, &nOvfl);
                   assert( rc!=SQLITE_OK || aOvfl==0 || nOvfl==pCsr->nPage );
                   if( rc!=SQLITE_OK ) return rc;
                   if( aOvfl==0 ) break;
   
                   nCopy = U-4;
                   if( nCopy>nRem ) nCopy = nRem;
                   memcpy(&pCsr->pRec[nPayload-nRem], &aOvfl[4], nCopy);
                   nRem -= nCopy;
   
                   pgnoOvfl = get_uint32(aOvfl);
                   sqlite3_free(aOvfl);
                 }
               }
       
               iHdr = dbdataGetVarint(pCsr->pRec, &nHdr);
               pCsr->nHdr = nHdr;
               pCsr->pHdrPtr = &pCsr->pRec[iHdr];
               pCsr->pPtr = &pCsr->pRec[pCsr->nHdr];
               pCsr->iField = (bHasRowid ? -1 : 0);
             }
           }
         }else{
           pCsr->iField++;
           if( pCsr->iField>0 ){
             sqlite3_int64 iType;
             if( pCsr->pHdrPtr>&pCsr->pRec[pCsr->nRec] ){
               bNextPage = 1;
             }else{
               pCsr->pHdrPtr += dbdataGetVarint(pCsr->pHdrPtr, &iType);
               pCsr->pPtr += dbdataValueBytes(iType);
             }
           }
         }
   
         if( bNextPage ){
           sqlite3_free(pCsr->aPage);
           sqlite3_free(pCsr->pRec);
           pCsr->aPage = 0;
           pCsr->pRec = 0;
           if( pCsr->bOnePage ) return SQLITE_OK;
           pCsr->iPgno++;
         }else{
           if( pCsr->iField<0 || pCsr->pHdrPtr<&pCsr->pRec[pCsr->nHdr] ){
             return SQLITE_OK;
           }
   
           /* Advance to the next cell. The next iteration of the loop will load
           ** the record and so on. */
           sqlite3_free(pCsr->pRec);
           pCsr->pRec = 0;
           pCsr->iCell++;
         }
       }
     }
   
     assert( !"can't get here" );
     return SQLITE_OK;
   }
   
   /* 
   ** Return true if the cursor is at EOF.
   */
   static int dbdataEof(sqlite3_vtab_cursor *pCursor){
     DbdataCursor *pCsr = (DbdataCursor*)pCursor;
     return pCsr->aPage==0;
   }
   
   /* 
   ** Determine the size in pages of database zSchema (where zSchema is
   ** "main", "temp" or the name of an attached database) and set 
   ** pCsr->szDb accordingly. If successful, return SQLITE_OK. Otherwise,
   ** an SQLite error code.
   */
   static int dbdataDbsize(DbdataCursor *pCsr, const char *zSchema){
     DbdataTable *pTab = (DbdataTable*)pCsr->base.pVtab;
     char *zSql = 0;
     int rc, rc2;
     sqlite3_stmt *pStmt = 0;
   
     zSql = sqlite3_mprintf("PRAGMA %Q.page_count", zSchema);
     if( zSql==0 ) return SQLITE_NOMEM;
     rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pStmt, 0);
     sqlite3_free(zSql);
     if( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
       pCsr->szDb = sqlite3_column_int(pStmt, 0);
     }
     rc2 = sqlite3_finalize(pStmt);
     if( rc==SQLITE_OK ) rc = rc2;
     return rc;
   }
   
   /* 
   ** xFilter method for sqlite_dbdata and sqlite_dbptr.
   */
   static int dbdataFilter(
     sqlite3_vtab_cursor *pCursor, 
     int idxNum, const char *idxStr,
     int argc, sqlite3_value **argv
   ){
     DbdataCursor *pCsr = (DbdataCursor*)pCursor;
     DbdataTable *pTab = (DbdataTable*)pCursor->pVtab;
     int rc = SQLITE_OK;
     const char *zSchema = "main";
   
     dbdataResetCursor(pCsr);
     assert( pCsr->iPgno==1 );
     if( idxNum & 0x01 ){
       zSchema = (const char*)sqlite3_value_text(argv[0]);
     }
     if( idxNum & 0x02 ){
       pCsr->iPgno = sqlite3_value_int(argv[(idxNum & 0x01)]);
       pCsr->bOnePage = 1;
     }else{
       pCsr->nPage = dbdataDbsize(pCsr, zSchema);
       rc = dbdataDbsize(pCsr, zSchema);
     }
   
     if( rc==SQLITE_OK ){
       if( pTab->pStmt ){
         pCsr->pStmt = pTab->pStmt;
         pTab->pStmt = 0;
       }else{
         rc = sqlite3_prepare_v2(pTab->db, 
             "SELECT data FROM sqlite_dbpage(?) WHERE pgno=?", -1,
             &pCsr->pStmt, 0
         );
       }
     }
     if( rc==SQLITE_OK ){
       rc = sqlite3_bind_text(pCsr->pStmt, 1, zSchema, -1, SQLITE_TRANSIENT);
     }else{
       pTab->base.zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pTab->db));
     }
     if( rc==SQLITE_OK ){
       rc = dbdataNext(pCursor);
     }
     return rc;
   }
   
   /* 
   ** Return a column for the sqlite_dbdata or sqlite_dbptr table.
   */
   static int dbdataColumn(
     sqlite3_vtab_cursor *pCursor, 
     sqlite3_context *ctx, 
     int i
   ){
     DbdataCursor *pCsr = (DbdataCursor*)pCursor;
     DbdataTable *pTab = (DbdataTable*)pCursor->pVtab;
     if( pTab->bPtr ){
       switch( i ){
         case DBPTR_COLUMN_PGNO:
           sqlite3_result_int64(ctx, pCsr->iPgno);
           break;
         case DBPTR_COLUMN_CHILD: {
           int iOff = pCsr->iPgno==1 ? 100 : 0;
           if( pCsr->iCell<0 ){
             iOff += 8;
           }else{
             iOff += 12 + pCsr->iCell*2;
             if( iOff>pCsr->nPage ) return SQLITE_OK;
             iOff = get_uint16(&pCsr->aPage[iOff]);
           }
           if( iOff<=pCsr->nPage ){
             sqlite3_result_int64(ctx, get_uint32(&pCsr->aPage[iOff]));
           }
           break;
         }
       }
     }else{
       switch( i ){
         case DBDATA_COLUMN_PGNO:
           sqlite3_result_int64(ctx, pCsr->iPgno);
           break;
         case DBDATA_COLUMN_CELL:
           sqlite3_result_int(ctx, pCsr->iCell);
           break;
         case DBDATA_COLUMN_FIELD:
           sqlite3_result_int(ctx, pCsr->iField);
           break;
         case DBDATA_COLUMN_VALUE: {
           if( pCsr->iField<0 ){
             sqlite3_result_int64(ctx, pCsr->iIntkey);
           }else{
             sqlite3_int64 iType;
             dbdataGetVarint(pCsr->pHdrPtr, &iType);
             dbdataValue(
                 ctx, iType, pCsr->pPtr, &pCsr->pRec[pCsr->nRec] - pCsr->pPtr
             );
           }
           break;
         }
       }
     }
     return SQLITE_OK;
   }
   
   /* 
   ** Return the rowid for an sqlite_dbdata or sqlite_dptr table.
   */
   static int dbdataRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
     DbdataCursor *pCsr = (DbdataCursor*)pCursor;
     *pRowid = pCsr->iRowid;
     return SQLITE_OK;
   }
   
   
   /*
   ** Invoke this routine to register the "sqlite_dbdata" virtual table module
   */
   static int sqlite3DbdataRegister(sqlite3 *db){
     static sqlite3_module dbdata_module = {
       0,                            /* iVersion */
       0,                            /* xCreate */
       dbdataConnect,                /* xConnect */
       dbdataBestIndex,              /* xBestIndex */
       dbdataDisconnect,             /* xDisconnect */
       0,                            /* xDestroy */
       dbdataOpen,                   /* xOpen - open a cursor */
       dbdataClose,                  /* xClose - close a cursor */
       dbdataFilter,                 /* xFilter - configure scan constraints */
       dbdataNext,                   /* xNext - advance a cursor */
       dbdataEof,                    /* xEof - check for end of scan */
       dbdataColumn,                 /* xColumn - read data */
       dbdataRowid,                  /* 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, "sqlite_dbdata", &dbdata_module, 0);
     if( rc==SQLITE_OK ){
       rc = sqlite3_create_module(db, "sqlite_dbptr", &dbdata_module, (void*)1);
     }
     return rc;
   }
   
   #ifdef _WIN32
   
   #endif
   int sqlite3_dbdata_init(
     sqlite3 *db, 
     char **pzErrMsg, 
     const sqlite3_api_routines *pApi
   ){
     SQLITE_EXTENSION_INIT2(pApi);
     return sqlite3DbdataRegister(db);
   }
   
   /************************* End ../ext/misc/dbdata.c ********************/
   #endif
   
 #if defined(SQLITE_ENABLE_SESSION)  #if defined(SQLITE_ENABLE_SESSION)
 /*  /*
 ** State information for a single open session  ** State information for a single open session
Line 590  struct OpenSession { Line 11197  struct OpenSession {
 };  };
 #endif  #endif
   
/*typedef struct ExpertInfo ExpertInfo;
** Shell output mode information from before ".explain on",struct ExpertInfo {
** saved so that it can be restored by ".explain off"  sqlite3expert *pExpert;
*/  int bVerbose;
typedef struct SavedModeInfo SavedModeInfo; 
struct SavedModeInfo { 
  int valid;          /* Is there legit data in here? */ 
  int mode;           /* Mode prior to ".explain on" */ 
  int showHeader;     /* The ".header" setting prior to ".explain on" */ 
  int colWidth[100];  /* Column widths prior to ".explain on" */ 
 };  };
   
   /* A single line in the EQP output */
   typedef struct EQPGraphRow EQPGraphRow;
   struct EQPGraphRow {
     int iEqpId;           /* ID for this row */
     int iParentId;        /* ID of the parent row */
     EQPGraphRow *pNext;   /* Next row in sequence */
     char zText[1];        /* Text to display for this row */
   };
   
   /* All EQP output is collected into an instance of the following */
   typedef struct EQPGraph EQPGraph;
   struct EQPGraph {
     EQPGraphRow *pRow;    /* Linked list of all rows of the EQP output */
     EQPGraphRow *pLast;   /* Last element of the pRow list */
     char zPrefix[100];    /* Graph prefix */
   };
   
 /*  /*
 ** State information about the database connection is contained in an  ** State information about the database connection is contained in an
 ** instance of the following structure.  ** instance of the following structure.
Line 609  struct SavedModeInfo { Line 11227  struct SavedModeInfo {
 typedef struct ShellState ShellState;  typedef struct ShellState ShellState;
 struct ShellState {  struct ShellState {
   sqlite3 *db;           /* The database */    sqlite3 *db;           /* The database */
  int echoOn;            /* True to echo input commands */  u8 autoExplain;        /* Automatically turn on .explain mode */
  int autoExplain;       /* Automatically turn on .explain mode */  u8 autoEQP;            /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
  int autoEQP;           /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */  u8 autoEQPtest;        /* autoEQP is in test mode */
  int statsOn;           /* True to display memory stats before each finalize */  u8 autoEQPtrace;       /* autoEQP is in trace mode */
  int scanstatsOn;       /* True to display scan stats before each finalize */  u8 scanstatsOn;        /* True to display scan stats before each finalize */
  int countChanges;      /* True to display change counts */  u8 openMode;           /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
  int backslashOn;       /* Resolve C-style \x escapes in SQL input text */  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 */
   unsigned statsOn;      /* True to display memory stats before each finalize */
   unsigned mEqpLines;    /* Mask of veritical lines in the EQP output graph */
   int outCount;          /* Revert to stdout when reaching zero */    int outCount;          /* Revert to stdout when reaching zero */
   int cnt;               /* Number of records displayed so far */    int cnt;               /* Number of records displayed so far */
     int lineno;            /* Line number of last line read from in */
     int openFlags;         /* Additional flags to open.  (SQLITE_OPEN_NOFOLLOW) */
     FILE *in;              /* Read commands from this stream */
   FILE *out;             /* Write results here */    FILE *out;             /* Write results here */
   FILE *traceOut;        /* Output for sqlite3_trace() */    FILE *traceOut;        /* Output for sqlite3_trace() */
   int nErr;              /* Number of errors seen */    int nErr;              /* Number of errors seen */
   int mode;              /* An output mode setting */    int mode;              /* An output mode setting */
     int modePrior;         /* Saved mode */
   int cMode;             /* temporary output mode for the current query */    int cMode;             /* temporary output mode for the current query */
   int normalMode;        /* Output mode before ".explain on" */    int normalMode;        /* Output mode before ".explain on" */
   int writableSchema;    /* True if PRAGMA writable_schema=ON */    int writableSchema;    /* True if PRAGMA writable_schema=ON */
   int showHeader;        /* True to show column names in List or Column mode */    int showHeader;        /* True to show column names in List or Column mode */
     int nCheck;            /* Number of ".check" commands run */
     unsigned nProgress;    /* Number of progress callbacks encountered */
     unsigned mxProgress;   /* Maximum progress callbacks before failing */
     unsigned flgProgress;  /* Flags for the progress callback */
   unsigned shellFlgs;    /* Various flags */    unsigned shellFlgs;    /* Various flags */
     unsigned priorShFlgs;  /* Saved copy of flags */
     sqlite3_int64 szMax;   /* --maxsize argument to .open */
   char *zDestTable;      /* Name of destination table when MODE_Insert */    char *zDestTable;      /* Name of destination table when MODE_Insert */
     char *zTempFile;       /* Temporary file that might need deleting */
     char zTestcase[30];    /* Name of current test case */
   char colSeparator[20]; /* Column separator character for several modes */    char colSeparator[20]; /* Column separator character for several modes */
   char rowSeparator[20]; /* Row separator character for MODE_Ascii */    char rowSeparator[20]; /* Row separator character for MODE_Ascii */
  int colWidth[100];     /* Requested width of each column when in column mode*/  char colSepPrior[20];  /* Saved column separator */
  int actualWidth[100];  /* Actual width of each column */  char rowSepPrior[20];  /* Saved row separator */
   int *colWidth;         /* Requested width of each column in columnar modes */
   int *actualWidth;      /* Actual width of each column */
   int nWidth;            /* Number of slots in colWidth[] and actualWidth[] */
   char nullValue[20];    /* The text to print when a NULL comes back from    char nullValue[20];    /* The text to print when a NULL comes back from
                          ** the database */                           ** the database */
   char outfile[FILENAME_MAX]; /* Filename for *out */    char outfile[FILENAME_MAX]; /* Filename for *out */
Line 643  struct ShellState { Line 11280  struct ShellState {
   int *aiIndent;         /* Array of indents used in MODE_Explain */    int *aiIndent;         /* Array of indents used in MODE_Explain */
   int nIndent;           /* Size of array aiIndent[] */    int nIndent;           /* Size of array aiIndent[] */
   int iIndent;           /* Index of current op in aiIndent[] */    int iIndent;           /* Index of current op in aiIndent[] */
     EQPGraph sGraph;       /* Information for the graphical EXPLAIN QUERY PLAN */
 #if defined(SQLITE_ENABLE_SESSION)  #if defined(SQLITE_ENABLE_SESSION)
   int nSession;             /* Number of active sessions */    int nSession;             /* Number of active sessions */
   OpenSession aSession[4];  /* Array of sessions.  [0] is in focus. */    OpenSession aSession[4];  /* Array of sessions.  [0] is in focus. */
 #endif  #endif
     ExpertInfo expert;        /* Valid if previous command was ".expert OPT..." */
 };  };
   
   
   /* Allowed values for ShellState.autoEQP
   */
   #define AUTOEQP_off      0           /* Automatic EXPLAIN QUERY PLAN is off */
   #define AUTOEQP_on       1           /* Automatic EQP is on */
   #define AUTOEQP_trigger  2           /* On and also show plans for triggers */
   #define AUTOEQP_full     3           /* Show full EXPLAIN */
   
   /* Allowed values for ShellState.openMode
   */
   #define SHELL_OPEN_UNSPEC      0      /* No open-mode specified */
   #define SHELL_OPEN_NORMAL      1      /* Normal database file */
   #define SHELL_OPEN_APPENDVFS   2      /* Use appendvfs */
   #define SHELL_OPEN_ZIPFILE     3      /* Use the zipfile virtual table */
   #define SHELL_OPEN_READONLY    4      /* Open a normal database read-only */
   #define SHELL_OPEN_DESERIALIZE 5      /* Open using sqlite3_deserialize() */
   #define SHELL_OPEN_HEXDB       6      /* Use "dbtotxt" output as data source */
   
   /* Allowed values for ShellState.eTraceType
   */
   #define SHELL_TRACE_PLAIN      0      /* Show input SQL text */
   #define SHELL_TRACE_EXPANDED   1      /* Show expanded SQL text */
   #define SHELL_TRACE_NORMALIZED 2      /* Show normalized SQL text */
   
   /* Bits in the ShellState.flgProgress variable */
   #define SHELL_PROGRESS_QUIET 0x01  /* Omit announcing every progress callback */
   #define SHELL_PROGRESS_RESET 0x02  /* Reset the count when the progres
                                      ** callback limit is reached, and for each
                                      ** top-level SQL statement */
   #define SHELL_PROGRESS_ONCE  0x04  /* Cancel the --limit after firing once */
   
 /*  /*
 ** These are the allowed shellFlgs values  ** These are the allowed shellFlgs values
 */  */
#define SHFLG_Scratch     0x00001     /* The --scratch option is used */#define SHFLG_Pagecache      0x00000001 /* The --pagecache option is used */
#define SHFLG_Pagecache   0x00002     /* The --pagecache option is used */#define SHFLG_Lookaside      0x00000002 /* Lookaside memory is used */
#define SHFLG_Lookaside   0x00004     /* Lookaside memory is used */#define SHFLG_Backslash      0x00000004 /* The --backslash option is used */
 #define SHFLG_PreserveRowid  0x00000008 /* .dump preserves rowid values */
 #define SHFLG_Newlines       0x00000010 /* .dump --newline flag */
 #define SHFLG_CountChanges   0x00000020 /* .changes setting */
 #define SHFLG_Echo           0x00000040 /* .echo or --echo setting */
 #define SHFLG_HeaderSet      0x00000080 /* .header has been used */
 #define SHFLG_DumpDataOnly   0x00000100 /* .dump show data only */
 #define SHFLG_DumpNoSys      0x00000200 /* .dump omits system tables */
   
 /*  /*
   ** Macros for testing and setting shellFlgs
   */
   #define ShellHasFlag(P,X)    (((P)->shellFlgs & (X))!=0)
   #define ShellSetFlag(P,X)    ((P)->shellFlgs|=(X))
   #define ShellClearFlag(P,X)  ((P)->shellFlgs&=(~(X)))
   
   /*
 ** These are the allowed modes.  ** These are the allowed modes.
 */  */
 #define MODE_Line     0  /* One column per line.  Blank line between records */  #define MODE_Line     0  /* One column per line.  Blank line between records */
Line 665  struct ShellState { Line 11349  struct ShellState {
 #define MODE_Semi     3  /* Same as MODE_List but append ";" to each line */  #define MODE_Semi     3  /* Same as MODE_List but append ";" to each line */
 #define MODE_Html     4  /* Generate an XHTML table */  #define MODE_Html     4  /* Generate an XHTML table */
 #define MODE_Insert   5  /* Generate SQL "insert" statements */  #define MODE_Insert   5  /* Generate SQL "insert" statements */
#define MODE_Tcl      6  /* Generate ANSI-C or TCL quoted elements */#define MODE_Quote    6  /* Quote values as for SQL */
#define MODE_Csv      7  /* Quote strings, numbers are plain */#define MODE_Tcl      7  /* Generate ANSI-C or TCL quoted elements */
#define MODE_Explain  8  /* Like MODE_Column, but do not truncate data */#define MODE_Csv      8  /* Quote strings, numbers are plain */
#define MODE_Ascii    9  /* Use ASCII unit and record separators (0x1F/0x1E) */#define MODE_Explain  9  /* Like MODE_Column, but do not truncate data */
#define MODE_Pretty  10  /* Pretty-print schemas */#define MODE_Ascii   10  /* Use ASCII unit and record separators (0x1F/0x1E) */
 #define MODE_Pretty  11  /* Pretty-print schemas */
 #define MODE_EQP     12  /* Converts EXPLAIN QUERY PLAN output into a graph */
 #define MODE_Json    13  /* Output JSON */
 #define MODE_Markdown 14 /* Markdown formatting */
 #define MODE_Table   15  /* MySQL-style table formatting */
 #define MODE_Box     16  /* Unicode box-drawing characters */
   
 static const char *modeDescr[] = {  static const char *modeDescr[] = {
   "line",    "line",
Line 678  static const char *modeDescr[] = { Line 11368  static const char *modeDescr[] = {
   "semi",    "semi",
   "html",    "html",
   "insert",    "insert",
     "quote",
   "tcl",    "tcl",
   "csv",    "csv",
   "explain",    "explain",
   "ascii",    "ascii",
   "prettyprint",    "prettyprint",
     "eqp",
     "json",
     "markdown",
     "table",
     "box"
 };  };
   
 /*  /*
Line 699  static const char *modeDescr[] = { Line 11395  static const char *modeDescr[] = {
 #define SEP_Record    "\x1E"  #define SEP_Record    "\x1E"
   
 /*  /*
 ** Number of elements in an array  
 */  
 #define ArraySize(X)  (int)(sizeof(X)/sizeof(X[0]))  
   
 /*  
 ** A callback for the sqlite3_log() interface.  ** A callback for the sqlite3_log() interface.
 */  */
 static void shellLog(void *pArg, int iErrCode, const char *zMsg){  static void shellLog(void *pArg, int iErrCode, const char *zMsg){
Line 714  static void shellLog(void *pArg, int iErrCode, const c Line 11405  static void shellLog(void *pArg, int iErrCode, const c
 }  }
   
 /*  /*
   ** SQL function:  shell_putsnl(X)
   **
   ** Write the text X to the screen (or whatever output is being directed)
   ** adding a newline at the end, and then return X.
   */
   static void shellPutsFunc(
     sqlite3_context *pCtx,
     int nVal,
     sqlite3_value **apVal
   ){
     ShellState *p = (ShellState*)sqlite3_user_data(pCtx);
     (void)nVal;
     utf8_printf(p->out, "%s\n", sqlite3_value_text(apVal[0]));
     sqlite3_result_value(pCtx, apVal[0]);
   }
   
   /*
   ** SQL function:   edit(VALUE)
   **                 edit(VALUE,EDITOR)
   **
   ** These steps:
   **
   **     (1) Write VALUE into a temporary file.
   **     (2) Run program EDITOR on that temporary file.
   **     (3) Read the temporary file back and return its content as the result.
   **     (4) Delete the temporary file
   **
   ** If the EDITOR argument is omitted, use the value in the VISUAL
   ** environment variable.  If still there is no EDITOR, through an error.
   **
   ** Also throw an error if the EDITOR program returns a non-zero exit code.
   */
   #ifndef SQLITE_NOHAVE_SYSTEM
   static void editFunc(
     sqlite3_context *context,
     int argc,
     sqlite3_value **argv
   ){
     const char *zEditor;
     char *zTempFile = 0;
     sqlite3 *db;
     char *zCmd = 0;
     int bBin;
     int rc;
     int hasCRNL = 0;
     FILE *f = 0;
     sqlite3_int64 sz;
     sqlite3_int64 x;
     unsigned char *p = 0;
   
     if( argc==2 ){
       zEditor = (const char*)sqlite3_value_text(argv[1]);
     }else{
       zEditor = getenv("VISUAL");
     }
     if( zEditor==0 ){
       sqlite3_result_error(context, "no editor for edit()", -1);
       return;
     }
     if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
       sqlite3_result_error(context, "NULL input to edit()", -1);
       return;
     }
     db = sqlite3_context_db_handle(context);
     zTempFile = 0;
     sqlite3_file_control(db, 0, SQLITE_FCNTL_TEMPFILENAME, &zTempFile);
     if( zTempFile==0 ){
       sqlite3_uint64 r = 0;
       sqlite3_randomness(sizeof(r), &r);
       zTempFile = sqlite3_mprintf("temp%llx", r);
       if( zTempFile==0 ){
         sqlite3_result_error_nomem(context);
         return;
       }
     }
     bBin = sqlite3_value_type(argv[0])==SQLITE_BLOB;
     /* When writing the file to be edited, do \n to \r\n conversions on systems
     ** that want \r\n line endings */
     f = fopen(zTempFile, bBin ? "wb" : "w");
     if( f==0 ){
       sqlite3_result_error(context, "edit() cannot open temp file", -1);
       goto edit_func_end;
     }
     sz = sqlite3_value_bytes(argv[0]);
     if( bBin ){
       x = fwrite(sqlite3_value_blob(argv[0]), 1, (size_t)sz, f);
     }else{
       const char *z = (const char*)sqlite3_value_text(argv[0]);
       /* Remember whether or not the value originally contained \r\n */
       if( z && strstr(z,"\r\n")!=0 ) hasCRNL = 1;
       x = fwrite(sqlite3_value_text(argv[0]), 1, (size_t)sz, f);
     }
     fclose(f);
     f = 0;
     if( x!=sz ){
       sqlite3_result_error(context, "edit() could not write the whole file", -1);
       goto edit_func_end;
     }
     zCmd = sqlite3_mprintf("%s \"%s\"", zEditor, zTempFile);
     if( zCmd==0 ){
       sqlite3_result_error_nomem(context);
       goto edit_func_end;
     }
     rc = system(zCmd);
     sqlite3_free(zCmd);
     if( rc ){
       sqlite3_result_error(context, "EDITOR returned non-zero", -1);
       goto edit_func_end;
     }
     f = fopen(zTempFile, "rb");
     if( f==0 ){
       sqlite3_result_error(context,
         "edit() cannot reopen temp file after edit", -1);
       goto edit_func_end;
     }
     fseek(f, 0, SEEK_END);
     sz = ftell(f);
     rewind(f);
     p = sqlite3_malloc64( sz+1 );
     if( p==0 ){
       sqlite3_result_error_nomem(context);
       goto edit_func_end;
     }
     x = fread(p, 1, (size_t)sz, f);
     fclose(f);
     f = 0;
     if( x!=sz ){
       sqlite3_result_error(context, "could not read back the whole file", -1);
       goto edit_func_end;
     }
     if( bBin ){
       sqlite3_result_blob64(context, p, sz, sqlite3_free);
     }else{
       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 */
         for(i=j=0; i<sz; i++){
           if( p[i]=='\r' && p[i+1]=='\n' ) i++;
           p[j++] = p[i];
         }
         sz = j;
         p[sz] = 0;
       } 
       sqlite3_result_text64(context, (const char*)p, sz,
                             sqlite3_free, SQLITE_UTF8);
     }
     p = 0;
   
   edit_func_end:
     if( f ) fclose(f);
     unlink(zTempFile);
     sqlite3_free(zTempFile);
     sqlite3_free(p);
   }
   #endif /* SQLITE_NOHAVE_SYSTEM */
   
   /*
   ** Save or restore the current output mode
   */
   static void outputModePush(ShellState *p){
     p->modePrior = p->mode;
     p->priorShFlgs = p->shellFlgs;
     memcpy(p->colSepPrior, p->colSeparator, sizeof(p->colSeparator));
     memcpy(p->rowSepPrior, p->rowSeparator, sizeof(p->rowSeparator));
   }
   static void outputModePop(ShellState *p){
     p->mode = p->modePrior;
     p->shellFlgs = p->priorShFlgs;
     memcpy(p->colSeparator, p->colSepPrior, sizeof(p->colSeparator));
     memcpy(p->rowSeparator, p->rowSepPrior, sizeof(p->rowSeparator));
   }
   
   /*
 ** Output the given string as a hex-encoded blob (eg. X'1234' )  ** Output the given string as a hex-encoded blob (eg. X'1234' )
 */  */
 static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){  static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){
Line 725  static void output_hex_blob(FILE *out, const void *pBl Line 11593  static void output_hex_blob(FILE *out, const void *pBl
 }  }
   
 /*  /*
   ** Find a string that is not found anywhere in z[].  Return a pointer
   ** to that string.
   **
   ** Try to use zA and zB first.  If both of those are already found in z[]
   ** then make up some string and store it in the buffer zBuf.
   */
   static const char *unused_string(
     const char *z,                    /* Result must not appear anywhere in z */
     const char *zA, const char *zB,   /* Try these first */
     char *zBuf                        /* Space to store a generated string */
   ){
     unsigned i = 0;
     if( strstr(z, zA)==0 ) return zA;
     if( strstr(z, zB)==0 ) return zB;
     do{
       sqlite3_snprintf(20,zBuf,"(%s%u)", zA, i++);
     }while( strstr(z,zBuf)!=0 );
     return zBuf;
   }
   
   /*
 ** Output the given string as a quoted string using SQL quoting conventions.  ** Output the given string as a quoted string using SQL quoting conventions.
   **
   ** See also: output_quoted_escaped_string()
 */  */
 static void output_quoted_string(FILE *out, const char *z){  static void output_quoted_string(FILE *out, const char *z){
   int i;    int i;
  int nSingle = 0;  char c;
   setBinaryMode(out, 1);    setBinaryMode(out, 1);
  for(i=0; z[i]; i++){  for(i=0; (c = z[i])!=0 && c!='\''; i++){}
    if( z[i]=='\'' ) nSingle++;  if( c==0 ){
     utf8_printf(out,"'%s'",z);
   }else{
     raw_printf(out, "'");
     while( *z ){
       for(i=0; (c = z[i])!=0 && c!='\''; i++){}
       if( c=='\'' ) i++;
       if( i ){
         utf8_printf(out, "%.*s", i, z);
         z += i;
       }
       if( c=='\'' ){
         raw_printf(out, "'");
         continue;
       }
       if( c==0 ){
         break;
       }
       z++;
     }
     raw_printf(out, "'");
   }    }
  if( nSingle==0 ){  setTextMode(out, 1);
 }
 
 /*
 ** Output the given string as a quoted string using SQL quoting conventions.
 ** Additionallly , escape the "\n" and "\r" characters so that they do not
 ** get corrupted by end-of-line translation facilities in some operating
 ** systems.
 **
 ** This is like output_quoted_string() but with the addition of the \r\n
 ** escape mechanism.
 */
 static void output_quoted_escaped_string(FILE *out, const char *z){
   int i;
   char c;
   setBinaryMode(out, 1);
   for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){}
   if( c==0 ){
     utf8_printf(out,"'%s'",z);      utf8_printf(out,"'%s'",z);
   }else{    }else{
    raw_printf(out,"'");    const char *zNL = 0;
     const char *zCR = 0;
     int nNL = 0;
     int nCR = 0;
     char zBuf1[20], zBuf2[20];
     for(i=0; z[i]; i++){
       if( z[i]=='\n' ) nNL++;
       if( z[i]=='\r' ) nCR++;
     }
     if( nNL ){
       raw_printf(out, "replace(");
       zNL = unused_string(z, "\\n", "\\012", zBuf1);
     }
     if( nCR ){
       raw_printf(out, "replace(");
       zCR = unused_string(z, "\\r", "\\015", zBuf2);
     }
     raw_printf(out, "'");
     while( *z ){      while( *z ){
      for(i=0; z[i] && z[i]!='\''; i++){}      for(i=0; (c = z[i])!=0 && c!='\n' && c!='\r' && c!='\''; i++){}
      if( i==0 ){      if( c=='\'' ) i++;
        raw_printf(out,"''");      if( i ){
        z++;        utf8_printf(out, "%.*s", i, z);
      }else if( z[i]=='\'' ){        z += i;
        utf8_printf(out,"%.*s''",i,z);      }
        z += i+1;      if( c=='\'' ){
      }else{        raw_printf(out, "'");
        utf8_printf(out,"%s",z);        continue;
       }
       if( c==0 ){
         break;          break;
       }        }
         z++;
         if( c=='\n' ){
           raw_printf(out, "%s", zNL);
           continue;
         }
         raw_printf(out, "%s", zCR);
     }      }
    raw_printf(out,"'");    raw_printf(out, "'");
     if( nCR ){
       raw_printf(out, ",'%s',char(13))", zCR);
     }
     if( nNL ){
       raw_printf(out, ",'%s',char(10))", zNL);
     }
   }    }
   setTextMode(out, 1);    setTextMode(out, 1);
 }  }
Line 788  static void output_c_string(FILE *out, const char *z){ Line 11747  static void output_c_string(FILE *out, const char *z){
 }  }
   
 /*  /*
   ** Output the given string as a quoted according to JSON quoting rules.
   */
   static void output_json_string(FILE *out, const char *z, int n){
     unsigned int c;
     if( n<0 ) n = (int)strlen(z);
     fputc('"', out);
     while( n-- ){
       c = *(z++);
       if( c=='\\' || c=='"' ){
         fputc('\\', out);
         fputc(c, out);
       }else if( c<=0x1f ){
         fputc('\\', out);
         if( c=='\b' ){
           fputc('b', out);
         }else if( c=='\f' ){
           fputc('f', out);
         }else if( c=='\n' ){
           fputc('n', out);
         }else if( c=='\r' ){
           fputc('r', out);
         }else if( c=='\t' ){
           fputc('t', out);
         }else{
            raw_printf(out, "u%04x",c);
         }
       }else{
         fputc(c, out);
       }
     }
     fputc('"', out);
   }
   
   /*
 ** Output the given string with characters that are special to  ** Output the given string with characters that are special to
 ** HTML escaped.  ** HTML escaped.
 */  */
Line 867  static void output_csv(ShellState *p, const char *z, i Line 11860  static void output_csv(ShellState *p, const char *z, i
       }        }
     }      }
     if( i==0 ){      if( i==0 ){
      putc('"', out);      char *zQuoted = sqlite3_mprintf("\"%w\"", z);
      for(i=0; z[i]; i++){      utf8_printf(out, "%s", zQuoted);
        if( z[i]=='"' ) putc('"', out);      sqlite3_free(zQuoted);
        putc(z[i], out); 
      } 
      putc('"', out); 
     }else{      }else{
       utf8_printf(out, "%s", z);        utf8_printf(out, "%s", z);
     }      }
Line 882  static void output_csv(ShellState *p, const char *z, i Line 11872  static void output_csv(ShellState *p, const char *z, i
   }    }
 }  }
   
 #ifdef SIGINT  
 /*  /*
 ** This routine runs when the user presses Ctrl-C  ** This routine runs when the user presses Ctrl-C
 */  */
Line 892  static void interrupt_handler(int NotUsed){ Line 11881  static void interrupt_handler(int NotUsed){
   if( seenInterrupt>2 ) exit(1);    if( seenInterrupt>2 ) exit(1);
   if( globalDb ) sqlite3_interrupt(globalDb);    if( globalDb ) sqlite3_interrupt(globalDb);
 }  }
   
   #if (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
   /*
   ** This routine runs for console events (e.g. Ctrl-C) on Win32
   */
   static BOOL WINAPI ConsoleCtrlHandler(
     DWORD dwCtrlType /* One of the CTRL_*_EVENT constants */
   ){
     if( dwCtrlType==CTRL_C_EVENT ){
       interrupt_handler(0);
       return TRUE;
     }
     return FALSE;
   }
 #endif  #endif
   
   #ifndef SQLITE_OMIT_AUTHORIZATION
 /*  /*
 ** When the ".auth ON" is set, the following authorizer callback is  ** When the ".auth ON" is set, the following authorizer callback is
 ** invoked.  It always returns SQLITE_OK.  ** invoked.  It always returns SQLITE_OK.
Line 926  static int shellAuth( Line 11930  static int shellAuth(
   az[1] = zA2;    az[1] = zA2;
   az[2] = zA3;    az[2] = zA3;
   az[3] = zA4;    az[3] = zA4;
  raw_printf(p->out, "authorizer: %s", azAction[op]);  utf8_printf(p->out, "authorizer: %s", azAction[op]);
   for(i=0; i<4; i++){    for(i=0; i<4; i++){
     raw_printf(p->out, " ");      raw_printf(p->out, " ");
     if( az[i] ){      if( az[i] ){
Line 938  static int shellAuth( Line 11942  static int shellAuth(
   raw_printf(p->out, "\n");    raw_printf(p->out, "\n");
   return SQLITE_OK;    return SQLITE_OK;
 }  }
  #endif
   
 /*  /*
   ** Print a schema statement.  Part of MODE_Semi and MODE_Pretty output.
   **
   ** This routine converts some CREATE TABLE statements for shadow tables
   ** in FTS3/4/5 into CREATE TABLE IF NOT EXISTS statements.
   */
   static void printSchemaLine(FILE *out, const char *z, const char *zTail){
     if( z==0 ) return;
     if( zTail==0 ) return;
     if( sqlite3_strglob("CREATE TABLE ['\"]*", z)==0 ){
       utf8_printf(out, "CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail);
     }else{
       utf8_printf(out, "%s%s", z, zTail);
     }
   }
   static void printSchemaLineN(FILE *out, char *z, int n, const char *zTail){
     char c = z[n];
     z[n] = 0;
     printSchemaLine(out, z, zTail);
     z[n] = c;
   }
   
   /*
   ** Return true if string z[] has nothing but whitespace and comments to the
   ** end of the first line.
   */
   static int wsToEol(const char *z){
     int i;
     for(i=0; z[i]; i++){
       if( z[i]=='\n' ) return 1;
       if( IsSpace(z[i]) ) continue;
       if( z[i]=='-' && z[i+1]=='-' ) return 1;
       return 0;
     }
     return 1;
   }
   
   /*
   ** Add a new entry to the EXPLAIN QUERY PLAN data
   */
   static void eqp_append(ShellState *p, int iEqpId, int p2, const char *zText){
     EQPGraphRow *pNew;
     int nText = strlen30(zText);
     if( p->autoEQPtest ){
       utf8_printf(p->out, "%d,%d,%s\n", iEqpId, p2, zText);
     }
     pNew = sqlite3_malloc64( sizeof(*pNew) + nText );
     if( pNew==0 ) shell_out_of_memory();
     pNew->iEqpId = iEqpId;
     pNew->iParentId = p2;
     memcpy(pNew->zText, zText, nText+1);
     pNew->pNext = 0;
     if( p->sGraph.pLast ){
       p->sGraph.pLast->pNext = pNew;
     }else{
       p->sGraph.pRow = pNew;
     }
     p->sGraph.pLast = pNew;
   }
   
   /*
   ** Free and reset the EXPLAIN QUERY PLAN data that has been collected
   ** in p->sGraph.
   */
   static void eqp_reset(ShellState *p){
     EQPGraphRow *pRow, *pNext;
     for(pRow = p->sGraph.pRow; pRow; pRow = pNext){
       pNext = pRow->pNext;
       sqlite3_free(pRow);
     }
     memset(&p->sGraph, 0, sizeof(p->sGraph));
   }
   
   /* Return the next EXPLAIN QUERY PLAN line with iEqpId that occurs after
   ** pOld, or return the first such line if pOld is NULL
   */
   static EQPGraphRow *eqp_next_row(ShellState *p, int iEqpId, EQPGraphRow *pOld){
     EQPGraphRow *pRow = pOld ? pOld->pNext : p->sGraph.pRow;
     while( pRow && pRow->iParentId!=iEqpId ) pRow = pRow->pNext;
     return pRow;
   }
   
   /* Render a single level of the graph that has iEqpId as its parent.  Called
   ** recursively to render sublevels.
   */
   static void eqp_render_level(ShellState *p, int iEqpId){
     EQPGraphRow *pRow, *pNext;
     int n = strlen30(p->sGraph.zPrefix);
     char *z;
     for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){
       pNext = eqp_next_row(p, iEqpId, pRow);
       z = pRow->zText;
       utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix,
                   pNext ? "|--" : "`--", z);
       if( n<(int)sizeof(p->sGraph.zPrefix)-7 ){
         memcpy(&p->sGraph.zPrefix[n], pNext ? "|  " : "   ", 4);
         eqp_render_level(p, pRow->iEqpId);
         p->sGraph.zPrefix[n] = 0;
       }
     }
   }
   
   /*
   ** Display and reset the EXPLAIN QUERY PLAN data
   */
   static void eqp_render(ShellState *p){
     EQPGraphRow *pRow = p->sGraph.pRow;
     if( pRow ){
       if( pRow->zText[0]=='-' ){
         if( pRow->pNext==0 ){
           eqp_reset(p);
           return;
         }
         utf8_printf(p->out, "%s\n", pRow->zText+3);
         p->sGraph.pRow = pRow->pNext;
         sqlite3_free(pRow);
       }else{
         utf8_printf(p->out, "QUERY PLAN\n");
       }
       p->sGraph.zPrefix[0] = 0;
       eqp_render_level(p, 0);
       eqp_reset(p);
     }
   }
   
   #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
   /*
   ** Progress handler callback.
   */
   static int progress_handler(void *pClientData) {
     ShellState *p = (ShellState*)pClientData;
     p->nProgress++;
     if( p->nProgress>=p->mxProgress && p->mxProgress>0 ){
       raw_printf(p->out, "Progress limit reached (%u)\n", p->nProgress);
       if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
       if( p->flgProgress & SHELL_PROGRESS_ONCE ) p->mxProgress = 0;
       return 1;
     }
     if( (p->flgProgress & SHELL_PROGRESS_QUIET)==0 ){
       raw_printf(p->out, "Progress %u\n", p->nProgress);
     }
     return 0;
   }
   #endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
   
   /*
   ** Print N dashes
   */
   static void print_dashes(FILE *out, int N){
     const char zDash[] = "--------------------------------------------------";
     const int nDash = sizeof(zDash) - 1;
     while( N>nDash ){
       fputs(zDash, out);
       N -= nDash;
     }
     raw_printf(out, "%.*s", N, zDash);
   }
   
   /*
   ** Print a markdown or table-style row separator using ascii-art
   */
   static void print_row_separator(
     ShellState *p,
     int nArg,
     const char *zSep
   ){
     int i;
     if( nArg>0 ){
       fputs(zSep, p->out);
       print_dashes(p->out, p->actualWidth[0]+2);
       for(i=1; i<nArg; i++){
         fputs(zSep, p->out);
         print_dashes(p->out, p->actualWidth[i]+2);
       }
       fputs(zSep, p->out);
     }
     fputs("\n", p->out);
   }
   
   /*
 ** This is the callback routine that the shell  ** This is the callback routine that the shell
 ** invokes for each row of a query result.  ** invokes for each row of a query result.
 */  */
Line 949  static int shell_callback( Line 12132  static int shell_callback(
   int nArg,        /* Number of result columns */    int nArg,        /* Number of result columns */
   char **azArg,    /* Text of each result column */    char **azArg,    /* Text of each result column */
   char **azCol,    /* Column names */    char **azCol,    /* Column names */
  int *aiType      /* Column types */  int *aiType      /* Column types.  Might be NULL */
 ){  ){
   int i;    int i;
   ShellState *p = (ShellState*)pArg;    ShellState *p = (ShellState*)pArg;
   
     if( azArg==0 ) return 0;
   switch( p->cMode ){    switch( p->cMode ){
     case MODE_Line: {      case MODE_Line: {
       int w = 5;        int w = 5;
Line 969  static int shell_callback( Line 12153  static int shell_callback(
       }        }
       break;        break;
     }      }
    case MODE_Explain:    case MODE_Explain: {
    case MODE_Column: {      static const int aExplainWidth[] = {4, 13, 4, 4, 4, 13, 2, 13};
      static const int aExplainWidths[] = {4, 13, 4, 4, 4, 13, 2, 13};      if( nArg>ArraySize(aExplainWidth) ){
      const int *colWidth;        nArg = ArraySize(aExplainWidth);
      int showHdr; 
      char *rowSep; 
      if( p->cMode==MODE_Column ){ 
        colWidth = p->colWidth; 
        showHdr = p->showHeader; 
        rowSep = p->rowSeparator; 
      }else{ 
        colWidth = aExplainWidths; 
        showHdr = 1; 
        rowSep = SEP_Row; 
       }        }
       if( p->cnt++==0 ){        if( p->cnt++==0 ){
         for(i=0; i<nArg; i++){          for(i=0; i<nArg; i++){
          int w, n;          int w = aExplainWidth[i];
          if( i<ArraySize(p->colWidth) ){          utf8_width_print(p->out, w, azCol[i]);
            w = colWidth[i];          fputs(i==nArg-1 ? "\n" : "  ", p->out);
          }else{ 
            w = 0; 
          } 
          if( w==0 ){ 
            w = strlen30(azCol[i] ? azCol[i] : ""); 
            if( w<10 ) w = 10; 
            n = strlen30(azArg && azArg[i] ? azArg[i] : p->nullValue); 
            if( w<n ) w = n; 
          } 
          if( i<ArraySize(p->actualWidth) ){ 
            p->actualWidth[i] = w; 
          } 
          if( showHdr ){ 
            if( w<0 ){ 
              utf8_printf(p->out,"%*.*s%s",-w,-w,azCol[i], 
                      i==nArg-1 ? rowSep : "  "); 
            }else{ 
              utf8_printf(p->out,"%-*.*s%s",w,w,azCol[i], 
                      i==nArg-1 ? rowSep : "  "); 
            } 
          } 
         }          }
        if( showHdr ){        for(i=0; i<nArg; i++){
          for(i=0; i<nArg; i++){          int w = aExplainWidth[i];
            int w;          print_dashes(p->out, w);
            if( i<ArraySize(p->actualWidth) ){          fputs(i==nArg-1 ? "\n" : "  ", p->out);
               w = p->actualWidth[i]; 
               if( w<0 ) w = -w; 
            }else{ 
               w = 10; 
            } 
            utf8_printf(p->out,"%-*.*s%s",w,w, 
                   "----------------------------------------------------------" 
                   "----------------------------------------------------------", 
                    i==nArg-1 ? rowSep : "  "); 
          } 
         }          }
       }        }
       if( azArg==0 ) break;        if( azArg==0 ) break;
       for(i=0; i<nArg; i++){        for(i=0; i<nArg; i++){
        int w;        int w = aExplainWidth[i];
        if( i<ArraySize(p->actualWidth) ){        if( i==nArg-1 ) w = 0;
           w = p->actualWidth[i];        if( azArg[i] && strlenChar(azArg[i])>w ){
        }else{          w = strlenChar(azArg[i]);
           w = 10; 
         }          }
         if( p->cMode==MODE_Explain && azArg[i] && strlen30(azArg[i])>w ){  
           w = strlen30(azArg[i]);  
         }  
         if( i==1 && p->aiIndent && p->pStmt ){          if( i==1 && p->aiIndent && p->pStmt ){
           if( p->iIndent<p->nIndent ){            if( p->iIndent<p->nIndent ){
             utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], "");              utf8_printf(p->out, "%*.s", p->aiIndent[p->iIndent], "");
           }            }
           p->iIndent++;            p->iIndent++;
         }          }
        if( w<0 ){        utf8_width_print(p->out, w, azArg[i] ? azArg[i] : p->nullValue);
          utf8_printf(p->out,"%*.*s%s",-w,-w,        fputs(i==nArg-1 ? "\n" : "  ", p->out);
              azArg[i] ? azArg[i] : p->nullValue, 
              i==nArg-1 ? rowSep : "  "); 
        }else{ 
          utf8_printf(p->out,"%-*.*s%s",w,w, 
              azArg[i] ? azArg[i] : p->nullValue, 
              i==nArg-1 ? rowSep : "  "); 
        } 
       }        }
       break;        break;
     }      }
     case MODE_Semi: {   /* .schema and .fullschema output */      case MODE_Semi: {   /* .schema and .fullschema output */
      utf8_printf(p->out, "%s;\n", azArg[0]);      printSchemaLine(p->out, azArg[0], ";\n");
       break;        break;
     }      }
     case MODE_Pretty: {  /* .schema and .fullschema with --indent */      case MODE_Pretty: {  /* .schema and .fullschema with --indent */
Line 1080  static int shell_callback( Line 12212  static int shell_callback(
       for(i=0; IsSpace(z[i]); i++){}        for(i=0; IsSpace(z[i]); i++){}
       for(; (c = z[i])!=0; i++){        for(; (c = z[i])!=0; i++){
         if( IsSpace(c) ){          if( IsSpace(c) ){
             if( z[j-1]=='\r' ) z[j-1] = '\n';
           if( IsSpace(z[j-1]) || z[j-1]=='(' ) continue;            if( IsSpace(z[j-1]) || z[j-1]=='(' ) continue;
         }else if( (c=='(' || c==')') && j>0 && IsSpace(z[j-1]) ){          }else if( (c=='(' || c==')') && j>0 && IsSpace(z[j-1]) ){
           j--;            j--;
Line 1089  static int shell_callback( Line 12222  static int shell_callback(
       while( j>0 && IsSpace(z[j-1]) ){ j--; }        while( j>0 && IsSpace(z[j-1]) ){ j--; }
       z[j] = 0;        z[j] = 0;
       if( strlen30(z)>=79 ){        if( strlen30(z)>=79 ){
        for(i=j=0; (c = z[i])!=0; i++){        for(i=j=0; (c = z[i])!=0; i++){ /* Copy from z[i] back to z[j] */
           if( c==cEnd ){            if( c==cEnd ){
             cEnd = 0;              cEnd = 0;
           }else if( c=='"' || c=='\'' || c=='`' ){            }else if( c=='"' || c=='\'' || c=='`' ){
             cEnd = c;              cEnd = c;
           }else if( c=='[' ){            }else if( c=='[' ){
             cEnd = ']';              cEnd = ']';
             }else if( c=='-' && z[i+1]=='-' ){
               cEnd = '\n';
           }else if( c=='(' ){            }else if( c=='(' ){
             nParen++;              nParen++;
           }else if( c==')' ){            }else if( c==')' ){
             nParen--;              nParen--;
             if( nLine>0 && nParen==0 && j>0 ){              if( nLine>0 && nParen==0 && j>0 ){
              utf8_printf(p->out, "%.*s\n", j, z);              printSchemaLineN(p->out, z, j, "\n");
               j = 0;                j = 0;
             }              }
           }            }
           z[j++] = c;            z[j++] = c;
          if( nParen==1 && (c=='(' || c==',' || c=='\n') ){          if( nParen==1 && cEnd==0
            && (c=='(' || c=='\n' || (c==',' && !wsToEol(z+i+1)))
           ){
             if( c=='\n' ) j--;              if( c=='\n' ) j--;
            utf8_printf(p->out, "%.*s\n  ", j, z);            printSchemaLineN(p->out, z, j, "\n  ");
             j = 0;              j = 0;
             nLine++;              nLine++;
             while( IsSpace(z[i+1]) ){ i++; }              while( IsSpace(z[i+1]) ){ i++; }
Line 1116  static int shell_callback( Line 12253  static int shell_callback(
         }          }
         z[j] = 0;          z[j] = 0;
       }        }
      utf8_printf(p->out, "%s;\n", z);      printSchemaLine(p->out, z, ";\n");
       sqlite3_free(z);        sqlite3_free(z);
       break;        break;
     }      }
Line 1194  static int shell_callback( Line 12331  static int shell_callback(
       break;        break;
     }      }
     case MODE_Insert: {      case MODE_Insert: {
       p->cnt++;  
       if( azArg==0 ) break;        if( azArg==0 ) break;
       utf8_printf(p->out,"INSERT INTO %s",p->zDestTable);        utf8_printf(p->out,"INSERT INTO %s",p->zDestTable);
       if( p->showHeader ){        if( p->showHeader ){
         raw_printf(p->out,"(");          raw_printf(p->out,"(");
         for(i=0; i<nArg; i++){          for(i=0; i<nArg; i++){
          char *zSep = i>0 ? ",": "";          if( i>0 ) raw_printf(p->out, ",");
          utf8_printf(p->out, "%s%s", zSep, azCol[i]);          if( quoteChar(azCol[i]) ){
             char *z = sqlite3_mprintf("\"%w\"", azCol[i]);
             utf8_printf(p->out, "%s", z);
             sqlite3_free(z);
           }else{
             raw_printf(p->out, "%s", azCol[i]);
           }
         }          }
         raw_printf(p->out,")");          raw_printf(p->out,")");
       }        }
      raw_printf(p->out," VALUES(");      p->cnt++;
       for(i=0; i<nArg; i++){        for(i=0; i<nArg; i++){
        char *zSep = i>0 ? ",": "";        raw_printf(p->out, i>0 ? "," : " VALUES(");
         if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){          if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
          utf8_printf(p->out,"%sNULL",zSep);          utf8_printf(p->out,"NULL");
         }else if( aiType && aiType[i]==SQLITE_TEXT ){          }else if( aiType && aiType[i]==SQLITE_TEXT ){
          if( zSep[0] ) utf8_printf(p->out,"%s",zSep);          if( ShellHasFlag(p, SHFLG_Newlines) ){
             output_quoted_string(p->out, azArg[i]);
           }else{
             output_quoted_escaped_string(p->out, azArg[i]);
           }
         }else if( aiType && aiType[i]==SQLITE_INTEGER ){
           utf8_printf(p->out,"%s", azArg[i]);
         }else if( aiType && aiType[i]==SQLITE_FLOAT ){
           char z[50];
           double r = sqlite3_column_double(p->pStmt, i);
           sqlite3_uint64 ur;
           memcpy(&ur,&r,sizeof(r));
           if( ur==0x7ff0000000000000LL ){
             raw_printf(p->out, "1e999");
           }else if( ur==0xfff0000000000000LL ){
             raw_printf(p->out, "-1e999");
           }else{
             sqlite3_snprintf(50,z,"%!.20g", r);
             raw_printf(p->out, "%s", z);
           }
         }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
           const void *pBlob = sqlite3_column_blob(p->pStmt, i);
           int nBlob = sqlite3_column_bytes(p->pStmt, i);
           output_hex_blob(p->out, pBlob, nBlob);
         }else if( isNumber(azArg[i], 0) ){
           utf8_printf(p->out,"%s", azArg[i]);
         }else if( ShellHasFlag(p, SHFLG_Newlines) ){
           output_quoted_string(p->out, azArg[i]);            output_quoted_string(p->out, azArg[i]);
        }else if( aiType && (aiType[i]==SQLITE_INTEGER        }else{
                             || aiType[i]==SQLITE_FLOAT) ){          output_quoted_escaped_string(p->out, azArg[i]);
          utf8_printf(p->out,"%s%s",zSep, azArg[i]);        }
       }
       raw_printf(p->out,");\n");
       break;
     }
     case MODE_Json: {
       if( azArg==0 ) break;
       if( p->cnt==0 ){
         fputs("[{", p->out);
       }else{
         fputs(",\n{", p->out);
       }
       p->cnt++;
       for(i=0; i<nArg; i++){
         output_json_string(p->out, azCol[i], -1);
         putc(':', p->out);
         if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
           fputs("null",p->out);
         }else if( aiType && aiType[i]==SQLITE_FLOAT ){
           char z[50];
           double r = sqlite3_column_double(p->pStmt, i);
           sqlite3_uint64 ur;
           memcpy(&ur,&r,sizeof(r));
           if( ur==0x7ff0000000000000LL ){
             raw_printf(p->out, "1e999");
           }else if( ur==0xfff0000000000000LL ){
             raw_printf(p->out, "-1e999");
           }else{
             sqlite3_snprintf(50,z,"%!.20g", r);
             raw_printf(p->out, "%s", z);
           }
         }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){          }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
           const void *pBlob = sqlite3_column_blob(p->pStmt, i);            const void *pBlob = sqlite3_column_blob(p->pStmt, i);
           int nBlob = sqlite3_column_bytes(p->pStmt, i);            int nBlob = sqlite3_column_bytes(p->pStmt, i);
          if( zSep[0] ) utf8_printf(p->out,"%s",zSep);          output_json_string(p->out, pBlob, nBlob);
         }else if( aiType && aiType[i]==SQLITE_TEXT ){
           output_json_string(p->out, azArg[i], -1);
         }else{
           utf8_printf(p->out,"%s", azArg[i]);
         }
         if( i<nArg-1 ){
           putc(',', p->out);
         }
       }
       putc('}', p->out);
       break;
     }
     case MODE_Quote: {
       if( azArg==0 ) break;
       if( p->cnt==0 && p->showHeader ){
         for(i=0; i<nArg; i++){
           if( i>0 ) fputs(p->colSeparator, p->out);
           output_quoted_string(p->out, azCol[i]);
         }
         fputs(p->rowSeparator, p->out);
       }
       p->cnt++;
       for(i=0; i<nArg; i++){
         if( i>0 ) fputs(p->colSeparator, p->out);
         if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
           utf8_printf(p->out,"NULL");
         }else if( aiType && aiType[i]==SQLITE_TEXT ){
           output_quoted_string(p->out, azArg[i]);
         }else if( aiType && aiType[i]==SQLITE_INTEGER ){
           utf8_printf(p->out,"%s", azArg[i]);
         }else if( aiType && aiType[i]==SQLITE_FLOAT ){
           char z[50];
           double r = sqlite3_column_double(p->pStmt, i);
           sqlite3_snprintf(50,z,"%!.20g", r);
           raw_printf(p->out, "%s", z);
         }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){
           const void *pBlob = sqlite3_column_blob(p->pStmt, i);
           int nBlob = sqlite3_column_bytes(p->pStmt, i);
           output_hex_blob(p->out, pBlob, nBlob);            output_hex_blob(p->out, pBlob, nBlob);
         }else if( isNumber(azArg[i], 0) ){          }else if( isNumber(azArg[i], 0) ){
          utf8_printf(p->out,"%s%s",zSep, azArg[i]);          utf8_printf(p->out,"%s", azArg[i]);
         }else{          }else{
           if( zSep[0] ) utf8_printf(p->out,"%s",zSep);  
           output_quoted_string(p->out, azArg[i]);            output_quoted_string(p->out, azArg[i]);
         }          }
       }        }
      raw_printf(p->out,");\n");      fputs(p->rowSeparator, p->out);
       break;        break;
     }      }
     case MODE_Ascii: {      case MODE_Ascii: {
Line 1247  static int shell_callback( Line 12482  static int shell_callback(
       utf8_printf(p->out, "%s", p->rowSeparator);        utf8_printf(p->out, "%s", p->rowSeparator);
       break;        break;
     }      }
       case MODE_EQP: {
         eqp_append(p, atoi(azArg[0]), atoi(azArg[1]), azArg[3]);
         break;
       }
   }    }
   return 0;    return 0;
 }  }
Line 1261  static int callback(void *pArg, int nArg, char **azArg Line 12500  static int callback(void *pArg, int nArg, char **azArg
 }  }
   
 /*  /*
   ** This is the callback routine from sqlite3_exec() that appends all
   ** output onto the end of a ShellText object.
   */
   static int captureOutputCallback(void *pArg, int nArg, char **azArg, char **az){
     ShellText *p = (ShellText*)pArg;
     int i;
     UNUSED_PARAMETER(az);
     if( azArg==0 ) return 0;
     if( p->n ) appendText(p, "|", 0);
     for(i=0; i<nArg; i++){
       if( i ) appendText(p, ",", 0);
       if( azArg[i] ) appendText(p, azArg[i], 0);
     }
     return 0;
   }
   
   /*
   ** Generate an appropriate SELFTEST table in the main database.
   */
   static void createSelftestTable(ShellState *p){
     char *zErrMsg = 0;
     sqlite3_exec(p->db,
       "SAVEPOINT selftest_init;\n"
       "CREATE TABLE IF NOT EXISTS selftest(\n"
       "  tno INTEGER PRIMARY KEY,\n"   /* Test number */
       "  op TEXT,\n"                   /* Operator:  memo run */
       "  cmd TEXT,\n"                  /* Command text */
       "  ans TEXT\n"                   /* Desired answer */
       ");"
       "CREATE TEMP TABLE [_shell$self](op,cmd,ans);\n"
       "INSERT INTO [_shell$self](rowid,op,cmd)\n"
       "  VALUES(coalesce((SELECT (max(tno)+100)/10 FROM selftest),10),\n"
       "         'memo','Tests generated by --init');\n"
       "INSERT INTO [_shell$self]\n"
       "  SELECT 'run',\n"
       "    'SELECT hex(sha3_query(''SELECT type,name,tbl_name,sql "
                                    "FROM sqlite_schema ORDER BY 2'',224))',\n"
       "    hex(sha3_query('SELECT type,name,tbl_name,sql "
                             "FROM sqlite_schema ORDER BY 2',224));\n"
       "INSERT INTO [_shell$self]\n"
       "  SELECT 'run',"
       "    'SELECT hex(sha3_query(''SELECT * FROM \"' ||"
       "        printf('%w',name) || '\" NOT INDEXED'',224))',\n"
       "    hex(sha3_query(printf('SELECT * FROM \"%w\" NOT INDEXED',name),224))\n"
       "  FROM (\n"
       "    SELECT name FROM sqlite_schema\n"
       "     WHERE type='table'\n"
       "       AND name<>'selftest'\n"
       "       AND coalesce(rootpage,0)>0\n"
       "  )\n"
       " ORDER BY name;\n"
       "INSERT INTO [_shell$self]\n"
       "  VALUES('run','PRAGMA integrity_check','ok');\n"
       "INSERT INTO selftest(tno,op,cmd,ans)"
       "  SELECT rowid*10,op,cmd,ans FROM [_shell$self];\n"
       "DROP TABLE [_shell$self];"
       ,0,0,&zErrMsg);
     if( zErrMsg ){
       utf8_printf(stderr, "SELFTEST initialization failure: %s\n", zErrMsg);
       sqlite3_free(zErrMsg);
     }
     sqlite3_exec(p->db, "RELEASE selftest_init",0,0,0);
   }
   
   
   /*
 ** Set the destination table field of the ShellState structure to  ** Set the destination table field of the ShellState structure to
 ** the name of the table given.  Escape any quote characters in the  ** the name of the table given.  Escape any quote characters in the
 ** table name.  ** table name.
 */  */
 static void set_table_name(ShellState *p, const char *zName){  static void set_table_name(ShellState *p, const char *zName){
   int i, n;    int i, n;
  int needQuote;  char cQuote;
   char *z;    char *z;
   
   if( p->zDestTable ){    if( p->zDestTable ){
Line 1275  static void set_table_name(ShellState *p, const char * Line 12580  static void set_table_name(ShellState *p, const char *
     p->zDestTable = 0;      p->zDestTable = 0;
   }    }
   if( zName==0 ) return;    if( zName==0 ) return;
  needQuote = !isalpha((unsigned char)*zName) && *zName!='_';  cQuote = quoteChar(zName);
  for(i=n=0; zName[i]; i++, n++){  n = strlen30(zName);
    if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ){  if( cQuote ) n += n+2;
      needQuote = 1; 
      if( zName[i]=='\'' ) n++; 
    } 
  } 
  if( needQuote ) n += 2; 
   z = p->zDestTable = malloc( n+1 );    z = p->zDestTable = malloc( n+1 );
  if( z==0 ){  if( z==0 ) shell_out_of_memory();
    raw_printf(stderr,"Error: out of memory\n"); 
    exit(1); 
  } 
   n = 0;    n = 0;
  if( needQuote ) z[n++] = '\'';  if( cQuote ) z[n++] = cQuote;
   for(i=0; zName[i]; i++){    for(i=0; zName[i]; i++){
     z[n++] = zName[i];      z[n++] = zName[i];
    if( zName[i]=='\'' ) z[n++] = '\'';    if( zName[i]==cQuote ) z[n++] = cQuote;
   }    }
  if( needQuote ) z[n++] = '\'';  if( cQuote ) z[n++] = cQuote;
   z[n] = 0;    z[n] = 0;
 }  }
   
 /* zIn is either a pointer to a NULL-terminated string in memory obtained  
 ** from malloc(), or a NULL pointer. The string pointed to by zAppend is  
 ** added to zIn, and the result returned in memory obtained from malloc().  
 ** zIn, if it was not NULL, is freed.  
 **  
 ** If the third argument, quote, is not '\0', then it is used as a  
 ** quote character for zAppend.  
 */  
 static char *appendText(char *zIn, char const *zAppend, char quote){  
   int len;  
   int i;  
   int nAppend = strlen30(zAppend);  
   int nIn = (zIn?strlen30(zIn):0);  
   
   len = nAppend+nIn+1;  
   if( quote ){  
     len += 2;  
     for(i=0; i<nAppend; i++){  
       if( zAppend[i]==quote ) len++;  
     }  
   }  
   
   zIn = (char *)realloc(zIn, len);  
   if( !zIn ){  
     return 0;  
   }  
   
   if( quote ){  
     char *zCsr = &zIn[nIn];  
     *zCsr++ = quote;  
     for(i=0; i<nAppend; i++){  
       *zCsr++ = zAppend[i];  
       if( zAppend[i]==quote ) *zCsr++ = quote;  
     }  
     *zCsr++ = quote;  
     *zCsr++ = '\0';  
     assert( (zCsr-zIn)==len );  
   }else{  
     memcpy(&zIn[nIn], zAppend, nAppend);  
     zIn[len-1] = '\0';  
   }  
   
   return zIn;  
 }  
   
   
 /*  /*
 ** Execute a query statement that will generate SQL output.  Print  ** Execute a query statement that will generate SQL output.  Print
 ** the result columns, comma-separated, on a line and then add a  ** the result columns, comma-separated, on a line and then add a
Line 1356  static char *appendText(char *zIn, char const *zAppend Line 12608  static char *appendText(char *zIn, char const *zAppend
 */  */
 static int run_table_dump_query(  static int run_table_dump_query(
   ShellState *p,           /* Query context */    ShellState *p,           /* Query context */
  const char *zSelect,     /* SELECT statement to extract content */  const char *zSelect      /* SELECT statement to extract content */
  const char *zFirstRow    /* Print before first row, if not NULL */ 
 ){  ){
   sqlite3_stmt *pSelect;    sqlite3_stmt *pSelect;
   int rc;    int rc;
Line 1374  static int run_table_dump_query( Line 12625  static int run_table_dump_query(
   rc = sqlite3_step(pSelect);    rc = sqlite3_step(pSelect);
   nResult = sqlite3_column_count(pSelect);    nResult = sqlite3_column_count(pSelect);
   while( rc==SQLITE_ROW ){    while( rc==SQLITE_ROW ){
     if( zFirstRow ){  
       utf8_printf(p->out, "%s", zFirstRow);  
       zFirstRow = 0;  
     }  
     z = (const char*)sqlite3_column_text(pSelect, 0);      z = (const char*)sqlite3_column_text(pSelect, 0);
     utf8_printf(p->out, "%s", z);      utf8_printf(p->out, "%s", z);
     for(i=1; i<nResult; i++){      for(i=1; i<nResult; i++){
Line 1440  static void displayLinuxIoStats(FILE *out){ Line 12687  static void displayLinuxIoStats(FILE *out){
     };      };
     int i;      int i;
     for(i=0; i<ArraySize(aTrans); i++){      for(i=0; i<ArraySize(aTrans); i++){
      int n = (int)strlen(aTrans[i].zPattern);      int n = strlen30(aTrans[i].zPattern);
       if( strncmp(aTrans[i].zPattern, z, n)==0 ){        if( strncmp(aTrans[i].zPattern, z, n)==0 ){
        raw_printf(out, "%-36s %s", aTrans[i].zDesc, &z[n]);        utf8_printf(out, "%-36s %s", aTrans[i].zDesc, &z[n]);
         break;          break;
       }        }
     }      }
Line 1451  static void displayLinuxIoStats(FILE *out){ Line 12698  static void displayLinuxIoStats(FILE *out){
 }  }
 #endif  #endif
   
   /*
   ** Display a single line of status using 64-bit values.
   */
   static void displayStatLine(
     ShellState *p,            /* The shell context */
     char *zLabel,             /* Label for this one line */
     char *zFormat,            /* Format for the result */
     int iStatusCtrl,          /* Which status to display */
     int bReset                /* True to reset the stats */
   ){
     sqlite3_int64 iCur = -1;
     sqlite3_int64 iHiwtr = -1;
     int i, nPercent;
     char zLine[200];
     sqlite3_status64(iStatusCtrl, &iCur, &iHiwtr, bReset);
     for(i=0, nPercent=0; zFormat[i]; i++){
       if( zFormat[i]=='%' ) nPercent++;
     }
     if( nPercent>1 ){
       sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iCur, iHiwtr);
     }else{
       sqlite3_snprintf(sizeof(zLine), zLine, zFormat, iHiwtr);
     }
     raw_printf(p->out, "%-36s %s\n", zLabel, zLine);
   }
   
 /*  /*
 ** Display memory stats.  ** Display memory stats.
Line 1462  static int display_stats( Line 12734  static int display_stats(
 ){  ){
   int iCur;    int iCur;
   int iHiwtr;    int iHiwtr;
     FILE *out;
     if( pArg==0 || pArg->out==0 ) return 0;
     out = pArg->out;
   
  if( pArg && pArg->out ){  if( pArg->pStmt && pArg->statsOn==2 ){
     int nCol, i, x;
     sqlite3_stmt *pStmt = pArg->pStmt;
     char z[100];
     nCol = sqlite3_column_count(pStmt);
     raw_printf(out, "%-36s %d\n", "Number of output columns:", nCol);
     for(i=0; i<nCol; i++){
       sqlite3_snprintf(sizeof(z),z,"Column %d %nname:", i, &x);
       utf8_printf(out, "%-36s %s\n", z, sqlite3_column_name(pStmt,i));
 #ifndef SQLITE_OMIT_DECLTYPE
       sqlite3_snprintf(30, z+x, "declared type:");
       utf8_printf(out, "%-36s %s\n", z, sqlite3_column_decltype(pStmt, i));
 #endif
 #ifdef SQLITE_ENABLE_COLUMN_METADATA
       sqlite3_snprintf(30, z+x, "database name:");
       utf8_printf(out, "%-36s %s\n", z, sqlite3_column_database_name(pStmt,i));
       sqlite3_snprintf(30, z+x, "table name:");
       utf8_printf(out, "%-36s %s\n", z, sqlite3_column_table_name(pStmt,i));
       sqlite3_snprintf(30, z+x, "origin name:");
       utf8_printf(out, "%-36s %s\n", z, sqlite3_column_origin_name(pStmt,i));
 #endif
     }
   }
   
    iHiwtr = iCur = -1;  if( pArg->statsOn==3 ){
    sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHiwtr, bReset);    if( pArg->pStmt ){
    raw_printf(pArg->out,      iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
            "Memory Used:                         %d (max %d) bytes\n",      raw_printf(pArg->out, "VM-steps: %d\n", iCur);
            iCur, iHiwtr); 
    iHiwtr = iCur = -1; 
    sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHiwtr, bReset); 
    raw_printf(pArg->out, "Number of Outstanding Allocations:   %d (max %d)\n", 
            iCur, iHiwtr); 
    if( pArg->shellFlgs & SHFLG_Pagecache ){ 
      iHiwtr = iCur = -1; 
      sqlite3_status(SQLITE_STATUS_PAGECACHE_USED, &iCur, &iHiwtr, bReset); 
      raw_printf(pArg->out, 
              "Number of Pcache Pages Used:         %d (max %d) pages\n", 
              iCur, iHiwtr); 
     }      }
    iHiwtr = iCur = -1;    return 0;
    sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &iCur, &iHiwtr, bReset);  }
    raw_printf(pArg->out,
            "Number of Pcache Overflow Bytes:     %d (max %d) bytes\n",  displayStatLine(pArg, "Memory Used:",
            iCur, iHiwtr);     "%lld (max %lld) bytes", SQLITE_STATUS_MEMORY_USED, bReset);
    if( pArg->shellFlgs & SHFLG_Scratch ){  displayStatLine(pArg, "Number of Outstanding Allocations:",
      iHiwtr = iCur = -1;     "%lld (max %lld)", SQLITE_STATUS_MALLOC_COUNT, bReset);
      sqlite3_status(SQLITE_STATUS_SCRATCH_USED, &iCur, &iHiwtr, bReset);  if( pArg->shellFlgs & SHFLG_Pagecache ){
      raw_printf(pArg->out,    displayStatLine(pArg, "Number of Pcache Pages Used:",
              "Number of Scratch Allocations Used:  %d (max %d)\n",       "%lld (max %lld) pages", SQLITE_STATUS_PAGECACHE_USED, bReset);
              iCur, iHiwtr);  }
    }  displayStatLine(pArg, "Number of Pcache Overflow Bytes:",
    iHiwtr = iCur = -1;     "%lld (max %lld) bytes", SQLITE_STATUS_PAGECACHE_OVERFLOW, bReset);
    sqlite3_status(SQLITE_STATUS_SCRATCH_OVERFLOW, &iCur, &iHiwtr, bReset);  displayStatLine(pArg, "Largest Allocation:",
    raw_printf(pArg->out,     "%lld bytes", SQLITE_STATUS_MALLOC_SIZE, bReset);
            "Number of Scratch Overflow Bytes:    %d (max %d) bytes\n",  displayStatLine(pArg, "Largest Pcache Allocation:",
            iCur, iHiwtr);     "%lld bytes", SQLITE_STATUS_PAGECACHE_SIZE, bReset);
    iHiwtr = iCur = -1; 
    sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &iCur, &iHiwtr, bReset); 
    raw_printf(pArg->out, "Largest Allocation:                  %d bytes\n", 
            iHiwtr); 
    iHiwtr = iCur = -1; 
    sqlite3_status(SQLITE_STATUS_PAGECACHE_SIZE, &iCur, &iHiwtr, bReset); 
    raw_printf(pArg->out, "Largest Pcache Allocation:           %d bytes\n", 
            iHiwtr); 
    iHiwtr = iCur = -1; 
    sqlite3_status(SQLITE_STATUS_SCRATCH_SIZE, &iCur, &iHiwtr, bReset); 
    raw_printf(pArg->out, "Largest Scratch Allocation:          %d bytes\n", 
            iHiwtr); 
 #ifdef YYTRACKMAXSTACKDEPTH  #ifdef YYTRACKMAXSTACKDEPTH
    iHiwtr = iCur = -1;  displayStatLine(pArg, "Deepest Parser Stack:",
    sqlite3_status(SQLITE_STATUS_PARSER_STACK, &iCur, &iHiwtr, bReset);     "%lld (max %lld)", SQLITE_STATUS_PARSER_STACK, bReset);
    raw_printf(pArg->out, "Deepest Parser Stack:                %d (max %d)\n", 
            iCur, iHiwtr); 
 #endif  #endif
   }  
   
  if( pArg && pArg->out && db ){  if( db ){
     if( pArg->shellFlgs & SHFLG_Lookaside ){      if( pArg->shellFlgs & SHFLG_Lookaside ){
       iHiwtr = iCur = -1;        iHiwtr = iCur = -1;
       sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED,        sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED,
Line 1553  static int display_stats( Line 12824  static int display_stats(
     sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);      sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_WRITE, &iCur, &iHiwtr, 1);
     raw_printf(pArg->out, "Page cache writes:                   %d\n", iCur);      raw_printf(pArg->out, "Page cache writes:                   %d\n", iCur);
     iHiwtr = iCur = -1;      iHiwtr = iCur = -1;
       sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_SPILL, &iCur, &iHiwtr, 1);
       raw_printf(pArg->out, "Page cache spills:                   %d\n", iCur);
       iHiwtr = iCur = -1;
     sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);      sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
     raw_printf(pArg->out, "Schema Heap Usage:                   %d bytes\n",      raw_printf(pArg->out, "Schema Heap Usage:                   %d bytes\n",
             iCur);              iCur);
Line 1562  static int display_stats( Line 12836  static int display_stats(
             iCur);              iCur);
   }    }
   
  if( pArg && pArg->out && db && pArg->pStmt ){  if( pArg->pStmt ){
     iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP,      iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP,
                                bReset);                                 bReset);
     raw_printf(pArg->out, "Fullscan Steps:                      %d\n", iCur);      raw_printf(pArg->out, "Fullscan Steps:                      %d\n", iCur);
Line 1572  static int display_stats( Line 12846  static int display_stats(
     raw_printf(pArg->out, "Autoindex Inserts:                   %d\n", iCur);      raw_printf(pArg->out, "Autoindex Inserts:                   %d\n", iCur);
     iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);      iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
     raw_printf(pArg->out, "Virtual Machine Steps:               %d\n", iCur);      raw_printf(pArg->out, "Virtual Machine Steps:               %d\n", iCur);
       iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE,bReset);
       raw_printf(pArg->out, "Reprepare operations:                %d\n", iCur);
       iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset);
       raw_printf(pArg->out, "Number of times run:                 %d\n", iCur);
       iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_MEMUSED, bReset);
       raw_printf(pArg->out, "Memory used by prepared stmt:        %d\n", iCur);
   }    }
   
 #ifdef __linux__  #ifdef __linux__
Line 1670  static void explain_data_prepare(ShellState *p, sqlite Line 12950  static void explain_data_prepare(ShellState *p, sqlite
   int nAlloc = 0;                 /* Allocated size of p->aiIndent[], abYield */    int nAlloc = 0;                 /* Allocated size of p->aiIndent[], abYield */
   int iOp;                        /* Index of operation in p->aiIndent[] */    int iOp;                        /* Index of operation in p->aiIndent[] */
   
  const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext",  const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", 0 };
                           "NextIfOpen", "PrevIfOpen", 0 }; 
   const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead",    const char *azYield[] = { "Yield", "SeekLT", "SeekGT", "RowSetRead",
                             "Rewind", 0 };                              "Rewind", 0 };
   const char *azGoto[] = { "Goto", 0 };    const char *azGoto[] = { "Goto", 0 };
Line 1721  static void explain_data_prepare(ShellState *p, sqlite Line 13000  static void explain_data_prepare(ShellState *p, sqlite
       }        }
       nAlloc += 100;        nAlloc += 100;
       p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int));        p->aiIndent = (int*)sqlite3_realloc64(p->aiIndent, nAlloc*sizeof(int));
         if( p->aiIndent==0 ) shell_out_of_memory();
       abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int));        abYield = (int*)sqlite3_realloc64(abYield, nAlloc*sizeof(int));
         if( abYield==0 ) shell_out_of_memory();
     }      }
     abYield[iOp] = str_in_array(zOp, azYield);      abYield[iOp] = str_in_array(zOp, azYield);
     p->aiIndent[iOp] = 0;      p->aiIndent[iOp] = 0;
Line 1755  static void explain_data_delete(ShellState *p){ Line 13036  static void explain_data_delete(ShellState *p){
 /*  /*
 ** Disable and restore .wheretrace and .selecttrace settings.  ** Disable and restore .wheretrace and .selecttrace settings.
 */  */
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)static unsigned int savedSelectTrace;
extern int sqlite3SelectTrace;static unsigned int savedWhereTrace;
static int savedSelectTrace; 
#endif 
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE) 
extern int sqlite3WhereTrace; 
static int savedWhereTrace; 
#endif 
 static void disable_debug_trace_modes(void){  static void disable_debug_trace_modes(void){
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)  unsigned int zero = 0;
  savedSelectTrace = sqlite3SelectTrace;  sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 0, &savedSelectTrace);
  sqlite3SelectTrace = 0;  sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &zero);
#endif  sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 2, &savedWhereTrace);
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)  sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &zero);
  savedWhereTrace = sqlite3WhereTrace; 
  sqlite3WhereTrace = 0; 
#endif 
 }  }
 static void restore_debug_trace_modes(void){  static void restore_debug_trace_modes(void){
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)  sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &savedSelectTrace);
  sqlite3SelectTrace = savedSelectTrace;  sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &savedWhereTrace);
#endif 
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE) 
  sqlite3WhereTrace = savedWhereTrace; 
#endif 
 }  }
   
   /* Create the TEMP table used to store parameter bindings */
   static void bind_table_init(ShellState *p){
     int wrSchema = 0;
     int defensiveMode = 0;
     sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, -1, &defensiveMode);
     sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, 0, 0);
     sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema);
     sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0);
     sqlite3_exec(p->db,
       "CREATE TABLE IF NOT EXISTS temp.sqlite_parameters(\n"
       "  key TEXT PRIMARY KEY,\n"
       "  value ANY\n"
       ") WITHOUT ROWID;",
       0, 0, 0);
     sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0);
     sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, defensiveMode, 0);
   }
   
 /*  /*
   ** Bind parameters on a prepared statement.
   **
   ** Parameter bindings are taken from a TEMP table of the form:
   **
   **    CREATE TEMP TABLE sqlite_parameters(key TEXT PRIMARY KEY, value)
   **    WITHOUT ROWID;
   **
   ** No bindings occur if this table does not exist.  The name of the table
   ** begins with "sqlite_" so that it will not collide with ordinary application
   ** tables.  The table must be in the TEMP schema.
   */
   static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){
     int nVar;
     int i;
     int rc;
     sqlite3_stmt *pQ = 0;
   
     nVar = sqlite3_bind_parameter_count(pStmt);
     if( nVar==0 ) return;  /* Nothing to do */
     if( sqlite3_table_column_metadata(pArg->db, "TEMP", "sqlite_parameters",
                                       "key", 0, 0, 0, 0, 0)!=SQLITE_OK ){
       return; /* Parameter table does not exist */
     }
     rc = sqlite3_prepare_v2(pArg->db,
             "SELECT value FROM temp.sqlite_parameters"
             " WHERE key=?1", -1, &pQ, 0);
     if( rc || pQ==0 ) return;
     for(i=1; i<=nVar; i++){
       char zNum[30];
       const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
       if( zVar==0 ){
         sqlite3_snprintf(sizeof(zNum),zNum,"?%d",i);
         zVar = zNum;
       }
       sqlite3_bind_text(pQ, 1, zVar, -1, SQLITE_STATIC);
       if( sqlite3_step(pQ)==SQLITE_ROW ){
         sqlite3_bind_value(pStmt, i, sqlite3_column_value(pQ, 0));
       }else{
         sqlite3_bind_null(pStmt, i);
       }
       sqlite3_reset(pQ);
     }
     sqlite3_finalize(pQ);
   }
   
   /*
   ** UTF8 box-drawing characters.  Imagine box lines like this:
   **
   **           1
   **           |
   **       4 --+-- 2
   **           |
   **           3
   **
   ** Each box characters has between 2 and 4 of the lines leading from
   ** the center.  The characters are here identified by the numbers of
   ** their corresponding lines.
   */
   #define BOX_24   "\342\224\200"  /* U+2500 --- */
   #define BOX_13   "\342\224\202"  /* U+2502  |  */
   #define BOX_23   "\342\224\214"  /* U+250c  ,- */
   #define BOX_34   "\342\224\220"  /* U+2510 -,  */
   #define BOX_12   "\342\224\224"  /* U+2514  '- */
   #define BOX_14   "\342\224\230"  /* U+2518 -'  */
   #define BOX_123  "\342\224\234"  /* U+251c  |- */
   #define BOX_134  "\342\224\244"  /* U+2524 -|  */
   #define BOX_234  "\342\224\254"  /* U+252c -,- */
   #define BOX_124  "\342\224\264"  /* U+2534 -'- */
   #define BOX_1234 "\342\224\274"  /* U+253c -|- */
   
   /* Draw horizontal line N characters long using unicode box
   ** characters
   */
   static void print_box_line(FILE *out, int N){
     const char zDash[] = 
         BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24
         BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24 BOX_24;
     const int nDash = sizeof(zDash) - 1;
     N *= 3;
     while( N>nDash ){
       utf8_printf(out, zDash);
       N -= nDash;
     }
     utf8_printf(out, "%.*s", N, zDash);
   }
   
   /*
   ** Draw a horizontal separator for a MODE_Box table.
   */
   static void print_box_row_separator(
     ShellState *p,
     int nArg,
     const char *zSep1,
     const char *zSep2,
     const char *zSep3
   ){
     int i;
     if( nArg>0 ){
       utf8_printf(p->out, "%s", zSep1);
       print_box_line(p->out, p->actualWidth[0]+2);
       for(i=1; i<nArg; i++){
         utf8_printf(p->out, "%s", zSep2);
         print_box_line(p->out, p->actualWidth[i]+2);
       }
       utf8_printf(p->out, "%s", zSep3);
     }
     fputs("\n", p->out);
   }
   
   
   
   /*
   ** Run a prepared statement and output the result in one of the
   ** table-oriented formats: MODE_Column, MODE_Markdown, MODE_Table,
   ** or MODE_Box.
   **
   ** This is different from ordinary exec_prepared_stmt() in that
   ** it has to run the entire query and gather the results into memory
   ** first, in order to determine column widths, before providing
   ** any output.
   */
   static void exec_prepared_stmt_columnar(
     ShellState *p,                        /* Pointer to ShellState */
     sqlite3_stmt *pStmt                   /* Statment to run */
   ){
     sqlite3_int64 nRow = 0;
     int nColumn = 0;
     char **azData = 0;
     sqlite3_int64 nAlloc = 0;
     const char *z;
     int rc;
     sqlite3_int64 i, nData;
     int j, nTotal, w, n;
     const char *colSep = 0;
     const char *rowSep = 0;
   
     rc = sqlite3_step(pStmt);
     if( rc!=SQLITE_ROW ) return;
     nColumn = sqlite3_column_count(pStmt);
     nAlloc = nColumn*4;
     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));
     }
     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 );
     if( nColumn>p->nWidth ){
       p->colWidth = realloc(p->colWidth, nColumn*2*sizeof(int));
       if( p->colWidth==0 ) shell_out_of_memory();
       for(i=p->nWidth; i<nColumn; i++) p->colWidth[i] = 0;
       p->nWidth = nColumn;
       p->actualWidth = &p->colWidth[nColumn];
     }
     memset(p->actualWidth, 0, nColumn*sizeof(int));
     for(i=0; i<nColumn; i++){
       w = p->colWidth[i];
       if( w<0 ) w = -w;
       p->actualWidth[i] = w;
     }
     nTotal = nColumn*(nRow+1);
     for(i=0; i<nTotal; i++){
       z = azData[i];
       if( z==0 ) z = p->nullValue;
       n = strlenChar(z);
       j = i%nColumn;
       if( n>p->actualWidth[j] ) p->actualWidth[j] = n;
     }
     if( seenInterrupt ) goto columnar_end;
     switch( p->cMode ){
       case MODE_Column: {
         colSep = "  ";
         rowSep = "\n";
         if( p->showHeader ){
           for(i=0; i<nColumn; i++){
             w = p->actualWidth[i];
             if( p->colWidth[i]<0 ) w = -w;
             utf8_width_print(p->out, w, azData[i]);
             fputs(i==nColumn-1?"\n":"  ", p->out);
           }
           for(i=0; i<nColumn; i++){
             print_dashes(p->out, p->actualWidth[i]);
             fputs(i==nColumn-1?"\n":"  ", p->out);
           }
         }
         break;
       }
       case MODE_Table: {
         colSep = " | ";
         rowSep = " |\n";
         print_row_separator(p, nColumn, "+");
         fputs("| ", p->out);
         for(i=0; i<nColumn; i++){
           w = p->actualWidth[i];
           n = strlenChar(azData[i]);
           utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
           fputs(i==nColumn-1?" |\n":" | ", p->out);
         }
         print_row_separator(p, nColumn, "+");
         break;
       }
       case MODE_Markdown: {
         colSep = " | ";
         rowSep = " |\n";
         fputs("| ", p->out);
         for(i=0; i<nColumn; i++){
           w = p->actualWidth[i];
           n = strlenChar(azData[i]);
           utf8_printf(p->out, "%*s%s%*s", (w-n)/2, "", azData[i], (w-n+1)/2, "");
           fputs(i==nColumn-1?" |\n":" | ", p->out);
         }
         print_row_separator(p, nColumn, "|");
         break;
       }
       case MODE_Box: {
         colSep = " " BOX_13 " ";
         rowSep = " " BOX_13 "\n";
         print_box_row_separator(p, nColumn, BOX_23, BOX_234, BOX_34);
         utf8_printf(p->out, BOX_13 " ");
         for(i=0; i<nColumn; i++){
           w = p->actualWidth[i];
           n = strlenChar(azData[i]);
           utf8_printf(p->out, "%*s%s%*s%s",
               (w-n)/2, "", azData[i], (w-n+1)/2, "",
               i==nColumn-1?" "BOX_13"\n":" "BOX_13" ");
         }
         print_box_row_separator(p, nColumn, BOX_123, BOX_1234, BOX_134);
         break;
       }
     }
     for(i=nColumn, j=0; i<nTotal; i++, j++){
       if( j==0 && p->cMode!=MODE_Column ){
         utf8_printf(p->out, "%s", p->cMode==MODE_Box?BOX_13" ":"| ");
       }
       z = azData[i];
       if( z==0 ) z = p->nullValue;
       w = p->actualWidth[j];
       if( p->colWidth[j]<0 ) w = -w;
       utf8_width_print(p->out, w, z);
       if( j==nColumn-1 ){
         utf8_printf(p->out, "%s", rowSep);
         j = -1;
         if( seenInterrupt ) goto columnar_end;
       }else{
         utf8_printf(p->out, "%s", colSep);
       }
     }
     if( p->cMode==MODE_Table ){
       print_row_separator(p, nColumn, "+");
     }else if( p->cMode==MODE_Box ){
       print_box_row_separator(p, nColumn, BOX_12, BOX_124, BOX_14);
     }
   columnar_end:
     if( seenInterrupt ){
       utf8_printf(p->out, "Interrupt\n");
     }
     nData = (nRow+1)*nColumn;
     for(i=0; i<nData; i++) free(azData[i]);
     sqlite3_free(azData);
   }
   
   /*
 ** Run a prepared statement  ** Run a prepared statement
 */  */
 static void exec_prepared_stmt(  static void exec_prepared_stmt(
   ShellState *pArg,                                /* Pointer to ShellState */    ShellState *pArg,                                /* Pointer to ShellState */
  sqlite3_stmt *pStmt,                             /* Statment to run */  sqlite3_stmt *pStmt                              /* Statment to run */
  int (*xCallback)(void*,int,char**,char**,int*)   /* Callback function */ 
 ){  ){
   int rc;    int rc;
   
     if( pArg->cMode==MODE_Column
      || pArg->cMode==MODE_Table
      || pArg->cMode==MODE_Box
      || pArg->cMode==MODE_Markdown
     ){
       exec_prepared_stmt_columnar(pArg, pStmt);
       return;
     }
   
   /* perform the first step.  this will tell us if we    /* perform the first step.  this will tell us if we
   ** have a result set or not and how wide it is.    ** have a result set or not and how wide it is.
   */    */
   rc = sqlite3_step(pStmt);    rc = sqlite3_step(pStmt);
   /* if we have a result set... */    /* if we have a result set... */
   if( SQLITE_ROW == rc ){    if( SQLITE_ROW == rc ){
    /* if we have a callback... */    /* allocate space for col name ptr, value ptr, and type */
    if( xCallback ){    int nCol = sqlite3_column_count(pStmt);
      /* allocate space for col name ptr, value ptr, and type */    void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1);
      int nCol = sqlite3_column_count(pStmt);    if( !pData ){
      void *pData = sqlite3_malloc64(3*nCol*sizeof(const char*) + 1);      rc = SQLITE_NOMEM;
      if( !pData ){    }else{
        rc = SQLITE_NOMEM;      char **azCols = (char **)pData;      /* Names of result columns */
      }else{      char **azVals = &azCols[nCol];       /* Results */
        char **azCols = (char **)pData;      /* Names of result columns */      int *aiTypes = (int *)&azVals[nCol]; /* Result types */
        char **azVals = &azCols[nCol];       /* Results */      int i, x;
        int *aiTypes = (int *)&azVals[nCol]; /* Result types */      assert(sizeof(int) <= sizeof(char *));
        int i, x;      /* save off ptrs to column names */
        assert(sizeof(int) <= sizeof(char *));      for(i=0; i<nCol; i++){
        /* save off ptrs to column names */        azCols[i] = (char *)sqlite3_column_name(pStmt, i);
       }
       do{
         /* extract the data and data types */
         for(i=0; i<nCol; i++){          for(i=0; i<nCol; i++){
          azCols[i] = (char *)sqlite3_column_name(pStmt, i);          aiTypes[i] = x = sqlite3_column_type(pStmt, i);
        }          if( x==SQLITE_BLOB && pArg && pArg->cMode==MODE_Insert ){
        do{            azVals[i] = "";
          /* extract the data and data types */          }else{
          for(i=0; i<nCol; i++){            azVals[i] = (char*)sqlite3_column_text(pStmt, i);
            aiTypes[i] = x = sqlite3_column_type(pStmt, i);          }
            if( x==SQLITE_BLOB && pArg && pArg->cMode==MODE_Insert ){          if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){
              azVals[i] = "";            rc = SQLITE_NOMEM;
            }else{            break; /* from for */
              azVals[i] = (char*)sqlite3_column_text(pStmt, i);          }
            }        } /* end for */
            if( !azVals[i] && (aiTypes[i]!=SQLITE_NULL) ){ 
              rc = SQLITE_NOMEM; 
              break; /* from for */ 
            } 
          } /* end for */ 
   
          /* if data and types extracted successfully... */        /* if data and types extracted successfully... */
          if( SQLITE_ROW == rc ){        if( SQLITE_ROW == rc ){
            /* call the supplied callback with the result row data */          /* call the supplied callback with the result row data */
            if( xCallback(pArg, nCol, azVals, azCols, aiTypes) ){          if( shell_callback(pArg, nCol, azVals, azCols, aiTypes) ){
              rc = SQLITE_ABORT;            rc = SQLITE_ABORT;
            }else{          }else{
              rc = sqlite3_step(pStmt);            rc = sqlite3_step(pStmt);
            } 
           }            }
        } while( SQLITE_ROW == rc );        }
        sqlite3_free(pData);      } while( SQLITE_ROW == rc );
       sqlite3_free(pData);
       if( pArg->cMode==MODE_Json ){
         fputs("]\n", pArg->out);
       }        }
       }
     }
   }
   
   #ifndef SQLITE_OMIT_VIRTUALTABLE
   /*
   ** This function is called to process SQL if the previous shell command
   ** was ".expert". It passes the SQL in the second argument directly to
   ** the sqlite3expert object.
   **
   ** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
   ** code. In this case, (*pzErr) may be set to point to a buffer containing
   ** an English language error message. It is the responsibility of the
   ** caller to eventually free this buffer using sqlite3_free().
   */
   static int expertHandleSQL(
     ShellState *pState, 
     const char *zSql, 
     char **pzErr
   ){
     assert( pState->expert.pExpert );
     assert( pzErr==0 || *pzErr==0 );
     return sqlite3_expert_sql(pState->expert.pExpert, zSql, pzErr);
   }
   
   /*
   ** This function is called either to silently clean up the object
   ** created by the ".expert" command (if bCancel==1), or to generate a 
   ** report from it and then clean it up (if bCancel==0).
   **
   ** If successful, SQLITE_OK is returned. Otherwise, an SQLite error
   ** code. In this case, (*pzErr) may be set to point to a buffer containing
   ** an English language error message. It is the responsibility of the
   ** caller to eventually free this buffer using sqlite3_free().
   */
   static int expertFinish(
     ShellState *pState,
     int bCancel,
     char **pzErr
   ){
     int rc = SQLITE_OK;
     sqlite3expert *p = pState->expert.pExpert;
     assert( p );
     assert( bCancel || pzErr==0 || *pzErr==0 );
     if( bCancel==0 ){
       FILE *out = pState->out;
       int bVerbose = pState->expert.bVerbose;
   
       rc = sqlite3_expert_analyze(p, pzErr);
       if( rc==SQLITE_OK ){
         int nQuery = sqlite3_expert_count(p);
         int i;
   
         if( bVerbose ){
           const char *zCand = sqlite3_expert_report(p,0,EXPERT_REPORT_CANDIDATES);
           raw_printf(out, "-- Candidates -----------------------------\n");
           raw_printf(out, "%s\n", zCand);
         }
         for(i=0; i<nQuery; i++){
           const char *zSql = sqlite3_expert_report(p, i, EXPERT_REPORT_SQL);
           const char *zIdx = sqlite3_expert_report(p, i, EXPERT_REPORT_INDEXES);
           const char *zEQP = sqlite3_expert_report(p, i, EXPERT_REPORT_PLAN);
           if( zIdx==0 ) zIdx = "(no new indexes)\n";
           if( bVerbose ){
             raw_printf(out, "-- Query %d --------------------------------\n",i+1);
             raw_printf(out, "%s\n\n", zSql);
           }
           raw_printf(out, "%s\n", zIdx);
           raw_printf(out, "%s\n", zEQP);
         }
       }
     }
     sqlite3_expert_destroy(p);
     pState->expert.pExpert = 0;
     return rc;
   }
   
   /*
   ** Implementation of ".expert" dot command.
   */
   static int expertDotCommand(
     ShellState *pState,             /* Current shell tool state */
     char **azArg,                   /* Array of arguments passed to dot command */
     int nArg                        /* Number of entries in azArg[] */
   ){
     int rc = SQLITE_OK;
     char *zErr = 0;
     int i;
     int iSample = 0;
   
     assert( pState->expert.pExpert==0 );
     memset(&pState->expert, 0, sizeof(ExpertInfo));
   
     for(i=1; rc==SQLITE_OK && i<nArg; i++){
       char *z = azArg[i];
       int n;
       if( z[0]=='-' && z[1]=='-' ) z++;
       n = strlen30(z);
       if( n>=2 && 0==strncmp(z, "-verbose", n) ){
         pState->expert.bVerbose = 1;
       }
       else if( n>=2 && 0==strncmp(z, "-sample", n) ){
         if( i==(nArg-1) ){
           raw_printf(stderr, "option requires an argument: %s\n", z);
           rc = SQLITE_ERROR;
         }else{
           iSample = (int)integerValue(azArg[++i]);
           if( iSample<0 || iSample>100 ){
             raw_printf(stderr, "value out of range: %s\n", azArg[i]);
             rc = SQLITE_ERROR;
           }
         }
       }
       else{
         raw_printf(stderr, "unknown option: %s\n", z);
         rc = SQLITE_ERROR;
       }
     }
   
     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);
         rc = SQLITE_ERROR;
     }else{      }else{
      do{      sqlite3_expert_config(
        rc = sqlite3_step(pStmt);          pState->expert.pExpert, EXPERT_CONFIG_SAMPLE, iSample
      } while( rc == SQLITE_ROW );      );
     }      }
   }    }
   
     return rc;
 }  }
   #endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
   
 /*  /*
 ** Execute a statement or set of statements.  Print  ** Execute a statement or set of statements.  Print
Line 1860  static void exec_prepared_stmt( Line 13553  static void exec_prepared_stmt(
 ** and callback data argument.  ** and callback data argument.
 */  */
 static int shell_exec(  static int shell_exec(
   sqlite3 *db,                              /* An open database */  
   const char *zSql,                         /* SQL to be evaluated */  
   int (*xCallback)(void*,int,char**,char**,int*),   /* Callback function */  
                                             /* (not the same as sqlite3_exec) */  
   ShellState *pArg,                         /* Pointer to ShellState */    ShellState *pArg,                         /* Pointer to ShellState */
     const char *zSql,                         /* SQL to be evaluated */
   char **pzErrMsg                           /* Error msg written here */    char **pzErrMsg                           /* Error msg written here */
 ){  ){
   sqlite3_stmt *pStmt = NULL;     /* Statement to execute. */    sqlite3_stmt *pStmt = NULL;     /* Statement to execute. */
   int rc = SQLITE_OK;             /* Return Code */    int rc = SQLITE_OK;             /* Return Code */
   int rc2;    int rc2;
   const char *zLeftover;          /* Tail of unprocessed SQL */    const char *zLeftover;          /* Tail of unprocessed SQL */
     sqlite3 *db = pArg->db;
   
   if( pzErrMsg ){    if( pzErrMsg ){
     *pzErrMsg = NULL;      *pzErrMsg = NULL;
   }    }
   
   #ifndef SQLITE_OMIT_VIRTUALTABLE
     if( pArg->expert.pExpert ){
       rc = expertHandleSQL(pArg, zSql, pzErrMsg);
       return expertFinish(pArg, (rc!=SQLITE_OK), pzErrMsg);
     }
   #endif
   
   while( zSql[0] && (SQLITE_OK == rc) ){    while( zSql[0] && (SQLITE_OK == rc) ){
     static const char *zStmtSql;      static const char *zStmtSql;
     rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);      rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zLeftover);
Line 1891  static int shell_exec( Line 13589  static int shell_exec(
         continue;          continue;
       }        }
       zStmtSql = sqlite3_sql(pStmt);        zStmtSql = sqlite3_sql(pStmt);
         if( zStmtSql==0 ) zStmtSql = "";
       while( IsSpace(zStmtSql[0]) ) zStmtSql++;        while( IsSpace(zStmtSql[0]) ) zStmtSql++;
   
       /* save off the prepared statment handle and reset row count */        /* save off the prepared statment handle and reset row count */
Line 1900  static int shell_exec( Line 13599  static int shell_exec(
       }        }
   
       /* echo the sql statement if echo on */        /* echo the sql statement if echo on */
      if( pArg && pArg->echoOn ){      if( pArg && ShellHasFlag(pArg, SHFLG_Echo) ){
         utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);          utf8_printf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
       }        }
   
       /* Show the EXPLAIN QUERY PLAN if .eqp is on */        /* Show the EXPLAIN QUERY PLAN if .eqp is on */
      if( pArg && pArg->autoEQP && sqlite3_strlike("EXPLAIN%",zStmtSql,0)!=0 ){      if( pArg && pArg->autoEQP && sqlite3_stmt_isexplain(pStmt)==0 ){
         sqlite3_stmt *pExplain;          sqlite3_stmt *pExplain;
         char *zEQP;          char *zEQP;
           int triggerEQP = 0;
         disable_debug_trace_modes();          disable_debug_trace_modes();
           sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, -1, &triggerEQP);
           if( pArg->autoEQP>=AUTOEQP_trigger ){
             sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0);
           }
         zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zStmtSql);          zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zStmtSql);
         rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);          rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
         if( rc==SQLITE_OK ){          if( rc==SQLITE_OK ){
           while( sqlite3_step(pExplain)==SQLITE_ROW ){            while( sqlite3_step(pExplain)==SQLITE_ROW ){
            raw_printf(pArg->out,"--EQP-- %d,",sqlite3_column_int(pExplain, 0));            const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);
            raw_printf(pArg->out,"%d,", sqlite3_column_int(pExplain, 1));            int iEqpId = sqlite3_column_int(pExplain, 0);
            raw_printf(pArg->out,"%d,", sqlite3_column_int(pExplain, 2));            int iParentId = sqlite3_column_int(pExplain, 1);
            utf8_printf(pArg->out,"%s\n", sqlite3_column_text(pExplain, 3));            if( zEQPLine==0 ) zEQPLine = "";
             if( zEQPLine[0]=='-' ) eqp_render(pArg);
             eqp_append(pArg, iEqpId, iParentId, zEQPLine);
           }            }
             eqp_render(pArg);
         }          }
         sqlite3_finalize(pExplain);          sqlite3_finalize(pExplain);
         sqlite3_free(zEQP);          sqlite3_free(zEQP);
        if( pArg->autoEQP>=2 ){        if( pArg->autoEQP>=AUTOEQP_full ){
           /* Also do an EXPLAIN for ".eqp full" mode */            /* Also do an EXPLAIN for ".eqp full" mode */
           zEQP = sqlite3_mprintf("EXPLAIN %s", zStmtSql);            zEQP = sqlite3_mprintf("EXPLAIN %s", zStmtSql);
           rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);            rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
           if( rc==SQLITE_OK ){            if( rc==SQLITE_OK ){
             pArg->cMode = MODE_Explain;              pArg->cMode = MODE_Explain;
             explain_data_prepare(pArg, pExplain);              explain_data_prepare(pArg, pExplain);
            exec_prepared_stmt(pArg, pExplain, xCallback);            exec_prepared_stmt(pArg, pExplain);
             explain_data_delete(pArg);              explain_data_delete(pArg);
           }            }
           sqlite3_finalize(pExplain);            sqlite3_finalize(pExplain);
           sqlite3_free(zEQP);            sqlite3_free(zEQP);
         }          }
           if( pArg->autoEQP>=AUTOEQP_trigger && triggerEQP==0 ){
             sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 0, 0);
             /* Reprepare pStmt before reactiving trace modes */
             sqlite3_finalize(pStmt);
             sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
             if( pArg ) pArg->pStmt = pStmt;
           }
         restore_debug_trace_modes();          restore_debug_trace_modes();
       }        }
   
       if( pArg ){        if( pArg ){
         pArg->cMode = pArg->mode;          pArg->cMode = pArg->mode;
        if( pArg->autoExplain        if( pArg->autoExplain ){
         && sqlite3_column_count(pStmt)==8          if( sqlite3_stmt_isexplain(pStmt)==1 ){
         && sqlite3_strlike("EXPLAIN%", zStmtSql,0)==0            pArg->cMode = MODE_Explain;
        ){          }
          pArg->cMode = MODE_Explain;          if( sqlite3_stmt_isexplain(pStmt)==2 ){
             pArg->cMode = MODE_EQP;
           }
         }          }
   
         /* If the shell is currently in ".explain" mode, gather the extra          /* If the shell is currently in ".explain" mode, gather the extra
Line 1953  static int shell_exec( Line 13669  static int shell_exec(
         }          }
       }        }
   
      exec_prepared_stmt(pArg, pStmt, xCallback);      bind_prepared_stmt(pArg, pStmt);
       exec_prepared_stmt(pArg, pStmt);
       explain_data_delete(pArg);        explain_data_delete(pArg);
         eqp_render(pArg);
   
       /* print usage stats if stats on */        /* print usage stats if stats on */
       if( pArg && pArg->statsOn ){        if( pArg && pArg->statsOn ){
Line 1988  static int shell_exec( Line 13706  static int shell_exec(
   return rc;    return rc;
 }  }
   
   /*
   ** Release memory previously allocated by tableColumnList().
   */
   static void freeColumnList(char **azCol){
     int i;
     for(i=1; azCol[i]; i++){
       sqlite3_free(azCol[i]);
     }
     /* azCol[0] is a static string */
     sqlite3_free(azCol);
   }
   
 /*  /*
   ** Return a list of pointers to strings which are the names of all
   ** columns in table zTab.   The memory to hold the names is dynamically
   ** allocated and must be released by the caller using a subsequent call
   ** to freeColumnList().
   **
   ** The azCol[0] entry is usually NULL.  However, if zTab contains a rowid
   ** value that needs to be preserved, then azCol[0] is filled in with the
   ** name of the rowid column.
   **
   ** The first regular column in the table is azCol[1].  The list is terminated
   ** by an entry with azCol[i]==0.
   */
   static char **tableColumnList(ShellState *p, const char *zTab){
     char **azCol = 0;
     sqlite3_stmt *pStmt;
     char *zSql;
     int nCol = 0;
     int nAlloc = 0;
     int nPK = 0;       /* Number of PRIMARY KEY columns seen */
     int isIPK = 0;     /* True if one PRIMARY KEY column of type INTEGER */
     int preserveRowid = ShellHasFlag(p, SHFLG_PreserveRowid);
     int rc;
   
     zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab);
     rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
     sqlite3_free(zSql);
     if( rc ) return 0;
     while( sqlite3_step(pStmt)==SQLITE_ROW ){
       if( nCol>=nAlloc-2 ){
         nAlloc = nAlloc*2 + nCol + 10;
         azCol = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0]));
         if( azCol==0 ) shell_out_of_memory();
       }
       azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
       if( sqlite3_column_int(pStmt, 5) ){
         nPK++;
         if( nPK==1
          && sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2),
                             "INTEGER")==0
         ){
           isIPK = 1;
         }else{
           isIPK = 0;
         }
       }
     }
     sqlite3_finalize(pStmt);
     if( azCol==0 ) return 0;
     azCol[0] = 0;
     azCol[nCol+1] = 0;
   
     /* The decision of whether or not a rowid really needs to be preserved
     ** is tricky.  We never need to preserve a rowid for a WITHOUT ROWID table
     ** or a table with an INTEGER PRIMARY KEY.  We are unable to preserve
     ** rowids on tables where the rowid is inaccessible because there are other
     ** columns in the table named "rowid", "_rowid_", and "oid".
     */
     if( preserveRowid && isIPK ){
       /* If a single PRIMARY KEY column with type INTEGER was seen, then it
       ** might be an alise for the ROWID.  But it might also be a WITHOUT ROWID
       ** table or a INTEGER PRIMARY KEY DESC column, neither of which are
       ** ROWID aliases.  To distinguish these cases, check to see if
       ** there is a "pk" entry in "PRAGMA index_list".  There will be
       ** no "pk" index if the PRIMARY KEY really is an alias for the ROWID.
       */
       zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)"
                              " WHERE origin='pk'", zTab);
       rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
       sqlite3_free(zSql);
       if( rc ){
         freeColumnList(azCol);
         return 0;
       }
       rc = sqlite3_step(pStmt);
       sqlite3_finalize(pStmt);
       preserveRowid = rc==SQLITE_ROW;
     }
     if( preserveRowid ){
       /* Only preserve the rowid if we can find a name to use for the
       ** rowid */
       static char *azRowid[] = { "rowid", "_rowid_", "oid" };
       int i, j;
       for(j=0; j<3; j++){
         for(i=1; i<=nCol; i++){
           if( sqlite3_stricmp(azRowid[j],azCol[i])==0 ) break;
         }
         if( i>nCol ){
           /* At this point, we know that azRowid[j] is not the name of any
           ** ordinary column in the table.  Verify that azRowid[j] is a valid
           ** name for the rowid before adding it to azCol[0].  WITHOUT ROWID
           ** tables will fail this last check */
           rc = sqlite3_table_column_metadata(p->db,0,zTab,azRowid[j],0,0,0,0,0);
           if( rc==SQLITE_OK ) azCol[0] = azRowid[j];
           break;
         }
       }
     }
     return azCol;
   }
   
   /*
   ** Toggle the reverse_unordered_selects setting.
   */
   static void toggleSelectOrder(sqlite3 *db){
     sqlite3_stmt *pStmt = 0;
     int iSetting = 0;
     char zStmt[100];
     sqlite3_prepare_v2(db, "PRAGMA reverse_unordered_selects", -1, &pStmt, 0);
     if( sqlite3_step(pStmt)==SQLITE_ROW ){
       iSetting = sqlite3_column_int(pStmt, 0);
     }
     sqlite3_finalize(pStmt);
     sqlite3_snprintf(sizeof(zStmt), zStmt,
          "PRAGMA reverse_unordered_selects(%d)", !iSetting);
     sqlite3_exec(db, zStmt, 0, 0, 0);
   }
   
   /*
 ** This is a different callback routine used for dumping the database.  ** This is a different callback routine used for dumping the database.
 ** Each row received by this callback consists of a table name,  ** Each row received by this callback consists of a table name,
 ** the table type ("index" or "table") and SQL to create the table.  ** the table type ("index" or "table") and SQL to create the table.
 ** This routine should print text sufficient to recreate the table.  ** This routine should print text sufficient to recreate the table.
 */  */
static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
   int rc;    int rc;
   const char *zTable;    const char *zTable;
   const char *zType;    const char *zType;
   const char *zSql;    const char *zSql;
   const char *zPrepStmt = 0;  
   ShellState *p = (ShellState *)pArg;    ShellState *p = (ShellState *)pArg;
     int dataOnly;
     int noSys;
   
  UNUSED_PARAMETER(azCol);  UNUSED_PARAMETER(azNotUsed);
  if( nArg!=3 ) return 1;  if( nArg!=3 || azArg==0 ) return 0;
   zTable = azArg[0];    zTable = azArg[0];
   zType = azArg[1];    zType = azArg[1];
   zSql = azArg[2];    zSql = azArg[2];
     dataOnly = (p->shellFlgs & SHFLG_DumpDataOnly)!=0;
     noSys    = (p->shellFlgs & SHFLG_DumpNoSys)!=0;
   
  if( strcmp(zTable, "sqlite_sequence")==0 ){  if( strcmp(zTable, "sqlite_sequence")==0 && !noSys ){
    zPrepStmt = "DELETE FROM sqlite_sequence;\n";    if( !dataOnly ) raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
  }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){  }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 && !noSys ){
    raw_printf(p->out, "ANALYZE sqlite_master;\n");    if( !dataOnly ) raw_printf(p->out, "ANALYZE sqlite_schema;\n");
   }else if( strncmp(zTable, "sqlite_", 7)==0 ){    }else if( strncmp(zTable, "sqlite_", 7)==0 ){
     return 0;      return 0;
     }else if( dataOnly ){
       /* no-op */
   }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){    }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
     char *zIns;      char *zIns;
     if( !p->writableSchema ){      if( !p->writableSchema ){
Line 2022  static int dump_callback(void *pArg, int nArg, char ** Line 13874  static int dump_callback(void *pArg, int nArg, char **
       p->writableSchema = 1;        p->writableSchema = 1;
     }      }
     zIns = sqlite3_mprintf(      zIns = sqlite3_mprintf(
       "INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)"       "INSERT INTO sqlite_schema(type,name,tbl_name,rootpage,sql)"
        "VALUES('table','%q','%q',0,'%q');",         "VALUES('table','%q','%q',0,'%q');",
        zTable, zTable, zSql);         zTable, zTable, zSql);
     utf8_printf(p->out, "%s\n", zIns);      utf8_printf(p->out, "%s\n", zIns);
     sqlite3_free(zIns);      sqlite3_free(zIns);
     return 0;      return 0;
   }else{    }else{
    utf8_printf(p->out, "%s;\n", zSql);    printSchemaLine(p->out, zSql, ";\n");
   }    }
   
   if( strcmp(zType, "table")==0 ){    if( strcmp(zType, "table")==0 ){
    sqlite3_stmt *pTableInfo = 0;    ShellText sSelect;
    char *zSelect = 0;    ShellText sTable;
    char *zTableInfo = 0;    char **azCol;
    char *zTmp = 0;    int i;
    int nRow = 0;    char *savedDestTable;
     int savedMode;
   
    zTableInfo = appendText(zTableInfo, "PRAGMA table_info(", 0);    azCol = tableColumnList(p, zTable);
    zTableInfo = appendText(zTableInfo, zTable, '"');    if( azCol==0 ){
    zTableInfo = appendText(zTableInfo, ");", 0);      p->nErr++;
      return 0;
    rc = sqlite3_prepare_v2(p->db, zTableInfo, -1, &pTableInfo, 0); 
    free(zTableInfo); 
    if( rc!=SQLITE_OK || !pTableInfo ){ 
      return 1; 
     }      }
   
     zSelect = appendText(zSelect, "SELECT 'INSERT INTO ' || ", 0);  
     /* Always quote the table name, even if it appears to be pure ascii,      /* Always quote the table name, even if it appears to be pure ascii,
     ** in case it is a keyword. Ex:  INSERT INTO "table" ... */      ** in case it is a keyword. Ex:  INSERT INTO "table" ... */
    zTmp = appendText(zTmp, zTable, '"');    initText(&sTable);
    if( zTmp ){    appendText(&sTable, zTable, quoteChar(zTable));
      zSelect = appendText(zSelect, zTmp, '\'');    /* If preserving the rowid, add a column list after the table name.
      free(zTmp);    ** In other words:  "INSERT INTO tab(rowid,a,b,c,...) VALUES(...)"
    }    ** instead of the usual "INSERT INTO tab VALUES(...)".
    zSelect = appendText(zSelect, " || ' VALUES(' || ", 0);    */
    rc = sqlite3_step(pTableInfo);    if( azCol[0] ){
    while( rc==SQLITE_ROW ){      appendText(&sTable, "(", 0);
      const char *zText = (const char *)sqlite3_column_text(pTableInfo, 1);      appendText(&sTable, azCol[0], 0);
      zSelect = appendText(zSelect, "quote(", 0);      for(i=1; azCol[i]; i++){
      zSelect = appendText(zSelect, zText, '"');        appendText(&sTable, ",", 0);
      rc = sqlite3_step(pTableInfo);        appendText(&sTable, azCol[i], quoteChar(azCol[i]));
      if( rc==SQLITE_ROW ){ 
        zSelect = appendText(zSelect, "), ", 0); 
      }else{ 
        zSelect = appendText(zSelect, ") ", 0); 
       }        }
      nRow++;      appendText(&sTable, ")", 0);
     }      }
    rc = sqlite3_finalize(pTableInfo);
    if( rc!=SQLITE_OK || nRow==0 ){    /* Build an appropriate SELECT statement */
      free(zSelect);    initText(&sSelect);
      return 1;    appendText(&sSelect, "SELECT ", 0);
     if( azCol[0] ){
       appendText(&sSelect, azCol[0], 0);
       appendText(&sSelect, ",", 0);
     }      }
    zSelect = appendText(zSelect, "|| ')' FROM  ", 0);    for(i=1; azCol[i]; i++){
    zSelect = appendText(zSelect, zTable, '"');      appendText(&sSelect, azCol[i], quoteChar(azCol[i]));
       if( azCol[i+1] ){
         appendText(&sSelect, ",", 0);
       }
     }
     freeColumnList(azCol);
     appendText(&sSelect, " FROM ", 0);
     appendText(&sSelect, zTable, quoteChar(zTable));
   
    rc = run_table_dump_query(p, zSelect, zPrepStmt);    savedDestTable = p->zDestTable;
    if( rc==SQLITE_CORRUPT ){    savedMode = p->mode;
      zSelect = appendText(zSelect, " ORDER BY rowid DESC", 0);    p->zDestTable = sTable.z;
      run_table_dump_query(p, zSelect, 0);    p->mode = p->cMode = MODE_Insert;
     rc = shell_exec(p, sSelect.z, 0);
     if( (rc&0xff)==SQLITE_CORRUPT ){
       raw_printf(p->out, "/****** CORRUPTION ERROR *******/\n");
       toggleSelectOrder(p->db);
       shell_exec(p, sSelect.z, 0);
       toggleSelectOrder(p->db);
     }      }
    free(zSelect);    p->zDestTable = savedDestTable;
     p->mode = savedMode;
     freeText(&sTable);
     freeText(&sSelect);
     if( rc ) p->nErr++;
   }    }
   return 0;    return 0;
 }  }
Line 2128  static int run_schema_dump_query( Line 13992  static int run_schema_dump_query(
 }  }
   
 /*  /*
** Text of a help message** Text of help messages.
 **
 ** The help text for each individual command begins with a line that starts
 ** with ".".  Subsequent lines are supplimental information.
 **
 ** There must be two or more spaces between the end of the command and the
 ** start of the description of what that command does.
 */  */
static char zHelp[] =static const char *(azHelp[]) = {
  ".auth ON|OFF           Show authorizer callbacks\n"#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
  ".backup ?DB? FILE      Backup DB (default \"main\") to FILE\n"  ".archive ...             Manage SQL archives",
  ".bail on|off           Stop after hitting an error.  Default OFF\n"  "   Each command must have exactly one of the following options:",
  ".binary on|off         Turn binary output on or off.  Default OFF\n"  "     -c, --create               Create a new archive",
  ".changes on|off        Show number of rows changed by SQL\n"  "     -u, --update               Add or update files with changed mtime",
  ".clone NEWDB           Clone data into NEWDB from the existing database\n"  "     -i, --insert               Like -u but always add even if unchanged",
  ".databases             List names and files of attached databases\n"  "     -t, --list                 List contents of archive",
  ".dbinfo ?DB?           Show status information about the database\n"  "     -x, --extract              Extract files from archive",
  ".dump ?TABLE? ...      Dump the database in an SQL text format\n"  "   Optional arguments:",
  "                         If TABLE specified, only dump tables matching\n"  "     -v, --verbose              Print each filename as it is processed",
  "                         LIKE pattern TABLE.\n"  "     -f FILE, --file FILE       Use archive FILE (default is current db)",
  ".echo on|off           Turn command echo on or off\n"  "     -a FILE, --append FILE     Open FILE using the apndvfs VFS",
  ".eqp on|off|full       Enable or disable automatic EXPLAIN QUERY PLAN\n"  "     -C DIR, --directory DIR    Read/extract files from directory DIR",
  ".exit                  Exit this program\n"  "     -n, --dryrun               Show the SQL that would have occurred",
  ".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic\n"  "   Examples:",
  ".fullschema ?--indent? Show schema and the content of sqlite_stat tables\n"  "     .ar -cf ARCHIVE foo bar  # Create ARCHIVE from files foo and bar",
  ".headers on|off        Turn display of headers on or off\n"  "     .ar -tf ARCHIVE          # List members of ARCHIVE",
  ".help                  Show this message\n"  "     .ar -xvf ARCHIVE         # Verbosely extract files from ARCHIVE",
  ".import FILE TABLE     Import data from FILE into TABLE\n"  "   See also:",
  ".indexes ?TABLE?       Show names of all indexes\n"  "      http://sqlite.org/cli.html#sqlar_archive_support",
  "                         If TABLE specified, only show indexes for tables\n"#endif
  "                         matching LIKE pattern TABLE.\n"#ifndef SQLITE_OMIT_AUTHORIZATION
   ".auth ON|OFF             Show authorizer callbacks",
 #endif
   ".backup ?DB? FILE        Backup DB (default \"main\") to FILE",
   "       --append            Use the appendvfs",
   "       --async             Write to FILE without journal and fsync()",
   ".bail on|off             Stop after hitting an error.  Default OFF",
   ".binary on|off           Turn binary output on or off.  Default OFF",
   ".cd DIRECTORY            Change the working directory to DIRECTORY",
   ".changes on|off          Show number of rows changed by SQL",
   ".check GLOB              Fail if output since .testcase does not match",
   ".clone NEWDB             Clone data into NEWDB from the existing database",
   ".databases               List names and files of attached databases",
   ".dbconfig ?op? ?val?     List or change sqlite3_db_config() options",
   ".dbinfo ?DB?             Show status information about the database",
   ".dump ?OBJECTS?          Render database content as SQL",
   "   Options:",
   "     --data-only            Output only INSERT statements",
   "     --newlines             Allow unescaped newline characters in output",
   "     --nosys                Omit system tables (ex: \"sqlite_stat1\")",
   "     --preserve-rowids      Include ROWID values in the output",
   "   OBJECTS is a LIKE pattern for tables, indexes, triggers or views to dump",
   "   Additional LIKE patterns can be given in subsequent arguments",
   ".echo on|off             Turn command echo on or off",
   ".eqp on|off|full|...     Enable or disable automatic EXPLAIN QUERY PLAN",
   "   Other Modes:",
 #ifdef SQLITE_DEBUG
   "      test                  Show raw EXPLAIN QUERY PLAN output",
   "      trace                 Like \"full\" but enable \"PRAGMA vdbe_trace\"",
 #endif
   "      trigger               Like \"full\" but also show trigger bytecode",
   ".excel                   Display the output of next command in spreadsheet",
   "   --bom                   Put a UTF8 byte-order mark on intermediate file",
   ".exit ?CODE?             Exit this program with return-code CODE",
   ".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",
   "   --schema SCHEMA         Use SCHEMA instead of \"main\"",
   "   --help                  Show CMD details",
   ".fullschema ?--indent?   Show schema and the content of sqlite_stat tables",
   ".headers on|off          Turn display of headers on or off",
   ".help ?-all? ?PATTERN?   Show help text for PATTERN",
   ".import FILE TABLE       Import data from FILE into TABLE",
   "   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",
   "     -v                    \"Verbose\" - increase auxiliary output",
   "   Notes:",
   "     *  If TABLE does not exist, it is created.  The first row of input",
   "        determines the column names.",
   "     *  If neither --csv or --ascii are used, the input mode is derived",
   "        from the \".mode\" output mode",
   "     *  If FILE begins with \"|\" then it is a command that generates the",
   "        input text.",
 #ifndef SQLITE_OMIT_TEST_CONTROL
   ".imposter INDEX TABLE    Create imposter table TABLE on index INDEX",
 #endif
   ".indexes ?TABLE?         Show names of indexes",
   "                           If TABLE is specified, only show indexes for",
   "                           tables matching TABLE using the LIKE operator.",
 #ifdef SQLITE_ENABLE_IOTRACE  #ifdef SQLITE_ENABLE_IOTRACE
  ".iotrace FILE          Enable I/O diagnostic logging to FILE\n"  ".iotrace FILE            Enable I/O diagnostic logging to FILE",
 #endif  #endif
  ".limit ?LIMIT? ?VAL?   Display or change the value of an SQLITE_LIMIT\n"  ".limit ?LIMIT? ?VAL?     Display or change the value of an SQLITE_LIMIT",
   ".lint OPTIONS            Report potential schema issues.",
   "     Options:",
   "        fkey-indexes     Find missing foreign key indexes",
 #ifndef SQLITE_OMIT_LOAD_EXTENSION  #ifndef SQLITE_OMIT_LOAD_EXTENSION
  ".load FILE ?ENTRY?     Load an extension library\n"  ".load FILE ?ENTRY?       Load an extension library",
 #endif  #endif
  ".log FILE|off          Turn logging on or off.  FILE can be stderr/stdout\n"  ".log FILE|off            Turn logging on or off.  FILE can be stderr/stdout",
  ".mode MODE ?TABLE?     Set output mode where MODE is one of:\n"  ".mode MODE ?TABLE?       Set output mode",
  "                         ascii    Columns/rows delimited by 0x1F and 0x1E\n"  "   MODE is one of:",
  "                         csv      Comma-separated values\n"  "     ascii     Columns/rows delimited by 0x1F and 0x1E",
  "                         column   Left-aligned columns.  (See .width)\n"  "     box       Tables using unicode box-drawing characters",
  "                         html     HTML <table> code\n"  "     csv       Comma-separated values",
  "                         insert   SQL insert statements for TABLE\n"  "     column    Output in columns.  (See .width)",
  "                         line     One value per line\n"  "     html      HTML <table> code",
  "                         list     Values delimited by .separator strings\n"  "     insert    SQL insert statements for TABLE",
  "                         tabs     Tab-separated values\n"  "     json      Results in a JSON array",
  "                         tcl      TCL list elements\n"  "     line      One value per line",
  ".nullvalue STRING      Use STRING in place of NULL values\n"  "     list      Values delimited by \"|\"",
  ".once FILENAME         Output for the next SQL command only to FILENAME\n"  "     markdown  Markdown table format",
  ".open ?FILENAME?       Close existing database and reopen FILENAME\n"  "     quote     Escape answers as for SQL",
  ".output ?FILENAME?     Send output to FILENAME or stdout\n"  "     table     ASCII-art table",
  ".print STRING...       Print literal STRING\n"  "     tabs      Tab-separated values",
  ".prompt MAIN CONTINUE  Replace the standard prompts\n"  "     tcl       TCL list elements",
  ".quit                  Exit this program\n"  ".nullvalue STRING        Use STRING in place of NULL values",
  ".read FILENAME         Execute SQL in FILENAME\n"  ".once ?OPTIONS? ?FILE?   Output for the next SQL command only to FILE",
  ".restore ?DB? FILE     Restore content of DB (default \"main\") from FILE\n"  "     If FILE begins with '|' then open as a pipe",
  ".save FILE             Write in-memory database into FILE\n"  "       --bom  Put a UTF8 byte-order mark at the beginning",
  ".scanstats on|off      Turn sqlite3_stmt_scanstatus() metrics on or off\n"  "       -e     Send output to the system text editor",
  ".schema ?PATTERN?      Show the CREATE statements matching PATTERN\n"  "       -x     Send output as CSV to a spreadsheet (same as \".excel\")",
  "                          Add --indent for pretty-printing\n"#ifdef SQLITE_DEBUG
  ".separator COL ?ROW?   Change the column separator and optionally the row\n"  ".oom ?--repeat M? ?N?    Simulate an OOM error on the N-th allocation",
  "                         separator for both the output mode and .import\n"#endif 
   ".open ?OPTIONS? ?FILE?   Close existing database and reopen FILE",
   "     Options:",
   "        --append        Use appendvfs to append database to the end of FILE",
 #ifdef SQLITE_ENABLE_DESERIALIZE
   "        --deserialize   Load into memory useing sqlite3_deserialize()",
   "        --hexdb         Load the output of \"dbtotxt\" as an in-memory db",
   "        --maxsize N     Maximum size for --hexdb or --deserialized database",
 #endif
   "        --new           Initialize FILE to an empty database",
   "        --nofollow      Do not follow symbolic links",
   "        --readonly      Open FILE readonly",
   "        --zip           FILE is a ZIP archive",
   ".output ?FILE?           Send output to FILE or stdout if FILE is omitted",
   "   If FILE begins with '|' then open it as a pipe.",
   "   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",
   ".parameter CMD ...       Manage SQL parameter bindings",
   "   clear                   Erase all bindings",
   "   init                    Initialize the TEMP table that holds bindings",
   "   list                    List the current parameter bindings",
   "   set PARAMETER VALUE     Given SQL parameter PARAMETER a value of VALUE",
   "                           PARAMETER should start with one of: $ : @ ?",
   "   unset PARAMETER         Remove PARAMETER from the binding table",
   ".print STRING...         Print literal STRING",
 #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
   ".progress N              Invoke progress handler after every N opcodes",
   "   --limit N                 Interrupt after N progress callbacks",
   "   --once                    Do no more than one progress interrupt",
   "   --quiet|-q                No output except at interrupts",
   "   --reset                   Reset the count for each input and interrupt",
 #endif
   ".prompt MAIN CONTINUE    Replace the standard prompts",
   ".quit                    Exit this program",
   ".read FILE               Read input from FILE",
 #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",
   "   --recovery-db NAME       Store recovery metadata in database file NAME",
   "   --lost-and-found TABLE   Alternative name for the lost-and-found table",
   "   --no-rowids              Do not attempt to recover rowid values",
   "                            that are not also INTEGER PRIMARY KEYs",
 #endif
   ".restore ?DB? FILE       Restore content of DB (default \"main\") from FILE",
   ".save FILE               Write in-memory database into FILE",
   ".scanstats on|off        Turn sqlite3_stmt_scanstatus() metrics on or off",
   ".schema ?PATTERN?        Show the CREATE statements matching PATTERN",
   "   Options:",
   "      --indent             Try to pretty-print the schema",
   "      --nosys              Omit objects whose names start with \"sqlite_\"",
   ".selftest ?OPTIONS?      Run tests defined in the SELFTEST table",
   "    Options:",
   "       --init               Create a new SELFTEST table",
   "       -v                   Verbose output",
   ".separator COL ?ROW?     Change the column and row separators",
 #if defined(SQLITE_ENABLE_SESSION)  #if defined(SQLITE_ENABLE_SESSION)
  ".session CMD ...       Create or control sessions\n"  ".session ?NAME? CMD ...  Create or control sessions",
   "   Subcommands:",
   "     attach TABLE             Attach TABLE",
   "     changeset FILE           Write a changeset into FILE",
   "     close                    Close one session",
   "     enable ?BOOLEAN?         Set or query the enable bit",
   "     filter GLOB...           Reject tables matching GLOBs",
   "     indirect ?BOOLEAN?       Mark or query the indirect status",
   "     isempty                  Query whether the session is empty",
   "     list                     List currently open session names",
   "     open DB NAME             Open a new session on DB",
   "     patchset FILE            Write a patchset into FILE",
   "   If ?NAME? is omitted, the first defined session is used.",
 #endif  #endif
  ".shell CMD ARGS...     Run CMD ARGS... in a system shell\n"  ".sha3sum ...             Compute a SHA3 hash of database content",
  ".show                  Show the current values for various settings\n"  "    Options:",
  ".stats ?on|off?        Show stats or turn stats on or off\n"  "      --schema              Also hash the sqlite_schema table",
  ".system CMD ARGS...    Run CMD ARGS... in a system shell\n"  "      --sha3-224            Use the sha3-224 algorithm",
  ".tables ?TABLE?        List names of tables\n"  "      --sha3-256            Use the sha3-256 algorithm (default)",
  "                         If TABLE specified, only list tables matching\n"  "      --sha3-384            Use the sha3-384 algorithm",
  "                         LIKE pattern TABLE.\n"  "      --sha3-512            Use the sha3-512 algorithm",
  ".timeout MS            Try opening locked tables for MS milliseconds\n"  "    Any other argument is a LIKE pattern for tables to hash",
  ".timer on|off          Turn SQL timer on or off\n"#ifndef SQLITE_NOHAVE_SYSTEM
  ".trace FILE|off        Output each SQL statement as it is run\n"  ".shell CMD ARGS...       Run CMD ARGS... in a system shell",
  ".vfsinfo ?AUX?         Information about the top-level VFS\n"#endif
  ".vfslist               List all available VFSes\n"  ".show                    Show the current values for various settings",
  ".vfsname ?AUX?         Print the name of the VFS stack\n"  ".stats ?ARG?             Show stats or turn stats on or off",
  ".width NUM1 NUM2 ...   Set column widths for \"column\" mode\n"  "   off                      Turn off automatic stat display",
  "                         Negative values right-justify\n"  "   on                       Turn on automatic stat display",
;  "   stmt                     Show statement stats",
   "   vmstep                   Show the virtual machine step count only",
 #ifndef SQLITE_NOHAVE_SYSTEM
   ".system CMD ARGS...      Run CMD ARGS... in a system shell",
 #endif
   ".tables ?TABLE?          List names of tables matching LIKE pattern TABLE",
   ".testcase NAME           Begin redirecting output to 'testcase-out.txt'",
   ".testctrl CMD ...        Run various sqlite3_test_control() operations",
   "                           Run \".testctrl\" with no arguments for details",
   ".timeout MS              Try opening locked tables for MS milliseconds",
   ".timer on|off            Turn SQL timer on or off",
 #ifndef SQLITE_OMIT_TRACE
   ".trace ?OPTIONS?         Output each SQL statement as it is run",
   "    FILE                    Send output to FILE",
   "    stdout                  Send output to stdout",
   "    stderr                  Send output to stderr",
   "    off                     Disable tracing",
   "    --expanded              Expand query parameters",
 #ifdef SQLITE_ENABLE_NORMALIZE
   "    --normalized            Normal the SQL statements",
 #endif
   "    --plain                 Show SQL as it is input",
   "    --stmt                  Trace statement execution (SQLITE_TRACE_STMT)",
   "    --profile               Profile statements (SQLITE_TRACE_PROFILE)",
   "    --row                   Trace each row (SQLITE_TRACE_ROW)",
   "    --close                 Trace connection close (SQLITE_TRACE_CLOSE)",
 #endif /* SQLITE_OMIT_TRACE */
 #ifdef SQLITE_DEBUG
   ".unmodule NAME ...       Unregister virtual table modules",
   "    --allexcept             Unregister everything except those named",
 #endif
   ".vfsinfo ?AUX?           Information about the top-level VFS",
   ".vfslist                 List all available VFSes",
   ".vfsname ?AUX?           Print the name of the VFS stack",
   ".width NUM1 NUM2 ...     Set minimum column widths for columnar output",
   "     Negative values right-justify",
 };
   
 #if defined(SQLITE_ENABLE_SESSION)  
 /*  /*
** Print help information for the ".sessions" command** Output help text.
 **
 ** zPattern describes the set of commands for which help text is provided.
 ** If zPattern is NULL, then show all commands, but only give a one-line
 ** description of each.
 **
 ** Return the number of matches.
 */  */
void session_help(ShellState *p){static int showHelp(FILE *out, const char *zPattern){
  raw_printf(p->out,  int i = 0;
    ".session ?NAME? SUBCOMMAND ?ARGS...?\n"  int j = 0;
    "If ?NAME? is omitted, the first defined session is used.\n"  int n = 0;
    "Subcommands:\n"  char *zPat;
    "   attach TABLE             Attach TABLE\n"  if( zPattern==0
    "   changeset FILE           Write a changeset into FILE\n"   || zPattern[0]=='0'
    "   close                    Close one session\n"   || strcmp(zPattern,"-a")==0
    "   enable ?BOOLEAN?         Set or query the enable bit\n"   || strcmp(zPattern,"-all")==0
    "   filter GLOB...           Reject tables matching GLOBs\n"   || strcmp(zPattern,"--all")==0
    "   indirect ?BOOLEAN?       Mark or query the indirect status\n"  ){
    "   isempty                  Query whether the session is empty\n"    /* Show all commands, but only one line per command */
    "   list                     List currently open session names\n"    if( zPattern==0 ) zPattern = "";
    "   open DB NAME             Open a new session on DB\n"    for(i=0; i<ArraySize(azHelp); i++){
    "   patchset FILE            Write a patchset into FILE\n"      if( azHelp[i][0]=='.' || zPattern[0] ){
  );        utf8_printf(out, "%s\n", azHelp[i]);
         n++;
       }
     }
   }else{
     /* Look for commands that for which zPattern is an exact prefix */
     zPat = sqlite3_mprintf(".%s*", zPattern);
     for(i=0; i<ArraySize(azHelp); i++){
       if( sqlite3_strglob(zPat, azHelp[i])==0 ){
         utf8_printf(out, "%s\n", azHelp[i]);
         j = i+1;
         n++;
       }
     }
     sqlite3_free(zPat);
     if( n ){
       if( n==1 ){
         /* when zPattern is a prefix of exactly one command, then include the
         ** details of that command, which should begin at offset j */
         while( j<ArraySize(azHelp)-1 && azHelp[j][0]!='.' ){
           utf8_printf(out, "%s\n", azHelp[j]);
           j++;
         }
       }
       return n;
     }
     /* Look for commands that contain zPattern anywhere.  Show the complete
     ** text of all commands that match. */
     zPat = sqlite3_mprintf("%%%s%%", zPattern);
     for(i=0; i<ArraySize(azHelp); i++){
       if( azHelp[i][0]=='.' ) j = i;
       if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){
         utf8_printf(out, "%s\n", azHelp[j]);
         while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]!='.' ){
           j++;
           utf8_printf(out, "%s\n", azHelp[j]);
         }
         i = j;
         n++;
       }
     }
     sqlite3_free(zPat);
   }
   return n;
 }  }
 #endif  
   
   
 /* Forward reference */  /* Forward reference */
static int process_input(ShellState *p, FILE *in);static int process_input(ShellState *p);
 
 /*  /*
** Implementation of the "readfile(X)" SQL function.  The entire content** Read the content of file zName into memory obtained from sqlite3_malloc64()
** of the file named X is read and returned as a BLOB.  NULL is returned** and return a pointer to the buffer. The caller is responsible for freeing
** if the file does not exist or is unreadable.** the memory.
 **
 ** If parameter pnByte is not NULL, (*pnByte) is set to the number of bytes
 ** read.
 **
 ** For convenience, a nul-terminator byte is always appended to the data read
 ** from the file before the buffer is returned. This byte is not included in
 ** the final value of (*pnByte), if applicable.
 **
 ** NULL is returned if any error is encountered. The final value of *pnByte
 ** is undefined in this case.
 */  */
static void readfileFunc(static char *readFile(const char *zName, int *pnByte){
  sqlite3_context *context,  FILE *in = fopen(zName, "rb");
  int argc, 
  sqlite3_value **argv 
){ 
  const char *zName; 
  FILE *in; 
   long nIn;    long nIn;
  void *pBuf;  size_t nRead;
  char *pBuf;
  UNUSED_PARAMETER(argc);  if( in==0 ) return 0;
  zName = (const char*)sqlite3_value_text(argv[0]); 
  if( zName==0 ) return; 
  in = fopen(zName, "rb"); 
  if( in==0 ) return; 
   fseek(in, 0, SEEK_END);    fseek(in, 0, SEEK_END);
   nIn = ftell(in);    nIn = ftell(in);
   rewind(in);    rewind(in);
  pBuf = sqlite3_malloc64( nIn );  pBuf = sqlite3_malloc64( nIn+1 );
  if( pBuf && 1==fread(pBuf, nIn, 1, in) ){  if( pBuf==0 ){ fclose(in); return 0; }
    sqlite3_result_blob(context, pBuf, nIn, sqlite3_free);  nRead = fread(pBuf, nIn, 1, in);
  }else{  fclose(in);
   if( nRead!=1 ){
     sqlite3_free(pBuf);      sqlite3_free(pBuf);
       return 0;
   }    }
  fclose(in);  pBuf[nIn] = 0;
   if( pnByte ) *pnByte = nIn;
   return pBuf;
 }  }
   
 /*  
 ** Implementation of the "writefile(X,Y)" SQL function.  The argument Y  
 ** is written into file X.  The number of bytes written is returned.  Or  
 ** NULL is returned if something goes wrong, such as being unable to open  
 ** file X for writing.  
 */  
 static void writefileFunc(  
   sqlite3_context *context,  
   int argc,  
   sqlite3_value **argv  
 ){  
   FILE *out;  
   const char *z;  
   sqlite3_int64 rc;  
   const char *zFile;  
   
   UNUSED_PARAMETER(argc);  
   zFile = (const char*)sqlite3_value_text(argv[0]);  
   if( zFile==0 ) return;  
   out = fopen(zFile, "wb");  
   if( out==0 ) return;  
   z = (const char*)sqlite3_value_blob(argv[1]);  
   if( z==0 ){  
     rc = 0;  
   }else{  
     rc = fwrite(z, 1, sqlite3_value_bytes(argv[1]), out);  
   }  
   fclose(out);  
   sqlite3_result_int64(context, rc);  
 }  
   
 #if defined(SQLITE_ENABLE_SESSION)  #if defined(SQLITE_ENABLE_SESSION)
 /*  /*
 ** Close a single OpenSession object and release all of its associated  ** Close a single OpenSession object and release all of its associated
Line 2343  static int session_filter(void *pCtx, const char *zTab Line 14401  static int session_filter(void *pCtx, const char *zTab
 #endif  #endif
   
 /*  /*
   ** Try to deduce the type of file for zName based on its content.  Return
   ** one of the SHELL_OPEN_* constants.
   **
   ** If the file does not exist or is empty but its name looks like a ZIP
   ** archive and the dfltZip flag is true, then assume it is a ZIP archive.
   ** Otherwise, assume an ordinary database regardless of the filename if
   ** the type cannot be determined from content.
   */
   int deduceDatabaseType(const char *zName, int dfltZip){
     FILE *f = fopen(zName, "rb");
     size_t n;
     int rc = SHELL_OPEN_UNSPEC;
     char zBuf[100];
     if( f==0 ){
       if( dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
          return SHELL_OPEN_ZIPFILE;
       }else{
          return SHELL_OPEN_NORMAL;
       }
     }
     n = fread(zBuf, 16, 1, f);
     if( n==1 && memcmp(zBuf, "SQLite format 3", 16)==0 ){
       fclose(f);
       return SHELL_OPEN_NORMAL;
     }
     fseek(f, -25, SEEK_END);
     n = fread(zBuf, 25, 1, f);
     if( n==1 && memcmp(zBuf, "Start-Of-SQLite3-", 17)==0 ){
       rc = SHELL_OPEN_APPENDVFS;
     }else{
       fseek(f, -22, SEEK_END);
       n = fread(zBuf, 22, 1, f);
       if( n==1 && zBuf[0]==0x50 && zBuf[1]==0x4b && zBuf[2]==0x05
          && zBuf[3]==0x06 ){
         rc = SHELL_OPEN_ZIPFILE;
       }else if( n==0 && dfltZip && sqlite3_strlike("%.zip",zName,0)==0 ){
         rc = SHELL_OPEN_ZIPFILE;
       }
     }
     fclose(f);
     return rc;  
   }
   
   #ifdef SQLITE_ENABLE_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.
   */
   static unsigned char *readHexDb(ShellState *p, int *pnData){
     unsigned char *a = 0;
     int nLine;
     int n = 0;
     int pgsz = 0;
     int iOffset = 0;
     int j, k;
     int rc;
     FILE *in;
     unsigned int x[16];
     char zLine[1000];
     if( p->zDbFilename ){
       in = fopen(p->zDbFilename, "r");
       if( in==0 ){
         utf8_printf(stderr, "cannot open \"%s\" for reading\n", p->zDbFilename);
         return 0;
       }
       nLine = 0;
     }else{
       in = p->in;
       nLine = p->lineno;
       if( in==0 ) in = stdin;
     }
     *pnData = 0;
     nLine++;
     if( fgets(zLine, sizeof(zLine), in)==0 ) goto readHexDb_error;
     rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz);
     if( rc!=2 ) goto readHexDb_error;
     if( n<0 ) goto readHexDb_error;
     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;
     }
     memset(a, 0, n);
     if( pgsz<512 || pgsz>65536 || (pgsz & (pgsz-1))!=0 ){
       utf8_printf(stderr, "invalid pagesize\n");
       goto readHexDb_error;
     }
     for(nLine++; fgets(zLine, sizeof(zLine), in)!=0; nLine++){
       rc = sscanf(zLine, "| page %d offset %d", &j, &k);
       if( rc==2 ){
         iOffset = k;
         continue;
       }
       if( strncmp(zLine, "| end ", 6)==0 ){
         break;
       }
       rc = sscanf(zLine,"| %d: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
                   &j, &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[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 ){
           int ii;
           for(ii=0; ii<16; ii++) a[k+ii] = x[ii]&0xff;
         }
       }
     }
     *pnData = n;
     if( in!=p->in ){
       fclose(in);
     }else{
       p->lineno = nLine;
     }
     return a;
   
   readHexDb_error:
     if( in!=p->in ){
       fclose(in);
     }else{
       while( fgets(zLine, sizeof(zLine), p->in)!=0 ){
         nLine++;
         if(strncmp(zLine, "| end ", 6)==0 ) break;
       }
       p->lineno = nLine;
     }
     sqlite3_free(a);
     utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine);
     return 0;
   }
   #endif /* SQLITE_ENABLE_DESERIALIZE */
   
   /*
   ** Scalar function "shell_int32". The first argument to this function
   ** must be a blob. The second a non-negative integer. This function
   ** reads and returns a 32-bit big-endian integer from byte
   ** offset (4*<arg2>) of the blob.
   */
   static void shellInt32(
     sqlite3_context *context, 
     int argc, 
     sqlite3_value **argv
   ){
     const unsigned char *pBlob;
     int nBlob;
     int iInt;
   
     UNUSED_PARAMETER(argc);
     nBlob = sqlite3_value_bytes(argv[0]);
     pBlob = (const unsigned char*)sqlite3_value_blob(argv[0]);
     iInt = sqlite3_value_int(argv[1]);
   
     if( iInt>=0 && (iInt+1)*4<=nBlob ){
       const unsigned char *a = &pBlob[iInt*4];
       sqlite3_int64 iVal = ((sqlite3_int64)a[0]<<24)
                          + ((sqlite3_int64)a[1]<<16)
                          + ((sqlite3_int64)a[2]<< 8)
                          + ((sqlite3_int64)a[3]<< 0);
       sqlite3_result_int64(context, iVal);
     }
   }
   
   /*
   ** Scalar function "shell_idquote(X)" returns string X quoted as an identifier,
   ** using "..." with internal double-quote characters doubled.
   */
   static void shellIdQuote(
     sqlite3_context *context, 
     int argc, 
     sqlite3_value **argv
   ){
     const char *zName = (const char*)sqlite3_value_text(argv[0]);
     UNUSED_PARAMETER(argc);
     if( zName ){
       char *z = sqlite3_mprintf("\"%w\"", zName);
       sqlite3_result_text(context, z, -1, sqlite3_free);
     }
   }
   
   /*
   ** Scalar function "usleep(X)" invokes sqlite3_sleep(X) and returns X.
   */
   static void shellUSleepFunc(
     sqlite3_context *context, 
     int argcUnused, 
     sqlite3_value **argv
   ){
     int sleep = sqlite3_value_int(argv[0]);
     (void)argcUnused;
     sqlite3_sleep(sleep/1000);
     sqlite3_result_int(context, sleep);
   }
   
   /*
   ** Scalar function "shell_escape_crnl" used by the .recover command.
   ** The argument passed to this function is the output of built-in
   ** function quote(). If the first character of the input is "'", 
   ** indicating that the value passed to quote() was a text value,
   ** then this function searches the input for "\n" and "\r" characters
   ** and adds a wrapper similar to the following:
   **
   **   replace(replace(<input>, '\n', char(10), '\r', char(13));
   **
   ** Or, if the first character of the input is not "'", then a copy
   ** of the input is returned.
   */
   static void shellEscapeCrnl(
     sqlite3_context *context, 
     int argc, 
     sqlite3_value **argv
   ){
     const char *zText = (const char*)sqlite3_value_text(argv[0]);
     UNUSED_PARAMETER(argc);
     if( zText[0]=='\'' ){
       int nText = sqlite3_value_bytes(argv[0]);
       int i;
       char zBuf1[20];
       char zBuf2[20];
       const char *zNL = 0;
       const char *zCR = 0;
       int nCR = 0;
       int nNL = 0;
   
       for(i=0; zText[i]; i++){
         if( zNL==0 && zText[i]=='\n' ){
           zNL = unused_string(zText, "\\n", "\\012", zBuf1);
           nNL = (int)strlen(zNL);
         }
         if( zCR==0 && zText[i]=='\r' ){
           zCR = unused_string(zText, "\\r", "\\015", zBuf2);
           nCR = (int)strlen(zCR);
         }
       }
   
       if( zNL || zCR ){
         int iOut = 0;
         i64 nMax = (nNL > nCR) ? nNL : nCR;
         i64 nAlloc = nMax * nText + (nMax+64)*2;
         char *zOut = (char*)sqlite3_malloc64(nAlloc);
         if( zOut==0 ){
           sqlite3_result_error_nomem(context);
           return;
         }
   
         if( zNL && zCR ){
           memcpy(&zOut[iOut], "replace(replace(", 16);
           iOut += 16;
         }else{
           memcpy(&zOut[iOut], "replace(", 8);
           iOut += 8;
         }
         for(i=0; zText[i]; i++){
           if( zText[i]=='\n' ){
             memcpy(&zOut[iOut], zNL, nNL);
             iOut += nNL;
           }else if( zText[i]=='\r' ){
             memcpy(&zOut[iOut], zCR, nCR);
             iOut += nCR;
           }else{
             zOut[iOut] = zText[i];
             iOut++;
           }
         }
   
         if( zNL ){
           memcpy(&zOut[iOut], ",'", 2); iOut += 2;
           memcpy(&zOut[iOut], zNL, nNL); iOut += nNL;
           memcpy(&zOut[iOut], "', char(10))", 12); iOut += 12;
         }
         if( zCR ){
           memcpy(&zOut[iOut], ",'", 2); iOut += 2;
           memcpy(&zOut[iOut], zCR, nCR); iOut += nCR;
           memcpy(&zOut[iOut], "', char(13))", 12); iOut += 12;
         }
   
         sqlite3_result_text(context, zOut, iOut, SQLITE_TRANSIENT);
         sqlite3_free(zOut);
         return;
       }
     }
   
     sqlite3_result_value(context, argv[0]);
   }
   
   /* Flags for open_db().
   **
   ** The default behavior of open_db() is to exit(1) if the database fails to
   ** open.  The OPEN_DB_KEEPALIVE flag changes that so that it prints an error
   ** but still returns without calling exit.
   **
   ** The OPEN_DB_ZIPFILE flag causes open_db() to prefer to open files as a
   ** ZIP archive if the file does not exist or is empty and its name matches
   ** the *.zip pattern.
   */
   #define OPEN_DB_KEEPALIVE   0x001   /* Return after error if true */
   #define OPEN_DB_ZIPFILE     0x002   /* Open as ZIP if name matches *.zip */
   
   /*
 ** Make sure the database is open.  If it is not, then open it.  If  ** Make sure the database is open.  If it is not, then open it.  If
 ** the database fails to open, print an error message and exit.  ** the database fails to open, print an error message and exit.
 */  */
static void open_db(ShellState *p, int keepAlive){static void open_db(ShellState *p, int openFlags){
   if( p->db==0 ){    if( p->db==0 ){
    sqlite3_initialize();    if( p->openMode==SHELL_OPEN_UNSPEC ){
    sqlite3_open(p->zDbFilename, &p->db);      if( p->zDbFilename==0 || p->zDbFilename[0]==0 ){
    globalDb = p->db;        p->openMode = SHELL_OPEN_NORMAL;
    if( p->db && sqlite3_errcode(p->db)==SQLITE_OK ){      }else{
      sqlite3_create_function(p->db, "shellstatic", 0, SQLITE_UTF8, 0,        p->openMode = (u8)deduceDatabaseType(p->zDbFilename, 
          shellstaticFunc, 0, 0);                             (openFlags & OPEN_DB_ZIPFILE)!=0);
       }
     }      }
       switch( p->openMode ){
         case SHELL_OPEN_APPENDVFS: {
           sqlite3_open_v2(p->zDbFilename, &p->db, 
              SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, "apndvfs");
           break;
         }
         case SHELL_OPEN_HEXDB:
         case SHELL_OPEN_DESERIALIZE: {
           sqlite3_open(0, &p->db);
           break;
         }
         case SHELL_OPEN_ZIPFILE: {
           sqlite3_open(":memory:", &p->db);
           break;
         }
         case SHELL_OPEN_READONLY: {
           sqlite3_open_v2(p->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,
              SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, 0);
           break;
         }
       }
       globalDb = p->db;
     if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){      if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
       utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",        utf8_printf(stderr,"Error: unable to open database \"%s\": %s\n",
           p->zDbFilename, sqlite3_errmsg(p->db));            p->zDbFilename, sqlite3_errmsg(p->db));
      if( keepAlive ) return;      if( openFlags & OPEN_DB_KEEPALIVE ){
         sqlite3_open(":memory:", &p->db);
         return;
       }
       exit(1);        exit(1);
     }      }
 #ifndef SQLITE_OMIT_LOAD_EXTENSION  #ifndef SQLITE_OMIT_LOAD_EXTENSION
     sqlite3_enable_load_extension(p->db, 1);      sqlite3_enable_load_extension(p->db, 1);
 #endif  #endif
    sqlite3_create_function(p->db, "readfile", 1, SQLITE_UTF8, 0,    sqlite3_fileio_init(p->db, 0, 0);
                            readfileFunc, 0, 0);    sqlite3_shathree_init(p->db, 0, 0);
    sqlite3_create_function(p->db, "writefile", 2, SQLITE_UTF8, 0,    sqlite3_completion_init(p->db, 0, 0);
                            writefileFunc, 0, 0);    sqlite3_uint_init(p->db, 0, 0);
     sqlite3_decimal_init(p->db, 0, 0);
     sqlite3_ieee_init(p->db, 0, 0);
     sqlite3_series_init(p->db, 0, 0);
 #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
     sqlite3_dbdata_init(p->db, 0, 0);
 #endif
 #ifdef SQLITE_HAVE_ZLIB
     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);
     sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0,
                             shellModuleSchema, 0, 0);
     sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p,
                             shellPutsFunc, 0, 0);
     sqlite3_create_function(p->db, "shell_escape_crnl", 1, SQLITE_UTF8, 0,
                             shellEscapeCrnl, 0, 0);
     sqlite3_create_function(p->db, "shell_int32", 2, SQLITE_UTF8, 0,
                             shellInt32, 0, 0);
     sqlite3_create_function(p->db, "shell_idquote", 1, SQLITE_UTF8, 0,
                             shellIdQuote, 0, 0);
     sqlite3_create_function(p->db, "usleep",1,SQLITE_UTF8,0,
                             shellUSleepFunc, 0, 0);
 #ifndef SQLITE_NOHAVE_SYSTEM
     sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0,
                             editFunc, 0, 0);
     sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0,
                             editFunc, 0, 0);
 #endif
     if( p->openMode==SHELL_OPEN_ZIPFILE ){
       char *zSql = sqlite3_mprintf(
          "CREATE VIRTUAL TABLE zip USING zipfile(%Q);", p->zDbFilename);
       sqlite3_exec(p->db, zSql, 0, 0, 0);
       sqlite3_free(zSql);
     }
 #ifdef SQLITE_ENABLE_DESERIALIZE
     else
     if( p->openMode==SHELL_OPEN_DESERIALIZE || p->openMode==SHELL_OPEN_HEXDB ){
       int rc;
       int nData = 0;
       unsigned char *aData;
       if( p->openMode==SHELL_OPEN_DESERIALIZE ){
         aData = (unsigned char*)readFile(p->zDbFilename, &nData);
       }else{
         aData = readHexDb(p, &nData);
         if( aData==0 ){
           return;
         }
       }
       rc = sqlite3_deserialize(p->db, "main", aData, nData, nData,
                    SQLITE_DESERIALIZE_RESIZEABLE |
                    SQLITE_DESERIALIZE_FREEONCLOSE);
       if( rc ){
         utf8_printf(stderr, "Error: sqlite3_deserialize() returns %d\n", rc);
       }
       if( p->szMax>0 ){
         sqlite3_file_control(p->db, "main", SQLITE_FCNTL_SIZE_LIMIT, &p->szMax);
       }
     }
 #endif
   }    }
 }  }
   
 /*  /*
   ** Attempt to close the databaes connection.  Report errors.
   */
   void close_db(sqlite3 *db){
     int rc = sqlite3_close(db);
     if( rc ){
       utf8_printf(stderr, "Error: sqlite3_close() returns %d: %s\n",
           rc, sqlite3_errmsg(db));
     } 
   }
   
   #if HAVE_READLINE || HAVE_EDITLINE
   /*
   ** Readline completion callbacks
   */
   static char *readline_completion_generator(const char *text, int state){
     static sqlite3_stmt *pStmt = 0;
     char *zRet;
     if( state==0 ){
       char *zSql;
       sqlite3_finalize(pStmt);
       zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
                              "  FROM completion(%Q) ORDER BY 1", text);
       sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
       sqlite3_free(zSql);
     }
     if( sqlite3_step(pStmt)==SQLITE_ROW ){
       zRet = strdup((const char*)sqlite3_column_text(pStmt, 0));
     }else{
       sqlite3_finalize(pStmt);
       pStmt = 0;
       zRet = 0;
     }
     return zRet;
   }
   static char **readline_completion(const char *zText, int iStart, int iEnd){
     rl_attempted_completion_over = 1;
     return rl_completion_matches(zText, readline_completion_generator);
   }
   
   #elif HAVE_LINENOISE
   /*
   ** Linenoise completion callback
   */
   static void linenoise_completion(const char *zLine, linenoiseCompletions *lc){
     int nLine = strlen30(zLine);
     int i, iStart;
     sqlite3_stmt *pStmt = 0;
     char *zSql;
     char zBuf[1000];
   
     if( nLine>sizeof(zBuf)-30 ) return;
     if( zLine[0]=='.' || zLine[0]=='#') return;
     for(i=nLine-1; i>=0 && (isalnum(zLine[i]) || zLine[i]=='_'); i--){}
     if( i==nLine-1 ) return;
     iStart = i+1;
     memcpy(zBuf, zLine, iStart);
     zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase"
                            "  FROM completion(%Q,%Q) ORDER BY 1",
                            &zLine[iStart], zLine);
     sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0);
     sqlite3_free(zSql);
     sqlite3_exec(globalDb, "PRAGMA page_count", 0, 0, 0); /* Load the schema */
     while( sqlite3_step(pStmt)==SQLITE_ROW ){
       const char *zCompletion = (const char*)sqlite3_column_text(pStmt, 0);
       int nCompletion = sqlite3_column_bytes(pStmt, 0);
       if( iStart+nCompletion < sizeof(zBuf)-1 ){
         memcpy(zBuf+iStart, zCompletion, nCompletion+1);
         linenoiseAddCompletion(lc, zBuf);
       }
     }
     sqlite3_finalize(pStmt);
   }
   #endif
   
   /*
 ** Do C-language style dequoting.  ** Do C-language style dequoting.
 **  **
 **    \a    -> alarm  **    \a    -> alarm
Line 2432  static void resolve_backslashes(char *z){ Line 14958  static void resolve_backslashes(char *z){
 }  }
   
 /*  /*
 ** Return the value of a hexadecimal digit.  Return -1 if the input  
 ** is not a hex digit.  
 */  
 static int hexDigitValue(char c){  
   if( c>='0' && c<='9' ) return c - '0';  
   if( c>='a' && c<='f' ) return c - 'a' + 10;  
   if( c>='A' && c<='F' ) return c - 'A' + 10;  
   return -1;  
 }  
   
 /*  
 ** Interpret zArg as an integer value, possibly with suffixes.  
 */  
 static sqlite3_int64 integerValue(const char *zArg){  
   sqlite3_int64 v = 0;  
   static const struct { char *zSuffix; int iMult; } aMult[] = {  
     { "KiB", 1024 },  
     { "MiB", 1024*1024 },  
     { "GiB", 1024*1024*1024 },  
     { "KB",  1000 },  
     { "MB",  1000000 },  
     { "GB",  1000000000 },  
     { "K",   1000 },  
     { "M",   1000000 },  
     { "G",   1000000000 },  
   };  
   int i;  
   int isNeg = 0;  
   if( zArg[0]=='-' ){  
     isNeg = 1;  
     zArg++;  
   }else if( zArg[0]=='+' ){  
     zArg++;  
   }  
   if( zArg[0]=='0' && zArg[1]=='x' ){  
     int x;  
     zArg += 2;  
     while( (x = hexDigitValue(zArg[0]))>=0 ){  
       v = (v<<4) + x;  
       zArg++;  
     }  
   }else{  
     while( IsDigit(zArg[0]) ){  
       v = v*10 + zArg[0] - '0';  
       zArg++;  
     }  
   }  
   for(i=0; i<ArraySize(aMult); i++){  
     if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){  
       v *= aMult[i].iMult;  
       break;  
     }  
   }  
   return isNeg? -v : v;  
 }  
   
 /*  
 ** Interpret zArg as either an integer or a boolean value.  Return 1 or 0  ** Interpret zArg as either an integer or a boolean value.  Return 1 or 0
 ** for TRUE and FALSE.  Return the integer value if appropriate.  ** for TRUE and FALSE.  Return the integer value if appropriate.
 */  */
static int booleanValue(char *zArg){static int booleanValue(const char *zArg){
   int i;    int i;
   if( zArg[0]=='0' && zArg[1]=='x' ){    if( zArg[0]=='0' && zArg[1]=='x' ){
     for(i=2; hexDigitValue(zArg[i])>=0; i++){}      for(i=2; hexDigitValue(zArg[i])>=0; i++){}
Line 2512  static int booleanValue(char *zArg){ Line 14981  static int booleanValue(char *zArg){
 }  }
   
 /*  /*
   ** Set or clear a shell flag according to a boolean value.
   */
   static void setOrClearFlag(ShellState *p, unsigned mFlag, const char *zArg){
     if( booleanValue(zArg) ){
       ShellSetFlag(p, mFlag);
     }else{
       ShellClearFlag(p, mFlag);
     }
   }
   
   /*
 ** Close an output file, assuming it is not stderr or stdout  ** Close an output file, assuming it is not stderr or stdout
 */  */
 static void output_file_close(FILE *f){  static void output_file_close(FILE *f){
Line 2523  static void output_file_close(FILE *f){ Line 15003  static void output_file_close(FILE *f){
 ** recognized and do the right thing.  NULL is returned if the output  ** recognized and do the right thing.  NULL is returned if the output
 ** filename is "off".  ** filename is "off".
 */  */
static FILE *output_file_open(const char *zFile){static FILE *output_file_open(const char *zFile, int bTextMode){
   FILE *f;    FILE *f;
   if( strcmp(zFile,"stdout")==0 ){    if( strcmp(zFile,"stdout")==0 ){
     f = stdout;      f = stdout;
Line 2532  static FILE *output_file_open(const char *zFile){ Line 15012  static FILE *output_file_open(const char *zFile){
   }else if( strcmp(zFile, "off")==0 ){    }else if( strcmp(zFile, "off")==0 ){
     f = 0;      f = 0;
   }else{    }else{
    f = fopen(zFile, "wb");    f = fopen(zFile, bTextMode ? "w" : "wb");
     if( f==0 ){      if( f==0 ){
       utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);        utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
     }      }
Line 2540  static FILE *output_file_open(const char *zFile){ Line 15020  static FILE *output_file_open(const char *zFile){
   return f;    return f;
 }  }
   
   #ifndef SQLITE_OMIT_TRACE
 /*  /*
 ** A routine for handling output from sqlite3_trace().  ** A routine for handling output from sqlite3_trace().
 */  */
 static int sql_trace_callback(  static int sql_trace_callback(
  unsigned mType,  unsigned mType,         /* The trace type */
  void *pArg,  void *pArg,             /* The ShellState pointer */
  void *pP,  void *pP,               /* Usually a pointer to sqlite_stmt */
  void *pX  void *pX                /* Auxiliary output */
 ){  ){
  FILE *f = (FILE*)pArg;  ShellState *p = (ShellState*)pArg;
  UNUSED_PARAMETER(mType);  sqlite3_stmt *pStmt;
  UNUSED_PARAMETER(pP);  const char *zSql;
  if( f ){  int nSql;
    const char *z = (const char*)pX;  if( p->traceOut==0 ) return 0;
    int i = (int)strlen(z);  if( mType==SQLITE_TRACE_CLOSE ){
    while( i>0 && z[i-1]==';' ){ i--; }    utf8_printf(p->traceOut, "-- closing database connection\n");
    utf8_printf(f, "%.*s;\n", i, z);    return 0;
   }    }
     if( mType!=SQLITE_TRACE_ROW && ((const char*)pX)[0]=='-' ){
       zSql = (const char*)pX;
     }else{
       pStmt = (sqlite3_stmt*)pP;
       switch( p->eTraceType ){
         case SHELL_TRACE_EXPANDED: {
           zSql = sqlite3_expanded_sql(pStmt);
           break;
         }
   #ifdef SQLITE_ENABLE_NORMALIZE
         case SHELL_TRACE_NORMALIZED: {
           zSql = sqlite3_normalized_sql(pStmt);
           break;
         }
   #endif
         default: {
           zSql = sqlite3_sql(pStmt);
           break;
         }
       }
     }
     if( zSql==0 ) return 0;
     nSql = strlen30(zSql);
     while( nSql>0 && zSql[nSql-1]==';' ){ nSql--; }
     switch( mType ){
       case SQLITE_TRACE_ROW:
       case SQLITE_TRACE_STMT: {
         utf8_printf(p->traceOut, "%.*s;\n", nSql, zSql);
         break;
       }
       case SQLITE_TRACE_PROFILE: {
         sqlite3_int64 nNanosec = *(sqlite3_int64*)pX;
         utf8_printf(p->traceOut, "%.*s; -- %lld ns\n", nSql, zSql, nNanosec);
         break;
       }
     }
   return 0;    return 0;
 }  }
   #endif
   
 /*  /*
 ** A no-op routine that runs with the ".breakpoint" doc-command.  This is  ** A no-op routine that runs with the ".breakpoint" doc-command.  This is
Line 2577  typedef struct ImportCtx ImportCtx; Line 15095  typedef struct ImportCtx ImportCtx;
 struct ImportCtx {  struct ImportCtx {
   const char *zFile;  /* Name of the input file */    const char *zFile;  /* Name of the input file */
   FILE *in;           /* Read the CSV text from this input stream */    FILE *in;           /* Read the CSV text from this input stream */
     int (SQLITE_CDECL *xCloser)(FILE*);      /* Func to close in */
   char *z;            /* Accumulated text for a field */    char *z;            /* Accumulated text for a field */
   int n;              /* Number of bytes in z */    int n;              /* Number of bytes in z */
   int nAlloc;         /* Space allocated for z[] */    int nAlloc;         /* Space allocated for z[] */
   int nLine;          /* Current line number */    int nLine;          /* Current line number */
     int nRow;           /* Number of rows imported */
     int nErr;           /* Number of errors encountered */
     int bNotFirst;      /* True if one or more bytes already read */
   int cTerm;          /* Character that terminated the most recent field */    int cTerm;          /* Character that terminated the most recent field */
   int cColSep;        /* The column separator character.  (Usually ",") */    int cColSep;        /* The column separator character.  (Usually ",") */
   int cRowSep;        /* The row separator character.  (Usually "\n") */    int cRowSep;        /* The row separator character.  (Usually "\n") */
 };  };
   
   /* Clean up resourced used by an ImportCtx */
   static void import_cleanup(ImportCtx *p){
     if( p->in!=0 && p->xCloser!=0 ){
       p->xCloser(p->in);
       p->in = 0;
     }
     sqlite3_free(p->z);
     p->z = 0;
   }
   
 /* Append a single byte to z[] */  /* Append a single byte to z[] */
 static void import_append_char(ImportCtx *p, int c){  static void import_append_char(ImportCtx *p, int c){
   if( p->n+1>=p->nAlloc ){    if( p->n+1>=p->nAlloc ){
     p->nAlloc += p->nAlloc + 100;      p->nAlloc += p->nAlloc + 100;
     p->z = sqlite3_realloc64(p->z, p->nAlloc);      p->z = sqlite3_realloc64(p->z, p->nAlloc);
    if( p->z==0 ){    if( p->z==0 ) shell_out_of_memory();
      raw_printf(stderr, "out of memory\n"); 
      exit(1); 
    } 
   }    }
   p->z[p->n++] = (char)c;    p->z[p->n++] = (char)c;
 }  }
Line 2660  static char *SQLITE_CDECL csv_read_one_field(ImportCtx Line 15189  static char *SQLITE_CDECL csv_read_one_field(ImportCtx
       pc = c;        pc = c;
     }      }
   }else{    }else{
       /* If this is the first field being parsed and it begins with the
       ** UTF-8 BOM  (0xEF BB BF) then skip the BOM */
       if( (c&0xff)==0xef && p->bNotFirst==0 ){
         import_append_char(p, c);
         c = fgetc(p->in);
         if( (c&0xff)==0xbb ){
           import_append_char(p, c);
           c = fgetc(p->in);
           if( (c&0xff)==0xbf ){
             p->bNotFirst = 1;
             p->n = 0;
             return csv_read_one_field(p);
           }
         }
       }
     while( c!=EOF && c!=cSep && c!=rSep ){      while( c!=EOF && c!=cSep && c!=rSep ){
       import_append_char(p, c);        import_append_char(p, c);
       c = fgetc(p->in);        c = fgetc(p->in);
Line 2671  static char *SQLITE_CDECL csv_read_one_field(ImportCtx Line 15215  static char *SQLITE_CDECL csv_read_one_field(ImportCtx
     p->cTerm = c;      p->cTerm = c;
   }    }
   if( p->z ) p->z[p->n] = 0;    if( p->z ) p->z[p->n] = 0;
     p->bNotFirst = 1;
   return p->z;    return p->z;
 }  }
   
Line 2724  static void tryToCloneData( Line 15269  static void tryToCloneData(
   char *zInsert = 0;    char *zInsert = 0;
   int rc;    int rc;
   int i, j, n;    int i, j, n;
  int nTable = (int)strlen(zTable);  int nTable = strlen30(zTable);
   int k = 0;    int k = 0;
   int cnt = 0;    int cnt = 0;
   const int spinRate = 10000;    const int spinRate = 10000;
Line 2739  static void tryToCloneData( Line 15284  static void tryToCloneData(
   }    }
   n = sqlite3_column_count(pQuery);    n = sqlite3_column_count(pQuery);
   zInsert = sqlite3_malloc64(200 + nTable + n*3);    zInsert = sqlite3_malloc64(200 + nTable + n*3);
  if( zInsert==0 ){  if( zInsert==0 ) shell_out_of_memory();
    raw_printf(stderr, "out of memory\n"); 
    goto end_data_xfer; 
  } 
   sqlite3_snprintf(200+nTable,zInsert,    sqlite3_snprintf(200+nTable,zInsert,
                    "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable);                     "INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable);
  i = (int)strlen(zInsert);  i = strlen30(zInsert);
   for(j=1; j<n; j++){    for(j=1; j<n; j++){
     memcpy(zInsert+i, ",?", 2);      memcpy(zInsert+i, ",?", 2);
     i += 2;      i += 2;
Line 2824  end_data_xfer: Line 15366  end_data_xfer:
 ** Try to transfer all rows of the schema that match zWhere.  For  ** Try to transfer all rows of the schema that match zWhere.  For
 ** each row, invoke xForEach() on the object defined by that row.  ** each row, invoke xForEach() on the object defined by that row.
 ** If an error is encountered while moving forward through the  ** If an error is encountered while moving forward through the
** sqlite_master table, try again moving backwards.** sqlite_schema table, try again moving backwards.
 */  */
 static void tryToCloneSchema(  static void tryToCloneSchema(
   ShellState *p,    ShellState *p,
Line 2839  static void tryToCloneSchema( Line 15381  static void tryToCloneSchema(
   const unsigned char *zSql;    const unsigned char *zSql;
   char *zErrMsg = 0;    char *zErrMsg = 0;
   
  zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_master"  zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
                            " WHERE %s", zWhere);                             " WHERE %s", zWhere);
   rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);    rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
   if( rc ){    if( rc ){
Line 2866  static void tryToCloneSchema( Line 15408  static void tryToCloneSchema(
   if( rc!=SQLITE_DONE ){    if( rc!=SQLITE_DONE ){
     sqlite3_finalize(pQuery);      sqlite3_finalize(pQuery);
     sqlite3_free(zQuery);      sqlite3_free(zQuery);
    zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_master"    zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_schema"
                              " WHERE %s ORDER BY rowid DESC", zWhere);                               " WHERE %s ORDER BY rowid DESC", zWhere);
     rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);      rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
     if( rc ){      if( rc ){
Line 2920  static void tryToClone(ShellState *p, const char *zNew Line 15462  static void tryToClone(ShellState *p, const char *zNew
     sqlite3_exec(newDb, "COMMIT;", 0, 0, 0);      sqlite3_exec(newDb, "COMMIT;", 0, 0, 0);
     sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);      sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
   }    }
  sqlite3_close(newDb);  close_db(newDb);
 }  }
   
 /*  /*
** Change the output file back to stdout** Change the output file back to stdout.
 **
 ** If the p->doXdgOpen flag is set, that means the output was being
 ** redirected to a temporary file named by p->zTempFile.  In that case,
 ** launch start/open/xdg-open on that temporary file.
 */  */
 static void output_reset(ShellState *p){  static void output_reset(ShellState *p){
   if( p->outfile[0]=='|' ){    if( p->outfile[0]=='|' ){
Line 2933  static void output_reset(ShellState *p){ Line 15479  static void output_reset(ShellState *p){
 #endif  #endif
   }else{    }else{
     output_file_close(p->out);      output_file_close(p->out);
   #ifndef SQLITE_NOHAVE_SYSTEM
       if( p->doXdgOpen ){
         const char *zXdgOpenCmd =
   #if defined(_WIN32)
         "start";
   #elif defined(__APPLE__)
         "open";
   #else
         "xdg-open";
   #endif
         char *zCmd;
         zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile);
         if( system(zCmd) ){
           utf8_printf(stderr, "Failed: [%s]\n", zCmd);
         }else{
           /* Give the start/open/xdg-open command some time to get
           ** going before we continue, and potential delete the
           ** p->zTempFile data file out from under it */
           sqlite3_sleep(2000);
         }
         sqlite3_free(zCmd);
         outputModePop(p);
         p->doXdgOpen = 0;
       }
   #endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
   }    }
   p->outfile[0] = 0;    p->outfile[0] = 0;
   p->out = stdout;    p->out = stdout;
Line 2963  static unsigned int get4byteInt(unsigned char *a){ Line 15534  static unsigned int get4byteInt(unsigned char *a){
 }  }
   
 /*  /*
** Implementation of the ".info" command.** Implementation of the ".dbinfo" command.
 **  **
 ** Return 1 on error, 2 to exit, and 0 otherwise.  ** Return 1 on error, 2 to exit, and 0 otherwise.
 */  */
Line 2994  static int shell_dbinfo_command(ShellState *p, int nAr Line 15565  static int shell_dbinfo_command(ShellState *p, int nAr
      { "schema size:",       { "schema size:",
        "SELECT total(length(sql)) FROM %s" },         "SELECT total(length(sql)) FROM %s" },
   };    };
  sqlite3_file *pFile = 0;  int i, rc;
  int i;  unsigned iDataVersion;
   char *zSchemaTab;    char *zSchemaTab;
   char *zDb = nArg>=2 ? azArg[1] : "main";    char *zDb = nArg>=2 ? azArg[1] : "main";
     sqlite3_stmt *pStmt = 0;
   unsigned char aHdr[100];    unsigned char aHdr[100];
   open_db(p, 0);    open_db(p, 0);
   if( p->db==0 ) return 1;    if( p->db==0 ) return 1;
  sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_FILE_POINTER, &pFile);  rc = sqlite3_prepare_v2(p->db,
  if( pFile==0 || pFile->pMethods==0 || pFile->pMethods->xRead==0 ){             "SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
              -1, &pStmt, 0);
   if( rc ){
     utf8_printf(stderr, "error: %s\n", sqlite3_errmsg(p->db));
     sqlite3_finalize(pStmt);
     return 1;      return 1;
   }    }
  i = pFile->pMethods->xRead(pFile, aHdr, 100, 0);  sqlite3_bind_text(pStmt, 1, zDb, -1, SQLITE_STATIC);
  if( i!=SQLITE_OK ){  if( sqlite3_step(pStmt)==SQLITE_ROW
    && sqlite3_column_bytes(pStmt,0)>100
   ){
     memcpy(aHdr, sqlite3_column_blob(pStmt,0), 100);
     sqlite3_finalize(pStmt);
   }else{
     raw_printf(stderr, "unable to read database header\n");      raw_printf(stderr, "unable to read database header\n");
       sqlite3_finalize(pStmt);
     return 1;      return 1;
   }    }
   i = get2byteInt(aHdr+16);    i = get2byteInt(aHdr+16);
Line 3030  static int shell_dbinfo_command(ShellState *p, int nAr Line 15612  static int shell_dbinfo_command(ShellState *p, int nAr
     raw_printf(p->out, "\n");      raw_printf(p->out, "\n");
   }    }
   if( zDb==0 ){    if( zDb==0 ){
    zSchemaTab = sqlite3_mprintf("main.sqlite_master");    zSchemaTab = sqlite3_mprintf("main.sqlite_schema");
   }else if( strcmp(zDb,"temp")==0 ){    }else if( strcmp(zDb,"temp")==0 ){
    zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_master");    zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_schema");
   }else{    }else{
    zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_master", zDb);    zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_schema", zDb);
   }    }
   for(i=0; i<ArraySize(aQuery); i++){    for(i=0; i<ArraySize(aQuery); i++){
     char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);      char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
Line 3043  static int shell_dbinfo_command(ShellState *p, int nAr Line 15625  static int shell_dbinfo_command(ShellState *p, int nAr
     utf8_printf(p->out, "%-20s %d\n", aQuery[i].zName, val);      utf8_printf(p->out, "%-20s %d\n", aQuery[i].zName, val);
   }    }
   sqlite3_free(zSchemaTab);    sqlite3_free(zSchemaTab);
     sqlite3_file_control(p->db, zDb, SQLITE_FCNTL_DATA_VERSION, &iDataVersion);
     utf8_printf(p->out, "%-20s %u\n", "data version", iDataVersion);
   return 0;    return 0;
 }  }
   
Line 3056  static int shellDatabaseError(sqlite3 *db){ Line 15640  static int shellDatabaseError(sqlite3 *db){
 }  }
   
 /*  /*
** Print an out-of-memory message to stderr and return 1.** Compare the pattern in zGlob[] against the text in z[].  Return TRUE
 ** if they match and FALSE (0) if they do not match.
 **
 ** Globbing rules:
 **
 **      '*'       Matches any sequence of zero or more characters.
 **
 **      '?'       Matches exactly one character.
 **
 **     [...]      Matches one character from the enclosed list of
 **                characters.
 **
 **     [^...]     Matches one character not in the enclosed list.
 **
 **      '#'       Matches any sequence of one or more digits with an
 **                optional + or - sign in front
 **
 **      ' '       Any span of whitespace matches any other span of
 **                whitespace.
 **
 ** Extra whitespace at the end of z[] is ignored.
 */  */
static int shellNomemError(void){static int testcase_glob(const char *zGlob, const char *z){
  raw_printf(stderr, "Error: out of memory\n");  int c, c2;
  return 1;  int invert;
   int seen;
 
   while( (c = (*(zGlob++)))!=0 ){
     if( IsSpace(c) ){
       if( !IsSpace(*z) ) return 0;
       while( IsSpace(*zGlob) ) zGlob++;
       while( IsSpace(*z) ) z++;
     }else if( c=='*' ){
       while( (c=(*(zGlob++))) == '*' || c=='?' ){
         if( c=='?' && (*(z++))==0 ) return 0;
       }
       if( c==0 ){
         return 1;
       }else if( c=='[' ){
         while( *z && testcase_glob(zGlob-1,z)==0 ){
           z++;
         }
         return (*z)!=0;
       }
       while( (c2 = (*(z++)))!=0 ){
         while( c2!=c ){
           c2 = *(z++);
           if( c2==0 ) return 0;
         }
         if( testcase_glob(zGlob,z) ) return 1;
       }
       return 0;
     }else if( c=='?' ){
       if( (*(z++))==0 ) return 0;
     }else if( c=='[' ){
       int prior_c = 0;
       seen = 0;
       invert = 0;
       c = *(z++);
       if( c==0 ) return 0;
       c2 = *(zGlob++);
       if( c2=='^' ){
         invert = 1;
         c2 = *(zGlob++);
       }
       if( c2==']' ){
         if( c==']' ) seen = 1;
         c2 = *(zGlob++);
       }
       while( c2 && c2!=']' ){
         if( c2=='-' && zGlob[0]!=']' && zGlob[0]!=0 && prior_c>0 ){
           c2 = *(zGlob++);
           if( c>=prior_c && c<=c2 ) seen = 1;
           prior_c = 0;
         }else{
           if( c==c2 ){
             seen = 1;
           }
           prior_c = c2;
         }
         c2 = *(zGlob++);
       }
       if( c2==0 || (seen ^ invert)==0 ) return 0;
     }else if( c=='#' ){
       if( (z[0]=='-' || z[0]=='+') && IsDigit(z[1]) ) z++;
       if( !IsDigit(z[0]) ) return 0;
       z++;
       while( IsDigit(z[0]) ){ z++; }
     }else{
       if( c!=(*(z++)) ) return 0;
     }
   }
   while( IsSpace(*z) ){ z++; }
   return *z==0;
 }  }
   
   
 /*  /*
 ** Compare the string as a command-line option with either one or two  ** Compare the string as a command-line option with either one or two
 ** initial "-" characters.  ** initial "-" characters.
Line 3075  static int optionMatch(const char *zStr, const char *z Line 15749  static int optionMatch(const char *zStr, const char *z
 }  }
   
 /*  /*
   ** Delete a file.
   */
   int shellDeleteFile(const char *zFilename){
     int rc;
   #ifdef _WIN32
     wchar_t *z = sqlite3_win32_utf8_to_unicode(zFilename);
     rc = _wunlink(z);
     sqlite3_free(z);
   #else
     rc = unlink(zFilename);
   #endif
     return rc;
   }
   
   /*
   ** Try to delete the temporary file (if there is one) and free the
   ** memory used to hold the name of the temp file.
   */
   static void clearTempFile(ShellState *p){
     if( p->zTempFile==0 ) return;
     if( p->doXdgOpen ) return;
     if( shellDeleteFile(p->zTempFile) ) return;
     sqlite3_free(p->zTempFile);
     p->zTempFile = 0;
   }
   
   /*
   ** Create a new temp file name with the given suffix.
   */
   static void newTempFile(ShellState *p, const char *zSuffix){
     clearTempFile(p);
     sqlite3_free(p->zTempFile);
     p->zTempFile = 0;
     if( p->db ){
       sqlite3_file_control(p->db, 0, SQLITE_FCNTL_TEMPFILENAME, &p->zTempFile);
     }
     if( p->zTempFile==0 ){
       /* If p->db is an in-memory database then the TEMPFILENAME file-control
       ** will not work and we will need to fallback to guessing */
       char *zTemp;
       sqlite3_uint64 r;
       sqlite3_randomness(sizeof(r), &r);
       zTemp = getenv("TEMP");
       if( zTemp==0 ) zTemp = getenv("TMP");
       if( zTemp==0 ){
   #ifdef _WIN32
         zTemp = "\\tmp";
   #else
         zTemp = "/tmp";
   #endif
       }
       p->zTempFile = sqlite3_mprintf("%s/temp%llx.%s", zTemp, r, zSuffix);
     }else{
       p->zTempFile = sqlite3_mprintf("%z.%s", p->zTempFile, zSuffix);
     }
     if( p->zTempFile==0 ){
       raw_printf(stderr, "out of memory\n");
       exit(1);
     }
   }
   
   
   /*
   ** The implementation of SQL scalar function fkey_collate_clause(), used
   ** by the ".lint fkey-indexes" command. This scalar function is always
   ** called with four arguments - the parent table name, the parent column name,
   ** the child table name and the child column name.
   **
   **   fkey_collate_clause('parent-tab', 'parent-col', 'child-tab', 'child-col')
   **
   ** If either of the named tables or columns do not exist, this function
   ** returns an empty string. An empty string is also returned if both tables
   ** and columns exist but have the same default collation sequence. Or,
   ** if both exist but the default collation sequences are different, this
   ** function returns the string " COLLATE <parent-collation>", where
   ** <parent-collation> is the default collation sequence of the parent column.
   */
   static void shellFkeyCollateClause(
     sqlite3_context *pCtx,
     int nVal,
     sqlite3_value **apVal
   ){
     sqlite3 *db = sqlite3_context_db_handle(pCtx);
     const char *zParent;
     const char *zParentCol;
     const char *zParentSeq;
     const char *zChild;
     const char *zChildCol;
     const char *zChildSeq = 0;  /* Initialize to avoid false-positive warning */
     int rc;
   
     assert( nVal==4 );
     zParent = (const char*)sqlite3_value_text(apVal[0]);
     zParentCol = (const char*)sqlite3_value_text(apVal[1]);
     zChild = (const char*)sqlite3_value_text(apVal[2]);
     zChildCol = (const char*)sqlite3_value_text(apVal[3]);
   
     sqlite3_result_text(pCtx, "", -1, SQLITE_STATIC);
     rc = sqlite3_table_column_metadata(
         db, "main", zParent, zParentCol, 0, &zParentSeq, 0, 0, 0
     );
     if( rc==SQLITE_OK ){
       rc = sqlite3_table_column_metadata(
           db, "main", zChild, zChildCol, 0, &zChildSeq, 0, 0, 0
       );
     }
   
     if( rc==SQLITE_OK && sqlite3_stricmp(zParentSeq, zChildSeq) ){
       char *z = sqlite3_mprintf(" COLLATE %s", zParentSeq);
       sqlite3_result_text(pCtx, z, -1, SQLITE_TRANSIENT);
       sqlite3_free(z);
     }
   }
   
   
   /*
   ** The implementation of dot-command ".lint fkey-indexes".
   */
   static int lintFkeyIndexes(
     ShellState *pState,             /* Current shell tool state */
     char **azArg,                   /* Array of arguments passed to dot command */
     int nArg                        /* Number of entries in azArg[] */
   ){
     sqlite3 *db = pState->db;       /* Database handle to query "main" db of */
     FILE *out = pState->out;        /* Stream to write non-error output to */
     int bVerbose = 0;               /* If -verbose is present */
     int bGroupByParent = 0;         /* If -groupbyparent is present */
     int i;                          /* To iterate through azArg[] */
     const char *zIndent = "";       /* How much to indent CREATE INDEX by */
     int rc;                         /* Return code */
     sqlite3_stmt *pSql = 0;         /* Compiled version of SQL statement below */
   
     /*
     ** This SELECT statement returns one row for each foreign key constraint
     ** in the schema of the main database. The column values are:
     **
     ** 0. The text of an SQL statement similar to:
     **
     **      "EXPLAIN QUERY PLAN SELECT 1 FROM child_table WHERE child_key=?"
     **
     **    This SELECT is similar to the one that the foreign keys implementation
     **    needs to run internally on child tables. If there is an index that can
     **    be used to optimize this query, then it can also be used by the FK
     **    implementation to optimize DELETE or UPDATE statements on the parent
     **    table.
     **
     ** 1. A GLOB pattern suitable for sqlite3_strglob(). If the plan output by
     **    the EXPLAIN QUERY PLAN command matches this pattern, then the schema
     **    contains an index that can be used to optimize the query.
     **
     ** 2. Human readable text that describes the child table and columns. e.g.
     **
     **       "child_table(child_key1, child_key2)"
     **
     ** 3. Human readable text that describes the parent table and columns. e.g.
     **
     **       "parent_table(parent_key1, parent_key2)"
     **
     ** 4. A full CREATE INDEX statement for an index that could be used to
     **    optimize DELETE or UPDATE statements on the parent table. e.g.
     **
     **       "CREATE INDEX child_table_child_key ON child_table(child_key)"
     **
     ** 5. The name of the parent table.
     **
     ** These six values are used by the C logic below to generate the report.
     */
     const char *zSql =
     "SELECT "
       "     'EXPLAIN QUERY PLAN SELECT 1 FROM ' || quote(s.name) || ' WHERE '"
       "  || group_concat(quote(s.name) || '.' || quote(f.[from]) || '=?' "
       "  || fkey_collate_clause("
       "       f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]),' AND ')"
       ", "
       "     'SEARCH TABLE ' || s.name || ' USING COVERING INDEX*('"
       "  || group_concat('*=?', ' AND ') || ')'"
       ", "
       "     s.name  || '(' || group_concat(f.[from],  ', ') || ')'"
       ", "
       "     f.[table] || '(' || group_concat(COALESCE(f.[to], p.[name])) || ')'"
       ", "
       "     'CREATE INDEX ' || quote(s.name ||'_'|| group_concat(f.[from], '_'))"
       "  || ' ON ' || quote(s.name) || '('"
       "  || group_concat(quote(f.[from]) ||"
       "        fkey_collate_clause("
       "          f.[table], COALESCE(f.[to], p.[name]), s.name, f.[from]), ', ')"
       "  || ');'"
       ", "
       "     f.[table] "
       "FROM sqlite_schema AS s, pragma_foreign_key_list(s.name) AS f "
       "LEFT JOIN pragma_table_info AS p ON (pk-1=seq AND p.arg=f.[table]) "
       "GROUP BY s.name, f.id "
       "ORDER BY (CASE WHEN ? THEN f.[table] ELSE s.name END)"
     ;
     const char *zGlobIPK = "SEARCH TABLE * USING INTEGER PRIMARY KEY (rowid=?)";
   
     for(i=2; i<nArg; i++){
       int n = strlen30(azArg[i]);
       if( n>1 && sqlite3_strnicmp("-verbose", azArg[i], n)==0 ){
         bVerbose = 1;
       }
       else if( n>1 && sqlite3_strnicmp("-groupbyparent", azArg[i], n)==0 ){
         bGroupByParent = 1;
         zIndent = "    ";
       }
       else{
         raw_printf(stderr, "Usage: %s %s ?-verbose? ?-groupbyparent?\n",
             azArg[0], azArg[1]
         );
         return SQLITE_ERROR;
       }
     }
   
     /* Register the fkey_collate_clause() SQL function */
     rc = sqlite3_create_function(db, "fkey_collate_clause", 4, SQLITE_UTF8,
         0, shellFkeyCollateClause, 0, 0
     );
   
   
     if( rc==SQLITE_OK ){
       rc = sqlite3_prepare_v2(db, zSql, -1, &pSql, 0);
     }
     if( rc==SQLITE_OK ){
       sqlite3_bind_int(pSql, 1, bGroupByParent);
     }
   
     if( rc==SQLITE_OK ){
       int rc2;
       char *zPrev = 0;
       while( SQLITE_ROW==sqlite3_step(pSql) ){
         int res = -1;
         sqlite3_stmt *pExplain = 0;
         const char *zEQP = (const char*)sqlite3_column_text(pSql, 0);
         const char *zGlob = (const char*)sqlite3_column_text(pSql, 1);
         const char *zFrom = (const char*)sqlite3_column_text(pSql, 2);
         const char *zTarget = (const char*)sqlite3_column_text(pSql, 3);
         const char *zCI = (const char*)sqlite3_column_text(pSql, 4);
         const char *zParent = (const char*)sqlite3_column_text(pSql, 5);
   
         rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
         if( rc!=SQLITE_OK ) break;
         if( SQLITE_ROW==sqlite3_step(pExplain) ){
           const char *zPlan = (const char*)sqlite3_column_text(pExplain, 3);
           res = (
                 0==sqlite3_strglob(zGlob, zPlan)
              || 0==sqlite3_strglob(zGlobIPK, zPlan)
           );
         }
         rc = sqlite3_finalize(pExplain);
         if( rc!=SQLITE_OK ) break;
   
         if( res<0 ){
           raw_printf(stderr, "Error: internal error");
           break;
         }else{
           if( bGroupByParent
           && (bVerbose || res==0)
           && (zPrev==0 || sqlite3_stricmp(zParent, zPrev))
           ){
             raw_printf(out, "-- Parent table %s\n", zParent);
             sqlite3_free(zPrev);
             zPrev = sqlite3_mprintf("%s", zParent);
           }
   
           if( res==0 ){
             raw_printf(out, "%s%s --> %s\n", zIndent, zCI, zTarget);
           }else if( bVerbose ){
             raw_printf(out, "%s/* no extra indexes required for %s -> %s */\n",
                 zIndent, zFrom, zTarget
             );
           }
         }
       }
       sqlite3_free(zPrev);
   
       if( rc!=SQLITE_OK ){
         raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
       }
   
       rc2 = sqlite3_finalize(pSql);
       if( rc==SQLITE_OK && rc2!=SQLITE_OK ){
         rc = rc2;
         raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
       }
     }else{
       raw_printf(stderr, "%s\n", sqlite3_errmsg(db));
     }
   
     return rc;
   }
   
   /*
   ** Implementation of ".lint" dot command.
   */
   static int lintDotCommand(
     ShellState *pState,             /* Current shell tool state */
     char **azArg,                   /* Array of arguments passed to dot command */
     int nArg                        /* Number of entries in azArg[] */
   ){
     int n;
     n = (nArg>=2 ? strlen30(azArg[1]) : 0);
     if( n<1 || sqlite3_strnicmp(azArg[1], "fkey-indexes", n) ) goto usage;
     return lintFkeyIndexes(pState, azArg, nArg);
   
    usage:
     raw_printf(stderr, "Usage %s sub-command ?switches...?\n", azArg[0]);
     raw_printf(stderr, "Where sub-commands are:\n");
     raw_printf(stderr, "    fkey-indexes\n");
     return SQLITE_ERROR;
   }
   
   #if !defined SQLITE_OMIT_VIRTUALTABLE
   static void shellPrepare(
     sqlite3 *db, 
     int *pRc, 
     const char *zSql, 
     sqlite3_stmt **ppStmt
   ){
     *ppStmt = 0;
     if( *pRc==SQLITE_OK ){
       int rc = sqlite3_prepare_v2(db, zSql, -1, ppStmt, 0);
       if( rc!=SQLITE_OK ){
         raw_printf(stderr, "sql error: %s (%d)\n", 
             sqlite3_errmsg(db), sqlite3_errcode(db)
         );
         *pRc = rc;
       }
     }
   }
   
   /*
   ** Create a prepared statement using printf-style arguments for the SQL.
   **
   ** This routine is could be marked "static".  But it is not always used,
   ** depending on compile-time options.  By omitting the "static", we avoid
   ** nuisance compiler warnings about "defined but not used".
   */
   void shellPreparePrintf(
     sqlite3 *db, 
     int *pRc, 
     sqlite3_stmt **ppStmt,
     const char *zFmt, 
     ...
   ){
     *ppStmt = 0;
     if( *pRc==SQLITE_OK ){
       va_list ap;
       char *z;
       va_start(ap, zFmt);
       z = sqlite3_vmprintf(zFmt, ap);
       va_end(ap);
       if( z==0 ){
         *pRc = SQLITE_NOMEM;
       }else{
         shellPrepare(db, pRc, z, ppStmt);
         sqlite3_free(z);
       }
     }
   }
   
   /* Finalize the prepared statement created using shellPreparePrintf().
   **
   ** This routine is could be marked "static".  But it is not always used,
   ** depending on compile-time options.  By omitting the "static", we avoid
   ** nuisance compiler warnings about "defined but not used".
   */
   void shellFinalize(
     int *pRc, 
     sqlite3_stmt *pStmt
   ){
     if( pStmt ){
       sqlite3 *db = sqlite3_db_handle(pStmt);
       int rc = sqlite3_finalize(pStmt);
       if( *pRc==SQLITE_OK ){
         if( rc!=SQLITE_OK ){
           raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
         }
         *pRc = rc;
       }
     }
   }
   
   /* Reset the prepared statement created using shellPreparePrintf().
   **
   ** This routine is could be marked "static".  But it is not always used,
   ** depending on compile-time options.  By omitting the "static", we avoid
   ** nuisance compiler warnings about "defined but not used".
   */
   void shellReset(
     int *pRc, 
     sqlite3_stmt *pStmt
   ){
     int rc = sqlite3_reset(pStmt);
     if( *pRc==SQLITE_OK ){
       if( rc!=SQLITE_OK ){
         sqlite3 *db = sqlite3_db_handle(pStmt);
         raw_printf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
       }
       *pRc = rc;
     }
   }
   #endif /* !defined SQLITE_OMIT_VIRTUALTABLE */
   
   #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
   /******************************************************************************
   ** The ".archive" or ".ar" command.
   */
   /*
   ** Structure representing a single ".ar" command.
   */
   typedef struct ArCommand ArCommand;
   struct ArCommand {
     u8 eCmd;                        /* An AR_CMD_* value */
     u8 bVerbose;                    /* True if --verbose */
     u8 bZip;                        /* True if the archive is a ZIP */
     u8 bDryRun;                     /* True if --dry-run */
     u8 bAppend;                     /* True if --append */
     u8 fromCmdLine;                 /* Run from -A instead of .archive */
     int nArg;                       /* Number of command arguments */
     char *zSrcTable;                /* "sqlar", "zipfile($file)" or "zip" */
     const char *zFile;              /* --file argument, or NULL */
     const char *zDir;               /* --directory argument, or NULL */
     char **azArg;                   /* Array of command arguments */
     ShellState *p;                  /* Shell state */
     sqlite3 *db;                    /* Database containing the archive */
   };
   
   /*
   ** Print a usage message for the .ar command to stderr and return SQLITE_ERROR.
   */
   static int arUsage(FILE *f){
     showHelp(f,"archive");
     return SQLITE_ERROR;
   }
   
   /*
   ** Print an error message for the .ar command to stderr and return 
   ** SQLITE_ERROR.
   */
   static int arErrorMsg(ArCommand *pAr, const char *zFmt, ...){
     va_list ap;
     char *z;
     va_start(ap, zFmt);
     z = sqlite3_vmprintf(zFmt, ap);
     va_end(ap);
     utf8_printf(stderr, "Error: %s\n", z);
     if( pAr->fromCmdLine ){
       utf8_printf(stderr, "Use \"-A\" for more help\n");
     }else{
       utf8_printf(stderr, "Use \".archive --help\" for more help\n");
     }
     sqlite3_free(z);
     return SQLITE_ERROR;
   }
   
   /*
   ** Values for ArCommand.eCmd.
   */
   #define AR_CMD_CREATE       1
   #define AR_CMD_UPDATE       2
   #define AR_CMD_INSERT       3
   #define AR_CMD_EXTRACT      4
   #define AR_CMD_LIST         5
   #define AR_CMD_HELP         6
   
   /*
   ** 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
   
   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_UPDATE:
       case AR_CMD_INSERT:
       case AR_CMD_HELP:
         if( pAr->eCmd ){
           return arErrorMsg(pAr, "multiple command options");
         }
         pAr->eCmd = eSwitch;
         break;
   
       case AR_SWITCH_DRYRUN:
         pAr->bDryRun = 1;
         break;
       case AR_SWITCH_VERBOSE:
         pAr->bVerbose = 1;
         break;
       case AR_SWITCH_APPEND:
         pAr->bAppend = 1;
         /* Fall thru into --file */
       case AR_SWITCH_FILE:
         pAr->zFile = zArg;
         break;
       case AR_SWITCH_DIRECTORY:
         pAr->zDir = zArg;
         break;
     }
   
     return SQLITE_OK;
   }
   
   /*
   ** Parse the command line for an ".ar" command. The results are written into
   ** structure (*pAr). SQLITE_OK is returned if the command line is parsed
   ** successfully, otherwise an error message is written to stderr and 
   ** SQLITE_ERROR returned.
   */
   static int arParseCommand(
     char **azArg,                   /* Array of arguments passed to dot command */
     int nArg,                       /* Number of entries in azArg[] */
     ArCommand *pAr                  /* Populate this object */
   ){
     struct ArSwitch {
       const char *zLong;
       char cShort;
       u8 eSwitch;
       u8 bArg;
     } aSwitch[] = {
       { "create",    'c', AR_CMD_CREATE,       0 },
       { "extract",   'x', AR_CMD_EXTRACT,      0 },
       { "insert",    'i', AR_CMD_INSERT,       0 },
       { "list",      't', AR_CMD_LIST,         0 },
       { "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 },
     };
     int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch);
     struct ArSwitch *pEnd = &aSwitch[nSwitch];
   
     if( nArg<=1 ){
       utf8_printf(stderr, "Wrong number of arguments.  Usage:\n");
       return arUsage(stderr);
     }else{
       char *z = azArg[1];
       if( z[0]!='-' ){
         /* Traditional style [tar] invocation */
         int i;
         int iArg = 2;
         for(i=0; z[i]; i++){
           const char *zArg = 0;
           struct ArSwitch *pOpt;
           for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
             if( z[i]==pOpt->cShort ) break;
           }
           if( pOpt==pEnd ){
             return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
           }
           if( pOpt->bArg ){
             if( iArg>=nArg ){
               return arErrorMsg(pAr, "option requires an argument: %c",z[i]);
             }
             zArg = azArg[iArg++];
           }
           if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
         }
         pAr->nArg = nArg-iArg;
         if( pAr->nArg>0 ){
           pAr->azArg = &azArg[iArg];
         }
       }else{
         /* Non-traditional invocation */
         int iArg;
         for(iArg=1; iArg<nArg; iArg++){
           int n;
           z = azArg[iArg];
           if( z[0]!='-' ){
             /* All remaining command line words are command arguments. */
             pAr->azArg = &azArg[iArg];
             pAr->nArg = nArg-iArg;
             break;
           }
           n = strlen30(z);
   
           if( z[1]!='-' ){
             int i;
             /* One or more short options */
             for(i=1; i<n; i++){
               const char *zArg = 0;
               struct ArSwitch *pOpt;
               for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
                 if( z[i]==pOpt->cShort ) break;
               }
               if( pOpt==pEnd ){
                 return arErrorMsg(pAr, "unrecognized option: %c", z[i]);
               }
               if( pOpt->bArg ){
                 if( i<(n-1) ){
                   zArg = &z[i+1];
                   i = n;
                 }else{
                   if( iArg>=(nArg-1) ){
                     return arErrorMsg(pAr, "option requires an argument: %c",
                                       z[i]);
                   }
                   zArg = azArg[++iArg];
                 }
               }
               if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
             }
           }else if( z[2]=='\0' ){
             /* A -- option, indicating that all remaining command line words
             ** are command arguments.  */
             pAr->azArg = &azArg[iArg+1];
             pAr->nArg = nArg-iArg-1;
             break;
           }else{
             /* A long option */
             const char *zArg = 0;             /* Argument for option, if any */
             struct ArSwitch *pMatch = 0;      /* Matching option */
             struct ArSwitch *pOpt;            /* Iterator */
             for(pOpt=&aSwitch[0]; pOpt<pEnd; pOpt++){
               const char *zLong = pOpt->zLong;
               if( (n-2)<=strlen30(zLong) && 0==memcmp(&z[2], zLong, n-2) ){
                 if( pMatch ){
                   return arErrorMsg(pAr, "ambiguous option: %s",z);
                 }else{
                   pMatch = pOpt;
                 }
               }
             }
   
             if( pMatch==0 ){
               return arErrorMsg(pAr, "unrecognized option: %s", z);
             }
             if( pMatch->bArg ){
               if( iArg>=(nArg-1) ){
                 return arErrorMsg(pAr, "option requires an argument: %s", z);
               }
               zArg = azArg[++iArg];
             }
             if( arProcessSwitch(pAr, pMatch->eSwitch, zArg) ) return SQLITE_ERROR;
           }
         }
       }
     }
   
     return SQLITE_OK;
   }
   
   /*
   ** 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.
   **
   ** This function strips any trailing '/' characters from each argument.
   ** This is consistent with the way the [tar] command seems to work on
   ** Linux.
   */
   static int arCheckEntries(ArCommand *pAr){
     int rc = SQLITE_OK;
     if( pAr->nArg ){
       int i, j;
       sqlite3_stmt *pTest = 0;
   
       shellPreparePrintf(pAr->db, &rc, &pTest,
           "SELECT name FROM %s WHERE name=$name", 
           pAr->zSrcTable
       );
       j = sqlite3_bind_parameter_index(pTest, "$name");
       for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
         char *z = pAr->azArg[i];
         int n = strlen30(z);
         int bOk = 0;
         while( n>0 && z[n-1]=='/' ) n--;
         z[n] = '\0';
         sqlite3_bind_text(pTest, j, z, -1, SQLITE_STATIC);
         if( SQLITE_ROW==sqlite3_step(pTest) ){
           bOk = 1;
         }
         shellReset(&rc, pTest);
         if( rc==SQLITE_OK && bOk==0 ){
           utf8_printf(stderr, "not found in archive: %s\n", z);
           rc = SQLITE_ERROR;
         }
       }
       shellFinalize(&rc, pTest);
     }
     return rc;
   }
   
   /*
   ** Format a WHERE clause that can be used against the "sqlar" table to
   ** identify all archive members that match the command arguments held
   ** in (*pAr). Leave this WHERE clause in (*pzWhere) before returning.
   ** The caller is responsible for eventually calling sqlite3_free() on
   ** any non-NULL (*pzWhere) value.
   */
   static void arWhereClause(
     int *pRc, 
     ArCommand *pAr, 
     char **pzWhere                  /* OUT: New WHERE clause */
   ){
     char *zWhere = 0;
     if( *pRc==SQLITE_OK ){
       if( pAr->nArg==0 ){
         zWhere = sqlite3_mprintf("1");
       }else{
         int i;
         const char *zSep = "";
         for(i=0; i<pAr->nArg; i++){
           const char *z = pAr->azArg[i];
           zWhere = sqlite3_mprintf(
             "%z%s name = '%q' OR substr(name,1,%d) = '%q/'", 
             zWhere, zSep, z, strlen30(z)+1, z
           );
           if( zWhere==0 ){
             *pRc = SQLITE_NOMEM;
             break;
           }
           zSep = " OR ";
         }
       }
     }
     *pzWhere = zWhere;
   }
   
   /*
   ** Implementation of .ar "lisT" command. 
   */
   static int arListCommand(ArCommand *pAr){
     const char *zSql = "SELECT %s FROM %s WHERE %s"; 
     const char *azCols[] = {
       "name",
       "lsmode(mode), sz, datetime(mtime, 'unixepoch'), name"
     };
   
     char *zWhere = 0;
     sqlite3_stmt *pSql = 0;
     int rc;
   
     rc = arCheckEntries(pAr);
     arWhereClause(&rc, pAr, &zWhere);
   
     shellPreparePrintf(pAr->db, &rc, &pSql, zSql, azCols[pAr->bVerbose],
                        pAr->zSrcTable, zWhere);
     if( pAr->bDryRun ){
       utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
     }else{
       while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
         if( pAr->bVerbose ){
           utf8_printf(pAr->p->out, "%s % 10d  %s  %s\n",
               sqlite3_column_text(pSql, 0),
               sqlite3_column_int(pSql, 1), 
               sqlite3_column_text(pSql, 2),
               sqlite3_column_text(pSql, 3)
           );
         }else{
           utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
         }
       }
     }
     shellFinalize(&rc, pSql);
     sqlite3_free(zWhere);
     return rc;
   }
   
   
   /*
   ** Implementation of .ar "eXtract" command. 
   */
   static int arExtractCommand(ArCommand *pAr){
     const char *zSql1 = 
       "SELECT "
       " ($dir || name),"
       " writefile(($dir || name), %s, mode, mtime) "
       "FROM %s WHERE (%s) AND (data IS NULL OR $dirOnly = 0)"
       " AND name NOT GLOB '*..[/\\]*'";
   
     const char *azExtraArg[] = { 
       "sqlar_uncompress(data, sz)",
       "data"
     };
   
     sqlite3_stmt *pSql = 0;
     int rc = SQLITE_OK;
     char *zDir = 0;
     char *zWhere = 0;
     int i, j;
   
     /* If arguments are specified, check that they actually exist within
     ** the archive before proceeding. And formulate a WHERE clause to
     ** match them.  */
     rc = arCheckEntries(pAr);
     arWhereClause(&rc, pAr, &zWhere);
   
     if( rc==SQLITE_OK ){
       if( pAr->zDir ){
         zDir = sqlite3_mprintf("%s/", pAr->zDir);
       }else{
         zDir = sqlite3_mprintf("");
       }
       if( zDir==0 ) rc = SQLITE_NOMEM;
     }
   
     shellPreparePrintf(pAr->db, &rc, &pSql, zSql1, 
         azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere
     );
   
     if( rc==SQLITE_OK ){
       j = sqlite3_bind_parameter_index(pSql, "$dir");
       sqlite3_bind_text(pSql, j, zDir, -1, SQLITE_STATIC);
   
       /* Run the SELECT statement twice. The first time, writefile() is called
       ** for all archive members that should be extracted. The second time,
       ** only for the directories. This is because the timestamps for
       ** extracted directories must be reset after they are populated (as
       ** populating them changes the timestamp).  */
       for(i=0; i<2; i++){
         j = sqlite3_bind_parameter_index(pSql, "$dirOnly");
         sqlite3_bind_int(pSql, j, i);
         if( pAr->bDryRun ){
           utf8_printf(pAr->p->out, "%s\n", sqlite3_sql(pSql));
         }else{
           while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
             if( i==0 && pAr->bVerbose ){
               utf8_printf(pAr->p->out, "%s\n", sqlite3_column_text(pSql, 0));
             }
           }
         }
         shellReset(&rc, pSql);
       }
       shellFinalize(&rc, pSql);
     }
   
     sqlite3_free(zDir);
     sqlite3_free(zWhere);
     return rc;
   }
   
   /*
   ** Run the SQL statement in zSql.  Or if doing a --dryrun, merely print it out.
   */
   static int arExecSql(ArCommand *pAr, const char *zSql){
     int rc;
     if( pAr->bDryRun ){
       utf8_printf(pAr->p->out, "%s\n", zSql);
       rc = SQLITE_OK;
     }else{
       char *zErr = 0;
       rc = sqlite3_exec(pAr->db, zSql, 0, 0, &zErr);
       if( zErr ){
         utf8_printf(stdout, "ERROR: %s\n", zErr);
         sqlite3_free(zErr);
       }
     }
     return rc;
   }
   
   
   /*
   ** Implementation of .ar "create", "insert", and "update" commands.
   **
   **     create    ->     Create a new SQL archive
   **     insert    ->     Insert or reinsert all files listed
   **     update    ->     Insert files that have changed or that were not
   **                      previously in the archive
   **
   ** Create the "sqlar" table in the database if it does not already exist.
   ** Then add each file in the azFile[] array to the archive. Directories
   ** are added recursively. If argument bVerbose is non-zero, a message is
   ** printed on stdout for each file archived.
   **
   ** The create command is the same as update, except that it drops
   ** any existing "sqlar" table before beginning.  The "insert" command
   ** always overwrites every file named on the command-line, where as
   ** "update" only overwrites if the size or mtime or mode has changed.
   */
   static int arCreateOrUpdateCommand(
     ArCommand *pAr,                 /* Command arguments and options */
     int bUpdate,                    /* true for a --create. */
     int bOnlyIfChanged              /* Only update if file has changed */
   ){
     const char *zCreate = 
         "CREATE TABLE IF NOT EXISTS sqlar(\n"
         "  name TEXT PRIMARY KEY,  -- name of the file\n"
         "  mode INT,               -- access permissions\n"
         "  mtime INT,              -- last modification time\n"
         "  sz INT,                 -- original file size\n"
         "  data BLOB               -- compressed content\n"
         ")";
     const char *zDrop = "DROP TABLE IF EXISTS sqlar";
     const char *zInsertFmt[2] = {
        "REPLACE INTO %s(name,mode,mtime,sz,data)\n"
        "  SELECT\n"
        "    %s,\n"
        "    mode,\n"
        "    mtime,\n"
        "    CASE substr(lsmode(mode),1,1)\n"
        "      WHEN '-' THEN length(data)\n"
        "      WHEN 'd' THEN 0\n"
        "      ELSE -1 END,\n"
        "    sqlar_compress(data)\n"
        "  FROM fsdir(%Q,%Q) AS disk\n"
        "  WHERE lsmode(mode) NOT LIKE '?%%'%s;"
        ,
        "REPLACE INTO %s(name,mode,mtime,data)\n"
        "  SELECT\n"
        "    %s,\n"
        "    mode,\n"
        "    mtime,\n"
        "    data\n"
        "  FROM fsdir(%Q,%Q) AS disk\n"
        "  WHERE lsmode(mode) NOT LIKE '?%%'%s;"
     };
     int i;                          /* For iterating through azFile[] */
     int rc;                         /* Return code */
     const char *zTab = 0;           /* SQL table into which to insert */
     char *zSql;
     char zTemp[50];
     char *zExists = 0;
   
     arExecSql(pAr, "PRAGMA page_size=512");
     rc = arExecSql(pAr, "SAVEPOINT ar;");
     if( rc!=SQLITE_OK ) return rc;
     zTemp[0] = 0; 
     if( pAr->bZip ){
       /* Initialize the zipfile virtual table, if necessary */
       if( pAr->zFile ){
         sqlite3_uint64 r;
         sqlite3_randomness(sizeof(r),&r);
         sqlite3_snprintf(sizeof(zTemp),zTemp,"zip%016llx",r);
         zTab = zTemp;
         zSql = sqlite3_mprintf(
            "CREATE VIRTUAL TABLE temp.%s USING zipfile(%Q)",
            zTab, pAr->zFile
         );
         rc = arExecSql(pAr, zSql);
         sqlite3_free(zSql);
       }else{
         zTab = "zip";
       }
     }else{
       /* Initialize the table for an SQLAR */
       zTab = "sqlar";
       if( bUpdate==0 ){
         rc = arExecSql(pAr, zDrop);
         if( rc!=SQLITE_OK ) goto end_ar_transaction;
       }
       rc = arExecSql(pAr, zCreate);
     }
     if( bOnlyIfChanged ){
       zExists = sqlite3_mprintf(
         " AND NOT EXISTS("
             "SELECT 1 FROM %s AS mem"
             " WHERE mem.name=disk.name"
             " AND mem.mtime=disk.mtime"
             " AND mem.mode=disk.mode)", zTab);
     }else{
       zExists = sqlite3_mprintf("");
     }
     if( zExists==0 ) rc = SQLITE_NOMEM;
     for(i=0; i<pAr->nArg && rc==SQLITE_OK; i++){
       char *zSql2 = sqlite3_mprintf(zInsertFmt[pAr->bZip], zTab,
           pAr->bVerbose ? "shell_putsnl(name)" : "name",
           pAr->azArg[i], pAr->zDir, zExists);
       rc = arExecSql(pAr, zSql2);
       sqlite3_free(zSql2);
     }
   end_ar_transaction:
     if( rc!=SQLITE_OK ){
       sqlite3_exec(pAr->db, "ROLLBACK TO ar; RELEASE ar;", 0, 0, 0);
     }else{
       rc = arExecSql(pAr, "RELEASE ar;");
       if( pAr->bZip && pAr->zFile ){
         zSql = sqlite3_mprintf("DROP TABLE %s", zTemp);
         arExecSql(pAr, zSql);
         sqlite3_free(zSql);
       }
     }
     sqlite3_free(zExists);
     return rc;
   }
   
   /*
   ** Implementation of ".ar" dot command.
   */
   static int arDotCommand(
     ShellState *pState,          /* Current shell tool state */
     int fromCmdLine,             /* True if -A command-line option, not .ar cmd */
     char **azArg,                /* Array of arguments passed to dot command */
     int nArg                     /* Number of entries in azArg[] */
   ){
     ArCommand cmd;
     int rc;
     memset(&cmd, 0, sizeof(cmd));
     cmd.fromCmdLine = fromCmdLine;
     rc = arParseCommand(azArg, nArg, &cmd);
     if( rc==SQLITE_OK ){
       int eDbType = SHELL_OPEN_UNSPEC;
       cmd.p = pState;
       cmd.db = pState->db;
       if( cmd.zFile ){
         eDbType = deduceDatabaseType(cmd.zFile, 1);
       }else{
         eDbType = pState->openMode;
       }
       if( eDbType==SHELL_OPEN_ZIPFILE ){
         if( cmd.eCmd==AR_CMD_EXTRACT || cmd.eCmd==AR_CMD_LIST ){
           if( cmd.zFile==0 ){
             cmd.zSrcTable = sqlite3_mprintf("zip");
           }else{
             cmd.zSrcTable = sqlite3_mprintf("zipfile(%Q)", cmd.zFile);
           }
         }
         cmd.bZip = 1;
       }else if( cmd.zFile ){
         int flags;
         if( cmd.bAppend ) eDbType = SHELL_OPEN_APPENDVFS;
         if( cmd.eCmd==AR_CMD_CREATE || cmd.eCmd==AR_CMD_INSERT 
              || cmd.eCmd==AR_CMD_UPDATE ){
           flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE;
         }else{
           flags = SQLITE_OPEN_READONLY;
         }
         cmd.db = 0;
         if( cmd.bDryRun ){
           utf8_printf(pState->out, "-- open database '%s'%s\n", cmd.zFile,
                eDbType==SHELL_OPEN_APPENDVFS ? " using 'apndvfs'" : "");
         }
         rc = sqlite3_open_v2(cmd.zFile, &cmd.db, flags, 
                eDbType==SHELL_OPEN_APPENDVFS ? "apndvfs" : 0);
         if( rc!=SQLITE_OK ){
           utf8_printf(stderr, "cannot open file: %s (%s)\n", 
               cmd.zFile, sqlite3_errmsg(cmd.db)
           );
           goto end_ar_command;
         }
         sqlite3_fileio_init(cmd.db, 0, 0);
         sqlite3_sqlar_init(cmd.db, 0, 0);
         sqlite3_create_function(cmd.db, "shell_putsnl", 1, SQLITE_UTF8, cmd.p,
                                 shellPutsFunc, 0, 0);
   
       }
       if( cmd.zSrcTable==0 && cmd.bZip==0 && cmd.eCmd!=AR_CMD_HELP ){
         if( cmd.eCmd!=AR_CMD_CREATE
          && sqlite3_table_column_metadata(cmd.db,0,"sqlar","name",0,0,0,0,0)
         ){
           utf8_printf(stderr, "database does not contain an 'sqlar' table\n");
           rc = SQLITE_ERROR;
           goto end_ar_command;
         }
         cmd.zSrcTable = sqlite3_mprintf("sqlar");
       }
   
       switch( cmd.eCmd ){
         case AR_CMD_CREATE:
           rc = arCreateOrUpdateCommand(&cmd, 0, 0);
           break;
   
         case AR_CMD_EXTRACT:
           rc = arExtractCommand(&cmd);
           break;
   
         case AR_CMD_LIST:
           rc = arListCommand(&cmd);
           break;
   
         case AR_CMD_HELP:
           arUsage(pState->out);
           break;
   
         case AR_CMD_INSERT:
           rc = arCreateOrUpdateCommand(&cmd, 1, 0);
           break;
   
         default:
           assert( cmd.eCmd==AR_CMD_UPDATE );
           rc = arCreateOrUpdateCommand(&cmd, 1, 1);
           break;
       }
     }
   end_ar_command:
     if( cmd.db!=pState->db ){
       close_db(cmd.db);
     }
     sqlite3_free(cmd.zSrcTable);
   
     return rc;
   }
   /* End of the ".archive" or ".ar" command logic
   *******************************************************************************/
   #endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */
   
   #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
   /*
   ** If (*pRc) is not SQLITE_OK when this function is called, it is a no-op.
   ** Otherwise, the SQL statement or statements in zSql are executed using
   ** database connection db and the error code written to *pRc before
   ** this function returns.
   */
   static void shellExec(sqlite3 *db, int *pRc, const char *zSql){
     int rc = *pRc;
     if( rc==SQLITE_OK ){
       char *zErr = 0;
       rc = sqlite3_exec(db, zSql, 0, 0, &zErr);
       if( rc!=SQLITE_OK ){
         raw_printf(stderr, "SQL error: %s\n", zErr);
       }
       *pRc = rc;
     }
   }
   
   /*
   ** Like shellExec(), except that zFmt is a printf() style format string.
   */
   static void shellExecPrintf(sqlite3 *db, int *pRc, const char *zFmt, ...){
     char *z = 0;
     if( *pRc==SQLITE_OK ){
       va_list ap;
       va_start(ap, zFmt);
       z = sqlite3_vmprintf(zFmt, ap);
       va_end(ap);
       if( z==0 ){
         *pRc = SQLITE_NOMEM;
       }else{
         shellExec(db, pRc, z);
       }
       sqlite3_free(z);
     }
   }
   
   /*
   ** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
   ** Otherwise, an attempt is made to allocate, zero and return a pointer
   ** to a buffer nByte bytes in size. If an OOM error occurs, *pRc is set
   ** to SQLITE_NOMEM and NULL returned.
   */
   static void *shellMalloc(int *pRc, sqlite3_int64 nByte){
     void *pRet = 0;
     if( *pRc==SQLITE_OK ){
       pRet = sqlite3_malloc64(nByte);
       if( pRet==0 ){
         *pRc = SQLITE_NOMEM;
       }else{
         memset(pRet, 0, nByte);
       }
     }
     return pRet;
   }
   
   /*
   ** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
   ** Otherwise, zFmt is treated as a printf() style string. The result of
   ** formatting it along with any trailing arguments is written into a 
   ** buffer obtained from sqlite3_malloc(), and pointer to which is returned.
   ** It is the responsibility of the caller to eventually free this buffer
   ** using a call to sqlite3_free().
   ** 
   ** If an OOM error occurs, (*pRc) is set to SQLITE_NOMEM and a NULL 
   ** pointer returned.
   */
   static char *shellMPrintf(int *pRc, const char *zFmt, ...){
     char *z = 0;
     if( *pRc==SQLITE_OK ){
       va_list ap;
       va_start(ap, zFmt);
       z = sqlite3_vmprintf(zFmt, ap);
       va_end(ap);
       if( z==0 ){
         *pRc = SQLITE_NOMEM;
       }
     }
     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
   ** of the following struct.
   */
   typedef struct RecoverTable RecoverTable;
   struct RecoverTable {
     char *zQuoted;                  /* Quoted version of table name */
     int nCol;                       /* Number of columns in table */
     char **azlCol;                  /* Array of column lists */
     int iPk;                        /* Index of IPK column */
   };
   
   /*
   ** Free a RecoverTable object allocated by recoverFindTable() or
   ** recoverOrphanTable().
   */
   static void recoverFreeTable(RecoverTable *pTab){
     if( pTab ){
       sqlite3_free(pTab->zQuoted);
       if( pTab->azlCol ){
         int i;
         for(i=0; i<=pTab->nCol; i++){
           sqlite3_free(pTab->azlCol[i]);
         }
         sqlite3_free(pTab->azlCol);
       }
       sqlite3_free(pTab);
     }
   }
   
   /*
   ** This function is a no-op if (*pRc) is not SQLITE_OK when it is called.
   ** Otherwise, it allocates and returns a RecoverTable object based on the
   ** final four arguments passed to this function. It is the responsibility
   ** of the caller to eventually free the returned object using
   ** recoverFreeTable().
   */
   static RecoverTable *recoverNewTable(
     int *pRc,                       /* IN/OUT: Error code */
     const char *zName,              /* Name of table */
     const char *zSql,               /* CREATE TABLE statement */
     int bIntkey, 
     int nCol
   ){
     sqlite3 *dbtmp = 0;             /* sqlite3 handle for testing CREATE TABLE */
     int rc = *pRc;
     RecoverTable *pTab = 0;
   
     pTab = (RecoverTable*)shellMalloc(&rc, sizeof(RecoverTable));
     if( rc==SQLITE_OK ){
       int nSqlCol = 0;
       int bSqlIntkey = 0;
       sqlite3_stmt *pStmt = 0;
       
       rc = sqlite3_open("", &dbtmp);
       if( rc==SQLITE_OK ){
         sqlite3_create_function(dbtmp, "shell_idquote", 1, SQLITE_UTF8, 0,
                                 shellIdQuote, 0, 0);
       }
       if( rc==SQLITE_OK ){
         rc = sqlite3_exec(dbtmp, "PRAGMA writable_schema = on", 0, 0, 0);
       }
       if( rc==SQLITE_OK ){
         rc = sqlite3_exec(dbtmp, zSql, 0, 0, 0);
         if( rc==SQLITE_ERROR ){
           rc = SQLITE_OK;
           goto finished;
         }
       }
       shellPreparePrintf(dbtmp, &rc, &pStmt, 
           "SELECT count(*) FROM pragma_table_info(%Q)", zName
       );
       if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
         nSqlCol = sqlite3_column_int(pStmt, 0);
       }
       shellFinalize(&rc, pStmt);
   
       if( rc!=SQLITE_OK || nSqlCol<nCol ){
         goto finished;
       }
   
       shellPreparePrintf(dbtmp, &rc, &pStmt, 
         "SELECT ("
         "  SELECT substr(data,1,1)==X'0D' FROM sqlite_dbpage WHERE pgno=rootpage"
         ") FROM sqlite_schema WHERE name = %Q", zName
       );
       if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
         bSqlIntkey = sqlite3_column_int(pStmt, 0);
       }
       shellFinalize(&rc, pStmt);
   
       if( bIntkey==bSqlIntkey ){
         int i;
         const char *zPk = "_rowid_";
         sqlite3_stmt *pPkFinder = 0;
   
         /* If this is an intkey table and there is an INTEGER PRIMARY KEY,
         ** set zPk to the name of the PK column, and pTab->iPk to the index
         ** of the column, where columns are 0-numbered from left to right.
         ** Or, if this is a WITHOUT ROWID table or if there is no IPK column,
         ** leave zPk as "_rowid_" and pTab->iPk at -2.  */
         pTab->iPk = -2;
         if( bIntkey ){
           shellPreparePrintf(dbtmp, &rc, &pPkFinder, 
             "SELECT cid, name FROM pragma_table_info(%Q) "
             "  WHERE pk=1 AND type='integer' COLLATE nocase"
             "  AND NOT EXISTS (SELECT cid FROM pragma_table_info(%Q) WHERE pk=2)"
             , zName, zName
           );
           if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPkFinder) ){
             pTab->iPk = sqlite3_column_int(pPkFinder, 0);
             zPk = (const char*)sqlite3_column_text(pPkFinder, 1);
           }
         }
   
         pTab->zQuoted = shellMPrintf(&rc, "\"%w\"", zName);
         pTab->azlCol = (char**)shellMalloc(&rc, sizeof(char*) * (nSqlCol+1));
         pTab->nCol = nSqlCol;
   
         if( bIntkey ){
           pTab->azlCol[0] = shellMPrintf(&rc, "\"%w\"", zPk);
         }else{
           pTab->azlCol[0] = shellMPrintf(&rc, "");
         }
         i = 1;
         shellPreparePrintf(dbtmp, &rc, &pStmt, 
             "SELECT %Q || group_concat(shell_idquote(name), ', ') "
             "  FILTER (WHERE cid!=%d) OVER (ORDER BY %s cid) "
             "FROM pragma_table_info(%Q)", 
             bIntkey ? ", " : "", pTab->iPk, 
             bIntkey ? "" : "(CASE WHEN pk=0 THEN 1000000 ELSE pk END), ",
             zName
         );
         while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
           const char *zText = (const char*)sqlite3_column_text(pStmt, 0);
           pTab->azlCol[i] = shellMPrintf(&rc, "%s%s", pTab->azlCol[0], zText);
           i++;
         }
         shellFinalize(&rc, pStmt);
   
         shellFinalize(&rc, pPkFinder);
       }
     }
   
    finished:
     sqlite3_close(dbtmp);
     *pRc = rc;
     if( rc!=SQLITE_OK || (pTab && pTab->zQuoted==0) ){
       recoverFreeTable(pTab);
       pTab = 0;
     }
     return pTab;
   }
   
   /*
   ** This function is called to search the schema recovered from the
   ** sqlite_schema table of the (possibly) corrupt database as part
   ** of a ".recover" command. Specifically, for a table with root page
   ** iRoot and at least nCol columns. Additionally, if bIntkey is 0, the
   ** table must be a WITHOUT ROWID table, or if non-zero, not one of
   ** those.
   **
   ** If a table is found, a (RecoverTable*) object is returned. Or, if
   ** no such table is found, but bIntkey is false and iRoot is the 
   ** root page of an index in the recovered schema, then (*pbNoop) is
   ** set to true and NULL returned. Or, if there is no such table or
   ** index, NULL is returned and (*pbNoop) set to 0, indicating that
   ** the caller should write data to the orphans table.
   */
   static RecoverTable *recoverFindTable(
     ShellState *pState,             /* Shell state object */
     int *pRc,                       /* IN/OUT: Error code */
     int iRoot,                      /* Root page of table */
     int bIntkey,                    /* True for an intkey table */
     int nCol,                       /* Number of columns in table */
     int *pbNoop                     /* OUT: True if iRoot is root of index */
   ){
     sqlite3_stmt *pStmt = 0;
     RecoverTable *pRet = 0;
     int bNoop = 0;
     const char *zSql = 0;
     const char *zName = 0;
   
     /* Search the recovered schema for an object with root page iRoot. */
     shellPreparePrintf(pState->db, pRc, &pStmt,
         "SELECT type, name, sql FROM recovery.schema WHERE rootpage=%d", iRoot
     );
     while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
       const char *zType = (const char*)sqlite3_column_text(pStmt, 0);
       if( bIntkey==0 && sqlite3_stricmp(zType, "index")==0 ){
         bNoop = 1;
         break;
       }
       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;
       }
     }
   
     shellFinalize(pRc, pStmt);
     *pbNoop = bNoop;
     return pRet;
   }
   
   /*
   ** Return a RecoverTable object representing the orphans table.
   */
   static RecoverTable *recoverOrphanTable(
     ShellState *pState,             /* Shell state object */
     int *pRc,                       /* IN/OUT: Error code */
     const char *zLostAndFound,      /* Base name for orphans table */
     int nCol                        /* Number of user data columns */
   ){
     RecoverTable *pTab = 0;
     if( nCol>=0 && *pRc==SQLITE_OK ){
       int i;
   
       /* This block determines the name of the orphan table. The prefered
       ** name is zLostAndFound. But if that clashes with another name
       ** in the recovered schema, try zLostAndFound_0, zLostAndFound_1
       ** and so on until a non-clashing name is found.  */
       int iTab = 0;
       char *zTab = shellMPrintf(pRc, "%s", zLostAndFound);
       sqlite3_stmt *pTest = 0;
       shellPrepare(pState->db, pRc,
           "SELECT 1 FROM recovery.schema WHERE name=?", &pTest
       );
       if( pTest ) sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT);
       while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pTest) ){
         shellReset(pRc, pTest);
         sqlite3_free(zTab);
         zTab = shellMPrintf(pRc, "%s_%d", zLostAndFound, iTab++);
         sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT);
       }
       shellFinalize(pRc, pTest);
   
       pTab = (RecoverTable*)shellMalloc(pRc, sizeof(RecoverTable));
       if( pTab ){
         pTab->zQuoted = shellMPrintf(pRc, "\"%w\"", zTab);
         pTab->nCol = nCol;
         pTab->iPk = -2;
         if( nCol>0 ){
           pTab->azlCol = (char**)shellMalloc(pRc, sizeof(char*) * (nCol+1));
           if( pTab->azlCol ){
             pTab->azlCol[nCol] = shellMPrintf(pRc, "");
             for(i=nCol-1; i>=0; i--){
               pTab->azlCol[i] = shellMPrintf(pRc, "%s, NULL", pTab->azlCol[i+1]);
             }
           }
         }
   
         if( *pRc!=SQLITE_OK ){
           recoverFreeTable(pTab);
           pTab = 0;
         }else{
           raw_printf(pState->out, 
               "CREATE TABLE %s(rootpgno INTEGER, "
               "pgno INTEGER, nfield INTEGER, id INTEGER", pTab->zQuoted
           );
           for(i=0; i<nCol; i++){
             raw_printf(pState->out, ", c%d", i);
           }
           raw_printf(pState->out, ");\n");
         }
       }
       sqlite3_free(zTab);
     }
     return pTab;
   }
   
   /*
   ** This function is called to recover data from the database. A script
   ** to construct a new database containing all recovered data is output
   ** on stream pState->out.
   */
   static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
     int rc = SQLITE_OK;
     sqlite3_stmt *pLoop = 0;        /* Loop through all root pages */
     sqlite3_stmt *pPages = 0;       /* Loop through all pages in a group */
     sqlite3_stmt *pCells = 0;       /* Loop through all cells in a page */
     const char *zRecoveryDb = "";   /* Name of "recovery" database */
     const char *zLostAndFound = "lost_and_found";
     int i;
     int nOrphan = -1;
     RecoverTable *pOrphan = 0;
   
     int bFreelist = 1;              /* 0 if --freelist-corrupt is specified */
     int bRowids = 1;                /* 0 if --no-rowids */
     for(i=1; i<nArg; i++){
       char *z = azArg[i];
       int n;
       if( z[0]=='-' && z[1]=='-' ) z++;
       n = strlen30(z);
       if( n<=17 && memcmp("-freelist-corrupt", z, n)==0 ){
         bFreelist = 0;
       }else
       if( n<=12 && memcmp("-recovery-db", z, n)==0 && i<(nArg-1) ){
         i++;
         zRecoveryDb = azArg[i];
       }else
       if( n<=15 && memcmp("-lost-and-found", z, n)==0 && i<(nArg-1) ){
         i++;
         zLostAndFound = azArg[i];
       }else
       if( n<=10 && memcmp("-no-rowids", z, n)==0 ){
         bRowids = 0;
       }
       else{
         utf8_printf(stderr, "unexpected option: %s\n", azArg[i]); 
         showHelp(pState->out, azArg[0]);
         return 1;
       }
     }
   
     shellExecPrintf(pState->db, &rc,
       /* Attach an in-memory database named 'recovery'. Create an indexed 
       ** cache of the sqlite_dbptr virtual table. */
       "PRAGMA writable_schema = on;"
       "ATTACH %Q AS recovery;"
       "DROP TABLE IF EXISTS recovery.dbptr;"
       "DROP TABLE IF EXISTS recovery.freelist;"
       "DROP TABLE IF EXISTS recovery.map;"
       "DROP TABLE IF EXISTS recovery.schema;"
       "CREATE TABLE recovery.freelist(pgno INTEGER PRIMARY KEY);", zRecoveryDb
     );
   
     if( bFreelist ){
       shellExec(pState->db, &rc,
         "WITH trunk(pgno) AS ("
         "  SELECT shell_int32("
         "      (SELECT data FROM sqlite_dbpage WHERE pgno=1), 8) AS x "
         "      WHERE x>0"
         "    UNION"
         "  SELECT shell_int32("
         "      (SELECT data FROM sqlite_dbpage WHERE pgno=trunk.pgno), 0) AS x "
         "      FROM trunk WHERE x>0"
         "),"
         "freelist(data, n, freepgno) AS ("
         "  SELECT data, min(16384, shell_int32(data, 1)-1), t.pgno "
         "      FROM trunk t, sqlite_dbpage s WHERE s.pgno=t.pgno"
         "    UNION ALL"
         "  SELECT data, n-1, shell_int32(data, 2+n) "
         "      FROM freelist WHERE n>=0"
         ")"
         "REPLACE INTO recovery.freelist SELECT freepgno FROM freelist;"
       );
     }
   
     /* If this is an auto-vacuum database, add all pointer-map pages to
     ** the freelist table. Do this regardless of whether or not 
     ** --freelist-corrupt was specified.  */
     shellExec(pState->db, &rc, 
       "WITH ptrmap(pgno) AS ("
       "  SELECT 2 WHERE shell_int32("
       "    (SELECT data FROM sqlite_dbpage WHERE pgno=1), 13"
       "  )"
       "    UNION ALL "
       "  SELECT pgno+1+(SELECT page_size FROM pragma_page_size)/5 AS pp "
       "  FROM ptrmap WHERE pp<=(SELECT page_count FROM pragma_page_count)"
       ")"
       "REPLACE INTO recovery.freelist SELECT pgno FROM ptrmap"
     );
   
     shellExec(pState->db, &rc, 
       "CREATE TABLE recovery.dbptr("
       "      pgno, child, PRIMARY KEY(child, pgno)"
       ") WITHOUT ROWID;"
       "INSERT OR IGNORE INTO recovery.dbptr(pgno, child) "
       "    SELECT * FROM sqlite_dbptr"
       "      WHERE pgno NOT IN freelist AND child NOT IN freelist;"
   
       /* Delete any pointer to page 1. This ensures that page 1 is considered
       ** a root page, regardless of how corrupt the db is. */
       "DELETE FROM recovery.dbptr WHERE child = 1;"
   
       /* Delete all pointers to any pages that have more than one pointer
       ** to them. Such pages will be treated as root pages when recovering
       ** data.  */
       "DELETE FROM recovery.dbptr WHERE child IN ("
       "  SELECT child FROM recovery.dbptr GROUP BY child HAVING count(*)>1"
       ");"
   
       /* Create the "map" table that will (eventually) contain instructions
       ** for dealing with each page in the db that contains one or more 
       ** records. */
       "CREATE TABLE recovery.map("
         "pgno INTEGER PRIMARY KEY, maxlen INT, intkey, root INT"
       ");"
   
       /* Populate table [map]. If there are circular loops of pages in the
       ** database, the following adds all pages in such a loop to the map
       ** as individual root pages. This could be handled better.  */
       "WITH pages(i, maxlen) AS ("
       "  SELECT page_count, ("
       "    SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=page_count"
       "  ) FROM pragma_page_count WHERE page_count>0"
       "    UNION ALL"
       "  SELECT i-1, ("
       "    SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=i-1"
       "  ) FROM pages WHERE i>=2"
       ")"
       "INSERT INTO recovery.map(pgno, maxlen, intkey, root) "
       "  SELECT i, maxlen, NULL, ("
       "    WITH p(orig, pgno, parent) AS ("
       "      SELECT 0, i, (SELECT pgno FROM recovery.dbptr WHERE child=i)"
       "        UNION "
       "      SELECT i, p.parent, "
       "        (SELECT pgno FROM recovery.dbptr WHERE child=p.parent) FROM p"
       "    )"
       "    SELECT pgno FROM p WHERE (parent IS NULL OR pgno = orig)"
       ") "
       "FROM pages WHERE maxlen IS NOT NULL AND i NOT IN freelist;"
       "UPDATE recovery.map AS o SET intkey = ("
       "  SELECT substr(data, 1, 1)==X'0D' FROM sqlite_dbpage WHERE pgno=o.pgno"
       ");"
   
       /* Extract data from page 1 and any linked pages into table
       ** recovery.schema. With the same schema as an sqlite_schema table.  */
       "CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql);"
       "INSERT INTO recovery.schema SELECT "
       "  max(CASE WHEN field=0 THEN value ELSE NULL END),"
       "  max(CASE WHEN field=1 THEN value ELSE NULL END),"
       "  max(CASE WHEN field=2 THEN value ELSE NULL END),"
       "  max(CASE WHEN field=3 THEN value ELSE NULL END),"
       "  max(CASE WHEN field=4 THEN value ELSE NULL END)"
       "FROM sqlite_dbdata WHERE pgno IN ("
       "  SELECT pgno FROM recovery.map WHERE root=1"
       ")"
       "GROUP BY pgno, cell;"
       "CREATE INDEX recovery.schema_rootpage ON schema(rootpage);"
     );
   
     /* Open a transaction, then print out all non-virtual, non-"sqlite_%" 
     ** CREATE TABLE statements that extracted from the existing schema.  */
     if( rc==SQLITE_OK ){
       sqlite3_stmt *pStmt = 0;
       /* ".recover" might output content in an order which causes immediate
       ** foreign key constraints to be violated. So disable foreign-key
       ** constraint enforcement to prevent problems when running the output
       ** script. */
       raw_printf(pState->out, "PRAGMA foreign_keys=OFF;\n");
       raw_printf(pState->out, "BEGIN;\n");
       raw_printf(pState->out, "PRAGMA writable_schema = on;\n");
       shellPrepare(pState->db, &rc,
           "SELECT sql FROM recovery.schema "
           "WHERE type='table' AND sql LIKE 'create table%'", &pStmt
       );
       while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
         const char *zCreateTable = (const char*)sqlite3_column_text(pStmt, 0);
         raw_printf(pState->out, "CREATE TABLE IF NOT EXISTS %s;\n", 
             &zCreateTable[12]
         );
       }
       shellFinalize(&rc, pStmt);
     }
   
     /* Figure out if an orphan table will be required. And if so, how many
     ** user columns it should contain */
     shellPrepare(pState->db, &rc, 
         "SELECT coalesce(max(maxlen), -2) FROM recovery.map WHERE root>1"
         , &pLoop
     );
     if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){
       nOrphan = sqlite3_column_int(pLoop, 0);
     }
     shellFinalize(&rc, pLoop);
     pLoop = 0;
   
     shellPrepare(pState->db, &rc,
         "SELECT pgno FROM recovery.map WHERE root=?", &pPages
     );
   
     shellPrepare(pState->db, &rc,
         "SELECT max(field), group_concat(shell_escape_crnl(quote"
         "(case when (? AND field<0) then NULL else value end)"
         "), ', ')"
         ", min(field) "
         "FROM sqlite_dbdata WHERE pgno = ? AND field != ?"
         "GROUP BY cell", &pCells
     );
   
     /* Loop through each root page. */
     shellPrepare(pState->db, &rc, 
         "SELECT root, intkey, max(maxlen) FROM recovery.map" 
         " WHERE root>1 GROUP BY root, intkey ORDER BY root=("
         "  SELECT rootpage FROM recovery.schema WHERE name='sqlite_sequence'"
         ")", &pLoop
     );
     while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){
       int iRoot = sqlite3_column_int(pLoop, 0);
       int bIntkey = sqlite3_column_int(pLoop, 1);
       int nCol = sqlite3_column_int(pLoop, 2);
       int bNoop = 0;
       RecoverTable *pTab;
   
       assert( bIntkey==0 || bIntkey==1 );
       pTab = recoverFindTable(pState, &rc, iRoot, bIntkey, nCol, &bNoop);
       if( bNoop || rc ) continue;
       if( pTab==0 ){
         if( pOrphan==0 ){
           pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan);
         }
         pTab = pOrphan;
         if( pTab==0 ) break;
       }
   
       if( 0==sqlite3_stricmp(pTab->zQuoted, "\"sqlite_sequence\"") ){
         raw_printf(pState->out, "DELETE FROM sqlite_sequence;\n");
       }
       sqlite3_bind_int(pPages, 1, iRoot);
       if( bRowids==0 && pTab->iPk<0 ){
         sqlite3_bind_int(pCells, 1, 1);
       }else{
         sqlite3_bind_int(pCells, 1, 0);
       }
       sqlite3_bind_int(pCells, 3, pTab->iPk);
   
       while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPages) ){
         int iPgno = sqlite3_column_int(pPages, 0);
         sqlite3_bind_int(pCells, 2, iPgno);
         while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pCells) ){
           int nField = sqlite3_column_int(pCells, 0);
           int iMin = sqlite3_column_int(pCells, 2);
           const char *zVal = (const char*)sqlite3_column_text(pCells, 1);
   
           RecoverTable *pTab2 = pTab;
           if( pTab!=pOrphan && (iMin<0)!=bIntkey ){
             if( pOrphan==0 ){
               pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan);
             }
             pTab2 = pOrphan;
             if( pTab2==0 ) break;
           }
   
           nField = nField+1;
           if( pTab2==pOrphan ){
             raw_printf(pState->out, 
                 "INSERT INTO %s VALUES(%d, %d, %d, %s%s%s);\n",
                 pTab2->zQuoted, iRoot, iPgno, nField,
                 iMin<0 ? "" : "NULL, ", zVal, pTab2->azlCol[nField]
             );
           }else{
             raw_printf(pState->out, "INSERT INTO %s(%s) VALUES( %s );\n", 
                 pTab2->zQuoted, pTab2->azlCol[nField], zVal
             );
           }
         }
         shellReset(&rc, pCells);
       }
       shellReset(&rc, pPages);
       if( pTab!=pOrphan ) recoverFreeTable(pTab);
     }
     shellFinalize(&rc, pLoop);
     shellFinalize(&rc, pPages);
     shellFinalize(&rc, pCells);
     recoverFreeTable(pOrphan);
   
     /* The rest of the schema */
     if( rc==SQLITE_OK ){
       sqlite3_stmt *pStmt = 0;
       shellPrepare(pState->db, &rc, 
           "SELECT sql, name FROM recovery.schema "
           "WHERE sql NOT LIKE 'create table%'", &pStmt
       );
       while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
         const char *zSql = (const char*)sqlite3_column_text(pStmt, 0);
         if( sqlite3_strnicmp(zSql, "create virt", 11)==0 ){
           const char *zName = (const char*)sqlite3_column_text(pStmt, 1);
           char *zPrint = shellMPrintf(&rc, 
             "INSERT INTO sqlite_schema VALUES('table', %Q, %Q, 0, %Q)",
             zName, zName, zSql
           );
           raw_printf(pState->out, "%s;\n", zPrint);
           sqlite3_free(zPrint);
         }else{
           raw_printf(pState->out, "%s;\n", zSql);
         }
       }
       shellFinalize(&rc, pStmt);
     }
   
     if( rc==SQLITE_OK ){
       raw_printf(pState->out, "PRAGMA writable_schema = off;\n");
       raw_printf(pState->out, "COMMIT;\n");
     }
     sqlite3_exec(pState->db, "DETACH recovery", 0, 0, 0);
     return rc;
   }
   #endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
   
   
   /*
 ** If an input line begins with "." then invoke this routine to  ** If an input line begins with "." then invoke this routine to
 ** process that line.  ** process that line.
 **  **
Line 3085  static int do_meta_command(char *zLine, ShellState *p) Line 17533  static int do_meta_command(char *zLine, ShellState *p)
   int nArg = 0;    int nArg = 0;
   int n, c;    int n, c;
   int rc = 0;    int rc = 0;
  char *azArg[50];  char *azArg[52];
   
   #ifndef SQLITE_OMIT_VIRTUALTABLE
     if( p->expert.pExpert ){
       expertFinish(p, 1, 0);
     }
   #endif
   
   /* Parse the input line into tokens.    /* Parse the input line into tokens.
   */    */
  while( zLine[h] && nArg<ArraySize(azArg) ){  while( zLine[h] && nArg<ArraySize(azArg)-1 ){
     while( IsSpace(zLine[h]) ){ h++; }      while( IsSpace(zLine[h]) ){ h++; }
     if( zLine[h]==0 ) break;      if( zLine[h]==0 ) break;
     if( zLine[h]=='\'' || zLine[h]=='"' ){      if( zLine[h]=='\'' || zLine[h]=='"' ){
Line 3110  static int do_meta_command(char *zLine, ShellState *p) Line 17564  static int do_meta_command(char *zLine, ShellState *p)
       resolve_backslashes(azArg[nArg-1]);        resolve_backslashes(azArg[nArg-1]);
     }      }
   }    }
     azArg[nArg] = 0;
   
   /* Process the input line.    /* Process the input line.
   */    */
   if( nArg==0 ) return 0; /* no tokens, no error */    if( nArg==0 ) return 0; /* no tokens, no error */
   n = strlen30(azArg[0]);    n = strlen30(azArg[0]);
   c = azArg[0][0];    c = azArg[0][0];
     clearTempFile(p);
   
   #ifndef SQLITE_OMIT_AUTHORIZATION
   if( c=='a' && strncmp(azArg[0], "auth", n)==0 ){    if( c=='a' && strncmp(azArg[0], "auth", n)==0 ){
     if( nArg!=2 ){      if( nArg!=2 ){
       raw_printf(stderr, "Usage: .auth ON|OFF\n");        raw_printf(stderr, "Usage: .auth ON|OFF\n");
Line 3130  static int do_meta_command(char *zLine, ShellState *p) Line 17587  static int do_meta_command(char *zLine, ShellState *p)
       sqlite3_set_authorizer(p->db, 0, 0);        sqlite3_set_authorizer(p->db, 0, 0);
     }      }
   }else    }else
   #endif
   
   #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
     if( c=='a' && strncmp(azArg[0], "archive", n)==0 ){
       open_db(p, 0);
       rc = arDotCommand(p, 0, azArg, nArg);
     }else
   #endif
   
   if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0)    if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0)
    || (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0)     || (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0)
   ){    ){
Line 3139  static int do_meta_command(char *zLine, ShellState *p) Line 17604  static int do_meta_command(char *zLine, ShellState *p)
     sqlite3 *pDest;      sqlite3 *pDest;
     sqlite3_backup *pBackup;      sqlite3_backup *pBackup;
     int j;      int j;
       int bAsync = 0;
       const char *zVfs = 0;
     for(j=1; j<nArg; j++){      for(j=1; j<nArg; j++){
       const char *z = azArg[j];        const char *z = azArg[j];
       if( z[0]=='-' ){        if( z[0]=='-' ){
        while( z[0]=='-' ) z++;        if( z[1]=='-' ) z++;
        /* No options to process at this time */        if( strcmp(z, "-append")==0 ){
           zVfs = "apndvfs";
         }else
         if( strcmp(z, "-async")==0 ){
           bAsync = 1;
         }else
         {          {
           utf8_printf(stderr, "unknown option: %s\n", azArg[j]);            utf8_printf(stderr, "unknown option: %s\n", azArg[j]);
           return 1;            return 1;
Line 3154  static int do_meta_command(char *zLine, ShellState *p) Line 17626  static int do_meta_command(char *zLine, ShellState *p)
         zDb = zDestFile;          zDb = zDestFile;
         zDestFile = azArg[j];          zDestFile = azArg[j];
       }else{        }else{
        raw_printf(stderr, "too many arguments to .backup\n");        raw_printf(stderr, "Usage: .backup ?DB? ?OPTIONS? FILENAME\n");
         return 1;          return 1;
       }        }
     }      }
Line 3163  static int do_meta_command(char *zLine, ShellState *p) Line 17635  static int do_meta_command(char *zLine, ShellState *p)
       return 1;        return 1;
     }      }
     if( zDb==0 ) zDb = "main";      if( zDb==0 ) zDb = "main";
    rc = sqlite3_open(zDestFile, &pDest);    rc = sqlite3_open_v2(zDestFile, &pDest
                   SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, zVfs);
     if( rc!=SQLITE_OK ){      if( rc!=SQLITE_OK ){
       utf8_printf(stderr, "Error: cannot open \"%s\"\n", zDestFile);        utf8_printf(stderr, "Error: cannot open \"%s\"\n", zDestFile);
      sqlite3_close(pDest);      close_db(pDest);
       return 1;        return 1;
     }      }
       if( bAsync ){
         sqlite3_exec(pDest, "PRAGMA synchronous=OFF; PRAGMA journal_mode=OFF;",
                      0, 0, 0);
       }
     open_db(p, 0);      open_db(p, 0);
     pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);      pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);
     if( pBackup==0 ){      if( pBackup==0 ){
       utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));        utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
      sqlite3_close(pDest);      close_db(pDest);
       return 1;        return 1;
     }      }
     while(  (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){}      while(  (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){}
Line 3184  static int do_meta_command(char *zLine, ShellState *p) Line 17661  static int do_meta_command(char *zLine, ShellState *p)
       utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));        utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(pDest));
       rc = 1;        rc = 1;
     }      }
    sqlite3_close(pDest);    close_db(pDest);
   }else    }else
   
   if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){    if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){
Line 3209  static int do_meta_command(char *zLine, ShellState *p) Line 17686  static int do_meta_command(char *zLine, ShellState *p)
     }      }
   }else    }else
   
     if( c=='c' && strcmp(azArg[0],"cd")==0 ){
       if( nArg==2 ){
   #if defined(_WIN32) || defined(WIN32)
         wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]);
         rc = !SetCurrentDirectoryW(z);
         sqlite3_free(z);
   #else
         rc = chdir(azArg[1]);
   #endif
         if( rc ){
           utf8_printf(stderr, "Cannot change to directory \"%s\"\n", azArg[1]);
           rc = 1;
         }
       }else{
         raw_printf(stderr, "Usage: .cd DIRECTORY\n");
         rc = 1;
       }
     }else
   
   /* The undocumented ".breakpoint" command causes a call to the no-op    /* The undocumented ".breakpoint" command causes a call to the no-op
   ** routine named test_breakpoint().    ** routine named test_breakpoint().
   */    */
Line 3218  static int do_meta_command(char *zLine, ShellState *p) Line 17714  static int do_meta_command(char *zLine, ShellState *p)
   
   if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){    if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){
     if( nArg==2 ){      if( nArg==2 ){
      p->countChanges = booleanValue(azArg[1]);      setOrClearFlag(p, SHFLG_CountChanges, azArg[1]);
     }else{      }else{
       raw_printf(stderr, "Usage: .changes on|off\n");        raw_printf(stderr, "Usage: .changes on|off\n");
       rc = 1;        rc = 1;
     }      }
   }else    }else
   
     /* Cancel output redirection, if it is currently set (by .testcase)
     ** Then read the content of the testcase-out.txt file and compare against
     ** azArg[1].  If there are differences, report an error and exit.
     */
     if( c=='c' && n>=3 && strncmp(azArg[0], "check", n)==0 ){
       char *zRes = 0;
       output_reset(p);
       if( nArg!=2 ){
         raw_printf(stderr, "Usage: .check GLOB-PATTERN\n");
         rc = 2;
       }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){
         raw_printf(stderr, "Error: cannot read 'testcase-out.txt'\n");
         rc = 2;
       }else if( testcase_glob(azArg[1],zRes)==0 ){
         utf8_printf(stderr,
                    "testcase-%s FAILED\n Expected: [%s]\n      Got: [%s]\n",
                    p->zTestcase, azArg[1], zRes);
         rc = 1;
       }else{
         utf8_printf(stdout, "testcase-%s ok\n", p->zTestcase);
         p->nCheck++;
       }
       sqlite3_free(zRes);
     }else
   
   if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){    if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){
     if( nArg==2 ){      if( nArg==2 ){
       tryToClone(p, azArg[1]);        tryToClone(p, azArg[1]);
Line 3235  static int do_meta_command(char *zLine, ShellState *p) Line 17756  static int do_meta_command(char *zLine, ShellState *p)
   }else    }else
   
   if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){    if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
    ShellState data;    char **azName = 0;
    char *zErrMsg = 0;    int nName = 0;
     sqlite3_stmt *pStmt;
     int i;
     open_db(p, 0);      open_db(p, 0);
    memcpy(&data, p, sizeof(data));    rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
    data.showHeader = 1;    if( rc ){
    data.cMode = data.mode = MODE_Column;      utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
    data.colWidth[0] = 3; 
    data.colWidth[1] = 15; 
    data.colWidth[2] = 58; 
    data.cnt = 0; 
    sqlite3_exec(p->db, "PRAGMA database_list; ", callback, &data, &zErrMsg); 
    if( zErrMsg ){ 
      utf8_printf(stderr,"Error: %s\n", zErrMsg); 
      sqlite3_free(zErrMsg); 
       rc = 1;        rc = 1;
       }else{
         while( sqlite3_step(pStmt)==SQLITE_ROW ){
           const char *zSchema = (const char *)sqlite3_column_text(pStmt,1);
           const char *zFile = (const char*)sqlite3_column_text(pStmt,2);
           azName = sqlite3_realloc(azName, (nName+1)*2*sizeof(char*));
           if( azName==0 ){ shell_out_of_memory();  /* Does not return */ }
           azName[nName*2] = strdup(zSchema);
           azName[nName*2+1] = strdup(zFile);
           nName++;
         }
     }      }
       sqlite3_finalize(pStmt);
       for(i=0; i<nName; i++){
         int eTxn = sqlite3_txn_state(p->db, azName[i*2]);
         int bRdonly = sqlite3_db_readonly(p->db, azName[i*2]);
         const char *z = azName[i*2+1];
         utf8_printf(p->out, "%s: %s %s%s\n",
            azName[i*2],
            z && z[0] ? z : "\"\"",
            bRdonly ? "r/o" : "r/w",
            eTxn==SQLITE_TXN_NONE ? "" :
               eTxn==SQLITE_TXN_READ ? " read-txn" : " write-txn");
         free(azName[i*2]);
         free(azName[i*2+1]);
       }
       sqlite3_free(azName);
   }else    }else
   
  if( c=='d' && strncmp(azArg[0], "dbinfo", n)==0 ){  if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){
     static const struct DbConfigChoices {
       const char *zName;
       int op;
     } aDbConfig[] = {
         { "defensive",          SQLITE_DBCONFIG_DEFENSIVE             },
         { "dqs_ddl",            SQLITE_DBCONFIG_DQS_DDL               },
         { "dqs_dml",            SQLITE_DBCONFIG_DQS_DML               },
         { "enable_fkey",        SQLITE_DBCONFIG_ENABLE_FKEY           },
         { "enable_qpsg",        SQLITE_DBCONFIG_ENABLE_QPSG           },
         { "enable_trigger",     SQLITE_DBCONFIG_ENABLE_TRIGGER        },
         { "enable_view",        SQLITE_DBCONFIG_ENABLE_VIEW           },
         { "fts3_tokenizer",     SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
         { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE    },
         { "legacy_file_format", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT    },
         { "load_extension",     SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
         { "no_ckpt_on_close",   SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE      },
         { "reset_database",     SQLITE_DBCONFIG_RESET_DATABASE        },
         { "trigger_eqp",        SQLITE_DBCONFIG_TRIGGER_EQP           },
         { "trusted_schema",     SQLITE_DBCONFIG_TRUSTED_SCHEMA        },
         { "writable_schema",    SQLITE_DBCONFIG_WRITABLE_SCHEMA       },
     };
     int ii, v;
     open_db(p, 0);
     for(ii=0; ii<ArraySize(aDbConfig); ii++){
       if( nArg>1 && strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue;
       if( nArg>=3 ){
         sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0);
       }
       sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v);
       utf8_printf(p->out, "%19s %s\n", aDbConfig[ii].zName, v ? "on" : "off");
       if( nArg>1 ) break;
     }
     if( nArg>1 && ii==ArraySize(aDbConfig) ){
       utf8_printf(stderr, "Error: unknown dbconfig \"%s\"\n", azArg[1]);
       utf8_printf(stderr, "Enter \".dbconfig\" with no arguments for a list\n");
     }   
   }else
 
   if( c=='d' && n>=3 && strncmp(azArg[0], "dbinfo", n)==0 ){
     rc = shell_dbinfo_command(p, nArg, azArg);      rc = shell_dbinfo_command(p, nArg, azArg);
   }else    }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);
     }else
   #endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
   
   if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){    if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
       char *zLike = 0;
       char *zSql;
       int i;
       int savedShowHeader = p->showHeader;
       int savedShellFlags = p->shellFlgs;
       ShellClearFlag(p, 
          SHFLG_PreserveRowid|SHFLG_Newlines|SHFLG_Echo
          |SHFLG_DumpDataOnly|SHFLG_DumpNoSys);
       for(i=1; i<nArg; i++){
         if( azArg[i][0]=='-' ){
           const char *z = azArg[i]+1;
           if( z[0]=='-' ) z++;
           if( strcmp(z,"preserve-rowids")==0 ){
   #ifdef SQLITE_OMIT_VIRTUALTABLE
             raw_printf(stderr, "The --preserve-rowids option is not compatible"
                                " with SQLITE_OMIT_VIRTUALTABLE\n");
             rc = 1;
             sqlite3_free(zLike);
             goto meta_command_exit;
   #else
             ShellSetFlag(p, SHFLG_PreserveRowid);
   #endif
           }else
           if( strcmp(z,"newlines")==0 ){
             ShellSetFlag(p, SHFLG_Newlines);
           }else
           if( strcmp(z,"data-only")==0 ){
             ShellSetFlag(p, SHFLG_DumpDataOnly);
           }else
           if( strcmp(z,"nosys")==0 ){
             ShellSetFlag(p, SHFLG_DumpNoSys);
           }else
           {
             raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
             rc = 1;
             sqlite3_free(zLike);
             goto meta_command_exit;
           }
         }else if( zLike ){
           zLike = sqlite3_mprintf("%z OR name LIKE %Q ESCAPE '\\'",
                   zLike, azArg[i]);
         }else{
           zLike = sqlite3_mprintf("name LIKE %Q ESCAPE '\\'", azArg[i]);
         }
       }
   
     open_db(p, 0);      open_db(p, 0);
    /* When playing back a "dump", the content might appear in an order
    ** which causes immediate foreign key constraints to be violated.    if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
    ** So disable foreign-key constraint enforcement to prevent problems. */      /* When playing back a "dump", the content might appear in an order
    if( nArg!=1 && nArg!=2 ){      ** which causes immediate foreign key constraints to be violated.
      raw_printf(stderr, "Usage: .dump ?LIKE-PATTERN?\n");      ** So disable foreign-key constraint enforcement to prevent problems. */
      rc = 1;      raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");
      goto meta_command_exit;      raw_printf(p->out, "BEGIN TRANSACTION;\n");
     }      }
     raw_printf(p->out, "PRAGMA foreign_keys=OFF;\n");  
     raw_printf(p->out, "BEGIN TRANSACTION;\n");  
     p->writableSchema = 0;      p->writableSchema = 0;
       p->showHeader = 0;
       /* Set writable_schema=ON since doing so forces SQLite to initialize
       ** as much of the schema as it can even if the sqlite_schema table is
       ** corrupt. */
     sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);      sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
     p->nErr = 0;      p->nErr = 0;
    if( nArg==1 ){    if( zLike==0 ) zLike = sqlite3_mprintf("true");
      run_schema_dump_query(p,    zSql = sqlite3_mprintf(
        "SELECT name, type, sql FROM sqlite_master "      "SELECT name, type, sql FROM sqlite_schema "
        "WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'"      "WHERE (%s) AND type=='table'"
       "  AND sql NOT NULL"
       " ORDER BY tbl_name='sqlite_sequence', rowid",
       zLike
     );
     run_schema_dump_query(p,zSql);
     sqlite3_free(zSql);
     if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
       zSql = sqlite3_mprintf(
         "SELECT sql FROM sqlite_schema "
         "WHERE (%s) AND sql NOT NULL"
         "  AND type IN ('index','trigger','view')",
         zLike
       );        );
      run_schema_dump_query(p,      run_table_dump_query(p, zSql);
        "SELECT name, type, sql FROM sqlite_master "      sqlite3_free(zSql);
        "WHERE name=='sqlite_sequence'" 
      ); 
      run_table_dump_query(p, 
        "SELECT sql FROM sqlite_master " 
        "WHERE sql NOT NULL AND type IN ('index','trigger','view')", 0 
      ); 
    }else{ 
      int i; 
      for(i=1; i<nArg; i++){ 
        zShellStatic = azArg[i]; 
        run_schema_dump_query(p, 
          "SELECT name, type, sql FROM sqlite_master " 
          "WHERE tbl_name LIKE shellstatic() AND type=='table'" 
          "  AND sql NOT NULL"); 
        run_table_dump_query(p, 
          "SELECT sql FROM sqlite_master " 
          "WHERE sql NOT NULL" 
          "  AND type IN ('index','trigger','view')" 
          "  AND tbl_name LIKE shellstatic()", 0 
        ); 
        zShellStatic = 0; 
      } 
     }      }
       sqlite3_free(zLike);
     if( p->writableSchema ){      if( p->writableSchema ){
       raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");        raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
       p->writableSchema = 0;        p->writableSchema = 0;
     }      }
     sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);      sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
     sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);      sqlite3_exec(p->db, "RELEASE dump;", 0, 0, 0);
    raw_printf(p->out, p->nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n");    if( (p->shellFlgs & SHFLG_DumpDataOnly)==0 ){
       raw_printf(p->out, p->nErr?"ROLLBACK; -- due to errors\n":"COMMIT;\n");
     }
     p->showHeader = savedShowHeader;
     p->shellFlgs = savedShellFlags;
   }else    }else
   
   if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){    if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){
     if( nArg==2 ){      if( nArg==2 ){
      p->echoOn = booleanValue(azArg[1]);      setOrClearFlag(p, SHFLG_Echo, azArg[1]);
     }else{      }else{
       raw_printf(stderr, "Usage: .echo on|off\n");        raw_printf(stderr, "Usage: .echo on|off\n");
       rc = 1;        rc = 1;
Line 3322  static int do_meta_command(char *zLine, ShellState *p) Line 17951  static int do_meta_command(char *zLine, ShellState *p)
   
   if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){    if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){
     if( nArg==2 ){      if( nArg==2 ){
         p->autoEQPtest = 0;
         if( p->autoEQPtrace ){
           if( p->db ) sqlite3_exec(p->db, "PRAGMA vdbe_trace=OFF;", 0, 0, 0);
           p->autoEQPtrace = 0;
         }
       if( strcmp(azArg[1],"full")==0 ){        if( strcmp(azArg[1],"full")==0 ){
        p->autoEQP = 2;        p->autoEQP = AUTOEQP_full;
       }else if( strcmp(azArg[1],"trigger")==0 ){
         p->autoEQP = AUTOEQP_trigger;
 #ifdef SQLITE_DEBUG
       }else if( strcmp(azArg[1],"test")==0 ){
         p->autoEQP = AUTOEQP_on;
         p->autoEQPtest = 1;
       }else if( strcmp(azArg[1],"trace")==0 ){
         p->autoEQP = AUTOEQP_full;
         p->autoEQPtrace = 1;
         open_db(p, 0);
         sqlite3_exec(p->db, "SELECT name FROM sqlite_schema LIMIT 1", 0, 0, 0);
         sqlite3_exec(p->db, "PRAGMA vdbe_trace=ON;", 0, 0, 0);
 #endif
       }else{        }else{
        p->autoEQP = booleanValue(azArg[1]);        p->autoEQP = (u8)booleanValue(azArg[1]);
       }        }
     }else{      }else{
      raw_printf(stderr, "Usage: .eqp on|off|full\n");      raw_printf(stderr, "Usage: .eqp off|on|trace|trigger|full\n");
       rc = 1;        rc = 1;
     }      }
   }else    }else
Line 3338  static int do_meta_command(char *zLine, ShellState *p) Line 17985  static int do_meta_command(char *zLine, ShellState *p)
     rc = 2;      rc = 2;
   }else    }else
   
     /* The ".explain" command is automatic now.  It is largely pointless.  It
     ** retained purely for backwards compatibility */
   if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){    if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
     int val = 1;      int val = 1;
     if( nArg>=2 ){      if( nArg>=2 ){
Line 3360  static int do_meta_command(char *zLine, ShellState *p) Line 18009  static int do_meta_command(char *zLine, ShellState *p)
     }      }
   }else    }else
   
   #ifndef SQLITE_OMIT_VIRTUALTABLE
     if( c=='e' && strncmp(azArg[0], "expert", n)==0 ){
       open_db(p, 0);
       expertDotCommand(p, azArg, nArg);
     }else
   #endif
   
     if( c=='f' && strncmp(azArg[0], "filectrl", n)==0 ){
       static const struct {
          const char *zCtrlName;   /* Name of a test-control option */
          int ctrlCode;            /* Integer code for that option */
          const char *zUsage;      /* Usage notes */
       } aCtrl[] = {
         { "chunk_size",     SQLITE_FCNTL_CHUNK_SIZE,      "SIZE"           },
         { "data_version",   SQLITE_FCNTL_DATA_VERSION,    ""               },
         { "has_moved",      SQLITE_FCNTL_HAS_MOVED,       ""               },  
         { "lock_timeout",   SQLITE_FCNTL_LOCK_TIMEOUT,    "MILLISEC"       },
         { "persist_wal",    SQLITE_FCNTL_PERSIST_WAL,     "[BOOLEAN]"      },
      /* { "pragma",         SQLITE_FCNTL_PRAGMA,          "NAME ARG"       },*/
         { "psow",       SQLITE_FCNTL_POWERSAFE_OVERWRITE, "[BOOLEAN]"      },
         { "reserve_bytes",  SQLITE_FCNTL_RESERVE_BYTES,   "[N]"            },
         { "size_limit",     SQLITE_FCNTL_SIZE_LIMIT,      "[LIMIT]"        },
         { "tempfilename",   SQLITE_FCNTL_TEMPFILENAME,    ""               },
      /* { "win32_av_retry", SQLITE_FCNTL_WIN32_AV_RETRY,  "COUNT DELAY"    },*/
       };
       int filectrl = -1;
       int iCtrl = -1;
       sqlite3_int64 iRes = 0;  /* Integer result to display if rc2==1 */
       int isOk = 0;            /* 0: usage  1: %lld  2: no-result */
       int n2, i;
       const char *zCmd = 0;
       const char *zSchema = 0;
   
       open_db(p, 0);
       zCmd = nArg>=2 ? azArg[1] : "help";
   
       if( zCmd[0]=='-' 
        && (strcmp(zCmd,"--schema")==0 || strcmp(zCmd,"-schema")==0)
        && nArg>=4
       ){
         zSchema = azArg[2];
         for(i=3; i<nArg; i++) azArg[i-2] = azArg[i];
         nArg -= 2;
         zCmd = azArg[1];
       }
   
       /* The argument can optionally begin with "-" or "--" */
       if( zCmd[0]=='-' && zCmd[1] ){
         zCmd++;
         if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
       }
   
       /* --help lists all file-controls */
       if( strcmp(zCmd,"help")==0 ){
         utf8_printf(p->out, "Available file-controls:\n");
         for(i=0; i<ArraySize(aCtrl); i++){
           utf8_printf(p->out, "  .filectrl %s %s\n",
                       aCtrl[i].zCtrlName, aCtrl[i].zUsage);
         }
         rc = 1;
         goto meta_command_exit;
       }
   
       /* convert filectrl text option to value. allow any unique prefix
       ** of the option name, or a numerical value. */
       n2 = strlen30(zCmd);
       for(i=0; i<ArraySize(aCtrl); i++){
         if( strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
           if( filectrl<0 ){
             filectrl = aCtrl[i].ctrlCode;
             iCtrl = i;
           }else{
             utf8_printf(stderr, "Error: ambiguous file-control: \"%s\"\n"
                                 "Use \".filectrl --help\" for help\n", zCmd);
             rc = 1;
             goto meta_command_exit;
           }
         }
       }
       if( filectrl<0 ){
         utf8_printf(stderr,"Error: unknown file-control: %s\n"
                            "Use \".filectrl --help\" for help\n", zCmd);
       }else{
         switch(filectrl){
           case SQLITE_FCNTL_SIZE_LIMIT: {
             if( nArg!=2 && nArg!=3 ) break;
             iRes = nArg==3 ? integerValue(azArg[2]) : -1;
             sqlite3_file_control(p->db, zSchema, SQLITE_FCNTL_SIZE_LIMIT, &iRes);
             isOk = 1;
             break;
           }
           case SQLITE_FCNTL_LOCK_TIMEOUT:
           case SQLITE_FCNTL_CHUNK_SIZE: {
             int x;
             if( nArg!=3 ) break;
             x = (int)integerValue(azArg[2]);
             sqlite3_file_control(p->db, zSchema, filectrl, &x);
             isOk = 2;
             break;
           }
           case SQLITE_FCNTL_PERSIST_WAL:
           case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
             int x;
             if( nArg!=2 && nArg!=3 ) break;
             x = nArg==3 ? booleanValue(azArg[2]) : -1;
             sqlite3_file_control(p->db, zSchema, filectrl, &x);
             iRes = x;
             isOk = 1;
             break;
           }
           case SQLITE_FCNTL_DATA_VERSION:
           case SQLITE_FCNTL_HAS_MOVED: {
             int x;
             if( nArg!=2 ) break;
             sqlite3_file_control(p->db, zSchema, filectrl, &x);
             iRes = x;
             isOk = 1;
             break;
           }
           case SQLITE_FCNTL_TEMPFILENAME: {
             char *z = 0;
             if( nArg!=2 ) break;
             sqlite3_file_control(p->db, zSchema, filectrl, &z);
             if( z ){
               utf8_printf(p->out, "%s\n", z);
               sqlite3_free(z);
             }
             isOk = 2;
             break;
           }
           case SQLITE_FCNTL_RESERVE_BYTES: {
             int x;
             if( nArg>=3 ){
               x = atoi(azArg[2]);
               sqlite3_file_control(p->db, zSchema, filectrl, &x);
             }
             x = -1;
             sqlite3_file_control(p->db, zSchema, filectrl, &x);
             utf8_printf(p->out,"%d\n", x);
             isOk = 2;
             break;
           }
         }
       }
       if( isOk==0 && iCtrl>=0 ){
         utf8_printf(p->out, "Usage: .filectrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
         rc = 1;
       }else if( isOk==1 ){
         char zBuf[100];
         sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", iRes);
         raw_printf(p->out, "%s\n", zBuf);
       }
     }else
   
   if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){    if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){
     ShellState data;      ShellState data;
     char *zErrMsg = 0;      char *zErrMsg = 0;
Line 3380  static int do_meta_command(char *zLine, ShellState *p) Line 18183  static int do_meta_command(char *zLine, ShellState *p)
     rc = sqlite3_exec(p->db,      rc = sqlite3_exec(p->db,
        "SELECT sql FROM"         "SELECT sql FROM"
        "  (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"         "  (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
       "     FROM sqlite_master UNION ALL"       "     FROM sqlite_schema UNION ALL"
       "   SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) "       "   SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_schema) "
        "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "         "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
        "ORDER BY rowid",         "ORDER BY rowid",
        callback, &data, &zErrMsg         callback, &data, &zErrMsg
Line 3389  static int do_meta_command(char *zLine, ShellState *p) Line 18192  static int do_meta_command(char *zLine, ShellState *p)
     if( rc==SQLITE_OK ){      if( rc==SQLITE_OK ){
       sqlite3_stmt *pStmt;        sqlite3_stmt *pStmt;
       rc = sqlite3_prepare_v2(p->db,        rc = sqlite3_prepare_v2(p->db,
               "SELECT rowid FROM sqlite_master"               "SELECT rowid FROM sqlite_schema"
                " WHERE name GLOB 'sqlite_stat[134]'",                 " WHERE name GLOB 'sqlite_stat[134]'",
                -1, &pStmt, 0);                 -1, &pStmt, 0);
       doStats = sqlite3_step(pStmt)==SQLITE_ROW;        doStats = sqlite3_step(pStmt)==SQLITE_ROW;
Line 3398  static int do_meta_command(char *zLine, ShellState *p) Line 18201  static int do_meta_command(char *zLine, ShellState *p)
     if( doStats==0 ){      if( doStats==0 ){
       raw_printf(p->out, "/* No STAT tables available */\n");        raw_printf(p->out, "/* No STAT tables available */\n");
     }else{      }else{
      raw_printf(p->out, "ANALYZE sqlite_master;\n");      raw_printf(p->out, "ANALYZE sqlite_schema;\n");
      sqlite3_exec(p->db, "SELECT 'ANALYZE sqlite_master'",      sqlite3_exec(p->db, "SELECT 'ANALYZE sqlite_schema'",
                    callback, &data, &zErrMsg);                     callback, &data, &zErrMsg);
       data.cMode = data.mode = MODE_Insert;        data.cMode = data.mode = MODE_Insert;
       data.zDestTable = "sqlite_stat1";        data.zDestTable = "sqlite_stat1";
      shell_exec(p->db, "SELECT * FROM sqlite_stat1",      shell_exec(&data, "SELECT * FROM sqlite_stat1", &zErrMsg);
                 shell_callback, &data,&zErrMsg); 
      data.zDestTable = "sqlite_stat3"; 
      shell_exec(p->db, "SELECT * FROM sqlite_stat3", 
                 shell_callback, &data,&zErrMsg); 
       data.zDestTable = "sqlite_stat4";        data.zDestTable = "sqlite_stat4";
      shell_exec(p->db, "SELECT * FROM sqlite_stat4",      shell_exec(&data, "SELECT * FROM sqlite_stat4", &zErrMsg);
                 shell_callback, &data, &zErrMsg);      raw_printf(p->out, "ANALYZE sqlite_schema;\n");
      raw_printf(p->out, "ANALYZE sqlite_master;\n"); 
     }      }
   }else    }else
   
   if( c=='h' && strncmp(azArg[0], "headers", n)==0 ){    if( c=='h' && strncmp(azArg[0], "headers", n)==0 ){
     if( nArg==2 ){      if( nArg==2 ){
       p->showHeader = booleanValue(azArg[1]);        p->showHeader = booleanValue(azArg[1]);
         p->shellFlgs |= SHFLG_HeaderSet;
     }else{      }else{
       raw_printf(stderr, "Usage: .headers on|off\n");        raw_printf(stderr, "Usage: .headers on|off\n");
       rc = 1;        rc = 1;
Line 3425  static int do_meta_command(char *zLine, ShellState *p) Line 18224  static int do_meta_command(char *zLine, ShellState *p)
   }else    }else
   
   if( c=='h' && strncmp(azArg[0], "help", n)==0 ){    if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
    utf8_printf(p->out, "%s", zHelp);    if( nArg>=2 ){
       n = showHelp(p->out, azArg[1]);
       if( n==0 ){
         utf8_printf(p->out, "Nothing matches '%s'\n", azArg[1]);
       }
     }else{
       showHelp(p->out, 0);
     }
   }else    }else
   
   if( c=='i' && strncmp(azArg[0], "import", n)==0 ){    if( c=='i' && strncmp(azArg[0], "import", n)==0 ){
    char *zTable;               /* Insert data into this table */    char *zTable = 0;           /* Insert data into this table */
    char *zFile;                /* Name of file to extra content from */    char *zFile = 0;            /* Name of file to extra content from */
     sqlite3_stmt *pStmt = NULL; /* A statement */      sqlite3_stmt *pStmt = NULL; /* A statement */
     int nCol;                   /* Number of columns in the table */      int nCol;                   /* Number of columns in the table */
     int nByte;                  /* Number of bytes in an SQL string */      int nByte;                  /* Number of bytes in an SQL string */
Line 3440  static int do_meta_command(char *zLine, ShellState *p) Line 18246  static int do_meta_command(char *zLine, ShellState *p)
     char *zSql;                 /* An SQL statement */      char *zSql;                 /* An SQL statement */
     ImportCtx sCtx;             /* Reader context */      ImportCtx sCtx;             /* Reader context */
     char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */      char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
    int (SQLITE_CDECL *xCloser)(FILE*);      /* Func to close file */    int eVerbose = 0;           /* Larger for more console output */
     int nSkip = 0;              /* Initial lines to skip */
     int useOutputMode = 1;      /* Use output mode to determine separators */
   
     if( nArg!=3 ){  
       raw_printf(stderr, "Usage: .import FILE TABLE\n");  
       goto meta_command_exit;  
     }  
     zFile = azArg[1];  
     zTable = azArg[2];  
     seenInterrupt = 0;  
     memset(&sCtx, 0, sizeof(sCtx));      memset(&sCtx, 0, sizeof(sCtx));
    open_db(p, 0);    if( p->mode==MODE_Ascii ){
    nSep = strlen30(p->colSeparator);      xRead = ascii_read_one_field;
    if( nSep==0 ){    }else{
      raw_printf(stderr,      xRead = csv_read_one_field;
                 "Error: non-null column separator required for import\n"); 
      return 1; 
     }      }
    if( nSep>1 ){    for(i=1; i<nArg; i++){
      raw_printf(stderr, "Error: multi-character column separators not allowed"      char *z = azArg[i];
                      " for import\n");      if( z[0]=='-' && z[1]=='-' ) z++;
      return 1;      if( z[0]!='-' ){
         if( zFile==0 ){
           zFile = z;
         }else if( zTable==0 ){
           zTable = z;
         }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,"-skip")==0 && i<nArg-1 ){
         nSkip = integerValue(azArg[++i]);
       }else if( strcmp(z,"-ascii")==0 ){
         sCtx.cColSep = SEP_Unit[0];
         sCtx.cRowSep = SEP_Record[0];
         xRead = ascii_read_one_field;
         useOutputMode = 0;
       }else if( strcmp(z,"-csv")==0 ){
         sCtx.cColSep = ',';
         sCtx.cRowSep = '\n';
         xRead = csv_read_one_field;
         useOutputMode = 0;
       }else{
         utf8_printf(p->out, "ERROR: unknown option: \"%s\".  Usage:\n", z);
         showHelp(p->out, "import");
         rc = 1;
         goto meta_command_exit;
       }
     }      }
    nSep = strlen30(p->rowSeparator);    if( zTable==0 ){
    if( nSep==0 ){      utf8_printf(p->out, "ERROR: missing %s argument. Usage:\n",
      raw_printf(stderr, "Error: non-null row separator required for import\n");                  zFile==0 ? "FILE" : "TABLE");
      return 1;      showHelp(p->out, "import");
       rc = 1;
       goto meta_command_exit;
     }      }
    if( nSep==2 && p->mode==MODE_Csv && strcmp(p->rowSeparator, SEP_CrLf)==0 ){    seenInterrupt = 0;
      /* When importing CSV (only), if the row separator is set to the    open_db(p, 0);
      ** default output row separator, change it to the default input    if( useOutputMode ){
      ** row separator.  This avoids having to maintain different input      /* If neither the --csv or --ascii options are specified, then set
      ** and output row separators. */      ** the column and row separator characters from the output mode. */
      sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);      nSep = strlen30(p->colSeparator);
       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, 
               "Error: multi-character column separators not allowed"
               " for import\n");
         rc = 1;
         goto meta_command_exit;
       }
       nSep = strlen30(p->rowSeparator);        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 ){
           /* When importing CSV (only), if the row separator is set to the
           ** default output row separator, change it to the default input
           ** row separator.  This avoids having to maintain different input
           ** and output row separators. */
           sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
           nSep = strlen30(p->rowSeparator);
         }
         if( nSep>1 ){
           raw_printf(stderr, "Error: multi-character row separators not allowed"
                              " for import\n");
           rc = 1;
           goto meta_command_exit;
         }
         sCtx.cColSep = p->colSeparator[0];
         sCtx.cRowSep = p->rowSeparator[0];
     }      }
     if( nSep>1 ){  
       raw_printf(stderr, "Error: multi-character row separators not allowed"  
                       " for import\n");  
       return 1;  
     }  
     sCtx.zFile = zFile;      sCtx.zFile = zFile;
     sCtx.nLine = 1;      sCtx.nLine = 1;
     if( sCtx.zFile[0]=='|' ){      if( sCtx.zFile[0]=='|' ){
 #ifdef SQLITE_OMIT_POPEN  #ifdef SQLITE_OMIT_POPEN
       raw_printf(stderr, "Error: pipes are not supported in this OS\n");        raw_printf(stderr, "Error: pipes are not supported in this OS\n");
      return 1;      rc = 1;
       goto meta_command_exit;
 #else  #else
       sCtx.in = popen(sCtx.zFile+1, "r");        sCtx.in = popen(sCtx.zFile+1, "r");
       sCtx.zFile = "<pipe>";        sCtx.zFile = "<pipe>";
      xCloser = pclose;      sCtx.xCloser = pclose;
 #endif  #endif
     }else{      }else{
       sCtx.in = fopen(sCtx.zFile, "rb");        sCtx.in = fopen(sCtx.zFile, "rb");
      xCloser = fclose;      sCtx.xCloser = fclose;
     }      }
     if( p->mode==MODE_Ascii ){  
       xRead = ascii_read_one_field;  
     }else{  
       xRead = csv_read_one_field;  
     }  
     if( sCtx.in==0 ){      if( sCtx.in==0 ){
       utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);        utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
      return 1;      rc = 1;
       goto meta_command_exit;
     }      }
    sCtx.cColSep = p->colSeparator[0];    if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){
    sCtx.cRowSep = p->rowSeparator[0];      char zSep[2];
    zSql = sqlite3_mprintf("SELECT * FROM %s", zTable);      zSep[1] = 0;
       zSep[0] = sCtx.cColSep;
       utf8_printf(p->out, "Column separator ");
       output_c_string(p->out, zSep);
       utf8_printf(p->out, ", row separator ");
       zSep[0] = sCtx.cRowSep;
       output_c_string(p->out, zSep);
       utf8_printf(p->out, "\n");
     }
     while( (nSkip--)>0 ){
       while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
     }
     zSql = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
     if( zSql==0 ){      if( zSql==0 ){
      raw_printf(stderr, "Error: out of memory\n");      import_cleanup(&sCtx);
      xCloser(sCtx.in);      shell_out_of_memory();
      return 1; 
     }      }
     nByte = strlen30(zSql);      nByte = strlen30(zSql);
     rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);      rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
     import_append_char(&sCtx, 0);    /* To ensure sCtx.z is allocated */      import_append_char(&sCtx, 0);    /* To ensure sCtx.z is allocated */
     if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){      if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
      char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable);      char *zCreate = sqlite3_mprintf("CREATE TABLE \"%w\"", zTable);
       char cSep = '(';        char cSep = '(';
       while( xRead(&sCtx) ){        while( xRead(&sCtx) ){
         zCreate = sqlite3_mprintf("%z%c\n  \"%w\" TEXT", zCreate, cSep, sCtx.z);          zCreate = sqlite3_mprintf("%z%c\n  \"%w\" TEXT", zCreate, cSep, sCtx.z);
Line 3525  static int do_meta_command(char *zLine, ShellState *p) Line 18394  static int do_meta_command(char *zLine, ShellState *p)
       }        }
       if( cSep=='(' ){        if( cSep=='(' ){
         sqlite3_free(zCreate);          sqlite3_free(zCreate);
        sqlite3_free(sCtx.z);        import_cleanup(&sCtx);
        xCloser(sCtx.in); 
         utf8_printf(stderr,"%s: empty file\n", sCtx.zFile);          utf8_printf(stderr,"%s: empty file\n", sCtx.zFile);
        return 1;        rc = 1;
         goto meta_command_exit;
       }        }
       zCreate = sqlite3_mprintf("%z\n)", zCreate);        zCreate = sqlite3_mprintf("%z\n)", zCreate);
         if( eVerbose>=1 ){
           utf8_printf(p->out, "%s\n", zCreate);
         }
       rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);        rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
       sqlite3_free(zCreate);        sqlite3_free(zCreate);
       if( rc ){        if( rc ){
        utf8_printf(stderr, "CREATE TABLE %s(...) failed: %s\n", zTable,        utf8_printf(stderr, "CREATE TABLE \"%s\"(...) failed: %s\n", zTable,
                 sqlite3_errmsg(p->db));                  sqlite3_errmsg(p->db));
        sqlite3_free(sCtx.z);        import_cleanup(&sCtx);
        xCloser(sCtx.in);        rc = 1;
        return 1;        goto meta_command_exit;
       }        }
       rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);        rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
     }      }
Line 3546  static int do_meta_command(char *zLine, ShellState *p) Line 18418  static int do_meta_command(char *zLine, ShellState *p)
     if( rc ){      if( rc ){
       if (pStmt) sqlite3_finalize(pStmt);        if (pStmt) sqlite3_finalize(pStmt);
       utf8_printf(stderr,"Error: %s\n", sqlite3_errmsg(p->db));        utf8_printf(stderr,"Error: %s\n", sqlite3_errmsg(p->db));
      xCloser(sCtx.in);      import_cleanup(&sCtx);
      return 1;      rc = 1;
       goto meta_command_exit;
     }      }
     nCol = sqlite3_column_count(pStmt);      nCol = sqlite3_column_count(pStmt);
     sqlite3_finalize(pStmt);      sqlite3_finalize(pStmt);
Line 3555  static int do_meta_command(char *zLine, ShellState *p) Line 18428  static int do_meta_command(char *zLine, ShellState *p)
     if( nCol==0 ) return 0; /* no columns, no error */      if( nCol==0 ) return 0; /* no columns, no error */
     zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 );      zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 );
     if( zSql==0 ){      if( zSql==0 ){
      raw_printf(stderr, "Error: out of memory\n");      import_cleanup(&sCtx);
      xCloser(sCtx.in);      shell_out_of_memory();
      return 1; 
     }      }
     sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);      sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);
     j = strlen30(zSql);      j = strlen30(zSql);
Line 3567  static int do_meta_command(char *zLine, ShellState *p) Line 18439  static int do_meta_command(char *zLine, ShellState *p)
     }      }
     zSql[j++] = ')';      zSql[j++] = ')';
     zSql[j] = 0;      zSql[j] = 0;
       if( eVerbose>=2 ){
         utf8_printf(p->out, "Insert using: %s\n", zSql);
       }
     rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);      rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
     sqlite3_free(zSql);      sqlite3_free(zSql);
     if( rc ){      if( rc ){
       utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));        utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
       if (pStmt) sqlite3_finalize(pStmt);        if (pStmt) sqlite3_finalize(pStmt);
      xCloser(sCtx.in);      import_cleanup(&sCtx);
      return 1;      rc = 1;
       goto meta_command_exit;
     }      }
     needCommit = sqlite3_get_autocommit(p->db);      needCommit = sqlite3_get_autocommit(p->db);
     if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0);      if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
Line 3616  static int do_meta_command(char *zLine, ShellState *p) Line 18492  static int do_meta_command(char *zLine, ShellState *p)
         if( rc!=SQLITE_OK ){          if( rc!=SQLITE_OK ){
           utf8_printf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile,            utf8_printf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile,
                       startLine, sqlite3_errmsg(p->db));                        startLine, sqlite3_errmsg(p->db));
             sCtx.nErr++;
           }else{
             sCtx.nRow++;
         }          }
       }        }
     }while( sCtx.cTerm!=EOF );      }while( sCtx.cTerm!=EOF );
   
    xCloser(sCtx.in);    import_cleanup(&sCtx);
    sqlite3_free(sCtx.z); 
     sqlite3_finalize(pStmt);      sqlite3_finalize(pStmt);
     if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);      if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
       if( eVerbose>0 ){
         utf8_printf(p->out,
             "Added %d rows with %d errors using %d lines of input\n",
             sCtx.nRow, sCtx.nErr, sCtx.nLine-1);
       }
   }else    }else
   
  if( c=='i' && (strncmp(azArg[0], "indices", n)==0#ifndef SQLITE_UNTESTABLE
                 || strncmp(azArg[0], "indexes", n)==0) ){  if( c=='i' && strncmp(azArg[0], "imposter", n)==0 ){
    ShellState data;    char *zSql;
    char *zErrMsg = 0;    char *zCollist = 0;
     sqlite3_stmt *pStmt;
     int tnum = 0;
     int isWO = 0;  /* True if making an imposter of a WITHOUT ROWID table */
     int lenPK = 0; /* Length of the PRIMARY KEY string for isWO tables */
     int i;
     if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){
       utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n"
                           "       .imposter off\n");
       /* Also allowed, but not documented:
       **
       **    .imposter TABLE IMPOSTER
       **
       ** where TABLE is a WITHOUT ROWID table.  In that case, the
       ** imposter is another WITHOUT ROWID table with the columns in
       ** storage order. */
       rc = 1;
       goto meta_command_exit;
     }
     open_db(p, 0);      open_db(p, 0);
    memcpy(&data, p, sizeof(data));    if( nArg==2 ){
    data.showHeader = 0;      sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1);
    data.cMode = data.mode = MODE_List;      goto meta_command_exit;
    if( nArg==1 ){    }
      rc = sqlite3_exec(p->db,    zSql = sqlite3_mprintf(
        "SELECT name FROM sqlite_master "      "SELECT rootpage, 0 FROM sqlite_schema"
        "WHERE type='index' AND name NOT LIKE 'sqlite_%' "      " WHERE name='%q' AND type='index'"
        "UNION ALL "      "UNION ALL "
        "SELECT name FROM sqlite_temp_master "      "SELECT rootpage, 1 FROM sqlite_schema"
        "WHERE type='index' "      " WHERE name='%q' AND type='table'"
        "ORDER BY 1",      "   AND sql LIKE '%%without%%rowid%%'",
        callback, &data, &zErrMsg      azArg[1], azArg[1]
      );    );
    }else if( nArg==2 ){    sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
      zShellStatic = azArg[1];    sqlite3_free(zSql);
      rc = sqlite3_exec(p->db,    if( sqlite3_step(pStmt)==SQLITE_ROW ){
        "SELECT name FROM sqlite_master "      tnum = sqlite3_column_int(pStmt, 0);
        "WHERE type='index' AND tbl_name LIKE shellstatic() "      isWO = sqlite3_column_int(pStmt, 1);
        "UNION ALL "    }
        "SELECT name FROM sqlite_temp_master "    sqlite3_finalize(pStmt);
        "WHERE type='index' AND tbl_name LIKE shellstatic() "    zSql = sqlite3_mprintf("PRAGMA index_xinfo='%q'", azArg[1]);
        "ORDER BY 1",    rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
        callback, &data, &zErrMsg    sqlite3_free(zSql);
      );    i = 0;
      zShellStatic = 0;    while( sqlite3_step(pStmt)==SQLITE_ROW ){
    }else{      char zLabel[20];
      raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");      const char *zCol = (const char*)sqlite3_column_text(pStmt,2);
       i++;
       if( zCol==0 ){
         if( sqlite3_column_int(pStmt,1)==-1 ){
           zCol = "_ROWID_";
         }else{
           sqlite3_snprintf(sizeof(zLabel),zLabel,"expr%d",i);
           zCol = zLabel;
         }
       }
       if( isWO && lenPK==0 && sqlite3_column_int(pStmt,5)==0 && zCollist ){
         lenPK = (int)strlen(zCollist);
       }
       if( zCollist==0 ){
         zCollist = sqlite3_mprintf("\"%w\"", zCol);
       }else{
         zCollist = sqlite3_mprintf("%z,\"%w\"", zCollist, zCol);
       }
     }
     sqlite3_finalize(pStmt);
     if( i==0 || tnum==0 ){
       utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]);
       rc = 1;        rc = 1;
         sqlite3_free(zCollist);
       goto meta_command_exit;        goto meta_command_exit;
     }      }
    if( zErrMsg ){    if( lenPK==0 ) lenPK = 100000;
      utf8_printf(stderr,"Error: %s\n", zErrMsg);    zSql = sqlite3_mprintf(
      sqlite3_free(zErrMsg);          "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%.*s))WITHOUT ROWID",
           azArg[2], zCollist, lenPK, zCollist);
     sqlite3_free(zCollist);
     rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum);
     if( rc==SQLITE_OK ){
       rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
       sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0);
       if( rc ){
         utf8_printf(stderr, "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db));
       }else{
         utf8_printf(stdout, "%s;\n", zSql);
         raw_printf(stdout,
           "WARNING: writing to an imposter table will corrupt the \"%s\" %s!\n",
           azArg[1], isWO ? "table" : "index"
         );
       }
     }else{
       raw_printf(stderr, "SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc);
       rc = 1;        rc = 1;
     }else if( rc != SQLITE_OK ){  
       raw_printf(stderr,  
                  "Error: querying sqlite_master and sqlite_temp_master\n");  
       rc = 1;  
     }      }
       sqlite3_free(zSql);
   }else    }else
   #endif /* !defined(SQLITE_OMIT_TEST_CONTROL) */
   
 #ifdef SQLITE_ENABLE_IOTRACE  #ifdef SQLITE_ENABLE_IOTRACE
   if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){    if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){
Line 3694  static int do_meta_command(char *zLine, ShellState *p) Line 18632  static int do_meta_command(char *zLine, ShellState *p)
     }      }
   }else    }else
 #endif  #endif
   
   if( c=='l' && n>=5 && strncmp(azArg[0], "limits", n)==0 ){    if( c=='l' && n>=5 && strncmp(azArg[0], "limits", n)==0 ){
     static const struct {      static const struct {
        const char *zLimitName;   /* Name of a limit */         const char *zLimitName;   /* Name of a limit */
Line 3753  static int do_meta_command(char *zLine, ShellState *p) Line 18692  static int do_meta_command(char *zLine, ShellState *p)
     }      }
   }else    }else
   
     if( c=='l' && n>2 && strncmp(azArg[0], "lint", n)==0 ){
       open_db(p, 0);
       lintDotCommand(p, azArg, nArg);
     }else
   
 #ifndef SQLITE_OMIT_LOAD_EXTENSION  #ifndef SQLITE_OMIT_LOAD_EXTENSION
   if( c=='l' && strncmp(azArg[0], "load", n)==0 ){    if( c=='l' && strncmp(azArg[0], "load", n)==0 ){
     const char *zFile, *zProc;      const char *zFile, *zProc;
Line 3781  static int do_meta_command(char *zLine, ShellState *p) Line 18725  static int do_meta_command(char *zLine, ShellState *p)
     }else{      }else{
       const char *zFile = azArg[1];        const char *zFile = azArg[1];
       output_file_close(p->pLog);        output_file_close(p->pLog);
      p->pLog = output_file_open(zFile);      p->pLog = output_file_open(zFile, 0);
     }      }
   }else    }else
   
   if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){    if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){
     const char *zMode = nArg>=2 ? azArg[1] : "";      const char *zMode = nArg>=2 ? azArg[1] : "";
    int n2 = (int)strlen(zMode);    int n2 = strlen30(zMode);
     int c2 = zMode[0];      int c2 = zMode[0];
     if( c2=='l' && n2>2 && strncmp(azArg[1],"lines",n2)==0 ){      if( c2=='l' && n2>2 && strncmp(azArg[1],"lines",n2)==0 ){
       p->mode = MODE_Line;        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( c2=='c' && strncmp(azArg[1],"columns",n2)==0 ){
       p->mode = MODE_Column;        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 ){      }else if( c2=='l' && n2>2 && strncmp(azArg[1],"list",n2)==0 ){
       p->mode = MODE_List;        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( c2=='h' && strncmp(azArg[1],"html",n2)==0 ){
       p->mode = MODE_Html;        p->mode = MODE_Html;
     }else if( c2=='t' && strncmp(azArg[1],"tcl",n2)==0 ){      }else if( c2=='t' && strncmp(azArg[1],"tcl",n2)==0 ){
       p->mode = MODE_Tcl;        p->mode = MODE_Tcl;
       sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Space);        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( c2=='c' && strncmp(azArg[1],"csv",n2)==0 ){
       p->mode = MODE_Csv;        p->mode = MODE_Csv;
       sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);        sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
Line 3810  static int do_meta_command(char *zLine, ShellState *p) Line 18762  static int do_meta_command(char *zLine, ShellState *p)
     }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){      }else if( c2=='i' && strncmp(azArg[1],"insert",n2)==0 ){
       p->mode = MODE_Insert;        p->mode = MODE_Insert;
       set_table_name(p, nArg>=3 ? azArg[2] : "table");        set_table_name(p, nArg>=3 ? azArg[2] : "table");
       }else if( c2=='q' && strncmp(azArg[1],"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( c2=='a' && strncmp(azArg[1],"ascii",n2)==0 ){
       p->mode = MODE_Ascii;        p->mode = MODE_Ascii;
       sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit);        sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit);
       sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);        sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
    }else {    }else if( c2=='m' && strncmp(azArg[1],"markdown",n2)==0 ){
       p->mode = MODE_Markdown;
     }else if( c2=='t' && strncmp(azArg[1],"table",n2)==0 ){
       p->mode = MODE_Table;
     }else if( c2=='b' && strncmp(azArg[1],"box",n2)==0 ){
       p->mode = MODE_Box;
     }else if( c2=='j' && strncmp(azArg[1],"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: "        raw_printf(stderr, "Error: mode should be one of: "
         "ascii column csv html insert line list tabs tcl\n");         "ascii box column csv html insert json line list markdown "
          "quote table tabs tcl\n");
       rc = 1;        rc = 1;
     }      }
     p->cMode = p->mode;      p->cMode = p->mode;
Line 3832  static int do_meta_command(char *zLine, ShellState *p) Line 18799  static int do_meta_command(char *zLine, ShellState *p)
     }      }
   }else    }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 ){    if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
    sqlite3 *savedDb = p->db;    char *zNewFilename = 0;  /* Name of the database file to open */
    const char *zSavedFilename = p->zDbFilename;    int iName = 1;           /* Index in azArg[] of the filename */
    char *zNewFilename = 0;    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->db = 0;
    if( nArg>=2 ) zNewFilename = sqlite3_mprintf("%s", azArg[1]);    p->zDbFilename = 0;
    p->zDbFilename = zNewFilename;    sqlite3_free(p->zFreeOnClose);
    open_db(p, 1);    p->zFreeOnClose = 0;
    if( p->db!=0 ){    p->openMode = SHELL_OPEN_UNSPEC;
      session_close_all(p);    p->openFlags = 0;
      sqlite3_close(savedDb);    p->szMax = 0;
      sqlite3_free(p->zFreeOnClose);    /* Check for command-line arguments */
      p->zFreeOnClose = zNewFilename;    for(iName=1; iName<nArg; iName++){
    }else{      const char *z = azArg[iName];
      sqlite3_free(zNewFilename);      if( optionMatch(z,"new") ){
      p->db = savedDb;        newFlag = 1;
      p->zDbFilename = zSavedFilename;#ifdef SQLITE_HAVE_ZLIB
       }else if( optionMatch(z, "zip") ){
         p->openMode = SHELL_OPEN_ZIPFILE;
 #endif
       }else if( optionMatch(z, "append") ){
         p->openMode = SHELL_OPEN_APPENDVFS;
       }else if( optionMatch(z, "readonly") ){
         p->openMode = SHELL_OPEN_READONLY;
       }else if( optionMatch(z, "nofollow") ){
         p->openFlags |= SQLITE_OPEN_NOFOLLOW;
 #ifdef SQLITE_ENABLE_DESERIALIZE
       }else if( optionMatch(z, "deserialize") ){
         p->openMode = SHELL_OPEN_DESERIALIZE;
       }else if( optionMatch(z, "hexdb") ){
         p->openMode = SHELL_OPEN_HEXDB;
       }else if( optionMatch(z, "maxsize") && iName+1<nArg ){
         p->szMax = integerValue(azArg[++iName]);
 #endif /* SQLITE_ENABLE_DESERIALIZE */
       }else if( z[0]=='-' ){
         utf8_printf(stderr, "unknown option: %s\n", z);
         rc = 1;
         goto meta_command_exit;
       }else if( zNewFilename ){
         utf8_printf(stderr, "extra argument: \"%s\"\n", z);
         rc = 1;
         goto meta_command_exit;
       }else{
         zNewFilename = sqlite3_mprintf("%s", z);
       }
     }      }
       /* If a filename is specified, try to open it first */
       if( zNewFilename || p->openMode==SHELL_OPEN_HEXDB ){
         if( newFlag ) shellDeleteFile(zNewFilename);
         p->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;
         }
       }
       if( p->db==0 ){
         /* As a fall-back open a TEMP database */
         p->zDbFilename = 0;
         open_db(p, 0);
       }
   }else    }else
   
  if( c=='o'  if( (c=='o'
   && (strncmp(azArg[0], "output", n)==0 || strncmp(azArg[0], "once", n)==0)        && (strncmp(azArg[0], "output", n)==0||strncmp(azArg[0], "once", n)==0))
    || (c=='e' && n==5 && strcmp(azArg[0],"excel")==0)
   ){    ){
    const char *zFile = nArg>=2 ? azArg[1] : "stdout";    char *zFile = 0;
    if( nArg>2 ){    int bTxtMode = 0;
      utf8_printf(stderr, "Usage: .%s FILE\n", azArg[0]);    int i;
      rc = 1;    int eMode = 0;
      goto meta_command_exit;    int bBOM = 0;
     int bOnce = 0;  /* 0: .output, 1: .once, 2: .excel */
 
     if( c=='e' ){
       eMode = 'x';
       bOnce = 2;
     }else if( strncmp(azArg[0],"once",n)==0 ){
       bOnce = 1;
     }      }
    if( n>1 && strncmp(azArg[0], "once", n)==0 ){    for(i=1; i<nArg; i++){
      if( nArg<2 ){      char *z = azArg[i];
        raw_printf(stderr, "Usage: .once FILE\n");      if( z[0]=='-' ){
         if( z[1]=='-' ) z++;
         if( strcmp(z,"-bom")==0 ){
           bBOM = 1;
         }else if( c!='e' && strcmp(z,"-x")==0 ){
           eMode = 'x';  /* spreadsheet */
         }else if( c!='e' && strcmp(z,"-e")==0 ){
           eMode = 'e';  /* text editor */
         }else{
           utf8_printf(p->out, "ERROR: unknown option: \"%s\".  Usage:\n",
                       azArg[i]);
           showHelp(p->out, azArg[0]);
           rc = 1;
           goto meta_command_exit;
         }
       }else if( zFile==0 && eMode!='e' && eMode!='x' ){
         zFile = sqlite3_mprintf("%s", z);
         if( zFile[0]=='|' ){
           while( i+1<nArg ) zFile = sqlite3_mprintf("%z %s", zFile, azArg[++i]);
           break;
         }
       }else{
         utf8_printf(p->out,"ERROR: extra parameter: \"%s\".  Usage:\n",
                     azArg[i]);
         showHelp(p->out, azArg[0]);
         rc = 1;          rc = 1;
           sqlite3_free(zFile);
         goto meta_command_exit;          goto meta_command_exit;
       }        }
       }
       if( zFile==0 ) zFile = sqlite3_mprintf("stdout");
       if( bOnce ){
       p->outCount = 2;        p->outCount = 2;
     }else{      }else{
       p->outCount = 0;        p->outCount = 0;
     }      }
     output_reset(p);      output_reset(p);
   #ifndef SQLITE_NOHAVE_SYSTEM
       if( eMode=='e' || eMode=='x' ){
         p->doXdgOpen = 1;
         outputModePush(p);
         if( eMode=='x' ){
           /* spreadsheet mode.  Output as CSV. */
           newTempFile(p, "csv");
           ShellClearFlag(p, SHFLG_Echo);
           p->mode = MODE_Csv;
           sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
           sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
         }else{
           /* text editor mode */
           newTempFile(p, "txt");
           bTxtMode = 1;
         }
         sqlite3_free(zFile);
         zFile = sqlite3_mprintf("%s", p->zTempFile);
       }
   #endif /* SQLITE_NOHAVE_SYSTEM */
     if( zFile[0]=='|' ){      if( zFile[0]=='|' ){
 #ifdef SQLITE_OMIT_POPEN  #ifdef SQLITE_OMIT_POPEN
       raw_printf(stderr, "Error: pipes are not supported in this OS\n");        raw_printf(stderr, "Error: pipes are not supported in this OS\n");
Line 3884  static int do_meta_command(char *zLine, ShellState *p) Line 18983  static int do_meta_command(char *zLine, ShellState *p)
         p->out = stdout;          p->out = stdout;
         rc = 1;          rc = 1;
       }else{        }else{
           if( bBOM ) fprintf(p->out,"\357\273\277");
         sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);          sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
       }        }
 #endif  #endif
     }else{      }else{
      p->out = output_file_open(zFile);      p->out = output_file_open(zFile, bTxtMode);
       if( p->out==0 ){        if( p->out==0 ){
         if( strcmp(zFile,"off")!=0 ){          if( strcmp(zFile,"off")!=0 ){
           utf8_printf(stderr,"Error: cannot write to \"%s\"\n", zFile);            utf8_printf(stderr,"Error: cannot write to \"%s\"\n", zFile);
Line 3896  static int do_meta_command(char *zLine, ShellState *p) Line 18996  static int do_meta_command(char *zLine, ShellState *p)
         p->out = stdout;          p->out = stdout;
         rc = 1;          rc = 1;
       } else {        } else {
           if( bBOM ) fprintf(p->out,"\357\273\277");
         sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);          sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
       }        }
     }      }
       sqlite3_free(zFile);
   }else    }else
   
     if( c=='p' && n>=3 && strncmp(azArg[0], "parameter", n)==0 ){
       open_db(p,0);
       if( nArg<=1 ) goto parameter_syntax_error;
   
       /* .parameter clear
       ** Clear all bind parameters by dropping the TEMP table that holds them.
       */
       if( nArg==2 && strcmp(azArg[1],"clear")==0 ){
         sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp.sqlite_parameters;",
                      0, 0, 0);
       }else
   
       /* .parameter list
       ** List all bind parameters.
       */
       if( nArg==2 && strcmp(azArg[1],"list")==0 ){
         sqlite3_stmt *pStmt = 0;
         int rx;
         int len = 0;
         rx = sqlite3_prepare_v2(p->db,
                "SELECT max(length(key)) "
                "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
         if( rx==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
           len = sqlite3_column_int(pStmt, 0);
           if( len>40 ) len = 40;
         }
         sqlite3_finalize(pStmt);
         pStmt = 0;
         if( len ){
           rx = sqlite3_prepare_v2(p->db,
                "SELECT key, quote(value) "
                "FROM temp.sqlite_parameters;", -1, &pStmt, 0);
           while( sqlite3_step(pStmt)==SQLITE_ROW ){
             utf8_printf(p->out, "%-*s %s\n", len, sqlite3_column_text(pStmt,0),
                         sqlite3_column_text(pStmt,1));
           }
           sqlite3_finalize(pStmt);
         }
       }else
   
       /* .parameter init
       ** Make sure the TEMP table used to hold bind parameters exists.
       ** Create it if necessary.
       */
       if( nArg==2 && strcmp(azArg[1],"init")==0 ){
         bind_table_init(p);
       }else
   
       /* .parameter set NAME VALUE
       ** Set or reset a bind parameter.  NAME should be the full parameter
       ** name exactly as it appears in the query.  (ex: $abc, @def).  The
       ** VALUE can be in either SQL literal notation, or if not it will be
       ** understood to be a text string.
       */
       if( nArg==4 && strcmp(azArg[1],"set")==0 ){
         int rx;
         char *zSql;
         sqlite3_stmt *pStmt;
         const char *zKey = azArg[2];
         const char *zValue = azArg[3];
         bind_table_init(p);
         zSql = sqlite3_mprintf(
                     "REPLACE INTO temp.sqlite_parameters(key,value)"
                     "VALUES(%Q,%s);", zKey, zValue);
         if( zSql==0 ) shell_out_of_memory();
         pStmt = 0;
         rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
         sqlite3_free(zSql);
         if( rx!=SQLITE_OK ){
           sqlite3_finalize(pStmt);
           pStmt = 0;
           zSql = sqlite3_mprintf(
                      "REPLACE INTO temp.sqlite_parameters(key,value)"
                      "VALUES(%Q,%Q);", zKey, zValue);
           if( zSql==0 ) shell_out_of_memory();
           rx = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
           sqlite3_free(zSql);
           if( rx!=SQLITE_OK ){
             utf8_printf(p->out, "Error: %s\n", sqlite3_errmsg(p->db));
             sqlite3_finalize(pStmt);
             pStmt = 0;
             rc = 1;
           }
         }
         sqlite3_step(pStmt);
         sqlite3_finalize(pStmt);
       }else
   
       /* .parameter unset NAME
       ** Remove the NAME binding from the parameter binding table, if it
       ** exists.
       */
       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();
         sqlite3_exec(p->db, zSql, 0, 0, 0);
         sqlite3_free(zSql);
       }else
       /* If no command name matches, show a syntax error */
       parameter_syntax_error:
       showHelp(p->out, "parameter");
     }else
   
   if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){    if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){
     int i;      int i;
     for(i=1; i<nArg; i++){      for(i=1; i<nArg; i++){
Line 3910  static int do_meta_command(char *zLine, ShellState *p) Line 19116  static int do_meta_command(char *zLine, ShellState *p)
     raw_printf(p->out, "\n");      raw_printf(p->out, "\n");
   }else    }else
   
   #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
     if( c=='p' && n>=3 && strncmp(azArg[0], "progress", n)==0 ){
       int i;
       int nn = 0;
       p->flgProgress = 0;
       p->mxProgress = 0;
       p->nProgress = 0;
       for(i=1; i<nArg; i++){
         const char *z = azArg[i];
         if( z[0]=='-' ){
           z++;
           if( z[0]=='-' ) z++;
           if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){
             p->flgProgress |= SHELL_PROGRESS_QUIET;
             continue;
           }
           if( strcmp(z,"reset")==0 ){
             p->flgProgress |= SHELL_PROGRESS_RESET;
             continue;
           }
           if( strcmp(z,"once")==0 ){
             p->flgProgress |= SHELL_PROGRESS_ONCE;
             continue;
           }
           if( strcmp(z,"limit")==0 ){
             if( i+1>=nArg ){
               utf8_printf(stderr, "Error: missing argument on --limit\n");
               rc = 1;
               goto meta_command_exit;
             }else{
               p->mxProgress = (int)integerValue(azArg[++i]);
             }
             continue;
           }
           utf8_printf(stderr, "Error: unknown option: \"%s\"\n", azArg[i]);
           rc = 1;
           goto meta_command_exit;
         }else{
           nn = (int)integerValue(z);
         }
       }
       open_db(p, 0);
       sqlite3_progress_handler(p->db, nn, progress_handler, p);
     }else
   #endif /* SQLITE_OMIT_PROGRESS_CALLBACK */
   
   if( c=='p' && strncmp(azArg[0], "prompt", n)==0 ){    if( c=='p' && strncmp(azArg[0], "prompt", n)==0 ){
     if( nArg >= 2) {      if( nArg >= 2) {
       strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);        strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
Line 3924  static int do_meta_command(char *zLine, ShellState *p) Line 19176  static int do_meta_command(char *zLine, ShellState *p)
   }else    }else
   
   if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){    if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){
    FILE *alt;    FILE *inSaved = p->in;
     int savedLineno = p->lineno;
     if( nArg!=2 ){      if( nArg!=2 ){
       raw_printf(stderr, "Usage: .read FILE\n");        raw_printf(stderr, "Usage: .read FILE\n");
       rc = 1;        rc = 1;
       goto meta_command_exit;        goto meta_command_exit;
     }      }
    alt = fopen(azArg[1], "rb");    if( azArg[1][0]=='|' ){
    if( alt==0 ){#ifdef SQLITE_OMIT_POPEN
       raw_printf(stderr, "Error: pipes are not supported in this OS\n");
       rc = 1;
       p->out = stdout;
 #else
       p->in = popen(azArg[1]+1, "r");
       if( p->in==0 ){
         utf8_printf(stderr, "Error: cannot open \"%s\"\n", azArg[1]);
         rc = 1;
       }else{
         rc = process_input(p);
         pclose(p->in);
       }
 #endif
     }else if( notNormalFile(azArg[1]) || (p->in = fopen(azArg[1], "rb"))==0 ){
       utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);        utf8_printf(stderr,"Error: cannot open \"%s\"\n", azArg[1]);
       rc = 1;        rc = 1;
     }else{      }else{
      rc = process_input(p, alt);      rc = process_input(p);
      fclose(alt);      fclose(p->in);
     }      }
       p->in = inSaved;
       p->lineno = savedLineno;
   }else    }else
   
   if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 ){    if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 ){
Line 3961  static int do_meta_command(char *zLine, ShellState *p) Line 19230  static int do_meta_command(char *zLine, ShellState *p)
     rc = sqlite3_open(zSrcFile, &pSrc);      rc = sqlite3_open(zSrcFile, &pSrc);
     if( rc!=SQLITE_OK ){      if( rc!=SQLITE_OK ){
       utf8_printf(stderr, "Error: cannot open \"%s\"\n", zSrcFile);        utf8_printf(stderr, "Error: cannot open \"%s\"\n", zSrcFile);
      sqlite3_close(pSrc);      close_db(pSrc);
       return 1;        return 1;
     }      }
     open_db(p, 0);      open_db(p, 0);
     pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main");      pBackup = sqlite3_backup_init(p->db, zDb, pSrc, "main");
     if( pBackup==0 ){      if( pBackup==0 ){
       utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));        utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
      sqlite3_close(pSrc);      close_db(pSrc);
       return 1;        return 1;
     }      }
     while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK      while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK
Line 3988  static int do_meta_command(char *zLine, ShellState *p) Line 19257  static int do_meta_command(char *zLine, ShellState *p)
       utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));        utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
       rc = 1;        rc = 1;
     }      }
    sqlite3_close(pSrc);    close_db(pSrc);
   }else    }else
   
   
   if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){    if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){
     if( nArg==2 ){      if( nArg==2 ){
      p->scanstatsOn = booleanValue(azArg[1]);      p->scanstatsOn = (u8)booleanValue(azArg[1]);
 #ifndef SQLITE_ENABLE_STMT_SCANSTATUS  #ifndef SQLITE_ENABLE_STMT_SCANSTATUS
       raw_printf(stderr, "Warning: .scanstats not available in this build.\n");        raw_printf(stderr, "Warning: .scanstats not available in this build.\n");
 #endif  #endif
Line 4005  static int do_meta_command(char *zLine, ShellState *p) Line 19273  static int do_meta_command(char *zLine, ShellState *p)
   }else    }else
   
   if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){    if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
       ShellText sSelect;
     ShellState data;      ShellState data;
     char *zErrMsg = 0;      char *zErrMsg = 0;
       const char *zDiv = "(";
       const char *zName = 0;
       int iSchema = 0;
       int bDebug = 0;
       int bNoSystemTabs = 0;
       int ii;
   
     open_db(p, 0);      open_db(p, 0);
     memcpy(&data, p, sizeof(data));      memcpy(&data, p, sizeof(data));
     data.showHeader = 0;      data.showHeader = 0;
     data.cMode = data.mode = MODE_Semi;      data.cMode = data.mode = MODE_Semi;
    if( nArg>=2 && optionMatch(azArg[1], "indent") ){    initText(&sSelect);
      data.cMode = data.mode = MODE_Pretty;    for(ii=1; ii<nArg; ii++){
      nArg--;      if( optionMatch(azArg[ii],"indent") ){
      if( nArg==2 ) azArg[1] = azArg[2];        data.cMode = data.mode = MODE_Pretty;
       }else if( optionMatch(azArg[ii],"debug") ){
         bDebug = 1;
       }else if( optionMatch(azArg[ii],"nosys") ){
         bNoSystemTabs = 1;
       }else if( azArg[ii][0]=='-' ){
         utf8_printf(stderr, "Unknown option: \"%s\"\n", azArg[ii]);
         rc = 1;
         goto meta_command_exit;
       }else if( zName==0 ){
         zName = azArg[ii];
       }else{
         raw_printf(stderr, "Usage: .schema ?--indent? ?--nosys? ?LIKE-PATTERN?\n");
         rc = 1;
         goto meta_command_exit;
       }
     }      }
    if( nArg==2 && azArg[1][0]!='-' ){    if( zName!=0 ){
      int i;      int isSchema = sqlite3_strlike(zName, "sqlite_master", '\\')==0
      for(i=0; azArg[1][i]; i++) azArg[1][i] = ToLower(azArg[1][i]);                  || sqlite3_strlike(zName, "sqlite_schema", '\\')==0
      if( strcmp(azArg[1],"sqlite_master")==0 ){                  || sqlite3_strlike(zName,"sqlite_temp_master", '\\')==0
                   || sqlite3_strlike(zName,"sqlite_temp_schema", '\\')==0;
       if( isSchema ){
         char *new_argv[2], *new_colv[2];          char *new_argv[2], *new_colv[2];
        new_argv[0] = "CREATE TABLE sqlite_master (\n"        new_argv[0] = sqlite3_mprintf(
                       "CREATE TABLE %s (\n"
                       "  type text,\n"                        "  type text,\n"
                       "  name text,\n"                        "  name text,\n"
                       "  tbl_name text,\n"                        "  tbl_name text,\n"
                       "  rootpage integer,\n"                        "  rootpage integer,\n"
                       "  sql text\n"                        "  sql text\n"
                      ")";                      ")", zName);
         new_argv[1] = 0;          new_argv[1] = 0;
         new_colv[0] = "sql";          new_colv[0] = "sql";
         new_colv[1] = 0;          new_colv[1] = 0;
         callback(&data, 1, new_argv, new_colv);          callback(&data, 1, new_argv, new_colv);
        rc = SQLITE_OK;        sqlite3_free(new_argv[0]);
      }else if( strcmp(azArg[1],"sqlite_temp_master")==0 ){      }
        char *new_argv[2], *new_colv[2];    }
        new_argv[0] = "CREATE TEMP TABLE sqlite_temp_master (\n"    if( zDiv ){
                      "  type text,\n"      sqlite3_stmt *pStmt = 0;
                      "  name text,\n"      rc = sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list",
                      "  tbl_name text,\n"                              -1, &pStmt, 0);
                      "  rootpage integer,\n"      if( rc ){
                      "  sql text\n"        utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
                      ")";        sqlite3_finalize(pStmt);
        new_argv[1] = 0;        rc = 1;
        new_colv[0] = "sql";        goto meta_command_exit;
        new_colv[1] = 0;      }
        callback(&data, 1, new_argv, new_colv);      appendText(&sSelect, "SELECT sql FROM", 0);
        rc = SQLITE_OK;      iSchema = 0;
       while( sqlite3_step(pStmt)==SQLITE_ROW ){
         const char *zDb = (const char*)sqlite3_column_text(pStmt, 0);
         char zScNum[30];
         sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema);
         appendText(&sSelect, zDiv, 0);
         zDiv = " UNION ALL ";
         appendText(&sSelect, "SELECT shell_add_schema(sql,", 0);
         if( sqlite3_stricmp(zDb, "main")!=0 ){
           appendText(&sSelect, zDb, '\'');
         }else{
           appendText(&sSelect, "NULL", 0);
         }
         appendText(&sSelect, ",name) AS sql, type, tbl_name, name, rowid,", 0);
         appendText(&sSelect, zScNum, 0);
         appendText(&sSelect, " AS snum, ", 0);
         appendText(&sSelect, zDb, '\'');
         appendText(&sSelect, " AS sname FROM ", 0);
         appendText(&sSelect, zDb, quoteChar(zDb));
         appendText(&sSelect, ".sqlite_schema", 0);
       }
       sqlite3_finalize(pStmt);
 #ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS
       if( zName ){
         appendText(&sSelect,
            " UNION ALL SELECT shell_module_schema(name),"
            " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list",
         0);
       }
 #endif
       appendText(&sSelect, ") WHERE ", 0);
       if( zName ){
         char *zQarg = sqlite3_mprintf("%Q", zName);
         int bGlob = strchr(zName, '*') != 0 || strchr(zName, '?') != 0 ||
                     strchr(zName, '[') != 0;
         if( strchr(zName, '.') ){
           appendText(&sSelect, "lower(printf('%s.%s',sname,tbl_name))", 0);
         }else{
           appendText(&sSelect, "lower(tbl_name)", 0);
         }
         appendText(&sSelect, bGlob ? " GLOB " : " LIKE ", 0);
         appendText(&sSelect, zQarg, 0);
         if( !bGlob ){
           appendText(&sSelect, " ESCAPE '\\' ", 0);
         }
         appendText(&sSelect, " AND ", 0);
         sqlite3_free(zQarg);
       }
       if( bNoSystemTabs ){
         appendText(&sSelect, "name NOT LIKE 'sqlite_%%' AND ", 0);
       }
       appendText(&sSelect, "sql IS NOT NULL"
                            " ORDER BY snum, rowid", 0);
       if( bDebug ){
         utf8_printf(p->out, "SQL: %s;\n", sSelect.z);
       }else{        }else{
        zShellStatic = azArg[1];        rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg);
        rc = sqlite3_exec(p->db, 
          "SELECT sql FROM " 
          "  (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" 
          "     FROM sqlite_master UNION ALL" 
          "   SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " 
          "WHERE lower(tbl_name) LIKE shellstatic()" 
          "  AND type!='meta' AND sql NOTNULL " 
          "ORDER BY rowid", 
          callback, &data, &zErrMsg); 
        zShellStatic = 0; 
       }        }
    }else if( nArg==1 ){      freeText(&sSelect);
      rc = sqlite3_exec(p->db, 
         "SELECT sql FROM " 
         "  (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x" 
         "     FROM sqlite_master UNION ALL" 
         "   SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) " 
         "WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' " 
         "ORDER BY rowid", 
         callback, &data, &zErrMsg 
      ); 
    }else{ 
      raw_printf(stderr, "Usage: .schema ?--indent? ?LIKE-PATTERN?\n"); 
      rc = 1; 
      goto meta_command_exit; 
     }      }
     if( zErrMsg ){      if( zErrMsg ){
       utf8_printf(stderr,"Error: %s\n", zErrMsg);        utf8_printf(stderr,"Error: %s\n", zErrMsg);
Line 4087  static int do_meta_command(char *zLine, ShellState *p) Line 19412  static int do_meta_command(char *zLine, ShellState *p)
     }      }
   }else    }else
   
 #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)  
   if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){    if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){
    sqlite3SelectTrace = integerValue(azArg[1]);    unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
     sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &x);
   }else    }else
 #endif  
   
 #if defined(SQLITE_ENABLE_SESSION)  #if defined(SQLITE_ENABLE_SESSION)
   if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){    if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){
Line 4144  static int do_meta_command(char *zLine, ShellState *p) Line 19468  static int do_meta_command(char *zLine, ShellState *p)
       if( pSession->p==0 ) goto session_not_open;        if( pSession->p==0 ) goto session_not_open;
       out = fopen(azCmd[1], "wb");        out = fopen(azCmd[1], "wb");
       if( out==0 ){        if( out==0 ){
        utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n", azCmd[1]);        utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n",
                     azCmd[1]);
       }else{        }else{
         int szChng;          int szChng;
         void *pChng;          void *pChng;
Line 4285  static int do_meta_command(char *zLine, ShellState *p) Line 19610  static int do_meta_command(char *zLine, ShellState *p)
     }else      }else
     /* If no command name matches, show a syntax error */      /* If no command name matches, show a syntax error */
     session_syntax_error:      session_syntax_error:
    session_help(p);    showHelp(p->out, "session");
   }else    }else
 #endif  #endif
   
Line 4312  static int do_meta_command(char *zLine, ShellState *p) Line 19637  static int do_meta_command(char *zLine, ShellState *p)
   }else    }else
 #endif  #endif
   
     if( c=='s' && n>=4 && strncmp(azArg[0],"selftest",n)==0 ){
       int bIsInit = 0;         /* True to initialize the SELFTEST table */
       int bVerbose = 0;        /* Verbose output */
       int bSelftestExists;     /* True if SELFTEST already exists */
       int i, k;                /* Loop counters */
       int nTest = 0;           /* Number of tests runs */
       int nErr = 0;            /* Number of errors seen */
       ShellText str;           /* Answer for a query */
       sqlite3_stmt *pStmt = 0; /* Query against the SELFTEST table */
   
       open_db(p,0);
       for(i=1; i<nArg; i++){
         const char *z = azArg[i];
         if( z[0]=='-' && z[1]=='-' ) z++;
         if( strcmp(z,"-init")==0 ){
           bIsInit = 1;
         }else
         if( strcmp(z,"-v")==0 ){
           bVerbose++;
         }else
         {
           utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
                       azArg[i], azArg[0]);
           raw_printf(stderr, "Should be one of: --init -v\n");
           rc = 1;
           goto meta_command_exit;
         }
       }
       if( sqlite3_table_column_metadata(p->db,"main","selftest",0,0,0,0,0,0)
              != SQLITE_OK ){
         bSelftestExists = 0;
       }else{
         bSelftestExists = 1;
       }
       if( bIsInit ){
         createSelftestTable(p);
         bSelftestExists = 1;
       }
       initText(&str);
       appendText(&str, "x", 0);
       for(k=bSelftestExists; k>=0; k--){
         if( k==1 ){
           rc = sqlite3_prepare_v2(p->db,
               "SELECT tno,op,cmd,ans FROM selftest ORDER BY tno",
               -1, &pStmt, 0);
         }else{
           rc = sqlite3_prepare_v2(p->db,
             "VALUES(0,'memo','Missing SELFTEST table - default checks only',''),"
             "      (1,'run','PRAGMA integrity_check','ok')",
             -1, &pStmt, 0);
         }
         if( rc ){
           raw_printf(stderr, "Error querying the selftest table\n");
           rc = 1;
           sqlite3_finalize(pStmt);
           goto meta_command_exit;
         }
         for(i=1; sqlite3_step(pStmt)==SQLITE_ROW; i++){
           int tno = sqlite3_column_int(pStmt, 0);
           const char *zOp = (const char*)sqlite3_column_text(pStmt, 1);
           const char *zSql = (const char*)sqlite3_column_text(pStmt, 2);
           const char *zAns = (const char*)sqlite3_column_text(pStmt, 3);
   
           k = 0;
           if( bVerbose>0 ){
             char *zQuote = sqlite3_mprintf("%q", zSql);
             printf("%d: %s %s\n", tno, zOp, zSql);
             sqlite3_free(zQuote);
           }
           if( strcmp(zOp,"memo")==0 ){
             utf8_printf(p->out, "%s\n", zSql);
           }else
           if( strcmp(zOp,"run")==0 ){
             char *zErrMsg = 0;
             str.n = 0;
             str.z[0] = 0;
             rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg);
             nTest++;
             if( bVerbose ){
               utf8_printf(p->out, "Result: %s\n", str.z);
             }
             if( rc || zErrMsg ){
               nErr++;
               rc = 1;
               utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg);
               sqlite3_free(zErrMsg);
             }else if( strcmp(zAns,str.z)!=0 ){
               nErr++;
               rc = 1;
               utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns);
               utf8_printf(p->out, "%d:      Got: [%s]\n", tno, str.z);
             }
           }else
           {
             utf8_printf(stderr,
               "Unknown operation \"%s\" on selftest line %d\n", zOp, tno);
             rc = 1;
             break;
           }
         } /* End loop over rows of content from SELFTEST */
         sqlite3_finalize(pStmt);
       } /* End loop over k */
       freeText(&str);
       utf8_printf(p->out, "%d errors out of %d tests\n", nErr, nTest);
     }else
   
   if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){    if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){
     if( nArg<2 || nArg>3 ){      if( nArg<2 || nArg>3 ){
       raw_printf(stderr, "Usage: .separator COL ?ROW?\n");        raw_printf(stderr, "Usage: .separator COL ?ROW?\n");
Line 4327  static int do_meta_command(char *zLine, ShellState *p) Line 19758  static int do_meta_command(char *zLine, ShellState *p)
     }      }
   }else    }else
   
     if( c=='s' && n>=4 && strncmp(azArg[0],"sha3sum",n)==0 ){
       const char *zLike = 0;   /* Which table to checksum. 0 means everything */
       int i;                   /* Loop counter */
       int bSchema = 0;         /* Also hash the schema */
       int bSeparate = 0;       /* Hash each table separately */
       int iSize = 224;         /* Hash algorithm to use */
       int bDebug = 0;          /* Only show the query that would have run */
       sqlite3_stmt *pStmt;     /* For querying tables names */
       char *zSql;              /* SQL to be run */
       char *zSep;              /* Separator */
       ShellText sSql;          /* Complete SQL for the query to run the hash */
       ShellText sQuery;        /* Set of queries used to read all content */
       open_db(p, 0);
       for(i=1; i<nArg; i++){
         const char *z = azArg[i];
         if( z[0]=='-' ){
           z++;
           if( z[0]=='-' ) z++;
           if( strcmp(z,"schema")==0 ){
             bSchema = 1;
           }else
           if( strcmp(z,"sha3-224")==0 || strcmp(z,"sha3-256")==0
            || strcmp(z,"sha3-384")==0 || strcmp(z,"sha3-512")==0
           ){
             iSize = atoi(&z[5]);
           }else
           if( strcmp(z,"debug")==0 ){
             bDebug = 1;
           }else
           {
             utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
                         azArg[i], azArg[0]);
             showHelp(p->out, azArg[0]);
             rc = 1;
             goto meta_command_exit;
           }
         }else if( zLike ){
           raw_printf(stderr, "Usage: .sha3sum ?OPTIONS? ?LIKE-PATTERN?\n");
           rc = 1;
           goto meta_command_exit;
         }else{
           zLike = z;
           bSeparate = 1;
           if( sqlite3_strlike("sqlite\\_%", zLike, '\\')==0 ) bSchema = 1;
         }
       }
       if( bSchema ){
         zSql = "SELECT lower(name) FROM sqlite_schema"
                " WHERE type='table' AND coalesce(rootpage,0)>1"
                " UNION ALL SELECT 'sqlite_schema'"
                " ORDER BY 1 collate nocase";
       }else{
         zSql = "SELECT lower(name) FROM sqlite_schema"
                " WHERE type='table' AND coalesce(rootpage,0)>1"
                " AND name NOT LIKE 'sqlite_%'"
                " ORDER BY 1 collate nocase";
       }
       sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
       initText(&sQuery);
       initText(&sSql);
       appendText(&sSql, "WITH [sha3sum$query](a,b) AS(",0);
       zSep = "VALUES(";
       while( SQLITE_ROW==sqlite3_step(pStmt) ){
         const char *zTab = (const char*)sqlite3_column_text(pStmt,0);
         if( zLike && sqlite3_strlike(zLike, zTab, 0)!=0 ) continue;
         if( strncmp(zTab, "sqlite_",7)!=0 ){
           appendText(&sQuery,"SELECT * FROM ", 0);
           appendText(&sQuery,zTab,'"');
           appendText(&sQuery," NOT INDEXED;", 0);
         }else if( strcmp(zTab, "sqlite_schema")==0 ){
           appendText(&sQuery,"SELECT type,name,tbl_name,sql FROM sqlite_schema"
                              " ORDER BY name;", 0);
         }else if( strcmp(zTab, "sqlite_sequence")==0 ){
           appendText(&sQuery,"SELECT name,seq FROM sqlite_sequence"
                              " ORDER BY name;", 0);
         }else if( strcmp(zTab, "sqlite_stat1")==0 ){
           appendText(&sQuery,"SELECT tbl,idx,stat FROM sqlite_stat1"
                              " ORDER BY tbl,idx;", 0);
         }else if( strcmp(zTab, "sqlite_stat4")==0 ){
           appendText(&sQuery, "SELECT * FROM ", 0);
           appendText(&sQuery, zTab, 0);
           appendText(&sQuery, " ORDER BY tbl, idx, rowid;\n", 0);
         }
         appendText(&sSql, zSep, 0);
         appendText(&sSql, sQuery.z, '\'');
         sQuery.n = 0;
         appendText(&sSql, ",", 0);
         appendText(&sSql, zTab, '\'');
         zSep = "),(";
       }
       sqlite3_finalize(pStmt);
       if( bSeparate ){
         zSql = sqlite3_mprintf(
             "%s))"
             " SELECT lower(hex(sha3_query(a,%d))) AS hash, b AS label"
             "   FROM [sha3sum$query]",
             sSql.z, iSize);
       }else{
         zSql = sqlite3_mprintf(
             "%s))"
             " SELECT lower(hex(sha3_query(group_concat(a,''),%d))) AS hash"
             "   FROM [sha3sum$query]",
             sSql.z, iSize);
       }
       freeText(&sQuery);
       freeText(&sSql);
       if( bDebug ){
         utf8_printf(p->out, "%s\n", zSql);
       }else{
         shell_exec(p, zSql, 0);
       }
       sqlite3_free(zSql);
     }else
   
   #ifndef SQLITE_NOHAVE_SYSTEM
   if( c=='s'    if( c=='s'
    && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)     && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
   ){    ){
Line 4346  static int do_meta_command(char *zLine, ShellState *p) Line 19892  static int do_meta_command(char *zLine, ShellState *p)
     sqlite3_free(zCmd);      sqlite3_free(zCmd);
     if( x ) raw_printf(stderr, "System command returns %d\n", x);      if( x ) raw_printf(stderr, "System command returns %d\n", x);
   }else    }else
   #endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
   
   if( c=='s' && strncmp(azArg[0], "show", n)==0 ){    if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
    static const char *azBool[] = { "off", "on", "full", "unk" };    static const char *azBool[] = { "off", "on", "trigger", "full"};
     const char *zOut;
     int i;      int i;
     if( nArg!=1 ){      if( nArg!=1 ){
       raw_printf(stderr, "Usage: .show\n");        raw_printf(stderr, "Usage: .show\n");
       rc = 1;        rc = 1;
       goto meta_command_exit;        goto meta_command_exit;
     }      }
    utf8_printf(p->out, "%12.12s: %s\n","echo", azBool[p->echoOn!=0]);    utf8_printf(p->out, "%12.12s: %s\n","echo",
                                   azBool[ShellHasFlag(p, SHFLG_Echo)]);
     utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]);      utf8_printf(p->out, "%12.12s: %s\n","eqp", azBool[p->autoEQP&3]);
     utf8_printf(p->out, "%12.12s: %s\n","explain",      utf8_printf(p->out, "%12.12s: %s\n","explain",
          p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off");           p->mode==MODE_Explain ? "on" : p->autoExplain ? "auto" : "off");
Line 4372  static int do_meta_command(char *zLine, ShellState *p) Line 19921  static int do_meta_command(char *zLine, ShellState *p)
     utf8_printf(p->out,"%12.12s: ", "rowseparator");      utf8_printf(p->out,"%12.12s: ", "rowseparator");
       output_c_string(p->out, p->rowSeparator);        output_c_string(p->out, p->rowSeparator);
       raw_printf(p->out, "\n");        raw_printf(p->out, "\n");
    utf8_printf(p->out, "%12.12s: %s\n","stats", azBool[p->statsOn!=0]);    switch( p->statsOn ){
       case 0:  zOut = "off";     break;
       default: zOut = "on";      break;
       case 2:  zOut = "stmt";    break;
       case 3:  zOut = "vmstep";  break;
     }
     utf8_printf(p->out, "%12.12s: %s\n","stats", zOut);
     utf8_printf(p->out, "%12.12s: ", "width");      utf8_printf(p->out, "%12.12s: ", "width");
    for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) {    for (i=0;i<p->nWidth;i++) {
       raw_printf(p->out, "%d ", p->colWidth[i]);        raw_printf(p->out, "%d ", p->colWidth[i]);
     }      }
     raw_printf(p->out, "\n");      raw_printf(p->out, "\n");
       utf8_printf(p->out, "%12.12s: %s\n", "filename",
                   p->zDbFilename ? p->zDbFilename : "");
   }else    }else
   
   if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){    if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){
     if( nArg==2 ){      if( nArg==2 ){
      p->statsOn = booleanValue(azArg[1]);      if( strcmp(azArg[1],"stmt")==0 ){
         p->statsOn = 2;
       }else if( strcmp(azArg[1],"vmstep")==0 ){
         p->statsOn = 3;
       }else{
         p->statsOn = (u8)booleanValue(azArg[1]);
       }
     }else if( nArg==1 ){      }else if( nArg==1 ){
       display_stats(p->db, p, 0);        display_stats(p->db, p, 0);
     }else{      }else{
      raw_printf(stderr, "Usage: .stats ?on|off?\n");      raw_printf(stderr, "Usage: .stats ?on|off|stmt|vmstep?\n");
       rc = 1;        rc = 1;
     }      }
   }else    }else
   
  if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 ){  if( (c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0)
    || (c=='i' && (strncmp(azArg[0], "indices", n)==0
                  || strncmp(azArg[0], "indexes", n)==0) )
   ){
     sqlite3_stmt *pStmt;      sqlite3_stmt *pStmt;
     char **azResult;      char **azResult;
     int nRow, nAlloc;      int nRow, nAlloc;
     char *zSql = 0;  
     int ii;      int ii;
       ShellText s;
       initText(&s);
     open_db(p, 0);      open_db(p, 0);
     rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);      rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
    if( rc ) return shellDatabaseError(p->db);    if( rc ){
       sqlite3_finalize(pStmt);
       return shellDatabaseError(p->db);
     }
   
    /* Create an SQL statement to query for the list of tables in the    if( nArg>2 && c=='i' ){
    ** main and all attached databases where the table name matches the      /* It is an historical accident that the .indexes command shows an error
    ** LIKE pattern bound to variable "?1". */      ** when called with the wrong number of arguments whereas the .tables
    zSql = sqlite3_mprintf(      ** command does not. */
        "SELECT name FROM sqlite_master"      raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");
        " WHERE type IN ('table','view')"      rc = 1;
        "   AND name NOT LIKE 'sqlite_%%'"      sqlite3_finalize(pStmt);
        "   AND name LIKE ?1");      goto meta_command_exit;
    while( zSql && sqlite3_step(pStmt)==SQLITE_ROW ){    }
     for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){
       const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1);        const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1);
      if( zDbName==0 || strcmp(zDbName,"main")==0 ) continue;      if( zDbName==0 ) continue;
      if( strcmp(zDbName,"temp")==0 ){      if( s.z && s.z[0] ) appendText(&s, " UNION ALL ", 0);
        zSql = sqlite3_mprintf(      if( sqlite3_stricmp(zDbName, "main")==0 ){
                 "%z UNION ALL "        appendText(&s, "SELECT name FROM ", 0);
                 "SELECT 'temp.' || name FROM sqlite_temp_master" 
                 " WHERE type IN ('table','view')" 
                 "   AND name NOT LIKE 'sqlite_%%'" 
                 "   AND name LIKE ?1", zSql); 
       }else{        }else{
        zSql = sqlite3_mprintf(        appendText(&s, "SELECT ", 0);
                 "%z UNION ALL "        appendText(&s, zDbName, '\'');
                 "SELECT '%q.' || name FROM \"%w\".sqlite_master"        appendText(&s, "||'.'||name FROM ", 0);
                 " WHERE type IN ('table','view')" 
                 "   AND name NOT LIKE 'sqlite_%%'" 
                 "   AND name LIKE ?1", zSql, zDbName, zDbName); 
       }        }
         appendText(&s, zDbName, '"');
         appendText(&s, ".sqlite_schema ", 0);
         if( c=='t' ){
           appendText(&s," WHERE type IN ('table','view')"
                         "   AND name NOT LIKE 'sqlite_%'"
                         "   AND name LIKE ?1", 0);
         }else{
           appendText(&s," WHERE type='index'"
                         "   AND tbl_name LIKE ?1", 0);
         }
     }      }
     rc = sqlite3_finalize(pStmt);      rc = sqlite3_finalize(pStmt);
    if( zSql && rc==SQLITE_OK ){    appendText(&s, " ORDER BY 1", 0);
      zSql = sqlite3_mprintf("%z ORDER BY 1", zSql);    rc = sqlite3_prepare_v2(p->db, s.z, -1, &pStmt, 0);
      if( zSql ) rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);    freeText(&s);
    } 
    sqlite3_free(zSql); 
    if( !zSql ) return shellNomemError(); 
     if( rc ) return shellDatabaseError(p->db);      if( rc ) return shellDatabaseError(p->db);
   
     /* Run the SQL statement prepared by the above block. Store the results      /* Run the SQL statement prepared by the above block. Store the results
Line 4451  static int do_meta_command(char *zLine, ShellState *p) Line 20022  static int do_meta_command(char *zLine, ShellState *p)
         char **azNew;          char **azNew;
         int n2 = nAlloc*2 + 10;          int n2 = nAlloc*2 + 10;
         azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2);          azNew = sqlite3_realloc64(azResult, sizeof(azResult[0])*n2);
        if( azNew==0 ){        if( azNew==0 ) shell_out_of_memory();
          rc = shellNomemError(); 
          break; 
        } 
         nAlloc = n2;          nAlloc = n2;
         azResult = azNew;          azResult = azNew;
       }        }
       azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));        azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
      if( 0==azResult[nRow] ){      if( 0==azResult[nRow] ) shell_out_of_memory();
        rc = shellNomemError(); 
        break; 
      } 
       nRow++;        nRow++;
     }      }
     if( sqlite3_finalize(pStmt)!=SQLITE_OK ){      if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
Line 4495  static int do_meta_command(char *zLine, ShellState *p) Line 20060  static int do_meta_command(char *zLine, ShellState *p)
     sqlite3_free(azResult);      sqlite3_free(azResult);
   }else    }else
   
  if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 && nArg>=2 ){  /* Begin redirecting output to the file "testcase-out.txt" */
   if( c=='t' && strcmp(azArg[0],"testcase")==0 ){
     output_reset(p);
     p->out = output_file_open("testcase-out.txt", 0);
     if( p->out==0 ){
       raw_printf(stderr, "Error: cannot open 'testcase-out.txt'\n");
     }
     if( nArg>=2 ){
       sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]);
     }else{
       sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?");
     }
   }else
 
 #ifndef SQLITE_UNTESTABLE
   if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 ){
     static const struct {      static const struct {
        const char *zCtrlName;   /* Name of a test-control option */         const char *zCtrlName;   /* Name of a test-control option */
        int ctrlCode;            /* Integer code for that option */         int ctrlCode;            /* Integer code for that option */
          const char *zUsage;      /* Usage notes */
     } aCtrl[] = {      } aCtrl[] = {
      { "prng_save",             SQLITE_TESTCTRL_PRNG_SAVE              },      { "always",             SQLITE_TESTCTRL_ALWAYS,        "BOOLEAN"        },
      { "prng_restore",          SQLITE_TESTCTRL_PRNG_RESTORE           },      { "assert",             SQLITE_TESTCTRL_ASSERT,        "BOOLEAN"        },
      { "prng_reset",            SQLITE_TESTCTRL_PRNG_RESET             },    /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, ""       },*/
      { "bitvec_test",           SQLITE_TESTCTRL_BITVEC_TEST            },    /*{ "bitvec_test",        SQLITE_TESTCTRL_BITVEC_TEST,   ""             },*/
      { "fault_install",         SQLITE_TESTCTRL_FAULT_INSTALL          },      { "byteorder",          SQLITE_TESTCTRL_BYTEORDER,     ""               },
      { "benign_malloc_hooks",   SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS    },      { "extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,"BOOLEAN"   },
      { "pending_byte",          SQLITE_TESTCTRL_PENDING_BYTE           },    /*{ "fault_install",      SQLITE_TESTCTRL_FAULT_INSTALL, ""             },*/
      { "assert",                SQLITE_TESTCTRL_ASSERT                 },      { "imposter",         SQLITE_TESTCTRL_IMPOSTER, "SCHEMA ON/OFF ROOTPAGE"},
      { "always",                SQLITE_TESTCTRL_ALWAYS                 },      { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, "" },
      { "reserve",               SQLITE_TESTCTRL_RESERVE                },      { "localtime_fault",    SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN"       },
      { "optimizations",         SQLITE_TESTCTRL_OPTIMIZATIONS          },      { "never_corrupt",      SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN"        },
      { "iskeyword",             SQLITE_TESTCTRL_ISKEYWORD              },      { "optimizations",      SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK"   },
      { "scratchmalloc",         SQLITE_TESTCTRL_SCRATCHMALLOC          },#ifdef YYCOVERAGE
      { "byteorder",             SQLITE_TESTCTRL_BYTEORDER              },      { "parser_coverage",    SQLITE_TESTCTRL_PARSER_COVERAGE, ""             },
      { "never_corrupt",         SQLITE_TESTCTRL_NEVER_CORRUPT          },#endif
      { "imposter",              SQLITE_TESTCTRL_IMPOSTER               },      { "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,    ""               },
     };      };
     int testctrl = -1;      int testctrl = -1;
    int rc2 = 0;    int iCtrl = -1;
     int rc2 = 0;    /* 0: usage.  1: %d  2: %x  3: no-output */
     int isOk = 0;
     int i, n2;      int i, n2;
       const char *zCmd = 0;
   
     open_db(p, 0);      open_db(p, 0);
       zCmd = nArg>=2 ? azArg[1] : "help";
   
       /* The argument can optionally begin with "-" or "--" */
       if( zCmd[0]=='-' && zCmd[1] ){
         zCmd++;
         if( zCmd[0]=='-' && zCmd[1] ) zCmd++;
       }
   
       /* --help lists all test-controls */
       if( strcmp(zCmd,"help")==0 ){
         utf8_printf(p->out, "Available test-controls:\n");
         for(i=0; i<ArraySize(aCtrl); i++){
           utf8_printf(p->out, "  .testctrl %s %s\n",
                       aCtrl[i].zCtrlName, aCtrl[i].zUsage);
         }
         rc = 1;
         goto meta_command_exit;
       }
   
     /* convert testctrl text option to value. allow any unique prefix      /* convert testctrl text option to value. allow any unique prefix
     ** of the option name, or a numerical value. */      ** of the option name, or a numerical value. */
    n2 = strlen30(azArg[1]);    n2 = strlen30(zCmd);
     for(i=0; i<ArraySize(aCtrl); i++){      for(i=0; i<ArraySize(aCtrl); i++){
      if( strncmp(azArg[1], aCtrl[i].zCtrlName, n2)==0 ){      if( strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
         if( testctrl<0 ){          if( testctrl<0 ){
           testctrl = aCtrl[i].ctrlCode;            testctrl = aCtrl[i].ctrlCode;
             iCtrl = i;
         }else{          }else{
          utf8_printf(stderr, "ambiguous option name: \"%s\"\n", azArg[1]);          utf8_printf(stderr, "Error: ambiguous test-control: \"%s\"\n"
          testctrl = -1;                              "Use \".testctrl --help\" for help\n", zCmd);
          break;          rc = 1;
           goto meta_command_exit;
         }          }
       }        }
     }      }
    if( testctrl<0 ) testctrl = (int)integerValue(azArg[1]);    if( testctrl<0 ){
    if( (testctrl<SQLITE_TESTCTRL_FIRST) || (testctrl>SQLITE_TESTCTRL_LAST) ){      utf8_printf(stderr,"Error: unknown test-control: %s\n"
      utf8_printf(stderr,"Error: invalid testctrl option: %s\n", azArg[1]);                         "Use \".testctrl --help\" for help\n", zCmd);
     }else{      }else{
       switch(testctrl){        switch(testctrl){
   
         /* sqlite3_test_control(int, db, int) */          /* sqlite3_test_control(int, db, int) */
         case SQLITE_TESTCTRL_OPTIMIZATIONS:          case SQLITE_TESTCTRL_OPTIMIZATIONS:
         case SQLITE_TESTCTRL_RESERVE:  
           if( nArg==3 ){            if( nArg==3 ){
            int opt = (int)strtol(azArg[2], 0, 0);            unsigned int opt = (unsigned int)strtol(azArg[2], 0, 0);
             rc2 = sqlite3_test_control(testctrl, p->db, opt);              rc2 = sqlite3_test_control(testctrl, p->db, opt);
            raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2);            isOk = 3;
          } else { 
            utf8_printf(stderr,"Error: testctrl %s takes a single int option\n", 
                    azArg[1]); 
           }            }
           break;            break;
   
         /* sqlite3_test_control(int) */          /* sqlite3_test_control(int) */
         case SQLITE_TESTCTRL_PRNG_SAVE:          case SQLITE_TESTCTRL_PRNG_SAVE:
         case SQLITE_TESTCTRL_PRNG_RESTORE:          case SQLITE_TESTCTRL_PRNG_RESTORE:
         case SQLITE_TESTCTRL_PRNG_RESET:  
         case SQLITE_TESTCTRL_BYTEORDER:          case SQLITE_TESTCTRL_BYTEORDER:
           if( nArg==2 ){            if( nArg==2 ){
             rc2 = sqlite3_test_control(testctrl);              rc2 = sqlite3_test_control(testctrl);
            raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2);            isOk = testctrl==SQLITE_TESTCTRL_BYTEORDER ? 1 : 3;
          } else { 
            utf8_printf(stderr,"Error: testctrl %s takes no options\n", 
                        azArg[1]); 
           }            }
           break;            break;
   
Line 4574  static int do_meta_command(char *zLine, ShellState *p) Line 20175  static int do_meta_command(char *zLine, ShellState *p)
           if( nArg==3 ){            if( nArg==3 ){
             unsigned int opt = (unsigned int)integerValue(azArg[2]);              unsigned int opt = (unsigned int)integerValue(azArg[2]);
             rc2 = sqlite3_test_control(testctrl, opt);              rc2 = sqlite3_test_control(testctrl, opt);
            raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2);            isOk = 3;
          } else { 
            utf8_printf(stderr,"Error: testctrl %s takes a single unsigned" 
                           " int option\n", azArg[1]); 
           }            }
           break;            break;
   
           /* sqlite3_test_control(int, int, sqlite3*) */
           case SQLITE_TESTCTRL_PRNG_SEED:
             if( nArg==3 || nArg==4 ){
               int ii = (int)integerValue(azArg[2]);
               sqlite3 *db;
               if( ii==0 && strcmp(azArg[2],"random")==0 ){
                 sqlite3_randomness(sizeof(ii),&ii);
                 printf("-- random seed: %d\n", ii);
               }
               if( nArg==3 ){
                 db = 0;
               }else{
                 db = p->db;
                 /* Make sure the schema has been loaded */
                 sqlite3_table_column_metadata(db, 0, "x", 0, 0, 0, 0, 0, 0);
               }
               rc2 = sqlite3_test_control(testctrl, ii, db);
               isOk = 3;
             }
             break;
   
         /* sqlite3_test_control(int, int) */          /* sqlite3_test_control(int, int) */
         case SQLITE_TESTCTRL_ASSERT:          case SQLITE_TESTCTRL_ASSERT:
         case SQLITE_TESTCTRL_ALWAYS:          case SQLITE_TESTCTRL_ALWAYS:
         case SQLITE_TESTCTRL_NEVER_CORRUPT:  
           if( nArg==3 ){            if( nArg==3 ){
             int opt = booleanValue(azArg[2]);              int opt = booleanValue(azArg[2]);
             rc2 = sqlite3_test_control(testctrl, opt);              rc2 = sqlite3_test_control(testctrl, opt);
            raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2);            isOk = 1;
          } else { 
            utf8_printf(stderr,"Error: testctrl %s takes a single int option\n", 
                            azArg[1]); 
           }            }
           break;            break;
   
        /* sqlite3_test_control(int, char *) */        /* sqlite3_test_control(int, int) */
#ifdef SQLITE_N_KEYWORD        case SQLITE_TESTCTRL_LOCALTIME_FAULT:
        case SQLITE_TESTCTRL_ISKEYWORD:        case SQLITE_TESTCTRL_NEVER_CORRUPT:
           if( nArg==3 ){            if( nArg==3 ){
            const char *opt = azArg[2];            int opt = booleanValue(azArg[2]);
             rc2 = sqlite3_test_control(testctrl, opt);              rc2 = sqlite3_test_control(testctrl, opt);
            raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2);            isOk = 3;
          } else { 
            utf8_printf(stderr, 
                        "Error: testctrl %s takes a single char * option\n", 
                        azArg[1]); 
           }            }
           break;            break;
 #endif  
   
           /* sqlite3_test_control(sqlite3*) */
           case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS:
             rc2 = sqlite3_test_control(testctrl, p->db);
             isOk = 3;
             break;
   
         case SQLITE_TESTCTRL_IMPOSTER:          case SQLITE_TESTCTRL_IMPOSTER:
           if( nArg==5 ){            if( nArg==5 ){
             rc2 = sqlite3_test_control(testctrl, p->db,              rc2 = sqlite3_test_control(testctrl, p->db,
                           azArg[2],                            azArg[2],
                           integerValue(azArg[3]),                            integerValue(azArg[3]),
                           integerValue(azArg[4]));                            integerValue(azArg[4]));
            raw_printf(p->out, "%d (0x%08x)\n", rc2, rc2);            isOk = 3;
          }else{ 
            raw_printf(stderr,"Usage: .testctrl imposter dbName onoff tnum\n"); 
           }            }
           break;            break;
   
        case SQLITE_TESTCTRL_BITVEC_TEST:        case SQLITE_TESTCTRL_SEEK_COUNT: {
        case SQLITE_TESTCTRL_FAULT_INSTALL:          u64 x = 0;
        case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS:          rc2 = sqlite3_test_control(testctrl, p->db, &x);
        case SQLITE_TESTCTRL_SCRATCHMALLOC:          utf8_printf(p->out, "%llu\n", x);
        default:          isOk = 3;
          utf8_printf(stderr, 
                      "Error: CLI support for testctrl %s not implemented\n", 
                      azArg[1]); 
           break;            break;
           }
   
   #ifdef YYCOVERAGE
           case SQLITE_TESTCTRL_PARSER_COVERAGE:
             if( nArg==2 ){
               sqlite3_test_control(testctrl, p->out);
               isOk = 3;
             }
   #endif
       }        }
     }      }
       if( isOk==0 && iCtrl>=0 ){
         utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
         rc = 1;
       }else if( isOk==1 ){
         raw_printf(p->out, "%d\n", rc2);
       }else if( isOk==2 ){
         raw_printf(p->out, "0x%08x\n", rc2);
       }
   }else    }else
   #endif /* !defined(SQLITE_UNTESTABLE) */
   
   if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){    if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){
     open_db(p, 0);      open_db(p, 0);
Line 4653  static int do_meta_command(char *zLine, ShellState *p) Line 20282  static int do_meta_command(char *zLine, ShellState *p)
     }      }
   }else    }else
   
   #ifndef SQLITE_OMIT_TRACE
   if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){    if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){
       int mType = 0;
       int jj;
     open_db(p, 0);      open_db(p, 0);
    if( nArg!=2 ){    for(jj=1; jj<nArg; jj++){
      raw_printf(stderr, "Usage: .trace FILE|off\n");      const char *z = azArg[jj];
      rc = 1;      if( z[0]=='-' ){
      goto meta_command_exit;        if( optionMatch(z, "expanded") ){
           p->eTraceType = SHELL_TRACE_EXPANDED;
         }
 #ifdef SQLITE_ENABLE_NORMALIZE
         else if( optionMatch(z, "normalized") ){
           p->eTraceType = SHELL_TRACE_NORMALIZED;
         }
 #endif
         else if( optionMatch(z, "plain") ){
           p->eTraceType = SHELL_TRACE_PLAIN;
         }
         else if( optionMatch(z, "profile") ){
           mType |= SQLITE_TRACE_PROFILE;
         }
         else if( optionMatch(z, "row") ){
           mType |= SQLITE_TRACE_ROW;
         }
         else if( optionMatch(z, "stmt") ){
           mType |= SQLITE_TRACE_STMT;
         }
         else if( optionMatch(z, "close") ){
           mType |= SQLITE_TRACE_CLOSE;
         }
         else {
           raw_printf(stderr, "Unknown option \"%s\" on \".trace\"\n", z);
           rc = 1;
           goto meta_command_exit;
         }
       }else{
         output_file_close(p->traceOut);
         p->traceOut = output_file_open(azArg[1], 0);
       }
     }      }
     output_file_close(p->traceOut);  
     p->traceOut = output_file_open(azArg[1]);  
 #if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT)  
     if( p->traceOut==0 ){      if( p->traceOut==0 ){
       sqlite3_trace_v2(p->db, 0, 0, 0);        sqlite3_trace_v2(p->db, 0, 0, 0);
     }else{      }else{
      sqlite3_trace_v2(p->db, SQLITE_TRACE_STMT, sql_trace_callback,p->traceOut);      if( mType==0 ) mType = SQLITE_TRACE_STMT;
       sqlite3_trace_v2(p->db, mType, sql_trace_callback, p);
     }      }
 #endif  
   }else    }else
   #endif /* !defined(SQLITE_OMIT_TRACE) */
   
   #if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_VIRTUALTABLE)
     if( c=='u' && strncmp(azArg[0], "unmodule", n)==0 ){
       int ii;
       int lenOpt;
       char *zOpt;
       if( nArg<2 ){
         raw_printf(stderr, "Usage: .unmodule [--allexcept] NAME ...\n");
         rc = 1;
         goto meta_command_exit;
       }
       open_db(p, 0);
       zOpt = azArg[1];
       if( zOpt[0]=='-' && zOpt[1]=='-' && zOpt[2]!=0 ) zOpt++;
       lenOpt = (int)strlen(zOpt);
       if( lenOpt>=3 && strncmp(zOpt, "-allexcept",lenOpt)==0 ){
         assert( azArg[nArg]==0 );
         sqlite3_drop_modules(p->db, nArg>2 ? (const char**)(azArg+2) : 0);
       }else{
         for(ii=1; ii<nArg; ii++){
           sqlite3_create_module(p->db, azArg[ii], 0, 0);
         }
       }
     }else
   #endif
   
 #if SQLITE_USER_AUTHENTICATION  #if SQLITE_USER_AUTHENTICATION
   if( c=='u' && strncmp(azArg[0], "user", n)==0 ){    if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
     if( nArg<2 ){      if( nArg<2 ){
Line 4686  static int do_meta_command(char *zLine, ShellState *p) Line 20372  static int do_meta_command(char *zLine, ShellState *p)
         goto meta_command_exit;          goto meta_command_exit;
       }        }
       rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3],        rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3],
                                    (int)strlen(azArg[3]));                                     strlen30(azArg[3]));
       if( rc ){        if( rc ){
         utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]);          utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]);
         rc = 1;          rc = 1;
Line 4697  static int do_meta_command(char *zLine, ShellState *p) Line 20383  static int do_meta_command(char *zLine, ShellState *p)
         rc = 1;          rc = 1;
         goto meta_command_exit;          goto meta_command_exit;
       }        }
      rc = sqlite3_user_add(p->db, azArg[2],      rc = sqlite3_user_add(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
                            azArg[3], (int)strlen(azArg[3]), 
                             booleanValue(azArg[4]));                              booleanValue(azArg[4]));
       if( rc ){        if( rc ){
         raw_printf(stderr, "User-Add failed: %d\n", rc);          raw_printf(stderr, "User-Add failed: %d\n", rc);
Line 4710  static int do_meta_command(char *zLine, ShellState *p) Line 20395  static int do_meta_command(char *zLine, ShellState *p)
         rc = 1;          rc = 1;
         goto meta_command_exit;          goto meta_command_exit;
       }        }
      rc = sqlite3_user_change(p->db, azArg[2],      rc = sqlite3_user_change(p->db, azArg[2], azArg[3], strlen30(azArg[3]),
                              azArg[3], (int)strlen(azArg[3]), 
                               booleanValue(azArg[4]));                                booleanValue(azArg[4]));
       if( rc ){        if( rc ){
         raw_printf(stderr, "User-Edit failed: %d\n", rc);          raw_printf(stderr, "User-Edit failed: %d\n", rc);
Line 4739  static int do_meta_command(char *zLine, ShellState *p) Line 20423  static int do_meta_command(char *zLine, ShellState *p)
   if( c=='v' && strncmp(azArg[0], "version", n)==0 ){    if( c=='v' && strncmp(azArg[0], "version", n)==0 ){
     utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/,      utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
         sqlite3_libversion(), sqlite3_sourceid());          sqlite3_libversion(), sqlite3_sourceid());
   #if SQLITE_HAVE_ZLIB
       utf8_printf(p->out, "zlib version %s\n", zlibVersion());
   #endif
   #define CTIMEOPT_VAL_(opt) #opt
   #define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
   #if defined(__clang__) && defined(__clang_major__)
       utf8_printf(p->out, "clang-" CTIMEOPT_VAL(__clang_major__) "."
                       CTIMEOPT_VAL(__clang_minor__) "."
                       CTIMEOPT_VAL(__clang_patchlevel__) "\n");
   #elif defined(_MSC_VER)
       utf8_printf(p->out, "msvc-" CTIMEOPT_VAL(_MSC_VER) "\n");
   #elif defined(__GNUC__) && defined(__VERSION__)
       utf8_printf(p->out, "gcc-" __VERSION__ "\n");
   #endif
   }else    }else
   
   if( c=='v' && strncmp(azArg[0], "vfsinfo", n)==0 ){    if( c=='v' && strncmp(azArg[0], "vfsinfo", n)==0 ){
     const char *zDbName = nArg==2 ? azArg[1] : "main";      const char *zDbName = nArg==2 ? azArg[1] : "main";
    sqlite3_vfs *pVfs;    sqlite3_vfs *pVfs = 0;
     if( p->db ){      if( p->db ){
       sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs);        sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFS_POINTER, &pVfs);
       if( pVfs ){        if( pVfs ){
Line 4785  static int do_meta_command(char *zLine, ShellState *p) Line 20483  static int do_meta_command(char *zLine, ShellState *p)
     }      }
   }else    }else
   
 #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)  
   if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){    if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){
    sqlite3WhereTrace = nArg>=2 ? booleanValue(azArg[1]) : 0xff;    unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
     sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &x);
   }else    }else
 #endif  
   
   if( c=='w' && strncmp(azArg[0], "width", n)==0 ){    if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
     int j;      int j;
     assert( nArg<=ArraySize(azArg) );      assert( nArg<=ArraySize(azArg) );
    for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){    p->nWidth = nArg-1;
     p->colWidth = realloc(p->colWidth, p->nWidth*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++){
       p->colWidth[j-1] = (int)integerValue(azArg[j]);        p->colWidth[j-1] = (int)integerValue(azArg[j]);
     }      }
   }else    }else
Line 4804  static int do_meta_command(char *zLine, ShellState *p) Line 20505  static int do_meta_command(char *zLine, ShellState *p)
       " \"%s\". Enter \".help\" for help\n", azArg[0]);        " \"%s\". Enter \".help\" for help\n", azArg[0]);
     rc = 1;      rc = 1;
   }    }
 meta_command_exit:  meta_command_exit:
   if( p->outCount ){    if( p->outCount ){
     p->outCount--;      p->outCount--;
Line 4812  meta_command_exit: Line 20513  meta_command_exit:
   }    }
   return rc;    return rc;
 }  }
 /*  /*
 ** Return TRUE if a semicolon occurs anywhere in the first N characters  ** Return TRUE if a semicolon occurs anywhere in the first N characters
 ** of string z[].  ** of string z[].
Line 4822  static int line_contains_semicolon(const char *z, int  Line 20523  static int line_contains_semicolon(const char *z, int 
   for(i=0; i<N; i++){  if( z[i]==';' ) return 1; }    for(i=0; i<N; i++){  if( z[i]==';' ) return 1; }
   return 0;    return 0;
 }  }
 /*  /*
 ** Test to see if a line consists entirely of whitespace.  ** Test to see if a line consists entirely of whitespace.
 */  */
Line 4846  static int _all_whitespace(const char *z){ Line 20547  static int _all_whitespace(const char *z){
   }    }
   return 1;    return 1;
 }  }
 /*  /*
 ** Return TRUE if the line typed in is an SQL command terminator other  ** 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  ** than a semi-colon.  The SQL Server style "go" command is understood
Line 4863  static int line_is_command_terminator(const char *zLin Line 20564  static int line_is_command_terminator(const char *zLin
   }    }
   return 0;    return 0;
 }  }
 /*  /*
   ** We need a default sqlite3_complete() implementation to use in case
   ** the shell is compiled with SQLITE_OMIT_COMPLETE.  The default assumes
   ** any arbitrary text is a complete SQL statement.  This is not very
   ** user-friendly, but it does seem to work.
   */
   #ifdef SQLITE_OMIT_COMPLETE
   #define sqlite3_complete(x) 1
   #endif
   
   /*
 ** Return true if zSql is a complete SQL statement.  Return false if it  ** Return true if zSql is a complete SQL statement.  Return false if it
 ** ends in the middle of a string literal or C-style comment.  ** ends in the middle of a string literal or C-style comment.
 */  */
Line 4877  static int line_is_complete(char *zSql, int nSql){ Line 20588  static int line_is_complete(char *zSql, int nSql){
   zSql[nSql] = 0;    zSql[nSql] = 0;
   return rc;    return rc;
 }  }
 /*  /*
   ** Run a single line of SQL.  Return the number of errors.
   */
   static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
     int rc;
     char *zErrMsg = 0;
   
     open_db(p, 0);
     if( ShellHasFlag(p,SHFLG_Backslash) ) resolve_backslashes(zSql);
     if( p->flgProgress & SHELL_PROGRESS_RESET ) p->nProgress = 0;
     BEGIN_TIMER;
     rc = shell_exec(p, zSql, &zErrMsg);
     END_TIMER;
     if( rc || zErrMsg ){
       char zPrefix[100];
       if( in!=0 || !stdin_is_interactive ){
         sqlite3_snprintf(sizeof(zPrefix), zPrefix,
                          "Error: near line %d:", startline);
       }else{
         sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error:");
       }
       if( zErrMsg!=0 ){
         utf8_printf(stderr, "%s %s\n", zPrefix, zErrMsg);
         sqlite3_free(zErrMsg);
         zErrMsg = 0;
       }else{
         utf8_printf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db));
       }
       return 1;
     }else if( ShellHasFlag(p, SHFLG_CountChanges) ){
       raw_printf(p->out, "changes: %3d   total_changes: %d\n",
               sqlite3_changes(p->db), sqlite3_total_changes(p->db));
     }
     return 0;
   }
   
   
   /*
 ** Read input from *in and process it.  If *in==0 then input  ** Read input from *in and process it.  If *in==0 then input
 ** is interactive - the user is typing it it.  Otherwise, input  ** is interactive - the user is typing it it.  Otherwise, input
 ** is coming from a file or device.  A prompt is issued and history  ** is coming from a file or device.  A prompt is issued and history
Line 4887  static int line_is_complete(char *zSql, int nSql){ Line 20635  static int line_is_complete(char *zSql, int nSql){
 **  **
 ** Return the number of errors.  ** Return the number of errors.
 */  */
static int process_input(ShellState *p, FILE *in){static int process_input(ShellState *p){
   char *zLine = 0;          /* A single input line */    char *zLine = 0;          /* A single input line */
   char *zSql = 0;           /* Accumulated SQL text */    char *zSql = 0;           /* Accumulated SQL text */
   int nLine;                /* Length of current line */    int nLine;                /* Length of current line */
   int nSql = 0;             /* Bytes of zSql[] used */    int nSql = 0;             /* Bytes of zSql[] used */
   int nAlloc = 0;           /* Allocated zSql[] space */    int nAlloc = 0;           /* Allocated zSql[] space */
   int nSqlPrior = 0;        /* Bytes of zSql[] used by prior line */    int nSqlPrior = 0;        /* Bytes of zSql[] used by prior line */
   char *zErrMsg;            /* Error message returned */  
   int rc;                   /* Error code */    int rc;                   /* Error code */
   int errCnt = 0;           /* Number of errors seen */    int errCnt = 0;           /* Number of errors seen */
   int lineno = 0;           /* Current line number */  
   int startline = 0;        /* Line number for start of current input */    int startline = 0;        /* Line number for start of current input */
   
  while( errCnt==0 || !bail_on_error || (in==0 && stdin_is_interactive) ){  p->lineno = 0;
   while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){
     fflush(p->out);      fflush(p->out);
    zLine = one_input_line(in, zLine, nSql>0);    zLine = one_input_line(p->in, zLine, nSql>0);
     if( zLine==0 ){      if( zLine==0 ){
       /* End of input */        /* End of input */
      if( in==0 && stdin_is_interactive ) printf("\n");      if( p->in==0 && stdin_is_interactive ) printf("\n");
       break;        break;
     }      }
     if( seenInterrupt ){      if( seenInterrupt ){
      if( in!=0 ) break;      if( p->in!=0 ) break;
       seenInterrupt = 0;        seenInterrupt = 0;
     }      }
    lineno++;    p->lineno++;
     if( nSql==0 && _all_whitespace(zLine) ){      if( nSql==0 && _all_whitespace(zLine) ){
      if( p->echoOn ) printf("%s\n", zLine);      if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine);
       continue;        continue;
     }      }
    if( zLine && zLine[0]=='.' && nSql==0 ){    if( zLine && (zLine[0]=='.' || zLine[0]=='#') && nSql==0 ){
      if( p->echoOn ) printf("%s\n", zLine);      if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zLine);
      rc = do_meta_command(zLine, p);      if( zLine[0]=='.' ){
      if( rc==2 ){ /* exit requested */        rc = do_meta_command(zLine, p);
        break;        if( rc==2 ){ /* exit requested */
      }else if( rc ){          break;
        errCnt++;        }else if( rc ){
           errCnt++;
         }
       }        }
       continue;        continue;
     }      }
Line 4934  static int process_input(ShellState *p, FILE *in){ Line 20683  static int process_input(ShellState *p, FILE *in){
     if( nSql+nLine+2>=nAlloc ){      if( nSql+nLine+2>=nAlloc ){
       nAlloc = nSql+nLine+100;        nAlloc = nSql+nLine+100;
       zSql = realloc(zSql, nAlloc);        zSql = realloc(zSql, nAlloc);
      if( zSql==0 ){      if( zSql==0 ) shell_out_of_memory();
        raw_printf(stderr, "Error: out of memory\n"); 
        exit(1); 
      } 
     }      }
     nSqlPrior = nSql;      nSqlPrior = nSql;
     if( nSql==0 ){      if( nSql==0 ){
Line 4945  static int process_input(ShellState *p, FILE *in){ Line 20691  static int process_input(ShellState *p, FILE *in){
       for(i=0; zLine[i] && IsSpace(zLine[i]); i++){}        for(i=0; zLine[i] && IsSpace(zLine[i]); i++){}
       assert( nAlloc>0 && zSql!=0 );        assert( nAlloc>0 && zSql!=0 );
       memcpy(zSql, zLine+i, nLine+1-i);        memcpy(zSql, zLine+i, nLine+1-i);
      startline = lineno;      startline = p->lineno;
       nSql = nLine-i;        nSql = nLine-i;
     }else{      }else{
       zSql[nSql++] = '\n';        zSql[nSql++] = '\n';
Line 4954  static int process_input(ShellState *p, FILE *in){ Line 20700  static int process_input(ShellState *p, FILE *in){
     }      }
     if( nSql && line_contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior)      if( nSql && line_contains_semicolon(&zSql[nSqlPrior], nSql-nSqlPrior)
                 && sqlite3_complete(zSql) ){                  && sqlite3_complete(zSql) ){
      p->cnt = 0;      errCnt += runOneSqlLine(p, zSql, p->in, startline);
      open_db(p, 0); 
      if( p->backslashOn ) resolve_backslashes(zSql); 
      BEGIN_TIMER; 
      rc = shell_exec(p->db, zSql, shell_callback, p, &zErrMsg); 
      END_TIMER; 
      if( rc || zErrMsg ){ 
        char zPrefix[100]; 
        if( in!=0 || !stdin_is_interactive ){ 
          sqlite3_snprintf(sizeof(zPrefix), zPrefix, 
                           "Error: near line %d:", startline); 
        }else{ 
          sqlite3_snprintf(sizeof(zPrefix), zPrefix, "Error:"); 
        } 
        if( zErrMsg!=0 ){ 
          utf8_printf(stderr, "%s %s\n", zPrefix, zErrMsg); 
          sqlite3_free(zErrMsg); 
          zErrMsg = 0; 
        }else{ 
          utf8_printf(stderr, "%s %s\n", zPrefix, sqlite3_errmsg(p->db)); 
        } 
        errCnt++; 
      }else if( p->countChanges ){ 
        raw_printf(p->out, "changes: %3d   total_changes: %d\n", 
                sqlite3_changes(p->db), sqlite3_total_changes(p->db)); 
      } 
       nSql = 0;        nSql = 0;
       if( p->outCount ){        if( p->outCount ){
         output_reset(p);          output_reset(p);
         p->outCount = 0;          p->outCount = 0;
         }else{
           clearTempFile(p);
       }        }
     }else if( nSql && _all_whitespace(zSql) ){      }else if( nSql && _all_whitespace(zSql) ){
      if( p->echoOn ) printf("%s\n", zSql);      if( ShellHasFlag(p, SHFLG_Echo) ) printf("%s\n", zSql);
       nSql = 0;        nSql = 0;
     }      }
   }    }
  if( nSql ){  if( nSql && !_all_whitespace(zSql) ){
    if( !_all_whitespace(zSql) ){    errCnt += runOneSqlLine(p, zSql, p->in, startline);
      utf8_printf(stderr, "Error: incomplete SQL: %s\n", zSql); 
      errCnt++; 
    } 
   }    }
   free(zSql);    free(zSql);
   free(zLine);    free(zLine);
   return errCnt>0;    return errCnt>0;
 }  }
 /*  /*
 ** Return a pathname which is the user's home directory.  A  ** Return a pathname which is the user's home directory.  A
 ** 0 return indicates an error of some kind.  ** 0 return indicates an error of some kind.
 */  */
static char *find_home_dir(void){static char *find_home_dir(int clearFlag){
   static char *home_dir = NULL;    static char *home_dir = NULL;
     if( clearFlag ){
       free(home_dir);
       home_dir = 0;
       return 0;
     }
   if( home_dir ) return home_dir;    if( home_dir ) return home_dir;
 #if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) \  #if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) \
      && !defined(__RTP__) && !defined(_WRS_KERNEL)       && !defined(__RTP__) && !defined(_WRS_KERNEL)
   {    {
Line 5019  static char *find_home_dir(void){ Line 20744  static char *find_home_dir(void){
     }      }
   }    }
 #endif  #endif
 #if defined(_WIN32_WCE)  #if defined(_WIN32_WCE)
   /* Windows CE (arm-wince-mingw32ce-gcc) does not provide getenv()    /* Windows CE (arm-wince-mingw32ce-gcc) does not provide getenv()
    */     */
Line 5064  static char *find_home_dir(void){ Line 20789  static char *find_home_dir(void){
   
   return home_dir;    return home_dir;
 }  }
 /*  /*
 ** Read input from the file given by sqliterc_override.  Or if that  ** Read input from the file given by sqliterc_override.  Or if that
 ** parameter is NULL, take input from ~/.sqliterc  ** parameter is NULL, take input from ~/.sqliterc
Line 5078  static void process_sqliterc( Line 20803  static void process_sqliterc(
   char *home_dir = NULL;    char *home_dir = NULL;
   const char *sqliterc = sqliterc_override;    const char *sqliterc = sqliterc_override;
   char *zBuf = 0;    char *zBuf = 0;
  FILE *in = NULL;  FILE *inSaved = p->in;
  int savedLineno = p->lineno;
 
   if (sqliterc == NULL) {    if (sqliterc == NULL) {
    home_dir = find_home_dir();    home_dir = find_home_dir(0);
     if( home_dir==0 ){      if( home_dir==0 ){
       raw_printf(stderr, "-- warning: cannot find home directory;"        raw_printf(stderr, "-- warning: cannot find home directory;"
                       " cannot read ~/.sqliterc\n");                        " cannot read ~/.sqliterc\n");
       return;        return;
     }      }
     sqlite3_initialize();  
     zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);      zBuf = sqlite3_mprintf("%s/.sqliterc",home_dir);
     sqliterc = zBuf;      sqliterc = zBuf;
   }    }
  in = fopen(sqliterc,"rb");  p->in = fopen(sqliterc,"rb");
  if( in ){  if( p->in ){
     if( stdin_is_interactive ){      if( stdin_is_interactive ){
       utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc);        utf8_printf(stderr,"-- Loading resources from %s\n",sqliterc);
     }      }
    process_input(p,in);    if( process_input(p) && bail_on_error ) exit(1);
    fclose(in);    fclose(p->in);
   }else if( sqliterc_override!=0 ){
     utf8_printf(stderr,"cannot open: \"%s\"\n", sqliterc);
     if( bail_on_error ) exit(1);
   }    }
     p->in = inSaved;
     p->lineno = savedLineno;
   sqlite3_free(zBuf);    sqlite3_free(zBuf);
 }  }
 /*  /*
 ** Show available command line options  ** Show available command line options
 */  */
 static const char zOptions[] =  static const char zOptions[] =
   #if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
     "   -A ARGS...           run \".archive ARGS\" and exit\n"
   #endif
     "   -append              append the database to the end of the file\n"
   "   -ascii               set output mode to 'ascii'\n"    "   -ascii               set output mode to 'ascii'\n"
   "   -bail                stop after hitting an error\n"    "   -bail                stop after hitting an error\n"
   "   -batch               force batch I/O\n"    "   -batch               force batch I/O\n"
     "   -box                 set output mode to 'box'\n"
   "   -column              set output mode to 'column'\n"    "   -column              set output mode to 'column'\n"
   "   -cmd COMMAND         run \"COMMAND\" before reading stdin\n"    "   -cmd COMMAND         run \"COMMAND\" before reading stdin\n"
   "   -csv                 set output mode to 'csv'\n"    "   -csv                 set output mode to 'csv'\n"
   #if defined(SQLITE_ENABLE_DESERIALIZE)
     "   -deserialize         open the database using sqlite3_deserialize()\n"
   #endif
   "   -echo                print commands before execution\n"    "   -echo                print commands before execution\n"
   "   -init FILENAME       read/process named file\n"    "   -init FILENAME       read/process named file\n"
   "   -[no]header          turn headers on or off\n"    "   -[no]header          turn headers on or off\n"
Line 5121  static const char zOptions[] = Line 20859  static const char zOptions[] =
   "   -help                show this message\n"    "   -help                show this message\n"
   "   -html                set output mode to HTML\n"    "   -html                set output mode to HTML\n"
   "   -interactive         force interactive I/O\n"    "   -interactive         force interactive I/O\n"
     "   -json                set output mode to 'json'\n"
   "   -line                set output mode to 'line'\n"    "   -line                set output mode to 'line'\n"
   "   -list                set output mode to 'list'\n"    "   -list                set output mode to 'list'\n"
   "   -lookaside SIZE N    use N entries of SZ bytes for lookaside memory\n"    "   -lookaside SIZE N    use N entries of SZ bytes for lookaside memory\n"
     "   -markdown            set output mode to 'markdown'\n"
   #if defined(SQLITE_ENABLE_DESERIALIZE)
     "   -maxsize N           maximum size for a --deserialize database\n"
   #endif
     "   -memtrace            trace all memory allocations and deallocations\n"
   "   -mmap N              default mmap size set to N\n"    "   -mmap N              default mmap size set to N\n"
 #ifdef SQLITE_ENABLE_MULTIPLEX  #ifdef SQLITE_ENABLE_MULTIPLEX
   "   -multiplex           enable the multiplexor VFS\n"    "   -multiplex           enable the multiplexor VFS\n"
 #endif  #endif
   "   -newline SEP         set output row separator. Default: '\\n'\n"    "   -newline SEP         set output row separator. Default: '\\n'\n"
     "   -nofollow            refuse to open symbolic links to database files\n"
   "   -nullvalue TEXT      set text string for NULL values. Default ''\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"    "   -pagecache SIZE N    use N slots of SZ bytes each for page cache memory\n"
  "   -scratch SIZE N      use N slots of SZ bytes each for scratch memory\n"  "   -quote               set output mode to 'quote'\n"
   "   -readonly            open the database read-only\n"
   "   -separator SEP       set output column separator. Default: '|'\n"    "   -separator SEP       set output column separator. Default: '|'\n"
   #ifdef SQLITE_ENABLE_SORTER_REFERENCES
     "   -sorterref SIZE      sorter references threshold size\n"
   #endif
   "   -stats               print memory stats before each finalize\n"    "   -stats               print memory stats before each finalize\n"
     "   -table               set output mode to 'table'\n"
     "   -tabs                set output mode to 'tabs'\n"
   "   -version             show SQLite version\n"    "   -version             show SQLite version\n"
   "   -vfs NAME            use NAME as the default VFS\n"    "   -vfs NAME            use NAME as the default VFS\n"
 #ifdef SQLITE_ENABLE_VFSTRACE  #ifdef SQLITE_ENABLE_VFSTRACE
   "   -vfstrace            enable tracing of all VFS calls\n"    "   -vfstrace            enable tracing of all VFS calls\n"
 #endif  #endif
   #ifdef SQLITE_HAVE_ZLIB
     "   -zip                 open the file as a ZIP Archive\n"
   #endif
 ;  ;
 static void usage(int showDetail){  static void usage(int showDetail){
   utf8_printf(stderr,    utf8_printf(stderr,
Line 5152  static void usage(int showDetail){ Line 20906  static void usage(int showDetail){
   }    }
   exit(1);    exit(1);
 }  }
 /*  /*
   ** Internal check:  Verify that the SQLite is uninitialized.  Print a
   ** error message if it is initialized.
   */
   static void verify_uninitialized(void){
     if( sqlite3_config(-1)==SQLITE_MISUSE ){
       utf8_printf(stdout, "WARNING: attempt to configure SQLite after"
                           " initialization.\n");
     }
   }
   
   /*
 ** Initialize the state information in data  ** Initialize the state information in data
 */  */
 static void main_init(ShellState *data) {  static void main_init(ShellState *data) {
Line 5164  static void main_init(ShellState *data) { Line 20929  static void main_init(ShellState *data) {
   memcpy(data->rowSeparator,SEP_Row, 2);    memcpy(data->rowSeparator,SEP_Row, 2);
   data->showHeader = 0;    data->showHeader = 0;
   data->shellFlgs = SHFLG_Lookaside;    data->shellFlgs = SHFLG_Lookaside;
     verify_uninitialized();
   sqlite3_config(SQLITE_CONFIG_URI, 1);    sqlite3_config(SQLITE_CONFIG_URI, 1);
   sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);    sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
   sqlite3_config(SQLITE_CONFIG_MULTITHREAD);    sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
   sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");    sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
   sqlite3_snprintf(sizeof(continuePrompt), continuePrompt,"   ...> ");    sqlite3_snprintf(sizeof(continuePrompt), continuePrompt,"   ...> ");
 }  }
 /*  /*
 ** Output text to the console in a font that attracts extra attention.  ** Output text to the console in a font that attracts extra attention.
 */  */
 #ifdef _WIN32  #ifdef _WIN32
 static void printBold(const char *zText){  static void printBold(const char *zText){
   #if !SQLITE_OS_WINRT
   HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);    HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
   CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo;    CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo;
   GetConsoleScreenBufferInfo(out, &defaultScreenInfo);    GetConsoleScreenBufferInfo(out, &defaultScreenInfo);
   SetConsoleTextAttribute(out,    SetConsoleTextAttribute(out,
          FOREGROUND_RED|FOREGROUND_INTENSITY           FOREGROUND_RED|FOREGROUND_INTENSITY
   );    );
   #endif
   printf("%s", zText);    printf("%s", zText);
   #if !SQLITE_OS_WINRT
   SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes);    SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes);
   #endif
 }  }
 #else  #else
 static void printBold(const char *zText){  static void printBold(const char *zText){
   printf("\033[1m%s\033[0m", zText);    printf("\033[1m%s\033[0m", zText);
 }  }
 #endif  #endif
 /*  /*
 ** Get the argument to an --option.  Throw an error and die if no argument  ** Get the argument to an --option.  Throw an error and die if no argument
 ** is available.  ** is available.
Line 5203  static char *cmdline_option_value(int argc, char **arg Line 20973  static char *cmdline_option_value(int argc, char **arg
   }    }
   return argv[i];    return argv[i];
 }  }
 #ifndef SQLITE_SHELL_IS_UTF8  #ifndef SQLITE_SHELL_IS_UTF8
#  if (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)#  if (defined(_WIN32) || defined(WIN32)) \
    && (defined(_MSC_VER) || (defined(UNICODE) && defined(__GNUC__)))
 #    define SQLITE_SHELL_IS_UTF8          (0)  #    define SQLITE_SHELL_IS_UTF8          (0)
 #  else  #  else
 #    define SQLITE_SHELL_IS_UTF8          (1)  #    define SQLITE_SHELL_IS_UTF8          (1)
Line 5227  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ Line 20998  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
   int readStdin = 1;    int readStdin = 1;
   int nCmd = 0;    int nCmd = 0;
   char **azCmd = 0;    char **azCmd = 0;
     const char *zVfs = 0;           /* Value of -vfs command-line option */
   #if !SQLITE_SHELL_IS_UTF8
     char **argvToFree = 0;
     int argcToFree = 0;
   #endif
   
   setBinaryMode(stdin, 0);    setBinaryMode(stdin, 0);
   setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */    setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
   stdin_is_interactive = isatty(0);    stdin_is_interactive = isatty(0);
   stdout_is_console = isatty(1);    stdout_is_console = isatty(1);
   
   #ifdef SQLITE_DEBUG
     registerOomSimulator();
   #endif
   
   #if !defined(_WIN32_WCE)
     if( getenv("SQLITE_DEBUG_BREAK") ){
       if( isatty(0) && isatty(2) ){
         fprintf(stderr,
             "attach debugger to process %d and press any key to continue.\n",
             GETPID());
         fgetc(stdin);
       }else{
   #if defined(_WIN32) || defined(WIN32)
   #if SQLITE_OS_WINRT
         __debugbreak();
   #else
         DebugBreak();
   #endif
   #elif defined(SIGTRAP)
         raise(SIGTRAP);
   #endif
       }
     }
   #endif
   
 #if USE_SYSTEM_SQLITE+0!=1  #if USE_SYSTEM_SQLITE+0!=1
  if( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)!=0 ){  if( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){
     utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",      utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
             sqlite3_sourceid(), SQLITE_SOURCE_ID);              sqlite3_sourceid(), SQLITE_SOURCE_ID);
     exit(1);      exit(1);
   }    }
 #endif  #endif
   main_init(&data);    main_init(&data);
   
     /* On Windows, we must translate command-line arguments into UTF-8.
     ** The SQLite memory allocator subsystem has to be enabled in order to
     ** do this.  But we want to run an sqlite3_shutdown() afterwards so that
     ** subsequent sqlite3_config() calls will work.  So copy all results into
     ** memory that does not come from the SQLite memory allocator.
     */
 #if !SQLITE_SHELL_IS_UTF8  #if !SQLITE_SHELL_IS_UTF8
   sqlite3_initialize();    sqlite3_initialize();
  argv = sqlite3_malloc64(sizeof(argv[0])*argc);  argvToFree = malloc(sizeof(argv[0])*argc*2);
  if( argv==0 ){  argcToFree = argc;
    raw_printf(stderr, "out of memory\n");  argv = argvToFree + argc;
    exit(1);  if( argv==0 ) shell_out_of_memory();
  } 
   for(i=0; i<argc; i++){    for(i=0; i<argc; i++){
    argv[i] = sqlite3_win32_unicode_to_utf8(wargv[i]);    char *z = sqlite3_win32_unicode_to_utf8(wargv[i]);
    if( argv[i]==0 ){    int n;
      raw_printf(stderr, "out of memory\n");    if( z==0 ) shell_out_of_memory();
      exit(1);    n = (int)strlen(z);
    }    argv[i] = malloc( n+1 );
     if( argv[i]==0 ) shell_out_of_memory();
     memcpy(argv[i], z, n+1);
     argvToFree[i] = argv[i];
     sqlite3_free(z);
   }    }
     sqlite3_shutdown();
 #endif  #endif
   
   assert( argc>=1 && argv && argv[0] );    assert( argc>=1 && argv && argv[0] );
   Argv0 = argv[0];    Argv0 = argv[0];
   
Line 5264  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ Line 21077  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
   */    */
 #ifdef SIGINT  #ifdef SIGINT
   signal(SIGINT, interrupt_handler);    signal(SIGINT, interrupt_handler);
   #elif (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE)
     SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
 #endif  #endif
   
 #ifdef SQLITE_SHELL_DBNAME_PROC  #ifdef SQLITE_SHELL_DBNAME_PROC
Line 5283  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ Line 21098  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
   ** the size of the alternative malloc heap,    ** the size of the alternative malloc heap,
   ** and the first command to execute.    ** and the first command to execute.
   */    */
     verify_uninitialized();
   for(i=1; i<argc; i++){    for(i=1; i<argc; i++){
     char *z;      char *z;
     z = argv[i];      z = argv[i];
Line 5295  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ Line 21111  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
         readStdin = 0;          readStdin = 0;
         nCmd++;          nCmd++;
         azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd);          azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd);
        if( azCmd==0 ){        if( azCmd==0 ) shell_out_of_memory();
          raw_printf(stderr, "out of memory\n"); 
          exit(1); 
        } 
         azCmd[nCmd-1] = z;          azCmd[nCmd-1] = z;
       }        }
     }      }
Line 5329  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ Line 21142  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
 #else  #else
       (void)cmdline_option_value(argc, argv, ++i);        (void)cmdline_option_value(argc, argv, ++i);
 #endif  #endif
     }else if( strcmp(z,"-scratch")==0 ){  
       int n, sz;  
       sz = (int)integerValue(cmdline_option_value(argc,argv,++i));  
       if( sz>400000 ) sz = 400000;  
       if( sz<2500 ) sz = 2500;  
       n = (int)integerValue(cmdline_option_value(argc,argv,++i));  
       if( n>10 ) n = 10;  
       if( n<1 ) n = 1;  
       sqlite3_config(SQLITE_CONFIG_SCRATCH, malloc(n*sz+1), sz, n);  
       data.shellFlgs |= SHFLG_Scratch;  
     }else if( strcmp(z,"-pagecache")==0 ){      }else if( strcmp(z,"-pagecache")==0 ){
      int n, sz;      sqlite3_int64 n, sz;
      sz = (int)integerValue(cmdline_option_value(argc,argv,++i));      sz = integerValue(cmdline_option_value(argc,argv,++i));
       if( sz>70000 ) sz = 70000;        if( sz>70000 ) sz = 70000;
       if( sz<0 ) sz = 0;        if( sz<0 ) sz = 0;
      n = (int)integerValue(cmdline_option_value(argc,argv,++i));      n = integerValue(cmdline_option_value(argc,argv,++i));
       if( sz>0 && n>0 && 0xffffffffffffLL/sz<n ){
         n = 0xffffffffffffLL/sz;
       }
       sqlite3_config(SQLITE_CONFIG_PAGECACHE,        sqlite3_config(SQLITE_CONFIG_PAGECACHE,
                     (n>0 && sz>0) ? malloc(n*sz) : 0, sz, n);                      (n>0 && sz>0) ? malloc(n*sz) : 0, sz, n);
       data.shellFlgs |= SHFLG_Pagecache;        data.shellFlgs |= SHFLG_Pagecache;
Line 5375  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ Line 21181  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
     }else if( strcmp(z,"-mmap")==0 ){      }else if( strcmp(z,"-mmap")==0 ){
       sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));        sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
       sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, sz, sz);        sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, sz, sz);
   #ifdef SQLITE_ENABLE_SORTER_REFERENCES
       }else if( strcmp(z,"-sorterref")==0 ){
         sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
         sqlite3_config(SQLITE_CONFIG_SORTERREF_SIZE, (int)sz);
   #endif
     }else if( strcmp(z,"-vfs")==0 ){      }else if( strcmp(z,"-vfs")==0 ){
      sqlite3_vfs *pVfs = sqlite3_vfs_find(cmdline_option_value(argc,argv,++i));      zVfs = cmdline_option_value(argc, argv, ++i);
      if( pVfs ){#ifdef SQLITE_HAVE_ZLIB
        sqlite3_vfs_register(pVfs, 1);    }else if( strcmp(z,"-zip")==0 ){
      }else{      data.openMode = SHELL_OPEN_ZIPFILE;
        utf8_printf(stderr, "no such VFS: \"%s\"\n", argv[i]);#endif
        exit(1);    }else if( strcmp(z,"-append")==0 ){
      }      data.openMode = SHELL_OPEN_APPENDVFS;
 #ifdef SQLITE_ENABLE_DESERIALIZE
     }else if( strcmp(z,"-deserialize")==0 ){
       data.openMode = SHELL_OPEN_DESERIALIZE;
     }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
       data.szMax = integerValue(argv[++i]);
 #endif
     }else if( strcmp(z,"-readonly")==0 ){
       data.openMode = SHELL_OPEN_READONLY;
     }else if( strcmp(z,"-nofollow")==0 ){
       data.openFlags = SQLITE_OPEN_NOFOLLOW;
 #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
     }else if( strncmp(z, "-A",2)==0 ){
       /* All remaining command-line arguments are passed to the ".archive"
       ** command, so ignore them */
       break;
 #endif
     }else if( strcmp(z, "-memtrace")==0 ){
       sqlite3MemTraceActivate(stderr);
     }else if( strcmp(z,"-bail")==0 ){
       bail_on_error = 1;
     }      }
   }    }
     verify_uninitialized();
   
   
   #ifdef SQLITE_SHELL_INIT_PROC
     {
       /* If the SQLITE_SHELL_INIT_PROC macro is defined, then it is the name
       ** of a C-function that will perform initialization actions on SQLite that
       ** occur just before or after sqlite3_initialize(). Use this compile-time
       ** option to embed this shell program in larger applications. */
       extern void SQLITE_SHELL_INIT_PROC(void);
       SQLITE_SHELL_INIT_PROC();
     }
   #else
     /* All the sqlite3_config() calls have now been made. So it is safe
     ** to call sqlite3_initialize() and process any command line -vfs option. */
     sqlite3_initialize();
   #endif
   
     if( zVfs ){
       sqlite3_vfs *pVfs = sqlite3_vfs_find(zVfs);
       if( pVfs ){
         sqlite3_vfs_register(pVfs, 1);
       }else{
         utf8_printf(stderr, "no such VFS: \"%s\"\n", argv[i]);
         exit(1);
       }
     }
   
   if( data.zDbFilename==0 ){    if( data.zDbFilename==0 ){
 #ifndef SQLITE_OMIT_MEMORYDB  #ifndef SQLITE_OMIT_MEMORYDB
     data.zDbFilename = ":memory:";      data.zDbFilename = ":memory:";
Line 5395  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ Line 21254  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
 #endif  #endif
   }    }
   data.out = stdout;    data.out = stdout;
  sqlite3_appendvfs_init(0,0,0);
 
   /* Go ahead and open the database file if it already exists.  If the    /* Go ahead and open the database file if it already exists.  If the
   ** file does not exist, delay opening it.  This prevents empty database    ** file does not exist, delay opening it.  This prevents empty database
   ** files from being created if a user mistypes the database name argument    ** files from being created if a user mistypes the database name argument
Line 5426  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ Line 21286  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
       data.mode = MODE_Html;        data.mode = MODE_Html;
     }else if( strcmp(z,"-list")==0 ){      }else if( strcmp(z,"-list")==0 ){
       data.mode = MODE_List;        data.mode = MODE_List;
       }else if( strcmp(z,"-quote")==0 ){
         data.mode = MODE_Quote;
         sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Comma);
         sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
     }else if( strcmp(z,"-line")==0 ){      }else if( strcmp(z,"-line")==0 ){
       data.mode = MODE_Line;        data.mode = MODE_Line;
     }else if( strcmp(z,"-column")==0 ){      }else if( strcmp(z,"-column")==0 ){
       data.mode = MODE_Column;        data.mode = MODE_Column;
       }else if( strcmp(z,"-json")==0 ){
         data.mode = MODE_Json;
       }else if( strcmp(z,"-markdown")==0 ){
         data.mode = MODE_Markdown;
       }else if( strcmp(z,"-table")==0 ){
         data.mode = MODE_Table;
       }else if( strcmp(z,"-box")==0 ){
         data.mode = MODE_Box;
     }else if( strcmp(z,"-csv")==0 ){      }else if( strcmp(z,"-csv")==0 ){
       data.mode = MODE_Csv;        data.mode = MODE_Csv;
       memcpy(data.colSeparator,",",2);        memcpy(data.colSeparator,",",2);
   #ifdef SQLITE_HAVE_ZLIB
       }else if( strcmp(z,"-zip")==0 ){
         data.openMode = SHELL_OPEN_ZIPFILE;
   #endif
       }else if( strcmp(z,"-append")==0 ){
         data.openMode = SHELL_OPEN_APPENDVFS;
   #ifdef SQLITE_ENABLE_DESERIALIZE
       }else if( strcmp(z,"-deserialize")==0 ){
         data.openMode = SHELL_OPEN_DESERIALIZE;
       }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
         data.szMax = integerValue(argv[++i]);
   #endif
       }else if( strcmp(z,"-readonly")==0 ){
         data.openMode = SHELL_OPEN_READONLY;
       }else if( strcmp(z,"-nofollow")==0 ){
         data.openFlags |= SQLITE_OPEN_NOFOLLOW;
     }else if( strcmp(z,"-ascii")==0 ){      }else if( strcmp(z,"-ascii")==0 ){
       data.mode = MODE_Ascii;        data.mode = MODE_Ascii;
      sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,      sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Unit);
                       SEP_Unit);      sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Record);
      sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,    }else if( strcmp(z,"-tabs")==0 ){
                       SEP_Record);      data.mode = MODE_List;
       sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Tab);
       sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
     }else if( strcmp(z,"-separator")==0 ){      }else if( strcmp(z,"-separator")==0 ){
       sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,        sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
                        "%s",cmdline_option_value(argc,argv,++i));                         "%s",cmdline_option_value(argc,argv,++i));
Line 5453  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ Line 21343  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
     }else if( strcmp(z,"-noheader")==0 ){      }else if( strcmp(z,"-noheader")==0 ){
       data.showHeader = 0;        data.showHeader = 0;
     }else if( strcmp(z,"-echo")==0 ){      }else if( strcmp(z,"-echo")==0 ){
      data.echoOn = 1;      ShellSetFlag(&data, SHFLG_Echo);
     }else if( strcmp(z,"-eqp")==0 ){      }else if( strcmp(z,"-eqp")==0 ){
      data.autoEQP = 1;      data.autoEQP = AUTOEQP_on;
     }else if( strcmp(z,"-eqpfull")==0 ){      }else if( strcmp(z,"-eqpfull")==0 ){
      data.autoEQP = 2;      data.autoEQP = AUTOEQP_full;
     }else if( strcmp(z,"-stats")==0 ){      }else if( strcmp(z,"-stats")==0 ){
       data.statsOn = 1;        data.statsOn = 1;
     }else if( strcmp(z,"-scanstats")==0 ){      }else if( strcmp(z,"-scanstats")==0 ){
Line 5468  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ Line 21358  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
       ** prior to sending the SQL into SQLite.  Useful for injecting        ** prior to sending the SQL into SQLite.  Useful for injecting
       ** crazy bytes in the middle of SQL statements for testing and debugging.        ** crazy bytes in the middle of SQL statements for testing and debugging.
       */        */
      data.backslashOn = 1;      ShellSetFlag(&data, SHFLG_Backslash);
     }else if( strcmp(z,"-bail")==0 ){      }else if( strcmp(z,"-bail")==0 ){
      bail_on_error = 1;      /* No-op.  The bail_on_error flag should already be set. */
     }else if( strcmp(z,"-version")==0 ){      }else if( strcmp(z,"-version")==0 ){
       printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid());        printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid());
       return 0;        return 0;
Line 5480  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ Line 21370  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
       stdin_is_interactive = 0;        stdin_is_interactive = 0;
     }else if( strcmp(z,"-heap")==0 ){      }else if( strcmp(z,"-heap")==0 ){
       i++;        i++;
     }else if( strcmp(z,"-scratch")==0 ){  
       i+=2;  
     }else if( strcmp(z,"-pagecache")==0 ){      }else if( strcmp(z,"-pagecache")==0 ){
       i+=2;        i+=2;
     }else if( strcmp(z,"-lookaside")==0 ){      }else if( strcmp(z,"-lookaside")==0 ){
       i+=2;        i+=2;
     }else if( strcmp(z,"-mmap")==0 ){      }else if( strcmp(z,"-mmap")==0 ){
       i++;        i++;
       }else if( strcmp(z,"-memtrace")==0 ){
         i++;
   #ifdef SQLITE_ENABLE_SORTER_REFERENCES
       }else if( strcmp(z,"-sorterref")==0 ){
         i++;
   #endif
     }else if( strcmp(z,"-vfs")==0 ){      }else if( strcmp(z,"-vfs")==0 ){
       i++;        i++;
 #ifdef SQLITE_ENABLE_VFSTRACE  #ifdef SQLITE_ENABLE_VFSTRACE
Line 5512  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ Line 21406  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
         if( rc && bail_on_error ) return rc==2 ? 0 : rc;          if( rc && bail_on_error ) return rc==2 ? 0 : rc;
       }else{        }else{
         open_db(&data, 0);          open_db(&data, 0);
        rc = shell_exec(data.db, z, shell_callback, &data, &zErrMsg);        rc = shell_exec(&data, z, &zErrMsg);
         if( zErrMsg!=0 ){          if( zErrMsg!=0 ){
           utf8_printf(stderr,"Error: %s\n", zErrMsg);            utf8_printf(stderr,"Error: %s\n", zErrMsg);
           if( bail_on_error ) return rc!=0 ? rc : 1;            if( bail_on_error ) return rc!=0 ? rc : 1;
Line 5521  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ Line 21415  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
           if( bail_on_error ) return rc;            if( bail_on_error ) return rc;
         }          }
       }        }
   #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
       }else if( strncmp(z, "-A", 2)==0 ){
         if( nCmd>0 ){
           utf8_printf(stderr, "Error: cannot mix regular SQL or dot-commands"
                               " with \"%s\"\n", z);
           return 1;
         }
         open_db(&data, OPEN_DB_ZIPFILE);
         if( z[2] ){
           argv[i] = &z[2];
           arDotCommand(&data, 1, argv+(i-1), argc-(i-1));
         }else{
           arDotCommand(&data, 1, argv+i, argc-i);
         }
         readStdin = 0;
         break;
   #endif
     }else{      }else{
       utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);        utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
       raw_printf(stderr,"Use -help for a list of options.\n");        raw_printf(stderr,"Use -help for a list of options.\n");
Line 5537  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ Line 21448  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
     for(i=0; i<nCmd; i++){      for(i=0; i<nCmd; i++){
       if( azCmd[i][0]=='.' ){        if( azCmd[i][0]=='.' ){
         rc = do_meta_command(azCmd[i], &data);          rc = do_meta_command(azCmd[i], &data);
        if( rc ) return rc==2 ? 0 : rc;        if( rc ){
           free(azCmd);
           return rc==2 ? 0 : rc;
         }
       }else{        }else{
         open_db(&data, 0);          open_db(&data, 0);
        rc = shell_exec(data.db, azCmd[i], shell_callback, &data, &zErrMsg);        rc = shell_exec(&data, azCmd[i], &zErrMsg);
        if( zErrMsg!=0 ){        if( zErrMsg || rc ){
          utf8_printf(stderr,"Error: %s\n", zErrMsg);          if( zErrMsg!=0 ){
             utf8_printf(stderr,"Error: %s\n", zErrMsg);
           }else{
             utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]);
           }
           sqlite3_free(zErrMsg);
           free(azCmd);
           return rc!=0 ? rc : 1;            return rc!=0 ? rc : 1;
         }else if( rc!=0 ){  
           utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]);  
           return rc;  
         }          }
       }        }
     }      }
     free(azCmd);  
   }else{    }else{
     /* Run commands received from standard input      /* Run commands received from standard input
     */      */
     if( stdin_is_interactive ){      if( stdin_is_interactive ){
       char *zHome;        char *zHome;
      char *zHistory = 0;      char *zHistory;
       int nHistory;        int nHistory;
       printf(        printf(
         "SQLite version %s %.19s\n" /*extra-version-info*/          "SQLite version %s %.19s\n" /*extra-version-info*/
Line 5569  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ Line 21485  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
         printf(".\nUse \".open FILENAME\" to reopen on a "          printf(".\nUse \".open FILENAME\" to reopen on a "
                "persistent database.\n");                 "persistent database.\n");
       }        }
      zHome = find_home_dir();      zHistory = getenv("SQLITE_HISTORY");
      if( zHome ){      if( zHistory ){
         zHistory = strdup(zHistory);
       }else if( (zHome = find_home_dir(0))!=0 ){
         nHistory = strlen30(zHome) + 20;          nHistory = strlen30(zHome) + 20;
         if( (zHistory = malloc(nHistory))!=0 ){          if( (zHistory = malloc(nHistory))!=0 ){
           sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome);            sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome);
         }          }
       }        }
       if( zHistory ){ shell_read_history(zHistory); }        if( zHistory ){ shell_read_history(zHistory); }
      rc = process_input(&data, 0);#if HAVE_READLINE || HAVE_EDITLINE
       rl_attempted_completion_function = readline_completion;
 #elif HAVE_LINENOISE
       linenoiseSetCompletionCallback(linenoise_completion);
 #endif
       data.in = 0;
       rc = process_input(&data);
       if( zHistory ){        if( zHistory ){
        shell_stifle_history(100);        shell_stifle_history(2000);
         shell_write_history(zHistory);          shell_write_history(zHistory);
         free(zHistory);          free(zHistory);
       }        }
     }else{      }else{
      rc = process_input(&data, stdin);      data.in = stdin;
       rc = process_input(&data);
     }      }
   }    }
     free(azCmd);
   set_table_name(&data, 0);    set_table_name(&data, 0);
   if( data.db ){    if( data.db ){
     session_close_all(&data);      session_close_all(&data);
    sqlite3_close(data.db);    close_db(data.db);
   }    }
   sqlite3_free(data.zFreeOnClose);    sqlite3_free(data.zFreeOnClose);
     find_home_dir(1);
     output_reset(&data);
     data.doXdgOpen = 0;
     clearTempFile(&data);
 #if !SQLITE_SHELL_IS_UTF8  #if !SQLITE_SHELL_IS_UTF8
  for(i=0; i<argc; i++) sqlite3_free(argv[i]);  for(i=0; i<argcToFree; i++) free(argvToFree[i]);
  sqlite3_free(argv);  free(argvToFree);
 #endif  #endif
     free(data.colWidth);
     /* Clear the global data structure so that valgrind will detect memory
     ** leaks */
     memset(&data, 0, sizeof(data));
   return rc;    return rc;
 }  }

Removed from v.1.4  
changed lines
  Added in v.1.6


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>