Diff for /elwix/files/sqlite/dist/shell.c between versions 1.4.2.2 and 1.4.2.3

version 1.4.2.2, 2019/09/26 13:02:35 version 1.4.2.3, 2020/08/17 12:20:05
Line 36 Line 36
 #endif  #endif
   
 /*  /*
   ** Determine if we are dealing with WinRT, which provides only a subset of
   ** the full Win32 API.
   */
   #if !defined(SQLITE_OS_WINRT)
   # define SQLITE_OS_WINRT 0
   #endif
   
   /*
 ** Warning pragmas copied from msvc.h in the core.  ** Warning pragmas copied from msvc.h in the core.
 */  */
 #if defined(_MSC_VER)  #if defined(_MSC_VER)
Line 147  typedef unsigned char u8; Line 155  typedef unsigned char u8;
   
   
 #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
 # ifndef unlink  
 #  define unlink _unlink  
 # endif  
 # ifndef strdup  
 #  define strdup _strdup  
 # 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 191  typedef unsigned char u8; Line 203  typedef unsigned char u8;
 #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 */
Line 206  extern LPWSTR sqlite3_win32_utf8_to_unicode(const char Line 221  extern LPWSTR sqlite3_win32_utf8_to_unicode(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 310  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 326  static int hasTimer(void){ Line 342  static int hasTimer(void){
         FreeLibrary(hinstLib);          FreeLibrary(hinstLib);
       }        }
     }      }
   #endif
   }    }
   return 0;    return 0;
 }  }
Line 415  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 466  static void shell_out_of_memory(void){ Line 492  static void shell_out_of_memory(void){
   exit(1);    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 573  static int strlenChar(const char *z){ Line 642  static int strlenChar(const char *z){
 }  }
   
 /*  /*
   ** 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 884  static void shellModuleSchema( Line 968  static void shellModuleSchema(
 **    CREATE VIRTUAL TABLE  **    CREATE VIRTUAL TABLE
 **  **
 ** This UDF is used by the .schema command to insert the schema name of  ** This UDF is used by the .schema command to insert the schema name of
** attached databases into the middle of the sqlite_master.sql field.** attached databases into the middle of the sqlite_schema.sql field.
 */  */
 static void shellAddSchemaName(  static void shellAddSchemaName(
   sqlite3_context *pCtx,    sqlite3_context *pCtx,
Line 2007  int sqlite3_shathree_init( Line 2091  int sqlite3_shathree_init(
   int rc = SQLITE_OK;    int rc = SQLITE_OK;
   SQLITE_EXTENSION_INIT2(pApi);    SQLITE_EXTENSION_INIT2(pApi);
   (void)pzErrMsg;  /* Unused parameter */    (void)pzErrMsg;  /* Unused parameter */
  rc = sqlite3_create_function(db, "sha3", 1, SQLITE_UTF8, 0,  rc = sqlite3_create_function(db, "sha3", 1,
                               sha3Func, 0, 0);                      SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC,
                       0, sha3Func, 0, 0);
   if( rc==SQLITE_OK ){    if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "sha3", 2, SQLITE_UTF8, 0,    rc = sqlite3_create_function(db, "sha3", 2,
                                 sha3Func, 0, 0);                      SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC,
                       0, sha3Func, 0, 0);
   }    }
   if( rc==SQLITE_OK ){    if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "sha3_query", 1, SQLITE_UTF8, 0,    rc = sqlite3_create_function(db, "sha3_query", 1,
                                 sha3QueryFunc, 0, 0);                      SQLITE_UTF8 | SQLITE_DIRECTONLY,
                       0, sha3QueryFunc, 0, 0);
   }    }
   if( rc==SQLITE_OK ){    if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "sha3_query", 2, SQLITE_UTF8, 0,    rc = sqlite3_create_function(db, "sha3_query", 2,
                                 sha3QueryFunc, 0, 0);                      SQLITE_UTF8 | SQLITE_DIRECTONLY,
                       0, sha3QueryFunc, 0, 0);
   }    }
   return rc;    return rc;
 }  }
Line 2422  static int writeFile( Line 2510  static int writeFile(
   
   if( mtime>=0 ){    if( mtime>=0 ){
 #if defined(_WIN32)  #if defined(_WIN32)
   #if !SQLITE_OS_WINRT
     /* Windows */      /* Windows */
     FILETIME lastAccess;      FILETIME lastAccess;
     FILETIME lastWrite;      FILETIME lastWrite;
Line 2452  static int writeFile( Line 2541  static int writeFile(
     }else{      }else{
       return 1;        return 1;
     }      }
   #endif
 #elif defined(AT_FDCWD) && 0 /* utimensat() is not universally available */  #elif defined(AT_FDCWD) && 0 /* utimensat() is not universally available */
     /* Recent unix */      /* Recent unix */
     struct timespec times[2];      struct timespec times[2];
Line 2613  static int fsdirConnect( Line 2703  static int fsdirConnect(
     pNew = (fsdir_tab*)sqlite3_malloc( sizeof(*pNew) );      pNew = (fsdir_tab*)sqlite3_malloc( sizeof(*pNew) );
     if( pNew==0 ) return SQLITE_NOMEM;      if( pNew==0 ) return SQLITE_NOMEM;
     memset(pNew, 0, sizeof(*pNew));      memset(pNew, 0, sizeof(*pNew));
       sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY);
   }    }
   *ppVtab = (sqlite3_vtab*)pNew;    *ppVtab = (sqlite3_vtab*)pNew;
   return rc;    return rc;
Line 3006  int sqlite3_fileio_init( Line 3097  int sqlite3_fileio_init(
   int rc = SQLITE_OK;    int rc = SQLITE_OK;
   SQLITE_EXTENSION_INIT2(pApi);    SQLITE_EXTENSION_INIT2(pApi);
   (void)pzErrMsg;  /* Unused parameter */    (void)pzErrMsg;  /* Unused parameter */
  rc = sqlite3_create_function(db, "readfile", 1, SQLITE_UTF8, 0,  rc = sqlite3_create_function(db, "readfile", 1, 
                                SQLITE_UTF8|SQLITE_DIRECTONLY, 0,
                                readfileFunc, 0, 0);                                 readfileFunc, 0, 0);
   if( rc==SQLITE_OK ){    if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "writefile", -1, SQLITE_UTF8, 0,    rc = sqlite3_create_function(db, "writefile", -1,
                                  SQLITE_UTF8|SQLITE_DIRECTONLY, 0,
                                  writefileFunc, 0, 0);                                   writefileFunc, 0, 0);
   }    }
   if( rc==SQLITE_OK ){    if( rc==SQLITE_OK ){
Line 3144  static int completionConnect( Line 3237  static int completionConnect(
 #define COMPLETION_COLUMN_WHOLELINE 2  /* Entire line seen so far */  #define COMPLETION_COLUMN_WHOLELINE 2  /* Entire line seen so far */
 #define COMPLETION_COLUMN_PHASE     3  /* ePhase - used for debugging only */  #define COMPLETION_COLUMN_PHASE     3  /* ePhase - used for debugging only */
   
     sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
   rc = sqlite3_declare_vtab(db,    rc = sqlite3_declare_vtab(db,
       "CREATE TABLE x("        "CREATE TABLE x("
       "  candidate TEXT,"        "  candidate TEXT,"
Line 3251  static int completionNext(sqlite3_vtab_cursor *cur){ Line 3345  static int completionNext(sqlite3_vtab_cursor *cur){
             const char *zDb = (const char*)sqlite3_column_text(pS2, 1);              const char *zDb = (const char*)sqlite3_column_text(pS2, 1);
             zSql = sqlite3_mprintf(              zSql = sqlite3_mprintf(
                "%z%s"                 "%z%s"
               "SELECT name FROM \"%w\".sqlite_master",               "SELECT name FROM \"%w\".sqlite_schema",
                zSql, zSep, zDb                 zSql, zSep, zDb
             );              );
             if( zSql==0 ) return SQLITE_NOMEM;              if( zSql==0 ) return SQLITE_NOMEM;
Line 3275  static int completionNext(sqlite3_vtab_cursor *cur){ Line 3369  static int completionNext(sqlite3_vtab_cursor *cur){
             const char *zDb = (const char*)sqlite3_column_text(pS2, 1);              const char *zDb = (const char*)sqlite3_column_text(pS2, 1);
             zSql = sqlite3_mprintf(              zSql = sqlite3_mprintf(
                "%z%s"                 "%z%s"
               "SELECT pti.name FROM \"%w\".sqlite_master AS sm"               "SELECT pti.name FROM \"%w\".sqlite_schema AS sm"
                        " JOIN pragma_table_info(sm.name,%Q) AS pti"                         " JOIN pragma_table_info(sm.name,%Q) AS pti"
                " WHERE sm.type='table'",                 " WHERE sm.type='table'",
                zSql, zSep, zDb, zDb                 zSql, zSep, zDb, zDb
Line 3968  static int apndOpen( Line 4062  static int apndOpen(
   p = (ApndFile*)pFile;    p = (ApndFile*)pFile;
   memset(p, 0, sizeof(*p));    memset(p, 0, sizeof(*p));
   pSubFile = ORIGFILE(pFile);    pSubFile = ORIGFILE(pFile);
  p->base.pMethods = &apnd_io_methods;  pFile->pMethods = &apnd_io_methods;
   rc = pSubVfs->xOpen(pSubVfs, zName, pSubFile, flags, pOutFlags);    rc = pSubVfs->xOpen(pSubVfs, zName, pSubFile, flags, pOutFlags);
   if( rc ) goto apnd_open_done;    if( rc ) goto apnd_open_done;
   rc = pSubFile->pMethods->xFileSize(pSubFile, &sz);    rc = pSubFile->pMethods->xFileSize(pSubFile, &sz);
Line 4205  int sqlite3MemTraceDeactivate(void){ Line 4299  int sqlite3MemTraceDeactivate(void){
 }  }
   
 /************************* End ../ext/misc/memtrace.c ********************/  /************************* 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]);
       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 ********************/
 #ifdef SQLITE_HAVE_ZLIB  #ifdef SQLITE_HAVE_ZLIB
 /************************* Begin ../ext/misc/zipfile.c ******************/  /************************* Begin ../ext/misc/zipfile.c ******************/
 /*  /*
Line 4578  static int zipfileConnect( Line 5688  static int zipfileConnect(
       zipfileDequote(pNew->zFile);        zipfileDequote(pNew->zFile);
     }      }
   }    }
     sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY);
   *ppVtab = (sqlite3_vtab*)pNew;    *ppVtab = (sqlite3_vtab*)pNew;
   return rc;    return rc;
 }  }
Line 5190  static int zipfileDeflate( Line 6301  static int zipfileDeflate(
   u8 **ppOut, int *pnOut,         /* Output */    u8 **ppOut, int *pnOut,         /* Output */
   char **pzErr                    /* OUT: Error message */    char **pzErr                    /* OUT: Error message */
 ){  ){
   sqlite3_int64 nAlloc = compressBound(nIn);  
   u8 *aOut;  
   int rc = SQLITE_OK;    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);    aOut = (u8*)sqlite3_malloc64(nAlloc);
   if( aOut==0 ){    if( aOut==0 ){
     rc = SQLITE_NOMEM;      rc = SQLITE_NOMEM;
   }else{    }else{
     int res;      int res;
     z_stream str;  
     memset(&str, 0, sizeof(str));  
     str.next_in = (Bytef*)aIn;  
     str.avail_in = nIn;  
     str.next_out = aOut;      str.next_out = aOut;
     str.avail_out = nAlloc;      str.avail_out = nAlloc;
   
     deflateInit2(&str, 9, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);  
     res = deflate(&str, Z_FINISH);      res = deflate(&str, Z_FINISH);
   
     if( res==Z_STREAM_END ){      if( res==Z_STREAM_END ){
       *ppOut = aOut;        *ppOut = aOut;
       *pnOut = (int)str.total_out;        *pnOut = (int)str.total_out;
Line 5517  static int zipfileBestIndex( Line 6628  static int zipfileBestIndex(
       idx = i;        idx = i;
     }      }
   }    }
     pIdxInfo->estimatedCost = 1000.0;
   if( idx>=0 ){    if( idx>=0 ){
     pIdxInfo->aConstraintUsage[idx].argvIndex = 1;      pIdxInfo->aConstraintUsage[idx].argvIndex = 1;
     pIdxInfo->aConstraintUsage[idx].omit = 1;      pIdxInfo->aConstraintUsage[idx].omit = 1;
     pIdxInfo->estimatedCost = 1000.0;  
     pIdxInfo->idxNum = 1;      pIdxInfo->idxNum = 1;
   }else if( unusable ){    }else if( unusable ){
     return SQLITE_CONSTRAINT;      return SQLITE_CONSTRAINT;
Line 5642  static int zipfileGetMode( Line 6753  static int zipfileGetMode(
 ** identical, ignoring any trailing '/' character in either path.  */  ** identical, ignoring any trailing '/' character in either path.  */
 static int zipfileComparePath(const char *zA, const char *zB, int nB){  static int zipfileComparePath(const char *zA, const char *zB, int nB){
   int nA = (int)strlen(zA);    int nA = (int)strlen(zA);
  if( zA[nA-1]=='/' ) nA--;  if( nA>0 && zA[nA-1]=='/' ) nA--;
  if( zB[nB-1]=='/' ) nB--;  if( nB>0 && zB[nB-1]=='/' ) nB--;
   if( nA==nB && memcmp(zA, zB, nA)==0 ) return 0;    if( nA==nB && memcmp(zA, zB, nA)==0 ) return 0;
   return 1;    return 1;
 }  }
Line 5653  static int zipfileBegin(sqlite3_vtab *pVtab){ Line 6764  static int zipfileBegin(sqlite3_vtab *pVtab){
   int rc = SQLITE_OK;    int rc = SQLITE_OK;
   
   assert( pTab->pWriteFd==0 );    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    /* Open a write fd on the file. Also load the entire central directory
   ** structure into memory. During the transaction any new file data is     ** structure into memory. During the transaction any new file data is 
Line 5827  static int zipfileUpdate( Line 6942  static int zipfileUpdate(
   
     if( rc==SQLITE_OK ){      if( rc==SQLITE_OK ){
       zPath = (const char*)sqlite3_value_text(apVal[2]);        zPath = (const char*)sqlite3_value_text(apVal[2]);
         if( zPath==0 ) zPath = "";
       nPath = (int)strlen(zPath);        nPath = (int)strlen(zPath);
       mTime = zipfileGetTime(apVal[4]);        mTime = zipfileGetTime(apVal[4]);
     }      }
Line 5836  static int zipfileUpdate( Line 6952  static int zipfileUpdate(
       ** '/'. This appears to be required for compatibility with info-zip        ** '/'. This appears to be required for compatibility with info-zip
       ** (the unzip command on unix). It does not create directories        ** (the unzip command on unix). It does not create directories
       ** otherwise.  */        ** otherwise.  */
      if( zPath[nPath-1]!='/' ){      if( nPath<=0 || zPath[nPath-1]!='/' ){
         zFree = sqlite3_mprintf("%s/", zPath);          zFree = sqlite3_mprintf("%s/", zPath);
         if( zFree==0 ){ rc = SQLITE_NOMEM; }  
         zPath = (const char*)zFree;          zPath = (const char*)zFree;
        nPath++;        if( zFree==0 ){
           rc = SQLITE_NOMEM;
           nPath = 0;
         }else{
           nPath = (int)strlen(zPath);
         }
       }        }
     }      }
   
Line 6233  void zipfileStep(sqlite3_context *pCtx, int nVal, sqli Line 7353  void zipfileStep(sqlite3_context *pCtx, int nVal, sqli
   ** at the end of the path. Or, if this is not a directory and the path    ** at the end of the path. Or, if this is not a directory and the path
   ** ends in '/' it is an error. */    ** ends in '/' it is an error. */
   if( bIsDir==0 ){    if( bIsDir==0 ){
    if( zName[nName-1]=='/' ){    if( nName>0 && zName[nName-1]=='/' ){
       zErr = sqlite3_mprintf("non-directory name must not end with /");        zErr = sqlite3_mprintf("non-directory name must not end with /");
       rc = SQLITE_ERROR;        rc = SQLITE_ERROR;
       goto zipfile_step_out;        goto zipfile_step_out;
     }      }
   }else{    }else{
    if( zName[nName-1]!='/' ){    if( nName==0 || zName[nName-1]!='/' ){
       zName = zFree = sqlite3_mprintf("%s/", zName);        zName = zFree = sqlite3_mprintf("%s/", zName);
       nName++;  
       if( zName==0 ){        if( zName==0 ){
         rc = SQLITE_NOMEM;          rc = SQLITE_NOMEM;
         goto zipfile_step_out;          goto zipfile_step_out;
       }        }
         nName = (int)strlen(zName);
     }else{      }else{
       while( nName>1 && zName[nName-2]=='/' ) nName--;        while( nName>1 && zName[nName-2]=='/' ) nName--;
     }      }
Line 6407  int sqlite3_zipfile_init( Line 7527  int sqlite3_zipfile_init(
 /* #include "sqlite3ext.h" */  /* #include "sqlite3ext.h" */
 SQLITE_EXTENSION_INIT1  SQLITE_EXTENSION_INIT1
 #include <zlib.h>  #include <zlib.h>
   #include <assert.h>
   
 /*  /*
 ** Implementation of the "sqlar_compress(X)" SQL function.  ** Implementation of the "sqlar_compress(X)" SQL function.
Line 6501  int sqlite3_sqlar_init( Line 7622  int sqlite3_sqlar_init(
   int rc = SQLITE_OK;    int rc = SQLITE_OK;
   SQLITE_EXTENSION_INIT2(pApi);    SQLITE_EXTENSION_INIT2(pApi);
   (void)pzErrMsg;  /* Unused parameter */    (void)pzErrMsg;  /* Unused parameter */
  rc = sqlite3_create_function(db, "sqlar_compress", 1, SQLITE_UTF8, 0,  rc = sqlite3_create_function(db, "sqlar_compress", 1, 
                                SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
                                sqlarCompressFunc, 0, 0);                                 sqlarCompressFunc, 0, 0);
   if( rc==SQLITE_OK ){    if( rc==SQLITE_OK ){
    rc = sqlite3_create_function(db, "sqlar_uncompress", 2, SQLITE_UTF8, 0,    rc = sqlite3_create_function(db, "sqlar_uncompress", 2,
                                  SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
                                  sqlarUncompressFunc, 0, 0);                                   sqlarUncompressFunc, 0, 0);
   }    }
   return rc;    return rc;
Line 6525  int sqlite3_sqlar_init( Line 7648  int sqlite3_sqlar_init(
 **  **
 *************************************************************************  *************************************************************************
 */  */
#if !defined(SQLITEEXPERT_H)
#define SQLITEEXPERT_H 1
 /* #include "sqlite3.h" */  /* #include "sqlite3.h" */
   
 typedef struct sqlite3expert sqlite3expert;  typedef struct sqlite3expert sqlite3expert;
Line 6680  const char *sqlite3_expert_report(sqlite3expert*, int  Line 7803  const char *sqlite3_expert_report(sqlite3expert*, int 
 */  */
 void sqlite3_expert_destroy(sqlite3expert*);  void sqlite3_expert_destroy(sqlite3expert*);
   
   #endif  /* !defined(SQLITEEXPERT_H) */
   
   
 /************************* End ../ext/expert/sqlite3expert.h ********************/  /************************* End ../ext/expert/sqlite3expert.h ********************/
 /************************* Begin ../ext/expert/sqlite3expert.c ******************/  /************************* Begin ../ext/expert/sqlite3expert.c ******************/
 /*  /*
Line 7814  int idxFindIndexes( Line 8937  int idxFindIndexes(
       /* int iParent = sqlite3_column_int(pExplain, 1); */        /* int iParent = sqlite3_column_int(pExplain, 1); */
       /* int iNotUsed = sqlite3_column_int(pExplain, 2); */        /* int iNotUsed = sqlite3_column_int(pExplain, 2); */
       const char *zDetail = (const char*)sqlite3_column_text(pExplain, 3);        const char *zDetail = (const char*)sqlite3_column_text(pExplain, 3);
      int nDetail = STRLEN(zDetail);      int nDetail;
       int i;        int i;
   
         if( !zDetail ) continue;
         nDetail = STRLEN(zDetail);
   
       for(i=0; i<nDetail; i++){        for(i=0; i<nDetail; i++){
         const char *zIdx = 0;          const char *zIdx = 0;
        if( memcmp(&zDetail[i], " USING INDEX ", 13)==0 ){        if( i+13<nDetail && memcmp(&zDetail[i], " USING INDEX ", 13)==0 ){
           zIdx = &zDetail[i+13];            zIdx = &zDetail[i+13];
        }else if( memcmp(&zDetail[i], " USING COVERING INDEX ", 22)==0 ){        }else if( i+22<nDetail 
             && memcmp(&zDetail[i], " USING COVERING INDEX ", 22)==0 
         ){
           zIdx = &zDetail[i+22];            zIdx = &zDetail[i+22];
         }          }
         if( zIdx ){          if( zIdx ){
Line 7904  static int idxProcessOneTrigger( Line 9032  static int idxProcessOneTrigger(
   IdxTable *pTab = pWrite->pTab;    IdxTable *pTab = pWrite->pTab;
   const char *zTab = pTab->zName;    const char *zTab = pTab->zName;
   const char *zSql =     const char *zSql = 
    "SELECT 'CREATE TEMP' || substr(sql, 7) FROM sqlite_master "    "SELECT 'CREATE TEMP' || substr(sql, 7) FROM sqlite_schema "
     "WHERE tbl_name = %Q AND type IN ('table', 'trigger') "      "WHERE tbl_name = %Q AND type IN ('table', 'trigger') "
     "ORDER BY type;";      "ORDER BY type;";
   sqlite3_stmt *pSelect = 0;    sqlite3_stmt *pSelect = 0;
Line 8004  static int idxCreateVtabSchema(sqlite3expert *p, char  Line 9132  static int idxCreateVtabSchema(sqlite3expert *p, char 
   **   2) Create the equivalent virtual table in dbv.    **   2) Create the equivalent virtual table in dbv.
   */    */
   rc = idxPrepareStmt(p->db, &pSchema, pzErrmsg,    rc = idxPrepareStmt(p->db, &pSchema, pzErrmsg,
      "SELECT type, name, sql, 1 FROM sqlite_master "      "SELECT type, name, sql, 1 FROM sqlite_schema "
       "WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%%' "        "WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%%' "
       " UNION ALL "        " UNION ALL "
      "SELECT type, name, sql, 2 FROM sqlite_master "      "SELECT type, name, sql, 2 FROM sqlite_schema "
       "WHERE type = 'trigger'"        "WHERE type = 'trigger'"
      "  AND tbl_name IN(SELECT name FROM sqlite_master WHERE type = 'view') "      "  AND tbl_name IN(SELECT name FROM sqlite_schema WHERE type = 'view') "
       "ORDER BY 4, 1"        "ORDER BY 4, 1"
   );    );
   while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSchema) ){    while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSchema) ){
Line 8179  static int idxLargestIndex(sqlite3 *db, int *pnMax, ch Line 9307  static int idxLargestIndex(sqlite3 *db, int *pnMax, ch
   int rc = SQLITE_OK;    int rc = SQLITE_OK;
   const char *zMax =     const char *zMax = 
     "SELECT max(i.seqno) FROM "      "SELECT max(i.seqno) FROM "
    "  sqlite_master AS s, "    "  sqlite_schema AS s, "
     "  pragma_index_list(s.name) AS l, "      "  pragma_index_list(s.name) AS l, "
     "  pragma_index_info(l.name) AS i "      "  pragma_index_info(l.name) AS i "
     "WHERE s.type = 'table'";      "WHERE s.type = 'table'";
Line 8332  static int idxPopulateStat1(sqlite3expert *p, char **p Line 9460  static int idxPopulateStat1(sqlite3expert *p, char **p
   
   const char *zAllIndex =    const char *zAllIndex =
     "SELECT s.rowid, s.name, l.name FROM "      "SELECT s.rowid, s.name, l.name FROM "
    "  sqlite_master AS s, "    "  sqlite_schema AS s, "
     "  pragma_index_list(s.name) AS l "      "  pragma_index_list(s.name) AS l "
     "WHERE s.type = 'table'";      "WHERE s.type = 'table'";
   const char *zIndexXInfo =     const char *zIndexXInfo = 
Line 8406  static int idxPopulateStat1(sqlite3expert *p, char **p Line 9534  static int idxPopulateStat1(sqlite3expert *p, char **p
   sqlite3_free(pCtx);    sqlite3_free(pCtx);
   
   if( rc==SQLITE_OK ){    if( rc==SQLITE_OK ){
    rc = sqlite3_exec(p->dbm, "ANALYZE sqlite_master", 0, 0, 0);    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);    sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp."UNIQUE_TABLE_NAME,0,0,0);
Line 8445  sqlite3expert *sqlite3_expert_new(sqlite3 *db, char ** Line 9573  sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **
   if( rc==SQLITE_OK ){    if( rc==SQLITE_OK ){
     sqlite3_stmt *pSql;      sqlite3_stmt *pSql;
     rc = idxPrintfPrepareStmt(pNew->db, &pSql, pzErrmsg,       rc = idxPrintfPrepareStmt(pNew->db, &pSql, pzErrmsg, 
        "SELECT sql FROM sqlite_master WHERE name NOT LIKE 'sqlite_%%'"        "SELECT sql FROM sqlite_schema WHERE name NOT LIKE 'sqlite_%%'"
         " AND sql NOT LIKE 'CREATE VIRTUAL %%'"          " AND sql NOT LIKE 'CREATE VIRTUAL %%'"
     );      );
     while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){      while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
Line 8636  void sqlite3_expert_destroy(sqlite3expert *p){ Line 9764  void sqlite3_expert_destroy(sqlite3expert *p){
   }    }
 }  }
   
#endif /* ifndef SQLITE_OMIT_VIRTUAL_TABLE */#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
   
 /************************* End ../ext/expert/sqlite3expert.c ********************/  /************************* End ../ext/expert/sqlite3expert.c ********************/
   
Line 9510  struct OpenSession { Line 10638  struct OpenSession {
 };  };
 #endif  #endif
   
 /*  
 ** Shell output mode information from before ".explain on",  
 ** saved so that it can be restored by ".explain off"  
 */  
 typedef struct SavedModeInfo SavedModeInfo;  
 struct SavedModeInfo {  
   int valid;          /* Is there legit data in here? */  
   int mode;           /* Mode prior to ".explain on" */  
   int showHeader;     /* The ".header" setting prior to ".explain on" */  
   int colWidth[100];  /* Column widths prior to ".explain on" */  
 };  
   
 typedef struct ExpertInfo ExpertInfo;  typedef struct ExpertInfo ExpertInfo;
 struct ExpertInfo {  struct ExpertInfo {
   sqlite3expert *pExpert;    sqlite3expert *pExpert;
Line 9566  struct ShellState { Line 10682  struct ShellState {
   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 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 *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() */
Line 9581  struct ShellState { Line 10698  struct ShellState {
   unsigned mxProgress;   /* Maximum progress callbacks before failing */    unsigned mxProgress;   /* Maximum progress callbacks before failing */
   unsigned flgProgress;  /* Flags for the progress callback */    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 */    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 *zTempFile;       /* Temporary file that might need deleting */
Line 9589  struct ShellState { Line 10707  struct ShellState {
   char rowSeparator[20]; /* Row separator character for MODE_Ascii */    char rowSeparator[20]; /* Row separator character for MODE_Ascii */
   char colSepPrior[20];  /* Saved column separator */    char colSepPrior[20];  /* Saved column separator */
   char rowSepPrior[20];  /* Saved row separator */    char rowSepPrior[20];  /* Saved row separator */
  int colWidth[100];     /* Requested width of each column when in column mode*/  int *colWidth;         /* Requested width of each column in columnar modes */
  int actualWidth[100];  /* Actual width of each column */  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 9651  struct ShellState { Line 10770  struct ShellState {
 #define SHFLG_Newlines       0x00000010 /* .dump --newline flag */  #define SHFLG_Newlines       0x00000010 /* .dump --newline flag */
 #define SHFLG_CountChanges   0x00000020 /* .changes setting */  #define SHFLG_CountChanges   0x00000020 /* .changes setting */
 #define SHFLG_Echo           0x00000040 /* .echo or --echo setting */  #define SHFLG_Echo           0x00000040 /* .echo or --echo setting */
   #define SHFLG_HeaderSet      0x00000080 /* .header has been used */
   
 /*  /*
 ** Macros for testing and setting shellFlgs  ** Macros for testing and setting shellFlgs
Line 9675  struct ShellState { Line 10795  struct ShellState {
 #define MODE_Ascii   10  /* Use ASCII unit and record separators (0x1F/0x1E) */  #define MODE_Ascii   10  /* Use ASCII unit and record separators (0x1F/0x1E) */
 #define MODE_Pretty  11  /* Pretty-print schemas */  #define MODE_Pretty  11  /* Pretty-print schemas */
 #define MODE_EQP     12  /* Converts EXPLAIN QUERY PLAN output into a graph */  #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 9689  static const char *modeDescr[] = { Line 10813  static const char *modeDescr[] = {
   "explain",    "explain",
   "ascii",    "ascii",
   "prettyprint",    "prettyprint",
  "eqp"  "eqp",
   "json",
   "markdown",
   "table",
   "box"
 };  };
   
 /*  /*
Line 9801  static void editFunc( Line 10929  static void editFunc(
   }    }
   sz = sqlite3_value_bytes(argv[0]);    sz = sqlite3_value_bytes(argv[0]);
   if( bBin ){    if( bBin ){
    x = fwrite(sqlite3_value_blob(argv[0]), 1, sz, f);    x = fwrite(sqlite3_value_blob(argv[0]), 1, (size_t)sz, f);
   }else{    }else{
     const char *z = (const char*)sqlite3_value_text(argv[0]);      const char *z = (const char*)sqlite3_value_text(argv[0]);
     /* Remember whether or not the value originally contained \r\n */      /* Remember whether or not the value originally contained \r\n */
     if( z && strstr(z,"\r\n")!=0 ) hasCRNL = 1;      if( z && strstr(z,"\r\n")!=0 ) hasCRNL = 1;
    x = fwrite(sqlite3_value_text(argv[0]), 1, sz, f);    x = fwrite(sqlite3_value_text(argv[0]), 1, (size_t)sz, f);
   }    }
   fclose(f);    fclose(f);
   f = 0;    f = 0;
Line 9834  static void editFunc( Line 10962  static void editFunc(
   fseek(f, 0, SEEK_END);    fseek(f, 0, SEEK_END);
   sz = ftell(f);    sz = ftell(f);
   rewind(f);    rewind(f);
  p = sqlite3_malloc64( sz+(bBin==0) );  p = sqlite3_malloc64( sz+1 );
   if( p==0 ){    if( p==0 ){
     sqlite3_result_error_nomem(context);      sqlite3_result_error_nomem(context);
     goto edit_func_end;      goto edit_func_end;
   }    }
  x = fread(p, 1, sz, f);  x = fread(p, 1, (size_t)sz, f);
   fclose(f);    fclose(f);
   f = 0;    f = 0;
   if( x!=sz ){    if( x!=sz ){
Line 9881  edit_func_end: Line 11009  edit_func_end:
 */  */
 static void outputModePush(ShellState *p){  static void outputModePush(ShellState *p){
   p->modePrior = p->mode;    p->modePrior = p->mode;
     p->priorShFlgs = p->shellFlgs;
   memcpy(p->colSepPrior, p->colSeparator, sizeof(p->colSeparator));    memcpy(p->colSepPrior, p->colSeparator, sizeof(p->colSeparator));
   memcpy(p->rowSepPrior, p->rowSeparator, sizeof(p->rowSeparator));    memcpy(p->rowSepPrior, p->rowSeparator, sizeof(p->rowSeparator));
 }  }
 static void outputModePop(ShellState *p){  static void outputModePop(ShellState *p){
   p->mode = p->modePrior;    p->mode = p->modePrior;
     p->shellFlgs = p->priorShFlgs;
   memcpy(p->colSeparator, p->colSepPrior, sizeof(p->colSeparator));    memcpy(p->colSeparator, p->colSepPrior, sizeof(p->colSeparator));
   memcpy(p->rowSeparator, p->rowSepPrior, sizeof(p->rowSeparator));    memcpy(p->rowSeparator, p->rowSepPrior, sizeof(p->rowSeparator));
 }  }
Line 10056  static void output_c_string(FILE *out, const char *z){ Line 11186  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 10311  static void eqp_render_level(ShellState *p, int iEqpId Line 11475  static void eqp_render_level(ShellState *p, int iEqpId
   for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){    for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){
     pNext = eqp_next_row(p, iEqpId, pRow);      pNext = eqp_next_row(p, iEqpId, pRow);
     z = pRow->zText;      z = pRow->zText;
    utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix, pNext ? "|--" : "`--", z);    utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix,
                 pNext ? "|--" : "`--", z);
     if( n<(int)sizeof(p->sGraph.zPrefix)-7 ){      if( n<(int)sizeof(p->sGraph.zPrefix)-7 ){
       memcpy(&p->sGraph.zPrefix[n], pNext ? "|  " : "   ", 4);        memcpy(&p->sGraph.zPrefix[n], pNext ? "|  " : "   ", 4);
       eqp_render_level(p, pRow->iEqpId);        eqp_render_level(p, pRow->iEqpId);
Line 10364  static int progress_handler(void *pClientData) { Line 11529  static int progress_handler(void *pClientData) {
 #endif /* SQLITE_OMIT_PROGRESS_CALLBACK */  #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 10372  static int shell_callback( Line 11571  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;
Line 10393  static int shell_callback( Line 11592  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 = strlenChar(azCol[i] ? azCol[i] : ""); 
            if( w<10 ) w = 10; 
            n = strlenChar(azArg && azArg[i] ? azArg[i] : p->nullValue); 
            if( w<n ) w = n; 
          } 
          if( i<ArraySize(p->actualWidth) ){ 
            p->actualWidth[i] = w; 
          } 
          if( showHdr ){ 
            utf8_width_print(p->out, w, azCol[i]); 
            utf8_printf(p->out, "%s", i==nArg-1 ? rowSep : "  "); 
          } 
         }          }
        if( showHdr ){        for(i=0; i<nArg; i++){
          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( azArg[i] && strlenChar(azArg[i])>w ){
           w = p->actualWidth[i]; 
        }else{ 
           w = 10; 
        } 
        if( p->cMode==MODE_Explain && azArg[i] && strlenChar(azArg[i])>w ){ 
           w = strlenChar(azArg[i]);            w = strlenChar(azArg[i]);
         }          }
         if( i==1 && p->aiIndent && p->pStmt ){          if( i==1 && p->aiIndent && p->pStmt ){
Line 10464  static int shell_callback( Line 11622  static int shell_callback(
           p->iIndent++;            p->iIndent++;
         }          }
         utf8_width_print(p->out, w, azArg[i] ? azArg[i] : p->nullValue);          utf8_width_print(p->out, w, azArg[i] ? azArg[i] : p->nullValue);
        utf8_printf(p->out, "%s", i==nArg-1 ? rowSep : "  ");        fputs(i==nArg-1 ? "\n" : "  ", p->out);
       }        }
       break;        break;
     }      }
Line 10502  static int shell_callback( Line 11660  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++){  /* Copy changes from z[i] back to z[j] */        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=='`' ){
Line 10668  static int shell_callback( Line 11826  static int shell_callback(
       raw_printf(p->out,");\n");        raw_printf(p->out,");\n");
       break;        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 ){
             const void *pBlob = sqlite3_column_blob(p->pStmt, i);
             int nBlob = sqlite3_column_bytes(p->pStmt, i);
             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: {      case MODE_Quote: {
       if( azArg==0 ) break;        if( azArg==0 ) break;
       if( p->cnt==0 && p->showHeader ){        if( p->cnt==0 && p->showHeader ){
         for(i=0; i<nArg; i++){          for(i=0; i<nArg; i++){
          if( i>0 ) raw_printf(p->out, ",");          if( i>0 ) fputs(p->colSeparator, p->out);
           output_quoted_string(p->out, azCol[i]);            output_quoted_string(p->out, azCol[i]);
         }          }
        raw_printf(p->out,"\n");        fputs(p->rowSeparator, p->out);
       }        }
       p->cnt++;        p->cnt++;
       for(i=0; i<nArg; i++){        for(i=0; i<nArg; i++){
        if( i>0 ) raw_printf(p->out, ",");        if( i>0 ) fputs(p->colSeparator, p->out);
         if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){          if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
           utf8_printf(p->out,"NULL");            utf8_printf(p->out,"NULL");
         }else if( aiType && aiType[i]==SQLITE_TEXT ){          }else if( aiType && aiType[i]==SQLITE_TEXT ){
Line 10701  static int shell_callback( Line 11901  static int shell_callback(
           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 10774  static void createSelftestTable(ShellState *p){ Line 11974  static void createSelftestTable(ShellState *p){
     "INSERT INTO [_shell$self]\n"      "INSERT INTO [_shell$self]\n"
     "  SELECT 'run',\n"      "  SELECT 'run',\n"
     "    'SELECT hex(sha3_query(''SELECT type,name,tbl_name,sql "      "    'SELECT hex(sha3_query(''SELECT type,name,tbl_name,sql "
                                 "FROM sqlite_master ORDER BY 2'',224))',\n"                                 "FROM sqlite_schema ORDER BY 2'',224))',\n"
     "    hex(sha3_query('SELECT type,name,tbl_name,sql "      "    hex(sha3_query('SELECT type,name,tbl_name,sql "
                          "FROM sqlite_master ORDER BY 2',224));\n"                          "FROM sqlite_schema ORDER BY 2',224));\n"
     "INSERT INTO [_shell$self]\n"      "INSERT INTO [_shell$self]\n"
     "  SELECT 'run',"      "  SELECT 'run',"
     "    'SELECT hex(sha3_query(''SELECT * FROM \"' ||"      "    'SELECT hex(sha3_query(''SELECT * FROM \"' ||"
     "        printf('%w',name) || '\" NOT INDEXED'',224))',\n"      "        printf('%w',name) || '\" NOT INDEXED'',224))',\n"
     "    hex(sha3_query(printf('SELECT * FROM \"%w\" NOT INDEXED',name),224))\n"      "    hex(sha3_query(printf('SELECT * FROM \"%w\" NOT INDEXED',name),224))\n"
     "  FROM (\n"      "  FROM (\n"
    "    SELECT name FROM sqlite_master\n"    "    SELECT name FROM sqlite_schema\n"
     "     WHERE type='table'\n"      "     WHERE type='table'\n"
     "       AND name<>'selftest'\n"      "       AND name<>'selftest'\n"
     "       AND coalesce(rootpage,0)>0\n"      "       AND coalesce(rootpage,0)>0\n"
Line 10846  static void set_table_name(ShellState *p, const char * Line 12046  static void set_table_name(ShellState *p, const char *
 */  */
 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 10864  static int run_table_dump_query( Line 12063  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 11081  static int display_stats( Line 12276  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);    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE,bReset);
     raw_printf(pArg->out, "Reprepare operations:                %d\n", iCur);      raw_printf(pArg->out, "Reprepare operations:                %d\n", iCur);
     iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset);      iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset);
     raw_printf(pArg->out, "Number of times run:                 %d\n", iCur);      raw_printf(pArg->out, "Number of times run:                 %d\n", iCur);
Line 11272  static void explain_data_delete(ShellState *p){ Line 12467  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)  #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
extern int sqlite3SelectTrace;extern unsigned int sqlite3_unsupported_selecttrace;
 static int savedSelectTrace;  static int savedSelectTrace;
 #endif  #endif
 #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)  #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
Line 11281  static int savedWhereTrace; Line 12476  static int savedWhereTrace;
 #endif  #endif
 static void disable_debug_trace_modes(void){  static void disable_debug_trace_modes(void){
 #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)  #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
  savedSelectTrace = sqlite3SelectTrace;  savedSelectTrace = sqlite3_unsupported_selecttrace;
  sqlite3SelectTrace = 0;  sqlite3_unsupported_selecttrace = 0;
 #endif  #endif
 #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)  #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
   savedWhereTrace = sqlite3WhereTrace;    savedWhereTrace = sqlite3WhereTrace;
Line 11291  static void disable_debug_trace_modes(void){ Line 12486  static void disable_debug_trace_modes(void){
 }  }
 static void restore_debug_trace_modes(void){  static void restore_debug_trace_modes(void){
 #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)  #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
  sqlite3SelectTrace = savedSelectTrace;  sqlite3_unsupported_selecttrace = savedSelectTrace;
 #endif  #endif
 #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)  #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_WHERETRACE)
   sqlite3WhereTrace = savedWhereTrace;    sqlite3WhereTrace = savedWhereTrace;
Line 11301  static void restore_debug_trace_modes(void){ Line 12496  static void restore_debug_trace_modes(void){
 /* Create the TEMP table used to store parameter bindings */  /* Create the TEMP table used to store parameter bindings */
 static void bind_table_init(ShellState *p){  static void bind_table_init(ShellState *p){
   int wrSchema = 0;    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, &wrSchema);
   sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0);    sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0);
   sqlite3_exec(p->db,    sqlite3_exec(p->db,
Line 11310  static void bind_table_init(ShellState *p){ Line 12508  static void bind_table_init(ShellState *p){
     ") WITHOUT ROWID;",      ") WITHOUT ROWID;",
     0, 0, 0);      0, 0, 0);
   sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0);    sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0);
     sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, defensiveMode, 0);
 }  }
   
 /*  /*
Line 11320  static void bind_table_init(ShellState *p){ Line 12519  static void bind_table_init(ShellState *p){
 **    CREATE TEMP TABLE sqlite_parameters(key TEXT PRIMARY KEY, value)  **    CREATE TEMP TABLE sqlite_parameters(key TEXT PRIMARY KEY, value)
 **    WITHOUT ROWID;  **    WITHOUT ROWID;
 **  **
** No bindings occur if this table does not exist.  The special character '$'** No bindings occur if this table does not exist.  The name of the table
** is included in the table name to help prevent collisions with actual tables.** begins with "sqlite_" so that it will not collide with ordinary application
** The table must be in the TEMP schema.** tables.  The table must be in the TEMP schema.
 */  */
 static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){  static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){
   int nVar;    int nVar;
Line 11359  static void bind_prepared_stmt(ShellState *pArg, sqlit Line 12558  static void bind_prepared_stmt(ShellState *pArg, sqlit
 }  }
   
 /*  /*
   ** 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(
Line 11367  static void exec_prepared_stmt( Line 12792  static void exec_prepared_stmt(
 ){  ){
   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.
   */    */
Line 11414  static void exec_prepared_stmt( Line 12848  static void exec_prepared_stmt(
         }          }
       } while( SQLITE_ROW == rc );        } while( SQLITE_ROW == rc );
       sqlite3_free(pData);        sqlite3_free(pData);
         if( pArg->cMode==MODE_Json ){
           fputs("]\n", pArg->out);
         }
     }      }
   }    }
 }  }
Line 11626  static int shell_exec( Line 13063  static int shell_exec(
             const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);              const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);
             int iEqpId = sqlite3_column_int(pExplain, 0);              int iEqpId = sqlite3_column_int(pExplain, 0);
             int iParentId = sqlite3_column_int(pExplain, 1);              int iParentId = sqlite3_column_int(pExplain, 1);
               if( zEQPLine==0 ) zEQPLine = "";
             if( zEQPLine[0]=='-' ) eqp_render(pArg);              if( zEQPLine[0]=='-' ) eqp_render(pArg);
             eqp_append(pArg, iEqpId, iParentId, zEQPLine);              eqp_append(pArg, iEqpId, iParentId, zEQPLine);
           }            }
Line 11863  static int dump_callback(void *pArg, int nArg, char ** Line 13301  static int dump_callback(void *pArg, int nArg, char **
   if( strcmp(zTable, "sqlite_sequence")==0 ){    if( strcmp(zTable, "sqlite_sequence")==0 ){
     raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");      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 ){
    raw_printf(p->out, "ANALYZE sqlite_master;\n");    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( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){    }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
Line 11873  static int dump_callback(void *pArg, int nArg, char ** Line 13311  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);
Line 12004  static const char *(azHelp[]) = { Line 13442  static const char *(azHelp[]) = {
   ".archive ...             Manage SQL archives",    ".archive ...             Manage SQL archives",
   "   Each command must have exactly one of the following options:",    "   Each command must have exactly one of the following options:",
   "     -c, --create               Create a new archive",    "     -c, --create               Create a new archive",
  "     -u, --update               Add files or update files with changed mtime",  "     -u, --update               Add or update files with changed mtime",
  "     -i, --insert               Like -u but always add even if mtime unchanged",  "     -i, --insert               Like -u but always add even if unchanged",
   "     -t, --list                 List contents of archive",    "     -t, --list                 List contents of archive",
   "     -x, --extract              Extract files from archive",    "     -x, --extract              Extract files from archive",
   "   Optional arguments:",    "   Optional arguments:",
   "     -v, --verbose              Print each filename as it is processed",    "     -v, --verbose              Print each filename as it is processed",
  "     -f FILE, --file FILE       Operate on archive FILE (default is current db)",  "     -f FILE, --file FILE       Use archive FILE (default is current db)",
  "     -a FILE, --append FILE     Operate on FILE opened using the apndvfs VFS",  "     -a FILE, --append FILE     Open FILE using the apndvfs VFS",
  "     -C DIR, --directory DIR    Change to directory DIR to read/extract files",  "     -C DIR, --directory DIR    Read/extract files from directory DIR",
   "     -n, --dryrun               Show the SQL that would have occurred",    "     -n, --dryrun               Show the SQL that would have occurred",
   "   Examples:",    "   Examples:",
  "     .ar -cf archive.sar foo bar  # Create archive.sar from files foo and bar",  "     .ar -cf ARCHIVE foo bar  # Create ARCHIVE from files foo and bar",
  "     .ar -tf archive.sar          # List members of archive.sar",  "     .ar -tf ARCHIVE          # List members of ARCHIVE",
  "     .ar -xvf archive.sar         # Verbosely extract files from archive.sar",  "     .ar -xvf ARCHIVE         # Verbosely extract files from ARCHIVE",
   "   See also:",    "   See also:",
   "      http://sqlite.org/cli.html#sqlar_archive_support",    "      http://sqlite.org/cli.html#sqlar_archive_support",
 #endif  #endif
Line 12026  static const char *(azHelp[]) = { Line 13464  static const char *(azHelp[]) = {
 #endif  #endif
   ".backup ?DB? FILE        Backup DB (default \"main\") to FILE",    ".backup ?DB? FILE        Backup DB (default \"main\") to FILE",
   "       --append            Use the appendvfs",    "       --append            Use the appendvfs",
  "       --async             Write to FILE without a journal and without fsync()",  "       --async             Write to FILE without journal and fsync()",
   ".bail on|off             Stop after hitting an error.  Default OFF",    ".bail on|off             Stop after hitting an error.  Default OFF",
   ".binary on|off           Turn binary output on or off.  Default OFF",    ".binary on|off           Turn binary output on or off.  Default OFF",
   ".cd DIRECTORY            Change the working directory to DIRECTORY",    ".cd DIRECTORY            Change the working directory to DIRECTORY",
Line 12036  static const char *(azHelp[]) = { Line 13474  static const char *(azHelp[]) = {
   ".databases               List names and files of attached databases",    ".databases               List names and files of attached databases",
   ".dbconfig ?op? ?val?     List or change sqlite3_db_config() options",    ".dbconfig ?op? ?val?     List or change sqlite3_db_config() options",
   ".dbinfo ?DB?             Show status information about the database",    ".dbinfo ?DB?             Show status information about the database",
  ".dump ?TABLE? ...        Render all database content as SQL",  ".dump ?TABLE?            Render database content as SQL",
   "   Options:",    "   Options:",
   "     --preserve-rowids      Include ROWID values in the output",    "     --preserve-rowids      Include ROWID values in the output",
   "     --newlines             Allow unescaped newline characters in output",    "     --newlines             Allow unescaped newline characters in output",
   "   TABLE is a LIKE pattern for the tables to dump",    "   TABLE is a LIKE pattern for the tables to dump",
     "   Additional LIKE patterns can be given in subsequent arguments",
   ".echo on|off             Turn command echo on or off",    ".echo on|off             Turn command echo on or off",
   ".eqp on|off|full|...     Enable or disable automatic EXPLAIN QUERY PLAN",    ".eqp on|off|full|...     Enable or disable automatic EXPLAIN QUERY PLAN",
   "   Other Modes:",    "   Other Modes:",
 #ifdef SQLITE_DEBUG  #ifdef SQLITE_DEBUG
   "      test                  Show raw EXPLAIN QUERY PLAN output",    "      test                  Show raw EXPLAIN QUERY PLAN output",
  "      trace                 Like \"full\" but also enable \"PRAGMA vdbe_trace\"",  "      trace                 Like \"full\" but enable \"PRAGMA vdbe_trace\"",
 #endif  #endif
   "      trigger               Like \"full\" but also show trigger bytecode",    "      trigger               Like \"full\" but also show trigger bytecode",
  ".excel                   Display the output of next command in a spreadsheet",  ".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",    ".exit ?CODE?             Exit this program with return-code CODE",
  ".expert                  EXPERIMENTAL. Suggest indexes for specified queries",  ".expert                  EXPERIMENTAL. Suggest indexes for queries",
/* Because explain mode comes on automatically now, the ".explain" mode  ".explain ?on|off|auto?   Change the EXPLAIN formatting mode.  Default: auto",
** is removed from the help screen.  It is still supported for legacy, however */ 
/*".explain ?on|off|auto?   Turn EXPLAIN output mode on or off or to automatic",*/ 
   ".filectrl CMD ...        Run various sqlite3_file_control() operations",    ".filectrl CMD ...        Run various sqlite3_file_control() operations",
  "                           Run \".filectrl\" with no arguments for details",  "   --schema SCHEMA         Use SCHEMA instead of \"main\"",
   "   --help                  Show CMD details",
   ".fullschema ?--indent?   Show schema and the content of sqlite_stat tables",    ".fullschema ?--indent?   Show schema and the content of sqlite_stat tables",
   ".headers on|off          Turn display of headers on or off",    ".headers on|off          Turn display of headers on or off",
   ".help ?-all? ?PATTERN?   Show help text for PATTERN",    ".help ?-all? ?PATTERN?   Show help text for PATTERN",
   ".import FILE TABLE       Import data from FILE into TABLE",    ".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  #ifndef SQLITE_OMIT_TEST_CONTROL
   ".imposter INDEX TABLE    Create imposter table TABLE on index INDEX",    ".imposter INDEX TABLE    Create imposter table TABLE on index INDEX",
 #endif  #endif
Line 12080  static const char *(azHelp[]) = { Line 13531  static const char *(azHelp[]) = {
   ".log FILE|off            Turn logging on or off.  FILE can be stderr/stdout",    ".log FILE|off            Turn logging on or off.  FILE can be stderr/stdout",
   ".mode MODE ?TABLE?       Set output mode",    ".mode MODE ?TABLE?       Set output mode",
   "   MODE is one of:",    "   MODE is one of:",
  "     ascii    Columns/rows delimited by 0x1F and 0x1E",  "     ascii     Columns/rows delimited by 0x1F and 0x1E",
  "     csv      Comma-separated values",  "     box       Tables using unicode box-drawing characters",
  "     column   Left-aligned columns.  (See .width)",  "     csv       Comma-separated values",
  "     html     HTML <table> code",  "     column    Output in columns.  (See .width)",
  "     insert   SQL insert statements for TABLE",  "     html      HTML <table> code",
  "     line     One value per line",  "     insert    SQL insert statements for TABLE",
  "     list     Values delimited by \"|\"",  "     json      Results in a JSON array",
  "     quote    Escape answers as for SQL",  "     line      One value per line",
  "     tabs     Tab-separated values",  "     list      Values delimited by \"|\"",
  "     tcl      TCL list elements",  "     markdown  Markdown table format",
   "     quote     Escape answers as for SQL",
   "     table     ASCII-art table",
   "     tabs      Tab-separated values",
   "     tcl       TCL list elements",
   ".nullvalue STRING        Use STRING in place of NULL values",    ".nullvalue STRING        Use STRING in place of NULL values",
  ".once (-e|-x|FILE)       Output for the next SQL command only to FILE",  ".once ?OPTIONS? ?FILE?   Output for the next SQL command only to FILE",
   "     If FILE begins with '|' then open as a pipe",    "     If FILE begins with '|' then open as a pipe",
  "     Other options:",  "       --bom  Put a UTF8 byte-order mark at the beginning",
  "       -e    Invoke system text editor",  "       -e     Send output to the system text editor",
  "       -x    Open in a spreadsheet",  "       -x     Send output as CSV to a spreadsheet (same as \".excel\")",
 #ifdef SQLITE_DEBUG
   ".oom ?--repeat M? ?N?    Simulate an OOM error on the N-th allocation",
 #endif 
   ".open ?OPTIONS? ?FILE?   Close existing database and reopen FILE",    ".open ?OPTIONS? ?FILE?   Close existing database and reopen FILE",
   "     Options:",    "     Options:",
   "        --append        Use appendvfs to append database to the end of FILE",    "        --append        Use appendvfs to append database to the end of FILE",
 #ifdef SQLITE_ENABLE_DESERIALIZE  #ifdef SQLITE_ENABLE_DESERIALIZE
   "        --deserialize   Load into memory useing sqlite3_deserialize()",    "        --deserialize   Load into memory useing sqlite3_deserialize()",
  "        --hexdb         Load the output of \"dbtotxt\" as an in-memory database",  "        --hexdb         Load the output of \"dbtotxt\" as an in-memory db",
   "        --maxsize N     Maximum size for --hexdb or --deserialized database",    "        --maxsize N     Maximum size for --hexdb or --deserialized database",
 #endif  #endif
   "        --new           Initialize FILE to an empty database",    "        --new           Initialize FILE to an empty database",
     "        --nofollow      Do not follow symbolic links",
   "        --readonly      Open FILE readonly",    "        --readonly      Open FILE readonly",
   "        --zip           FILE is a ZIP archive",    "        --zip           FILE is a ZIP archive",
   ".output ?FILE?           Send output to FILE or stdout if FILE is omitted",    ".output ?FILE?           Send output to FILE or stdout if FILE is omitted",
  "     If FILE begins with '|' then open it as a pipe.",  "   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",    ".parameter CMD ...       Manage SQL parameter bindings",
   "   clear                   Erase all bindings",    "   clear                   Erase all bindings",
   "   init                    Initialize the TEMP table that holds bindings",    "   init                    Initialize the TEMP table that holds bindings",
   "   list                    List the current parameter bindings",    "   list                    List the current parameter bindings",
   "   set PARAMETER VALUE     Given SQL parameter PARAMETER a value of VALUE",    "   set PARAMETER VALUE     Given SQL parameter PARAMETER a value of VALUE",
  "                           PARAMETER should start with '$', ':', '@', or '?'",  "                           PARAMETER should start with one of: $ : @ ?",
   "   unset PARAMETER         Remove PARAMETER from the binding table",    "   unset PARAMETER         Remove PARAMETER from the binding table",
   ".print STRING...         Print literal STRING",    ".print STRING...         Print literal STRING",
 #ifndef SQLITE_OMIT_PROGRESS_CALLBACK  #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
Line 12129  static const char *(azHelp[]) = { Line 13592  static const char *(azHelp[]) = {
   ".read FILE               Read input from FILE",    ".read FILE               Read input from FILE",
 #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)  #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
   ".recover                 Recover as much data as possible from corrupt db.",    ".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  #endif
   ".restore ?DB? FILE       Restore content of DB (default \"main\") from FILE",    ".restore ?DB? FILE       Restore content of DB (default \"main\") from FILE",
   ".save FILE               Write in-memory database into FILE",    ".save FILE               Write in-memory database into FILE",
Line 12158  static const char *(azHelp[]) = { Line 13626  static const char *(azHelp[]) = {
 #endif  #endif
   ".sha3sum ...             Compute a SHA3 hash of database content",    ".sha3sum ...             Compute a SHA3 hash of database content",
   "    Options:",    "    Options:",
  "      --schema              Also hash the sqlite_master table",  "      --schema              Also hash the sqlite_schema table",
   "      --sha3-224            Use the sha3-224 algorithm",    "      --sha3-224            Use the sha3-224 algorithm",
  "      --sha3-256            Use the sha3-256 algorithm.  This is the default.",  "      --sha3-256            Use the sha3-256 algorithm (default)",
   "      --sha3-384            Use the sha3-384 algorithm",    "      --sha3-384            Use the sha3-384 algorithm",
   "      --sha3-512            Use the sha3-512 algorithm",    "      --sha3-512            Use the sha3-512 algorithm",
   "    Any other argument is a LIKE pattern for tables to hash",    "    Any other argument is a LIKE pattern for tables to hash",
Line 12194  static const char *(azHelp[]) = { Line 13662  static const char *(azHelp[]) = {
   "    --row                   Trace each row (SQLITE_TRACE_ROW)",    "    --row                   Trace each row (SQLITE_TRACE_ROW)",
   "    --close                 Trace connection close (SQLITE_TRACE_CLOSE)",    "    --close                 Trace connection close (SQLITE_TRACE_CLOSE)",
 #endif /* SQLITE_OMIT_TRACE */  #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",    ".vfsinfo ?AUX?           Information about the top-level VFS",
   ".vfslist                 List all available VFSes",    ".vfslist                 List all available VFSes",
   ".vfsname ?AUX?           Print the name of the VFS stack",    ".vfsname ?AUX?           Print the name of the VFS stack",
  ".width NUM1 NUM2 ...     Set column widths for \"column\" mode",  ".width NUM1 NUM2 ...     Set minimum column widths for columnar output",
   "     Negative values right-justify",    "     Negative values right-justify",
 };  };
   
Line 12219  static int showHelp(FILE *out, const char *zPattern){ Line 13691  static int showHelp(FILE *out, const char *zPattern){
    || zPattern[0]=='0'     || zPattern[0]=='0'
    || strcmp(zPattern,"-a")==0     || strcmp(zPattern,"-a")==0
    || strcmp(zPattern,"-all")==0     || strcmp(zPattern,"-all")==0
      || strcmp(zPattern,"--all")==0
   ){    ){
     /* Show all commands, but only one line per command */      /* Show all commands, but only one line per command */
     if( zPattern==0 ) zPattern = "";      if( zPattern==0 ) zPattern = "";
Line 12436  static unsigned char *readHexDb(ShellState *p, int *pn Line 13909  static unsigned char *readHexDb(ShellState *p, int *pn
   rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz);    rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz);
   if( rc!=2 ) goto readHexDb_error;    if( rc!=2 ) goto readHexDb_error;
   if( n<0 ) 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 );    a = sqlite3_malloc( n ? n : 1 );
   if( a==0 ){    if( a==0 ){
     utf8_printf(stderr, "Out of memory!\n");      utf8_printf(stderr, "Out of memory!\n");
Line 12521  static void shellInt32( Line 13996  static void shellInt32(
 }  }
   
 /*  /*
   ** 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 "shell_escape_crnl" used by the .recover command.  ** Scalar function "shell_escape_crnl" used by the .recover command.
 ** The argument passed to this function is the output of built-in  ** The argument passed to this function is the output of built-in
 ** function quote(). If the first character of the input is "'",   ** function quote(). If the first character of the input is "'", 
Line 12641  static void open_db(ShellState *p, int openFlags){ Line 14133  static void open_db(ShellState *p, int openFlags){
     switch( p->openMode ){      switch( p->openMode ){
       case SHELL_OPEN_APPENDVFS: {        case SHELL_OPEN_APPENDVFS: {
         sqlite3_open_v2(p->zDbFilename, &p->db,           sqlite3_open_v2(p->zDbFilename, &p->db, 
           SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, "apndvfs");           SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, "apndvfs");
         break;          break;
       }        }
       case SHELL_OPEN_HEXDB:        case SHELL_OPEN_HEXDB:
Line 12654  static void open_db(ShellState *p, int openFlags){ Line 14146  static void open_db(ShellState *p, int openFlags){
         break;          break;
       }        }
       case SHELL_OPEN_READONLY: {        case SHELL_OPEN_READONLY: {
        sqlite3_open_v2(p->zDbFilename, &p->db, SQLITE_OPEN_READONLY, 0);        sqlite3_open_v2(p->zDbFilename, &p->db,
             SQLITE_OPEN_READONLY|p->openFlags, 0);
         break;          break;
       }        }
       case SHELL_OPEN_UNSPEC:        case SHELL_OPEN_UNSPEC:
       case SHELL_OPEN_NORMAL: {        case SHELL_OPEN_NORMAL: {
        sqlite3_open(p->zDbFilename, &p->db);        sqlite3_open_v2(p->zDbFilename, &p->db,
            SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, 0);
         break;          break;
       }        }
     }      }
Line 12679  static void open_db(ShellState *p, int openFlags){ Line 14173  static void open_db(ShellState *p, int openFlags){
     sqlite3_fileio_init(p->db, 0, 0);      sqlite3_fileio_init(p->db, 0, 0);
     sqlite3_shathree_init(p->db, 0, 0);      sqlite3_shathree_init(p->db, 0, 0);
     sqlite3_completion_init(p->db, 0, 0);      sqlite3_completion_init(p->db, 0, 0);
       sqlite3_uint_init(p->db, 0, 0);
       sqlite3_decimal_init(p->db, 0, 0);
       sqlite3_ieee_init(p->db, 0, 0);
 #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)  #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
     sqlite3_dbdata_init(p->db, 0, 0);      sqlite3_dbdata_init(p->db, 0, 0);
 #endif  #endif
Line 12696  static void open_db(ShellState *p, int openFlags){ Line 14193  static void open_db(ShellState *p, int openFlags){
                             shellEscapeCrnl, 0, 0);                              shellEscapeCrnl, 0, 0);
     sqlite3_create_function(p->db, "shell_int32", 2, SQLITE_UTF8, 0,      sqlite3_create_function(p->db, "shell_int32", 2, SQLITE_UTF8, 0,
                             shellInt32, 0, 0);                              shellInt32, 0, 0);
       sqlite3_create_function(p->db, "shell_idquote", 1, SQLITE_UTF8, 0,
                               shellIdQuote, 0, 0);
 #ifndef SQLITE_NOHAVE_SYSTEM  #ifndef SQLITE_NOHAVE_SYSTEM
     sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0,      sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0,
                             editFunc, 0, 0);                              editFunc, 0, 0);
Line 13009  typedef struct ImportCtx ImportCtx; Line 14508  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 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 ){
Line 13267  end_data_xfer: Line 14779  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 13282  static void tryToCloneSchema( Line 14794  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 13309  static void tryToCloneSchema( Line 14821  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 13394  static void output_reset(ShellState *p){ Line 14906  static void output_reset(ShellState *p){
       zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile);        zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile);
       if( system(zCmd) ){        if( system(zCmd) ){
         utf8_printf(stderr, "Failed: [%s]\n", 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);        sqlite3_free(zCmd);
       outputModePop(p);        outputModePop(p);
       p->doXdgOpen = 0;        p->doXdgOpen = 0;
       sqlite3_sleep(100);  
     }      }
 #endif /* !defined(SQLITE_NOHAVE_SYSTEM) */  #endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
   }    }
Line 13431  static unsigned int get4byteInt(unsigned char *a){ Line 14947  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 13474  static int shell_dbinfo_command(ShellState *p, int nAr Line 14990  static int shell_dbinfo_command(ShellState *p, int nAr
              "SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",               "SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
              -1, &pStmt, 0);               -1, &pStmt, 0);
   if( rc ){    if( rc ){
    if( !sqlite3_compileoption_used("ENABLE_DBPAGE_VTAB") ){    utf8_printf(stderr, "error: %s\n", sqlite3_errmsg(p->db));
      utf8_printf(stderr, "the \".dbinfo\" command requires the " 
                          "-DSQLITE_ENABLE_DBPAGE_VTAB compile-time options\n"); 
    }else{ 
      utf8_printf(stderr, "error: %s\n", sqlite3_errmsg(p->db)); 
    } 
     sqlite3_finalize(pStmt);      sqlite3_finalize(pStmt);
     return 1;      return 1;
   }    }
Line 13514  static int shell_dbinfo_command(ShellState *p, int nAr Line 15025  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 13688  static void newTempFile(ShellState *p, const char *zSu Line 15199  static void newTempFile(ShellState *p, const char *zSu
     sqlite3_file_control(p->db, 0, SQLITE_FCNTL_TEMPFILENAME, &p->zTempFile);      sqlite3_file_control(p->db, 0, SQLITE_FCNTL_TEMPFILENAME, &p->zTempFile);
   }    }
   if( p->zTempFile==0 ){    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_uint64 r;
     sqlite3_randomness(sizeof(r), &r);      sqlite3_randomness(sizeof(r), &r);
    p->zTempFile = sqlite3_mprintf("temp%llx.%s", r, zSuffix);    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{    }else{
     p->zTempFile = sqlite3_mprintf("%z.%s", p->zTempFile, zSuffix);      p->zTempFile = sqlite3_mprintf("%z.%s", p->zTempFile, zSuffix);
   }    }
Line 13828  static int lintFkeyIndexes( Line 15351  static int lintFkeyIndexes(
     "  || ');'"      "  || ');'"
     ", "      ", "
     "     f.[table] "      "     f.[table] "
    "FROM sqlite_master AS s, pragma_foreign_key_list(s.name) AS f "    "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]) "      "LEFT JOIN pragma_table_info AS p ON (pk-1=seq AND p.arg=f.[table]) "
     "GROUP BY s.name, f.id "      "GROUP BY s.name, f.id "
     "ORDER BY (CASE WHEN ? THEN f.[table] ELSE s.name END)"      "ORDER BY (CASE WHEN ? THEN f.[table] ELSE s.name END)"
Line 14043  void shellReset( Line 15566  void shellReset(
 #endif /* !defined SQLITE_OMIT_VIRTUALTABLE */  #endif /* !defined SQLITE_OMIT_VIRTUALTABLE */
   
 #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)  #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
/*********************************************************************************/******************************************************************************
 ** The ".archive" or ".ar" command.  ** The ".archive" or ".ar" command.
 */  */
 /*  /*
Line 14241  static int arParseCommand( Line 15764  static int arParseCommand(
                 i = n;                  i = n;
               }else{                }else{
                 if( iArg>=(nArg-1) ){                  if( iArg>=(nArg-1) ){
                  return arErrorMsg(pAr, "option requires an argument: %c",z[i]);                  return arErrorMsg(pAr, "option requires an argument: %c",
                                     z[i]);
                 }                  }
                 zArg = azArg[++iArg];                  zArg = azArg[++iArg];
               }                }
Line 14629  end_ar_transaction: Line 16153  end_ar_transaction:
 ** Implementation of ".ar" dot command.  ** Implementation of ".ar" dot command.
 */  */
 static int arDotCommand(  static int arDotCommand(
  ShellState *pState,             /* Current shell tool state */  ShellState *pState,          /* Current shell tool state */
  int fromCmdLine,                /* True if -A command-line option, not .ar cmd */  int fromCmdLine,             /* True if -A command-line option, not .ar cmd */
  char **azArg,                   /* Array of arguments passed to dot command */  char **azArg,                /* Array of arguments passed to dot command */
  int nArg                        /* Number of entries in azArg[] */  int nArg                     /* Number of entries in azArg[] */
 ){  ){
   ArCommand cmd;    ArCommand cmd;
   int rc;    int rc;
Line 14732  end_ar_command: Line 16256  end_ar_command:
   return rc;    return rc;
 }  }
 /* End of the ".archive" or ".ar" command logic  /* End of the ".archive" or ".ar" command logic
**********************************************************************************/*******************************************************************************/
 #endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */  #endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */
   
 #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)  #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
Line 14874  static RecoverTable *recoverNewTable( Line 16398  static RecoverTable *recoverNewTable(
           
     rc = sqlite3_open("", &dbtmp);      rc = sqlite3_open("", &dbtmp);
     if( rc==SQLITE_OK ){      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);        rc = sqlite3_exec(dbtmp, "PRAGMA writable_schema = on", 0, 0, 0);
     }      }
     if( rc==SQLITE_OK ){      if( rc==SQLITE_OK ){
Line 14898  static RecoverTable *recoverNewTable( Line 16426  static RecoverTable *recoverNewTable(
     shellPreparePrintf(dbtmp, &rc, &pStmt,       shellPreparePrintf(dbtmp, &rc, &pStmt, 
       "SELECT ("        "SELECT ("
       "  SELECT substr(data,1,1)==X'0D' FROM sqlite_dbpage WHERE pgno=rootpage"        "  SELECT substr(data,1,1)==X'0D' FROM sqlite_dbpage WHERE pgno=rootpage"
      ") FROM sqlite_master WHERE name = %Q", zName      ") FROM sqlite_schema WHERE name = %Q", zName
     );      );
     if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){      if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
       bSqlIntkey = sqlite3_column_int(pStmt, 0);        bSqlIntkey = sqlite3_column_int(pStmt, 0);
Line 14929  static RecoverTable *recoverNewTable( Line 16457  static RecoverTable *recoverNewTable(
         }          }
       }        }
   
      pTab->zQuoted = shellMPrintf(&rc, "%Q", zName);      pTab->zQuoted = shellMPrintf(&rc, "\"%w\"", zName);
       pTab->azlCol = (char**)shellMalloc(&rc, sizeof(char*) * (nSqlCol+1));        pTab->azlCol = (char**)shellMalloc(&rc, sizeof(char*) * (nSqlCol+1));
       pTab->nCol = nSqlCol;        pTab->nCol = nSqlCol;
   
       if( bIntkey ){        if( bIntkey ){
        pTab->azlCol[0] = shellMPrintf(&rc, "%Q", zPk);        pTab->azlCol[0] = shellMPrintf(&rc, "\"%w\"", zPk);
       }else{        }else{
         pTab->azlCol[0] = shellMPrintf(&rc, "");          pTab->azlCol[0] = shellMPrintf(&rc, "");
       }        }
       i = 1;        i = 1;
       shellPreparePrintf(dbtmp, &rc, &pStmt,         shellPreparePrintf(dbtmp, &rc, &pStmt, 
          "SELECT %Q || group_concat(name, ', ') "          "SELECT %Q || group_concat(shell_idquote(name), ', ') "
           "  FILTER (WHERE cid!=%d) OVER (ORDER BY %s cid) "            "  FILTER (WHERE cid!=%d) OVER (ORDER BY %s cid) "
           "FROM pragma_table_info(%Q)",             "FROM pragma_table_info(%Q)", 
           bIntkey ? ", " : "", pTab->iPk,             bIntkey ? ", " : "", pTab->iPk, 
Line 14970  static RecoverTable *recoverNewTable( Line 16498  static RecoverTable *recoverNewTable(
   
 /*  /*
 ** This function is called to search the schema recovered from the  ** This function is called to search the schema recovered from the
** sqlite_master table of the (possibly) corrupt database as part** sqlite_schema table of the (possibly) corrupt database as part
 ** of a ".recover" command. Specifically, for a table with root page  ** of a ".recover" command. Specifically, for a table with root page
 ** iRoot and at least nCol columns. Additionally, if bIntkey is 0, the  ** 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  ** table must be a WITHOUT ROWID table, or if non-zero, not one of
Line 15054  static RecoverTable *recoverOrphanTable( Line 16582  static RecoverTable *recoverOrphanTable(
   
     pTab = (RecoverTable*)shellMalloc(pRc, sizeof(RecoverTable));      pTab = (RecoverTable*)shellMalloc(pRc, sizeof(RecoverTable));
     if( pTab ){      if( pTab ){
      pTab->zQuoted = shellMPrintf(pRc, "%Q", zTab);      pTab->zQuoted = shellMPrintf(pRc, "\"%w\"", zTab);
       pTab->nCol = nCol;        pTab->nCol = nCol;
       pTab->iPk = -2;        pTab->iPk = -2;
       if( nCol>0 ){        if( nCol>0 ){
Line 15103  static int recoverDatabaseCmd(ShellState *pState, int  Line 16631  static int recoverDatabaseCmd(ShellState *pState, int 
   RecoverTable *pOrphan = 0;    RecoverTable *pOrphan = 0;
   
   int bFreelist = 1;              /* 0 if --freelist-corrupt is specified */    int bFreelist = 1;              /* 0 if --freelist-corrupt is specified */
     int bRowids = 1;                /* 0 if --no-rowids */
   for(i=1; i<nArg; i++){    for(i=1; i<nArg; i++){
     char *z = azArg[i];      char *z = azArg[i];
     int n;      int n;
Line 15118  static int recoverDatabaseCmd(ShellState *pState, int  Line 16647  static int recoverDatabaseCmd(ShellState *pState, int 
     if( n<=15 && memcmp("-lost-and-found", z, n)==0 && i<(nArg-1) ){      if( n<=15 && memcmp("-lost-and-found", z, n)==0 && i<(nArg-1) ){
       i++;        i++;
       zLostAndFound = azArg[i];        zLostAndFound = azArg[i];
       }else
       if( n<=10 && memcmp("-no-rowids", z, n)==0 ){
         bRowids = 0;
     }      }
     else{      else{
      raw_printf(stderr, "unexpected option: %s\n", azArg[i]);       utf8_printf(stderr, "unexpected option: %s\n", azArg[i]); 
      raw_printf(stderr, "options are:\n");      showHelp(pState->out, azArg[0]);
      raw_printf(stderr, "    --freelist-corrupt\n"); 
      raw_printf(stderr, "    --recovery-db DATABASE\n"); 
      raw_printf(stderr, "    --lost-and-found TABLE-NAME\n"); 
       return 1;        return 1;
     }      }
   }    }
Line 15132  static int recoverDatabaseCmd(ShellState *pState, int  Line 16661  static int recoverDatabaseCmd(ShellState *pState, int 
   shellExecPrintf(pState->db, &rc,    shellExecPrintf(pState->db, &rc,
     /* Attach an in-memory database named 'recovery'. Create an indexed       /* Attach an in-memory database named 'recovery'. Create an indexed 
     ** cache of the sqlite_dbptr virtual table. */      ** cache of the sqlite_dbptr virtual table. */
       "PRAGMA writable_schema = on;"
     "ATTACH %Q AS recovery;"      "ATTACH %Q AS recovery;"
     "DROP TABLE IF EXISTS recovery.dbptr;"      "DROP TABLE IF EXISTS recovery.dbptr;"
     "DROP TABLE IF EXISTS recovery.freelist;"      "DROP TABLE IF EXISTS recovery.freelist;"
Line 15162  static int recoverDatabaseCmd(ShellState *pState, int  Line 16692  static int recoverDatabaseCmd(ShellState *pState, int 
     );      );
   }    }
   
     /* 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,     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("      "CREATE TABLE recovery.dbptr("
     "      pgno, child, PRIMARY KEY(child, pgno)"      "      pgno, child, PRIMARY KEY(child, pgno)"
     ") WITHOUT ROWID;"      ") WITHOUT ROWID;"
Line 15210  static int recoverDatabaseCmd(ShellState *pState, int  Line 16755  static int recoverDatabaseCmd(ShellState *pState, int 
     "    )"      "    )"
     "    SELECT pgno FROM p WHERE (parent IS NULL OR pgno = orig)"      "    SELECT pgno FROM p WHERE (parent IS NULL OR pgno = orig)"
     ") "      ") "
    "FROM pages WHERE maxlen > 0 AND i NOT IN freelist;"    "FROM pages WHERE maxlen IS NOT NULL AND i NOT IN freelist;"
     "UPDATE recovery.map AS o SET intkey = ("      "UPDATE recovery.map AS o SET intkey = ("
     "  SELECT substr(data, 1, 1)==X'0D' FROM sqlite_dbpage WHERE pgno=o.pgno"      "  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      /* Extract data from page 1 and any linked pages into table
    ** recovery.schema. With the same schema as an sqlite_master table.  */    ** recovery.schema. With the same schema as an sqlite_schema table.  */
     "CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql);"      "CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql);"
     "INSERT INTO recovery.schema SELECT "      "INSERT INTO recovery.schema SELECT "
     "  max(CASE WHEN field=0 THEN value ELSE NULL END),"      "  max(CASE WHEN field=0 THEN value ELSE NULL END),"
Line 15235  static int recoverDatabaseCmd(ShellState *pState, int  Line 16780  static int recoverDatabaseCmd(ShellState *pState, int 
   ** CREATE TABLE statements that extracted from the existing schema.  */    ** CREATE TABLE statements that extracted from the existing schema.  */
   if( rc==SQLITE_OK ){    if( rc==SQLITE_OK ){
     sqlite3_stmt *pStmt = 0;      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, "BEGIN;\n");
     raw_printf(pState->out, "PRAGMA writable_schema = on;\n");      raw_printf(pState->out, "PRAGMA writable_schema = on;\n");
     shellPrepare(pState->db, &rc,      shellPrepare(pState->db, &rc,
Line 15265  static int recoverDatabaseCmd(ShellState *pState, int  Line 16815  static int recoverDatabaseCmd(ShellState *pState, int 
   shellPrepare(pState->db, &rc,    shellPrepare(pState->db, &rc,
       "SELECT pgno FROM recovery.map WHERE root=?", &pPages        "SELECT pgno FROM recovery.map WHERE root=?", &pPages
   );    );
   
   shellPrepare(pState->db, &rc,    shellPrepare(pState->db, &rc,
      "SELECT max(field), group_concat(shell_escape_crnl(quote(value)), ', ')"      "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 != ?"        "FROM sqlite_dbdata WHERE pgno = ? AND field != ?"
       "GROUP BY cell", &pCells        "GROUP BY cell", &pCells
   );    );
Line 15285  static int recoverDatabaseCmd(ShellState *pState, int  Line 16839  static int recoverDatabaseCmd(ShellState *pState, int 
     int bNoop = 0;      int bNoop = 0;
     RecoverTable *pTab;      RecoverTable *pTab;
   
       assert( bIntkey==0 || bIntkey==1 );
     pTab = recoverFindTable(pState, &rc, iRoot, bIntkey, nCol, &bNoop);      pTab = recoverFindTable(pState, &rc, iRoot, bIntkey, nCol, &bNoop);
     if( bNoop || rc ) continue;      if( bNoop || rc ) continue;
     if( pTab==0 ){      if( pTab==0 ){
Line 15295  static int recoverDatabaseCmd(ShellState *pState, int  Line 16850  static int recoverDatabaseCmd(ShellState *pState, int 
       if( pTab==0 ) break;        if( pTab==0 ) break;
     }      }
   
    if( 0==sqlite3_stricmp(pTab->zQuoted, "'sqlite_sequence'") ){    if( 0==sqlite3_stricmp(pTab->zQuoted, "\"sqlite_sequence\"") ){
       raw_printf(pState->out, "DELETE FROM sqlite_sequence;\n");        raw_printf(pState->out, "DELETE FROM sqlite_sequence;\n");
     }      }
     sqlite3_bind_int(pPages, 1, iRoot);      sqlite3_bind_int(pPages, 1, iRoot);
    sqlite3_bind_int(pCells, 2, pTab->iPk);    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) ){      while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPages) ){
       int iPgno = sqlite3_column_int(pPages, 0);        int iPgno = sqlite3_column_int(pPages, 0);
      sqlite3_bind_int(pCells, 1, iPgno);      sqlite3_bind_int(pCells, 2, iPgno);
       while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pCells) ){        while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pCells) ){
         int nField = sqlite3_column_int(pCells, 0);          int nField = sqlite3_column_int(pCells, 0);
           int iMin = sqlite3_column_int(pCells, 2);
         const char *zVal = (const char*)sqlite3_column_text(pCells, 1);          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;          nField = nField+1;
        if( pTab==pOrphan ){        if( pTab2==pOrphan ){
           raw_printf(pState->out,             raw_printf(pState->out, 
               "INSERT INTO %s VALUES(%d, %d, %d, %s%s%s);\n",                "INSERT INTO %s VALUES(%d, %d, %d, %s%s%s);\n",
              pTab->zQuoted, iRoot, iPgno, nField,               pTab2->zQuoted, iRoot, iPgno, nField,
              bIntkey ? "" : "NULL, ", zVal, pTab->azlCol[nField]              iMin<0 ? "" : "NULL, ", zVal, pTab2->azlCol[nField]
           );            );
         }else{          }else{
           raw_printf(pState->out, "INSERT INTO %s(%s) VALUES( %s );\n",             raw_printf(pState->out, "INSERT INTO %s(%s) VALUES( %s );\n", 
              pTab->zQuoted, pTab->azlCol[nField], zVal              pTab2->zQuoted, pTab2->azlCol[nField], zVal
           );            );
         }          }
       }        }
Line 15343  static int recoverDatabaseCmd(ShellState *pState, int  Line 16913  static int recoverDatabaseCmd(ShellState *pState, int 
       if( sqlite3_strnicmp(zSql, "create virt", 11)==0 ){        if( sqlite3_strnicmp(zSql, "create virt", 11)==0 ){
         const char *zName = (const char*)sqlite3_column_text(pStmt, 1);          const char *zName = (const char*)sqlite3_column_text(pStmt, 1);
         char *zPrint = shellMPrintf(&rc,           char *zPrint = shellMPrintf(&rc, 
          "INSERT INTO sqlite_master VALUES('table', %Q, %Q, 0, %Q)",          "INSERT INTO sqlite_schema VALUES('table', %Q, %Q, 0, %Q)",
           zName, zName, zSql            zName, zName, zSql
         );          );
         raw_printf(pState->out, "%s;\n", zPrint);          raw_printf(pState->out, "%s;\n", zPrint);
Line 15376  static int do_meta_command(char *zLine, ShellState *p) Line 16946  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  #ifndef SQLITE_OMIT_VIRTUALTABLE
   if( p->expert.pExpert ){    if( p->expert.pExpert ){
Line 15386  static int do_meta_command(char *zLine, ShellState *p) Line 16956  static int do_meta_command(char *zLine, ShellState *p)
   
   /* 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 15407  static int do_meta_command(char *zLine, ShellState *p) Line 16977  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.
   */    */
Line 15620  static int do_meta_command(char *zLine, ShellState *p) Line 17191  static int do_meta_command(char *zLine, ShellState *p)
       const char *zName;        const char *zName;
       int op;        int op;
     } aDbConfig[] = {      } aDbConfig[] = {
           { "defensive",          SQLITE_DBCONFIG_DEFENSIVE             },
           { "dqs_ddl",            SQLITE_DBCONFIG_DQS_DDL               },
           { "dqs_dml",            SQLITE_DBCONFIG_DQS_DML               },
         { "enable_fkey",        SQLITE_DBCONFIG_ENABLE_FKEY           },          { "enable_fkey",        SQLITE_DBCONFIG_ENABLE_FKEY           },
           { "enable_qpsg",        SQLITE_DBCONFIG_ENABLE_QPSG           },
         { "enable_trigger",     SQLITE_DBCONFIG_ENABLE_TRIGGER        },          { "enable_trigger",     SQLITE_DBCONFIG_ENABLE_TRIGGER        },
           { "enable_view",        SQLITE_DBCONFIG_ENABLE_VIEW           },
         { "fts3_tokenizer",     SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },          { "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 },          { "load_extension",     SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
         { "no_ckpt_on_close",   SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE      },          { "no_ckpt_on_close",   SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE      },
         { "enable_qpsg",        SQLITE_DBCONFIG_ENABLE_QPSG           },  
         { "trigger_eqp",        SQLITE_DBCONFIG_TRIGGER_EQP           },  
         { "reset_database",     SQLITE_DBCONFIG_RESET_DATABASE        },          { "reset_database",     SQLITE_DBCONFIG_RESET_DATABASE        },
        { "defensive",          SQLITE_DBCONFIG_DEFENSIVE             },        { "trigger_eqp",        SQLITE_DBCONFIG_TRIGGER_EQP           },
         { "trusted_schema",     SQLITE_DBCONFIG_TRUSTED_SCHEMA        },
         { "writable_schema",    SQLITE_DBCONFIG_WRITABLE_SCHEMA       },          { "writable_schema",    SQLITE_DBCONFIG_WRITABLE_SCHEMA       },
         { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE    },  
         { "dqs_dml",            SQLITE_DBCONFIG_DQS_DML               },  
         { "dqs_ddl",            SQLITE_DBCONFIG_DQS_DDL               },  
     };      };
     int ii, v;      int ii, v;
     open_db(p, 0);      open_db(p, 0);
Line 15642  static int do_meta_command(char *zLine, ShellState *p) Line 17216  static int do_meta_command(char *zLine, ShellState *p)
         sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0);          sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0);
       }        }
       sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v);        sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v);
      utf8_printf(p->out, "%18s %s\n", aDbConfig[ii].zName, v ? "on" : "off");      utf8_printf(p->out, "%19s %s\n", aDbConfig[ii].zName, v ? "on" : "off");
       if( nArg>1 ) break;        if( nArg>1 ) break;
     }      }
     if( nArg>1 && ii==ArraySize(aDbConfig) ){      if( nArg>1 && ii==ArraySize(aDbConfig) ){
Line 15663  static int do_meta_command(char *zLine, ShellState *p) Line 17237  static int do_meta_command(char *zLine, ShellState *p)
 #endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */  #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 ){
    const char *zLike = 0;    char *zLike = 0;
     char *zSql;
     int i;      int i;
     int savedShowHeader = p->showHeader;      int savedShowHeader = p->showHeader;
     int savedShellFlags = p->shellFlgs;      int savedShellFlags = p->shellFlgs;
Line 15677  static int do_meta_command(char *zLine, ShellState *p) Line 17252  static int do_meta_command(char *zLine, ShellState *p)
           raw_printf(stderr, "The --preserve-rowids option is not compatible"            raw_printf(stderr, "The --preserve-rowids option is not compatible"
                              " with SQLITE_OMIT_VIRTUALTABLE\n");                               " with SQLITE_OMIT_VIRTUALTABLE\n");
           rc = 1;            rc = 1;
             sqlite3_free(zLike);
           goto meta_command_exit;            goto meta_command_exit;
 #else  #else
           ShellSetFlag(p, SHFLG_PreserveRowid);            ShellSetFlag(p, SHFLG_PreserveRowid);
Line 15688  static int do_meta_command(char *zLine, ShellState *p) Line 17264  static int do_meta_command(char *zLine, ShellState *p)
         {          {
           raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);            raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
           rc = 1;            rc = 1;
             sqlite3_free(zLike);
           goto meta_command_exit;            goto meta_command_exit;
         }          }
       }else if( zLike ){        }else if( zLike ){
        raw_printf(stderr, "Usage: .dump ?--preserve-rowids? "        zLike = sqlite3_mprintf("%z OR name LIKE %Q ESCAPE '\\'",
                           "?--newlines? ?LIKE-PATTERN?\n");                zLike, azArg[i]);
        rc = 1; 
        goto meta_command_exit; 
       }else{        }else{
        zLike = azArg[i];        zLike = sqlite3_mprintf("name LIKE %Q ESCAPE '\\'", azArg[i]);
       }        }
     }      }
   
Line 15710  static int do_meta_command(char *zLine, ShellState *p) Line 17285  static int do_meta_command(char *zLine, ShellState *p)
     p->writableSchema = 0;      p->writableSchema = 0;
     p->showHeader = 0;      p->showHeader = 0;
     /* Set writable_schema=ON since doing so forces SQLite to initialize      /* Set writable_schema=ON since doing so forces SQLite to initialize
    ** as much of the schema as it can even if the sqlite_master table is    ** as much of the schema as it can even if the sqlite_schema table is
     ** corrupt. */      ** 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( zLike==0 ){    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"
      run_schema_dump_query(p,      " ORDER BY tbl_name='sqlite_sequence', rowid",
        "SELECT name, type, sql FROM sqlite_master "      zLike
        "WHERE name=='sqlite_sequence'"    );
      );    run_schema_dump_query(p,zSql);
      run_table_dump_query(p,    sqlite3_free(zSql);
        "SELECT sql FROM sqlite_master "    zSql = sqlite3_mprintf(
        "WHERE sql NOT NULL AND type IN ('index','trigger','view')", 0      "SELECT sql FROM sqlite_schema "
      );      "WHERE (%s) AND sql NOT NULL"
    }else{      "  AND type IN ('index','trigger','view')",
      char *zSql;      zLike
      zSql = sqlite3_mprintf(    );
        "SELECT name, type, sql FROM sqlite_master "    run_table_dump_query(p, zSql);
        "WHERE tbl_name LIKE %Q AND type=='table'"    sqlite3_free(zSql);
        "  AND sql NOT NULL", zLike);    sqlite3_free(zLike);
      run_schema_dump_query(p,zSql); 
      sqlite3_free(zSql); 
      zSql = sqlite3_mprintf( 
        "SELECT sql FROM sqlite_master " 
        "WHERE sql NOT NULL" 
        "  AND type IN ('index','trigger','view')" 
        "  AND tbl_name LIKE %Q", zLike); 
      run_table_dump_query(p, zSql, 0); 
      sqlite3_free(zSql); 
    } 
     if( p->writableSchema ){      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;
Line 15782  static int do_meta_command(char *zLine, ShellState *p) Line 17347  static int do_meta_command(char *zLine, ShellState *p)
         p->autoEQP = AUTOEQP_full;          p->autoEQP = AUTOEQP_full;
         p->autoEQPtrace = 1;          p->autoEQPtrace = 1;
         open_db(p, 0);          open_db(p, 0);
        sqlite3_exec(p->db, "SELECT name FROM sqlite_master LIMIT 1", 0, 0, 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);          sqlite3_exec(p->db, "PRAGMA vdbe_trace=ON;", 0, 0, 0);
 #endif  #endif
       }else{        }else{
Line 15845  static int do_meta_command(char *zLine, ShellState *p) Line 17410  static int do_meta_command(char *zLine, ShellState *p)
       { "tempfilename",   SQLITE_FCNTL_TEMPFILENAME,    ""               },        { "tempfilename",   SQLITE_FCNTL_TEMPFILENAME,    ""               },
       { "has_moved",      SQLITE_FCNTL_HAS_MOVED,       ""               },          { "has_moved",      SQLITE_FCNTL_HAS_MOVED,       ""               },  
       { "lock_timeout",   SQLITE_FCNTL_LOCK_TIMEOUT,    "MILLISEC"       },        { "lock_timeout",   SQLITE_FCNTL_LOCK_TIMEOUT,    "MILLISEC"       },
         { "reserve_bytes",  SQLITE_FCNTL_RESERVE_BYTES,   "[N]"            },
     };      };
     int filectrl = -1;      int filectrl = -1;
     int iCtrl = -1;      int iCtrl = -1;
Line 15852  static int do_meta_command(char *zLine, ShellState *p) Line 17418  static int do_meta_command(char *zLine, ShellState *p)
     int isOk = 0;            /* 0: usage  1: %lld  2: no-result */      int isOk = 0;            /* 0: usage  1: %lld  2: no-result */
     int n2, i;      int n2, i;
     const char *zCmd = 0;      const char *zCmd = 0;
       const char *zSchema = 0;
   
     open_db(p, 0);      open_db(p, 0);
     zCmd = nArg>=2 ? azArg[1] : "help";      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 "--" */      /* The argument can optionally begin with "-" or "--" */
     if( zCmd[0]=='-' && zCmd[1] ){      if( zCmd[0]=='-' && zCmd[1] ){
       zCmd++;        zCmd++;
Line 15897  static int do_meta_command(char *zLine, ShellState *p) Line 17474  static int do_meta_command(char *zLine, ShellState *p)
         case SQLITE_FCNTL_SIZE_LIMIT: {          case SQLITE_FCNTL_SIZE_LIMIT: {
           if( nArg!=2 && nArg!=3 ) break;            if( nArg!=2 && nArg!=3 ) break;
           iRes = nArg==3 ? integerValue(azArg[2]) : -1;            iRes = nArg==3 ? integerValue(azArg[2]) : -1;
          sqlite3_file_control(p->db, 0, SQLITE_FCNTL_SIZE_LIMIT, &iRes);          sqlite3_file_control(p->db, zSchema, SQLITE_FCNTL_SIZE_LIMIT, &iRes);
           isOk = 1;            isOk = 1;
           break;            break;
         }          }
Line 15906  static int do_meta_command(char *zLine, ShellState *p) Line 17483  static int do_meta_command(char *zLine, ShellState *p)
           int x;            int x;
           if( nArg!=3 ) break;            if( nArg!=3 ) break;
           x = (int)integerValue(azArg[2]);            x = (int)integerValue(azArg[2]);
          sqlite3_file_control(p->db, 0, filectrl, &x);          sqlite3_file_control(p->db, zSchema, filectrl, &x);
           isOk = 2;            isOk = 2;
           break;            break;
         }          }
Line 15915  static int do_meta_command(char *zLine, ShellState *p) Line 17492  static int do_meta_command(char *zLine, ShellState *p)
           int x;            int x;
           if( nArg!=2 && nArg!=3 ) break;            if( nArg!=2 && nArg!=3 ) break;
           x = nArg==3 ? booleanValue(azArg[2]) : -1;            x = nArg==3 ? booleanValue(azArg[2]) : -1;
          sqlite3_file_control(p->db, 0, filectrl, &x);          sqlite3_file_control(p->db, zSchema, filectrl, &x);
           iRes = x;            iRes = x;
           isOk = 1;            isOk = 1;
           break;            break;
Line 15923  static int do_meta_command(char *zLine, ShellState *p) Line 17500  static int do_meta_command(char *zLine, ShellState *p)
         case SQLITE_FCNTL_HAS_MOVED: {          case SQLITE_FCNTL_HAS_MOVED: {
           int x;            int x;
           if( nArg!=2 ) break;            if( nArg!=2 ) break;
          sqlite3_file_control(p->db, 0, filectrl, &x);          sqlite3_file_control(p->db, zSchema, filectrl, &x);
           iRes = x;            iRes = x;
           isOk = 1;            isOk = 1;
           break;            break;
Line 15931  static int do_meta_command(char *zLine, ShellState *p) Line 17508  static int do_meta_command(char *zLine, ShellState *p)
         case SQLITE_FCNTL_TEMPFILENAME: {          case SQLITE_FCNTL_TEMPFILENAME: {
           char *z = 0;            char *z = 0;
           if( nArg!=2 ) break;            if( nArg!=2 ) break;
          sqlite3_file_control(p->db, 0, filectrl, &z);          sqlite3_file_control(p->db, zSchema, filectrl, &z);
           if( z ){            if( z ){
             utf8_printf(p->out, "%s\n", z);              utf8_printf(p->out, "%s\n", z);
             sqlite3_free(z);              sqlite3_free(z);
Line 15939  static int do_meta_command(char *zLine, ShellState *p) Line 17516  static int do_meta_command(char *zLine, ShellState *p)
           isOk = 2;            isOk = 2;
           break;            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 ){      if( isOk==0 && iCtrl>=0 ){
Line 15971  static int do_meta_command(char *zLine, ShellState *p) Line 17560  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 15980  static int do_meta_command(char *zLine, ShellState *p) Line 17569  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 15989  static int do_meta_command(char *zLine, ShellState *p) Line 17578  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(&data, "SELECT * FROM sqlite_stat1", &zErrMsg);        shell_exec(&data, "SELECT * FROM sqlite_stat1", &zErrMsg);
       data.zDestTable = "sqlite_stat3";  
       shell_exec(&data, "SELECT * FROM sqlite_stat3", &zErrMsg);  
       data.zDestTable = "sqlite_stat4";        data.zDestTable = "sqlite_stat4";
       shell_exec(&data, "SELECT * FROM sqlite_stat4", &zErrMsg);        shell_exec(&data, "SELECT * FROM sqlite_stat4", &zErrMsg);
      raw_printf(p->out, "ANALYZE sqlite_master;\n");      raw_printf(p->out, "ANALYZE sqlite_schema;\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 16024  static int do_meta_command(char *zLine, ShellState *p) Line 17612  static int do_meta_command(char *zLine, ShellState *p)
   }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 16035  static int do_meta_command(char *zLine, ShellState *p) Line 17623  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];
       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 %s", zTable);      zSql = sqlite3_mprintf("SELECT * FROM %s", zTable);
     if( zSql==0 ){      if( zSql==0 ){
      xCloser(sCtx.in);      import_cleanup(&sCtx);
       shell_out_of_memory();        shell_out_of_memory();
     }      }
     nByte = strlen30(zSql);      nByte = strlen30(zSql);
Line 16119  static int do_meta_command(char *zLine, ShellState *p) Line 17771  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 16140  static int do_meta_command(char *zLine, ShellState *p) Line 17795  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 16149  static int do_meta_command(char *zLine, ShellState *p) Line 17805  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 ){
      xCloser(sCtx.in);      import_cleanup(&sCtx);
       shell_out_of_memory();        shell_out_of_memory();
     }      }
     sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);      sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);
Line 16160  static int do_meta_command(char *zLine, ShellState *p) Line 17816  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 16209  static int do_meta_command(char *zLine, ShellState *p) Line 17869  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
   
 #ifndef SQLITE_UNTESTABLE  #ifndef SQLITE_UNTESTABLE
Line 16225  static int do_meta_command(char *zLine, ShellState *p) Line 17892  static int do_meta_command(char *zLine, ShellState *p)
     char *zCollist = 0;      char *zCollist = 0;
     sqlite3_stmt *pStmt;      sqlite3_stmt *pStmt;
     int tnum = 0;      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;      int i;
     if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){      if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){
       utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n"        utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n"
                           "       .imposter off\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;        rc = 1;
       goto meta_command_exit;        goto meta_command_exit;
     }      }
Line 16237  static int do_meta_command(char *zLine, ShellState *p) Line 17913  static int do_meta_command(char *zLine, ShellState *p)
       sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1);        sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1);
       goto meta_command_exit;        goto meta_command_exit;
     }      }
    zSql = sqlite3_mprintf("SELECT rootpage FROM sqlite_master"    zSql = sqlite3_mprintf(
                           " WHERE name='%q' AND type='index'", azArg[1]);      "SELECT rootpage, 0 FROM sqlite_schema"
       " WHERE name='%q' AND type='index'"
       "UNION ALL "
       "SELECT rootpage, 1 FROM sqlite_schema"
       " WHERE name='%q' AND type='table'"
       "   AND sql LIKE '%%without%%rowid%%'",
       azArg[1], azArg[1]
     );
     sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);      sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
     sqlite3_free(zSql);      sqlite3_free(zSql);
     if( sqlite3_step(pStmt)==SQLITE_ROW ){      if( sqlite3_step(pStmt)==SQLITE_ROW ){
       tnum = sqlite3_column_int(pStmt, 0);        tnum = sqlite3_column_int(pStmt, 0);
         isWO = sqlite3_column_int(pStmt, 1);
     }      }
     sqlite3_finalize(pStmt);      sqlite3_finalize(pStmt);
     if( tnum==0 ){  
       utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]);  
       rc = 1;  
       goto meta_command_exit;  
     }  
     zSql = sqlite3_mprintf("PRAGMA index_xinfo='%q'", azArg[1]);      zSql = sqlite3_mprintf("PRAGMA index_xinfo='%q'", azArg[1]);
     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);
Line 16266  static int do_meta_command(char *zLine, ShellState *p) Line 17945  static int do_meta_command(char *zLine, ShellState *p)
           zCol = zLabel;            zCol = zLabel;
         }          }
       }        }
         if( isWO && lenPK==0 && sqlite3_column_int(pStmt,5)==0 && zCollist ){
           lenPK = (int)strlen(zCollist);
         }
       if( zCollist==0 ){        if( zCollist==0 ){
         zCollist = sqlite3_mprintf("\"%w\"", zCol);          zCollist = sqlite3_mprintf("\"%w\"", zCol);
       }else{        }else{
Line 16273  static int do_meta_command(char *zLine, ShellState *p) Line 17955  static int do_meta_command(char *zLine, ShellState *p)
       }        }
     }      }
     sqlite3_finalize(pStmt);      sqlite3_finalize(pStmt);
       if( i==0 || tnum==0 ){
         utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]);
         rc = 1;
         sqlite3_free(zCollist);
         goto meta_command_exit;
       }
       if( lenPK==0 ) lenPK = 100000;
     zSql = sqlite3_mprintf(      zSql = sqlite3_mprintf(
          "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%s))WITHOUT ROWID",          "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%.*s))WITHOUT ROWID",
          azArg[2], zCollist, zCollist);          azArg[2], zCollist, lenPK, zCollist);
     sqlite3_free(zCollist);      sqlite3_free(zCollist);
     rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum);      rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum);
     if( rc==SQLITE_OK ){      if( rc==SQLITE_OK ){
Line 16286  static int do_meta_command(char *zLine, ShellState *p) Line 17975  static int do_meta_command(char *zLine, ShellState *p)
       }else{        }else{
         utf8_printf(stdout, "%s;\n", zSql);          utf8_printf(stdout, "%s;\n", zSql);
         raw_printf(stdout,          raw_printf(stdout,
           "WARNING: writing to an imposter table will corrupt the index!\n"          "WARNING: writing to an imposter table will corrupt the \"%s\" %s!\n",
           azArg[1], isWO ? "table" : "index"
         );          );
       }        }
     }else{      }else{
Line 16425  static int do_meta_command(char *zLine, ShellState *p) Line 18115  static int do_meta_command(char *zLine, ShellState *p)
       sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);        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);        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;
Line 16448  static int do_meta_command(char *zLine, ShellState *p) Line 18141  static int do_meta_command(char *zLine, ShellState *p)
       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 ){      }else if( c2=='q' && strncmp(azArg[1],"quote",n2)==0 ){
       p->mode = MODE_Quote;        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 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 ){      }else if( nArg==1 ){
       raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]);        raw_printf(p->out, "current output mode: %s\n", modeDescr[p->mode]);
     }else{      }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 quote 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 16472  static int do_meta_command(char *zLine, ShellState *p) Line 18176  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 ){
     char *zNewFilename;  /* Name of the database file to open */      char *zNewFilename;  /* Name of the database file to open */
     int iName = 1;       /* Index in azArg[] of the filename */      int iName = 1;       /* Index in azArg[] of the filename */
Line 16484  static int do_meta_command(char *zLine, ShellState *p) Line 18216  static int do_meta_command(char *zLine, ShellState *p)
     sqlite3_free(p->zFreeOnClose);      sqlite3_free(p->zFreeOnClose);
     p->zFreeOnClose = 0;      p->zFreeOnClose = 0;
     p->openMode = SHELL_OPEN_UNSPEC;      p->openMode = SHELL_OPEN_UNSPEC;
       p->openFlags = 0;
     p->szMax = 0;      p->szMax = 0;
     /* Check for command-line arguments */      /* Check for command-line arguments */
     for(iName=1; iName<nArg && azArg[iName][0]=='-'; iName++){      for(iName=1; iName<nArg && azArg[iName][0]=='-'; iName++){
Line 16498  static int do_meta_command(char *zLine, ShellState *p) Line 18231  static int do_meta_command(char *zLine, ShellState *p)
         p->openMode = SHELL_OPEN_APPENDVFS;          p->openMode = SHELL_OPEN_APPENDVFS;
       }else if( optionMatch(z, "readonly") ){        }else if( optionMatch(z, "readonly") ){
         p->openMode = SHELL_OPEN_READONLY;          p->openMode = SHELL_OPEN_READONLY;
         }else if( optionMatch(z, "nofollow") ){
           p->openFlags |= SQLITE_OPEN_NOFOLLOW;
 #ifdef SQLITE_ENABLE_DESERIALIZE  #ifdef SQLITE_ENABLE_DESERIALIZE
       }else if( optionMatch(z, "deserialize") ){        }else if( optionMatch(z, "deserialize") ){
         p->openMode = SHELL_OPEN_DESERIALIZE;          p->openMode = SHELL_OPEN_DESERIALIZE;
Line 16536  static int do_meta_command(char *zLine, ShellState *p) Line 18271  static int do_meta_command(char *zLine, ShellState *p)
         && (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)     || (c=='e' && n==5 && strcmp(azArg[0],"excel")==0)
   ){    ){
    const char *zFile = nArg>=2 ? azArg[1] : "stdout";    const char *zFile = 0;
     int bTxtMode = 0;      int bTxtMode = 0;
    if( azArg[0][0]=='e' ){    int i;
      /* Transform the ".excel" command into ".once -x" */    int eMode = 0;
      nArg = 2;    int bBOM = 0;
      azArg[0] = "once";    int bOnce = 0;  /* 0: .output, 1: .once, 2: .excel */
      zFile = azArg[1] = "-x";
      n = 4;    if( c=='e' ){
       eMode = 'x';
       bOnce = 2;
     }else if( strncmp(azArg[0],"once",n)==0 ){
       bOnce = 1;
     }      }
    if( nArg>2 ){    for(i=1; i<nArg; i++){
      utf8_printf(stderr, "Usage: .%s [-e|-x|FILE]\n", azArg[0]);      char *z = azArg[i];
      rc = 1;      if( z[0]=='-' ){
      goto meta_command_exit;        if( z[1]=='-' ) z++;
    }        if( strcmp(z,"-bom")==0 ){
    if( n>1 && strncmp(azArg[0], "once", n)==0 ){          bBOM = 1;
      if( nArg<2 ){        }else if( c!='e' && strcmp(z,"-x")==0 ){
        raw_printf(stderr, "Usage: .once (-e|-x|FILE)\n");          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 ){
         zFile = z;
       }else{
         utf8_printf(p->out,"ERROR: extra parameter: \"%s\".  Usage:\n",
                     azArg[i]);
         showHelp(p->out, azArg[0]);
         rc = 1;          rc = 1;
         goto meta_command_exit;          goto meta_command_exit;
       }        }
       }
       if( zFile==0 ) zFile = "stdout";
       if( bOnce ){
       p->outCount = 2;        p->outCount = 2;
     }else{      }else{
       p->outCount = 0;        p->outCount = 0;
     }      }
     output_reset(p);      output_reset(p);
     if( zFile[0]=='-' && zFile[1]=='-' ) zFile++;  
 #ifndef SQLITE_NOHAVE_SYSTEM  #ifndef SQLITE_NOHAVE_SYSTEM
    if( strcmp(zFile, "-e")==0 || strcmp(zFile, "-x")==0 ){    if( eMode=='e' || eMode=='x' ){
       p->doXdgOpen = 1;        p->doXdgOpen = 1;
       outputModePush(p);        outputModePush(p);
      if( zFile[1]=='x' ){      if( eMode=='x' ){
         /* spreadsheet mode.  Output as CSV. */
         newTempFile(p, "csv");          newTempFile(p, "csv");
           ShellClearFlag(p, SHFLG_Echo);
         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);
         sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);          sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
       }else{        }else{
           /* text editor mode */
         newTempFile(p, "txt");          newTempFile(p, "txt");
         bTxtMode = 1;          bTxtMode = 1;
       }        }
Line 16590  static int do_meta_command(char *zLine, ShellState *p) Line 18349  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
Line 16602  static int do_meta_command(char *zLine, ShellState *p) Line 18362  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);
       }        }
     }      }
Line 16615  static int do_meta_command(char *zLine, ShellState *p) Line 18376  static int do_meta_command(char *zLine, ShellState *p)
     ** Clear all bind parameters by dropping the TEMP table that holds them.      ** Clear all bind parameters by dropping the TEMP table that holds them.
     */      */
     if( nArg==2 && strcmp(azArg[1],"clear")==0 ){      if( nArg==2 && strcmp(azArg[1],"clear")==0 ){
       int wrSchema = 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, "DROP TABLE IF EXISTS temp.sqlite_parameters;",        sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp.sqlite_parameters;",
                    0, 0, 0);                     0, 0, 0);
       sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0);  
     }else      }else
   
     /* .parameter list      /* .parameter list
Line 16791  static int do_meta_command(char *zLine, ShellState *p) Line 18548  static int do_meta_command(char *zLine, ShellState *p)
       rc = 1;        rc = 1;
       goto meta_command_exit;        goto meta_command_exit;
     }      }
    p->in = fopen(azArg[1], "rb");    if( notNormalFile(azArg[1])
    if( p->in==0 ){     || (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{
Line 16895  static int do_meta_command(char *zLine, ShellState *p) Line 18653  static int do_meta_command(char *zLine, ShellState *p)
       }        }
     }      }
     if( zName!=0 ){      if( zName!=0 ){
      int isMaster = sqlite3_strlike(zName, "sqlite_master", '\\')==0;      int isSchema = sqlite3_strlike(zName, "sqlite_master", '\\')==0
      if( isMaster || sqlite3_strlike(zName,"sqlite_temp_master", '\\')==0 ){                  || sqlite3_strlike(zName, "sqlite_schema", '\\')==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] = sqlite3_mprintf(          new_argv[0] = sqlite3_mprintf(
                       "CREATE TABLE %s (\n"                        "CREATE TABLE %s (\n"
Line 16905  static int do_meta_command(char *zLine, ShellState *p) Line 18666  static int do_meta_command(char *zLine, ShellState *p)
                       "  tbl_name text,\n"                        "  tbl_name text,\n"
                       "  rootpage integer,\n"                        "  rootpage integer,\n"
                       "  sql text\n"                        "  sql text\n"
                      ")", isMaster ? "sqlite_master" : "sqlite_temp_master");                      ")", 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;
Line 16933  static int do_meta_command(char *zLine, ShellState *p) Line 18694  static int do_meta_command(char *zLine, ShellState *p)
         zDiv = " UNION ALL ";          zDiv = " UNION ALL ";
         appendText(&sSelect, "SELECT shell_add_schema(sql,", 0);          appendText(&sSelect, "SELECT shell_add_schema(sql,", 0);
         if( sqlite3_stricmp(zDb, "main")!=0 ){          if( sqlite3_stricmp(zDb, "main")!=0 ){
          appendText(&sSelect, zDb, '"');          appendText(&sSelect, zDb, '\'');
         }else{          }else{
           appendText(&sSelect, "NULL", 0);            appendText(&sSelect, "NULL", 0);
         }          }
Line 16942  static int do_meta_command(char *zLine, ShellState *p) Line 18703  static int do_meta_command(char *zLine, ShellState *p)
         appendText(&sSelect, " AS snum, ", 0);          appendText(&sSelect, " AS snum, ", 0);
         appendText(&sSelect, zDb, '\'');          appendText(&sSelect, zDb, '\'');
         appendText(&sSelect, " AS sname FROM ", 0);          appendText(&sSelect, " AS sname FROM ", 0);
        appendText(&sSelect, zDb, '"');        appendText(&sSelect, zDb, quoteChar(zDb));
        appendText(&sSelect, ".sqlite_master", 0);        appendText(&sSelect, ".sqlite_schema", 0);
       }        }
       sqlite3_finalize(pStmt);        sqlite3_finalize(pStmt);
#ifdef SQLITE_INTROSPECTION_PRAGMAS#ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS
       if( zName ){        if( zName ){
         appendText(&sSelect,          appendText(&sSelect,
            " UNION ALL SELECT shell_module_schema(name),"             " UNION ALL SELECT shell_module_schema(name),"
           " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list", 0);           " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list",
         0);
       }        }
 #endif  #endif
       appendText(&sSelect, ") WHERE ", 0);        appendText(&sSelect, ") WHERE ", 0);
Line 16994  static int do_meta_command(char *zLine, ShellState *p) Line 18756  static int do_meta_command(char *zLine, ShellState *p)
   
 #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)  #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 = (int)integerValue(azArg[1]);    sqlite3_unsupported_selecttrace = nArg>=2 ? (int)integerValue(azArg[1]) : 0xffff;
   }else    }else
 #endif  #endif
   
Line 17049  static int do_meta_command(char *zLine, ShellState *p) Line 18811  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 17370  static int do_meta_command(char *zLine, ShellState *p) Line 19133  static int do_meta_command(char *zLine, ShellState *p)
         {          {
           utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",            utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
                       azArg[i], azArg[0]);                        azArg[i], azArg[0]);
          raw_printf(stderr, "Should be one of: --schema"          showHelp(p->out, azArg[0]);
                             " --sha3-224 --sha3-256 --sha3-384 --sha3-512\n"); 
           rc = 1;            rc = 1;
           goto meta_command_exit;            goto meta_command_exit;
         }          }
Line 17386  static int do_meta_command(char *zLine, ShellState *p) Line 19148  static int do_meta_command(char *zLine, ShellState *p)
       }        }
     }      }
     if( bSchema ){      if( bSchema ){
      zSql = "SELECT lower(name) FROM sqlite_master"      zSql = "SELECT lower(name) FROM sqlite_schema"
              " WHERE type='table' AND coalesce(rootpage,0)>1"               " WHERE type='table' AND coalesce(rootpage,0)>1"
             " UNION ALL SELECT 'sqlite_master'"             " UNION ALL SELECT 'sqlite_schema'"
              " ORDER BY 1 collate nocase";               " ORDER BY 1 collate nocase";
     }else{      }else{
      zSql = "SELECT lower(name) FROM sqlite_master"      zSql = "SELECT lower(name) FROM sqlite_schema"
              " WHERE type='table' AND coalesce(rootpage,0)>1"               " WHERE type='table' AND coalesce(rootpage,0)>1"
              " AND name NOT LIKE 'sqlite_%'"               " AND name NOT LIKE 'sqlite_%'"
              " ORDER BY 1 collate nocase";               " ORDER BY 1 collate nocase";
Line 17408  static int do_meta_command(char *zLine, ShellState *p) Line 19170  static int do_meta_command(char *zLine, ShellState *p)
         appendText(&sQuery,"SELECT * FROM ", 0);          appendText(&sQuery,"SELECT * FROM ", 0);
         appendText(&sQuery,zTab,'"');          appendText(&sQuery,zTab,'"');
         appendText(&sQuery," NOT INDEXED;", 0);          appendText(&sQuery," NOT INDEXED;", 0);
      }else if( strcmp(zTab, "sqlite_master")==0 ){      }else if( strcmp(zTab, "sqlite_schema")==0 ){
        appendText(&sQuery,"SELECT type,name,tbl_name,sql FROM sqlite_master"        appendText(&sQuery,"SELECT type,name,tbl_name,sql FROM sqlite_schema"
                            " ORDER BY name;", 0);                             " ORDER BY name;", 0);
       }else if( strcmp(zTab, "sqlite_sequence")==0 ){        }else if( strcmp(zTab, "sqlite_sequence")==0 ){
         appendText(&sQuery,"SELECT name,seq FROM sqlite_sequence"          appendText(&sQuery,"SELECT name,seq FROM sqlite_sequence"
Line 17417  static int do_meta_command(char *zLine, ShellState *p) Line 19179  static int do_meta_command(char *zLine, ShellState *p)
       }else if( strcmp(zTab, "sqlite_stat1")==0 ){        }else if( strcmp(zTab, "sqlite_stat1")==0 ){
         appendText(&sQuery,"SELECT tbl,idx,stat FROM sqlite_stat1"          appendText(&sQuery,"SELECT tbl,idx,stat FROM sqlite_stat1"
                            " ORDER BY tbl,idx;", 0);                             " ORDER BY tbl,idx;", 0);
      }else if( strcmp(zTab, "sqlite_stat3")==0      }else if( strcmp(zTab, "sqlite_stat4")==0 ){
             || strcmp(zTab, "sqlite_stat4")==0 ){ 
         appendText(&sQuery, "SELECT * FROM ", 0);          appendText(&sQuery, "SELECT * FROM ", 0);
         appendText(&sQuery, zTab, 0);          appendText(&sQuery, zTab, 0);
         appendText(&sQuery, " ORDER BY tbl, idx, rowid;\n", 0);          appendText(&sQuery, " ORDER BY tbl, idx, rowid;\n", 0);
Line 17504  static int do_meta_command(char *zLine, ShellState *p) Line 19265  static int do_meta_command(char *zLine, ShellState *p)
       raw_printf(p->out, "\n");        raw_printf(p->out, "\n");
     utf8_printf(p->out, "%12.12s: %s\n","stats", azBool[p->statsOn!=0]);      utf8_printf(p->out, "%12.12s: %s\n","stats", azBool[p->statsOn!=0]);
     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");
Line 17561  static int do_meta_command(char *zLine, ShellState *p) Line 19322  static int do_meta_command(char *zLine, ShellState *p)
         appendText(&s, "||'.'||name FROM ", 0);          appendText(&s, "||'.'||name FROM ", 0);
       }        }
       appendText(&s, zDbName, '"');        appendText(&s, zDbName, '"');
      appendText(&s, ".sqlite_master ", 0);      appendText(&s, ".sqlite_schema ", 0);
       if( c=='t' ){        if( c=='t' ){
         appendText(&s," WHERE type IN ('table','view')"          appendText(&s," WHERE type IN ('table','view')"
                       "   AND name NOT LIKE 'sqlite_%'"                        "   AND name NOT LIKE 'sqlite_%'"
Line 17650  static int do_meta_command(char *zLine, ShellState *p) Line 19411  static int do_meta_command(char *zLine, ShellState *p)
        int ctrlCode;            /* Integer code for that option */         int ctrlCode;            /* Integer code for that option */
        const char *zUsage;      /* Usage notes */         const char *zUsage;      /* Usage notes */
     } aCtrl[] = {      } aCtrl[] = {
      { "always",             SQLITE_TESTCTRL_ALWAYS,        "BOOLEAN"            },      { "always",             SQLITE_TESTCTRL_ALWAYS,        "BOOLEAN"        },
      { "assert",             SQLITE_TESTCTRL_ASSERT,        "BOOLEAN"            },      { "assert",             SQLITE_TESTCTRL_ASSERT,        "BOOLEAN"        },
    /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, ""          },*/    /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, ""       },*/
    /*{ "bitvec_test",        SQLITE_TESTCTRL_BITVEC_TEST,   ""                },*/    /*{ "bitvec_test",        SQLITE_TESTCTRL_BITVEC_TEST,   ""             },*/
      { "byteorder",          SQLITE_TESTCTRL_BYTEORDER,     ""                   },      { "byteorder",          SQLITE_TESTCTRL_BYTEORDER,     ""               },
    /*{ "fault_install",      SQLITE_TESTCTRL_FAULT_INSTALL, ""                }, */      { "extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,"BOOLEAN"   },
      { "imposter",           SQLITE_TESTCTRL_IMPOSTER,   "SCHEMA ON/OFF ROOTPAGE"},    /*{ "fault_install",      SQLITE_TESTCTRL_FAULT_INSTALL, ""             },*/
      { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, "BOOLEAN"       },      { "imposter",         SQLITE_TESTCTRL_IMPOSTER, "SCHEMA ON/OFF ROOTPAGE"},
      { "localtime_fault",    SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN"           },      { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, "" },
      { "never_corrupt",      SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN"            },      { "localtime_fault",    SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN"       },
      { "optimizations",      SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK"       },      { "never_corrupt",      SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN"        },
       { "optimizations",      SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK"   },
 #ifdef YYCOVERAGE  #ifdef YYCOVERAGE
      { "parser_coverage",    SQLITE_TESTCTRL_PARSER_COVERAGE, ""                 },      { "parser_coverage",    SQLITE_TESTCTRL_PARSER_COVERAGE, ""             },
 #endif  #endif
      { "pending_byte",       SQLITE_TESTCTRL_PENDING_BYTE,  "OFFSET  "           },      { "pending_byte",       SQLITE_TESTCTRL_PENDING_BYTE,  "OFFSET  "       },
      { "prng_reset",         SQLITE_TESTCTRL_PRNG_RESET,    ""                   },      { "prng_restore",       SQLITE_TESTCTRL_PRNG_RESTORE,  ""               },
      { "prng_restore",       SQLITE_TESTCTRL_PRNG_RESTORE,  ""                   },      { "prng_save",          SQLITE_TESTCTRL_PRNG_SAVE,     ""               },
      { "prng_save",          SQLITE_TESTCTRL_PRNG_SAVE,     ""                   },      { "prng_seed",          SQLITE_TESTCTRL_PRNG_SEED,     "SEED ?db?"      },
      { "reserve",            SQLITE_TESTCTRL_RESERVE,       "BYTES-OF-RESERVE"   }, 
     };      };
     int testctrl = -1;      int testctrl = -1;
     int iCtrl = -1;      int iCtrl = -1;
Line 17721  static int do_meta_command(char *zLine, ShellState *p) Line 19482  static int do_meta_command(char *zLine, ShellState *p)
   
         /* 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);              int opt = (int)strtol(azArg[2], 0, 0);
             rc2 = sqlite3_test_control(testctrl, p->db, opt);              rc2 = sqlite3_test_control(testctrl, p->db, opt);
Line 17749  static int do_meta_command(char *zLine, ShellState *p) Line 19509  static int do_meta_command(char *zLine, ShellState *p)
           }            }
           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_INTERNAL_FUNCTIONS:  
           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);
Line 17770  static int do_meta_command(char *zLine, ShellState *p) Line 19550  static int do_meta_command(char *zLine, ShellState *p)
           }            }
           break;            break;
   
           /* 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,
Line 17790  static int do_meta_command(char *zLine, ShellState *p) Line 19576  static int do_meta_command(char *zLine, ShellState *p)
       }        }
     }      }
     if( isOk==0 && iCtrl>=0 ){      if( isOk==0 && iCtrl>=0 ){
      utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd, aCtrl[iCtrl].zUsage);      utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
       rc = 1;        rc = 1;
     }else if( isOk==1 ){      }else if( isOk==1 ){
       raw_printf(p->out, "%d\n", rc2);        raw_printf(p->out, "%d\n", rc2);
Line 17868  static int do_meta_command(char *zLine, ShellState *p) Line 19654  static int do_meta_command(char *zLine, ShellState *p)
   }else    }else
 #endif /* !defined(SQLITE_OMIT_TRACE) */  #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 17882  static int do_meta_command(char *zLine, ShellState *p) Line 19693  static int do_meta_command(char *zLine, ShellState *p)
         rc = 1;          rc = 1;
         goto meta_command_exit;          goto meta_command_exit;
       }        }
      rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3], strlen30(azArg[3]));      rc = sqlite3_user_authenticate(p->db, azArg[2], 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 18002  static int do_meta_command(char *zLine, ShellState *p) Line 19814  static int do_meta_command(char *zLine, ShellState *p)
   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 18347  static const char zOptions[] = Line 20163  static const char zOptions[] =
   "   -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"
Line 18362  static const char zOptions[] = Line 20179  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)  #if defined(SQLITE_ENABLE_DESERIALIZE)
   "   -maxsize N           maximum size for a --deserialize database\n"    "   -maxsize N           maximum size for a --deserialize database\n"
 #endif  #endif
Line 18374  static const char zOptions[] = Line 20193  static const char zOptions[] =
   "   -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"
   "   -quote               set output mode to 'quote'\n"    "   -quote               set output mode to 'quote'\n"
Line 18383  static const char zOptions[] = Line 20203  static const char zOptions[] =
   "   -sorterref SIZE      sorter references threshold size\n"    "   -sorterref SIZE      sorter references threshold size\n"
 #endif  #endif
   "   -stats               print memory stats before each finalize\n"    "   -stats               print memory stats before each finalize\n"
     "   -table               set output mode to 'table'\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
Line 18440  static void main_init(ShellState *data) { Line 20261  static void main_init(ShellState *data) {
 */  */
 #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){
Line 18502  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ Line 20327  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
   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 !defined(_WIN32_WCE)
   if( getenv("SQLITE_DEBUG_BREAK") ){    if( getenv("SQLITE_DEBUG_BREAK") ){
     if( isatty(0) && isatty(2) ){      if( isatty(0) && isatty(2) ){
Line 18511  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ Line 20340  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
       fgetc(stdin);        fgetc(stdin);
     }else{      }else{
 #if defined(_WIN32) || defined(WIN32)  #if defined(_WIN32) || defined(WIN32)
   #if SQLITE_OS_WINRT
         __debugbreak();
   #else
       DebugBreak();        DebugBreak();
   #endif
 #elif defined(SIGTRAP)  #elif defined(SIGTRAP)
       raise(SIGTRAP);        raise(SIGTRAP);
 #endif  #endif
Line 18684  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ Line 20517  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
 #endif  #endif
     }else if( strcmp(z,"-readonly")==0 ){      }else if( strcmp(z,"-readonly")==0 ){
       data.openMode = SHELL_OPEN_READONLY;        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)  #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
     }else if( strncmp(z, "-A",2)==0 ){      }else if( strncmp(z, "-A",2)==0 ){
       /* All remaining command-line arguments are passed to the ".archive"        /* All remaining command-line arguments are passed to the ".archive"
Line 18770  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ Line 20605  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
       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);
Line 18787  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ Line 20630  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
 #endif  #endif
     }else if( strcmp(z,"-readonly")==0 ){      }else if( strcmp(z,"-readonly")==0 ){
       data.openMode = SHELL_OPEN_READONLY;        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,
Line 18985  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ Line 20830  int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
   for(i=0; i<argcToFree; i++) free(argvToFree[i]);    for(i=0; i<argcToFree; i++) free(argvToFree[i]);
   free(argvToFree);    free(argvToFree);
 #endif  #endif
     free(data.colWidth);
   /* Clear the global data structure so that valgrind will detect memory    /* Clear the global data structure so that valgrind will detect memory
   ** leaks */    ** leaks */
   memset(&data, 0, sizeof(data));    memset(&data, 0, sizeof(data));

Removed from v.1.4.2.2  
changed lines
  Added in v.1.4.2.3


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