Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
update sqlite to 3.40.0
Baptiste Daroussin committed 3 years ago
commit 00bf7636beb0f028334dfc54e037de0c930491c5
parent 700d396
4 files changed +7427 -2758
modified auto.def
@@ -344,7 +344,7 @@ if {[get-define CCACHE] ne {none}} {
}

make-config-header pkg_config.h -bare { DEFAULT_* }
-
make-config-header external/sqlite/config.h
+
make-config-header external/sqlite/sqlite_cfg.h
make-template mk/defs.mk.in
make-template libpkg/pkg.h.in
make-template libpkg/pkg.pc.in
modified external/sqlite/shell.c
@@ -34,6 +34,8 @@
/* This needs to come before any includes for MSVC compiler */
#define _CRT_SECURE_NO_WARNINGS
#endif
+
typedef unsigned int u32;
+
typedef unsigned short int u16;

/*
** Optionally #include a user-defined header, whereby compilation options
@@ -56,6 +58,15 @@
#endif

/*
+
** If SQLITE_SHELL_FIDDLE is defined then the shell is modified
+
** somewhat for use as a WASM module in a web browser. This flag
+
** should only be used when building the "fiddle" web application, as
+
** the browser-mode build has much different user input requirements
+
** and this build mode rewires the user input subsystem to account for
+
** that.
+
*/
+

+
/*
** Warning pragmas copied from msvc.h in the core.
*/
#if defined(_MSC_VER)
@@ -94,6 +105,14 @@
# define _LARGEFILE_SOURCE 1
#endif

+
#if defined(SQLITE_SHELL_FIDDLE) && !defined(_POSIX_SOURCE)
+
/*
+
** emcc requires _POSIX_SOURCE (or one of several similar defines)
+
** to expose strdup().
+
*/
+
# define _POSIX_SOURCE
+
#endif
+

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
@@ -247,20 +266,21 @@ static void setTextMode(FILE *file, int isOutput){
# define setTextMode(X,Y)
#endif

-
/*
-
** When compiling with emcc (a.k.a. emscripten), we're building a
-
** WebAssembly (WASM) bundle and need to disable and rewire a few
-
** things.
-
*/
-
#ifdef __EMSCRIPTEN__
-
#define SQLITE_SHELL_WASM_MODE
-
#else
-
#undef SQLITE_SHELL_WASM_MODE
-
#endif
-

/* True if the timer is enabled */
static int enableTimer = 0;

+
/* A version of strcmp() that works with NULL values */
+
static int cli_strcmp(const char *a, const char *b){
+
  if( a==0 ) a = "";
+
  if( b==0 ) b = "";
+
  return strcmp(a,b);
+
}
+
static int cli_strncmp(const char *a, const char *b, size_t n){
+
  if( a==0 ) a = "";
+
  if( b==0 ) b = "";
+
  return strncmp(a,b,n);
+
}
+

/* Return the current wall-clock time */
static sqlite3_int64 timeOfDay(void){
  static sqlite3_vfs *clockVfs = 0;
@@ -549,6 +569,7 @@ static void utf8_width_print(FILE *pOut, int w, const char *zUtf){
  int i;
  int n;
  int aw = w<0 ? -w : w;
+
  if( zUtf==0 ) zUtf = "";
  for(i=n=0; zUtf[i]; i++){
    if( (zUtf[i]&0xc0)!=0x80 ){
      n++;
@@ -692,7 +713,7 @@ static char *local_getline(char *zLine, FILE *in){
  if( stdin_is_interactive && in==stdin ){
    char *zTrans = sqlite3_win32_mbcs_to_utf8_v2(zLine, 0);
    if( zTrans ){
-
      int nTrans = strlen30(zTrans)+1;
+
      i64 nTrans = strlen(zTrans)+1;
      if( nTrans>nLine ){
        zLine = realloc(zLine, nTrans);
        shell_check_oom(zLine);
@@ -719,7 +740,7 @@ static char *local_getline(char *zLine, FILE *in){
** be freed by the caller or else passed back into this routine via the
** zPrior argument for reuse.
*/
-
#ifndef SQLITE_SHELL_WASM_MODE
+
#ifndef SQLITE_SHELL_FIDDLE
static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
  char *zPrompt;
  char *zResult;
@@ -739,7 +760,7 @@ static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
  }
  return zResult;
}
-
#endif /* !SQLITE_SHELL_WASM_MODE */
+
#endif /* !SQLITE_SHELL_FIDDLE */

/*
** Return the value of a hexadecimal digit.  Return -1 if the input
@@ -828,9 +849,9 @@ static void freeText(ShellText *p){
** quote character for zAppend.
*/
static void appendText(ShellText *p, const char *zAppend, char quote){
-
  int len;
-
  int i;
-
  int nAppend = strlen30(zAppend);
+
  i64 len;
+
  i64 i;
+
  i64 nAppend = strlen30(zAppend);

  len = nAppend+p->n+1;
  if( quote ){
@@ -989,10 +1010,10 @@ static void shellAddSchemaName(
  const char *zName = (const char*)sqlite3_value_text(apVal[2]);
  sqlite3 *db = sqlite3_context_db_handle(pCtx);
  UNUSED_PARAMETER(nVal);
-
  if( zIn!=0 && strncmp(zIn, "CREATE ", 7)==0 ){
+
  if( zIn!=0 && cli_strncmp(zIn, "CREATE ", 7)==0 ){
    for(i=0; i<ArraySize(aPrefix); i++){
      int n = strlen30(aPrefix[i]);
-
      if( strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){
+
      if( cli_strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){
        char *z = 0;
        char *zFake = 0;
        if( zSchema ){
@@ -3796,6 +3817,7 @@ SQLITE_EXTENSION_INIT1

/* The end-of-input character */
#define RE_EOF            0    /* End of input */
+
#define RE_START  0xfffffff    /* Start of input - larger than an UTF-8 */

/* The NFA is implemented as sequence of opcodes taken from the following
** set.  Each opcode has a single integer argument.
@@ -3817,6 +3839,33 @@ SQLITE_EXTENSION_INIT1
#define RE_OP_SPACE      15    /* space:  [ \t\n\r\v\f] */
#define RE_OP_NOTSPACE   16    /* Not a digit */
#define RE_OP_BOUNDARY   17    /* Boundary between word and non-word */
+
#define RE_OP_ATSTART    18    /* Currently at the start of the string */
+

+
#if defined(SQLITE_DEBUG)
+
/* Opcode names used for symbolic debugging */
+
static const char *ReOpName[] = {
+
  "EOF",
+
  "MATCH",
+
  "ANY",
+
  "ANYSTAR",
+
  "FORK",
+
  "GOTO",
+
  "ACCEPT",
+
  "CC_INC",
+
  "CC_EXC",
+
  "CC_VALUE",
+
  "CC_RANGE",
+
  "WORD",
+
  "NOTWORD",
+
  "DIGIT",
+
  "NOTDIGIT",
+
  "SPACE",
+
  "NOTSPACE",
+
  "BOUNDARY",
+
  "ATSTART",
+
};
+
#endif /* SQLITE_DEBUG */
+


/* Each opcode is a "state" in the NFA */
typedef unsigned short ReStateNumber;
@@ -3851,7 +3900,7 @@ struct ReCompiled {
  int *aArg;                  /* Arguments to each operator */
  unsigned (*xNextChar)(ReInput*);  /* Next character function */
  unsigned char zInit[12];    /* Initial text to match */
-
  int nInit;                  /* Number of characters in zInit */
+
  int nInit;                  /* Number of bytes in zInit */
  unsigned nState;            /* Number of entries in aOp[] and aArg[] */
  unsigned nAlloc;            /* Slots allocated for aOp[] and aArg[] */
};
@@ -3924,7 +3973,7 @@ static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
  ReStateNumber *pToFree;
  unsigned int i = 0;
  unsigned int iSwap = 0;
-
  int c = RE_EOF+1;
+
  int c = RE_START;
  int cPrev = 0;
  int rc = 0;
  ReInput in;
@@ -3943,6 +3992,7 @@ static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
      in.i++;
    }
    if( in.i+pRe->nInit>in.mx ) return 0;
+
    c = RE_START-1;
  }

  if( pRe->nState<=(sizeof(aSpace)/(sizeof(aSpace[0])*2)) ){
@@ -3971,6 +4021,10 @@ static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
          if( pRe->aArg[x]==c ) re_add_state(pNext, x+1);
          break;
        }
+
        case RE_OP_ATSTART: {
+
          if( cPrev==RE_START ) re_add_state(pThis, x+1);
+
          break;
+
        }
        case RE_OP_ANY: {
          if( c!=0 ) re_add_state(pNext, x+1);
          break;
@@ -4052,7 +4106,9 @@ static int re_match(ReCompiled *pRe, const unsigned char *zIn, int nIn){
    }
  }
  for(i=0; i<pNext->nState; i++){
-
    if( pRe->aOp[pNext->aState[i]]==RE_OP_ACCEPT ){ rc = 1; break; }
+
    int x = pNext->aState[i];
+
    while( pRe->aOp[x]==RE_OP_GOTO ) x += pRe->aArg[x];
+
    if( pRe->aOp[x]==RE_OP_ACCEPT ){ rc = 1; break; }
  }
re_match_end:
  sqlite3_free(pToFree);
@@ -4207,7 +4263,6 @@ static const char *re_subcompile_string(ReCompiled *p){
    iStart = p->nState;
    switch( c ){
      case '|':
-
      case '$':
      case ')': {
        p->sIn.i--;
        return 0;
@@ -4244,6 +4299,14 @@ static const char *re_subcompile_string(ReCompiled *p){
        re_insert(p, iPrev, RE_OP_FORK, p->nState - iPrev+1);
        break;
      }
+
      case '$': {
+
        re_append(p, RE_OP_MATCH, RE_EOF);
+
        break;
+
      }
+
      case '^': {
+
        re_append(p, RE_OP_ATSTART, 0);
+
        break;
+
      }
      case '{': {
        int m = 0, n = 0;
        int sz, j;
@@ -4262,6 +4325,7 @@ static const char *re_subcompile_string(ReCompiled *p){
        if( m==0 ){
          if( n==0 ) return "both m and n are zero in '{m,n}'";
          re_insert(p, iPrev, RE_OP_FORK, sz+1);
+
          iPrev++;
          n--;
        }else{
          for(j=1; j<m; j++) re_copy(p, iPrev, sz);
@@ -4380,11 +4444,7 @@ static const char *re_compile(ReCompiled **ppRe, const char *zIn, int noCase){
    re_free(pRe);
    return zErr;
  }
-
  if( rePeek(pRe)=='$' && pRe->sIn.i+1>=pRe->sIn.mx ){
-
    re_append(pRe, RE_OP_MATCH, RE_EOF);
-
    re_append(pRe, RE_OP_ACCEPT, 0);
-
    *ppRe = pRe;
-
  }else if( pRe->sIn.i>=pRe->sIn.mx ){
+
  if( pRe->sIn.i>=pRe->sIn.mx ){
    re_append(pRe, RE_OP_ACCEPT, 0);
    *ppRe = pRe;
  }else{
@@ -4468,6 +4528,67 @@ static void re_sql_func(
  }
}

+
#if defined(SQLITE_DEBUG)
+
/*
+
** This function is used for testing and debugging only.  It is only available
+
** if the SQLITE_DEBUG compile-time option is used.
+
**
+
** Compile a regular expression and then convert the compiled expression into
+
** text and return that text.
+
*/
+
static void re_bytecode_func(
+
  sqlite3_context *context,
+
  int argc,
+
  sqlite3_value **argv
+
){
+
  const char *zPattern;
+
  const char *zErr;
+
  ReCompiled *pRe;
+
  sqlite3_str *pStr;
+
  int i;
+
  int n;
+
  char *z;
+

+
  zPattern = (const char*)sqlite3_value_text(argv[0]);
+
  if( zPattern==0 ) return;
+
  zErr = re_compile(&pRe, zPattern, sqlite3_user_data(context)!=0);
+
  if( zErr ){
+
    re_free(pRe);
+
    sqlite3_result_error(context, zErr, -1);
+
    return;
+
  }
+
  if( pRe==0 ){
+
    sqlite3_result_error_nomem(context);
+
    return;
+
  }
+
  pStr = sqlite3_str_new(0);
+
  if( pStr==0 ) goto re_bytecode_func_err;
+
  if( pRe->nInit>0 ){
+
    sqlite3_str_appendf(pStr, "INIT     ");
+
    for(i=0; i<pRe->nInit; i++){
+
      sqlite3_str_appendf(pStr, "%02x", pRe->zInit[i]);
+
    }
+
    sqlite3_str_appendf(pStr, "\n");
+
  }
+
  for(i=0; (unsigned)i<pRe->nState; i++){
+
    sqlite3_str_appendf(pStr, "%-8s %4d\n",
+
         ReOpName[(unsigned char)pRe->aOp[i]], pRe->aArg[i]);
+
  }
+
  n = sqlite3_str_length(pStr);
+
  z = sqlite3_str_finish(pStr);
+
  if( n==0 ){
+
    sqlite3_free(z);
+
  }else{
+
    sqlite3_result_text(context, z, n-1, sqlite3_free);
+
  }
+

+
re_bytecode_func_err:
+
  re_free(pRe);
+
}
+

+
#endif /* SQLITE_DEBUG */
+

+

/*
** Invoke this routine to register the regexp() function with the
** SQLite database connection.
@@ -4492,12 +4613,19 @@ int sqlite3_regexp_init(
    rc = sqlite3_create_function(db, "regexpi", 2,
                            SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
                            (void*)db, re_sql_func, 0, 0);
+
#if defined(SQLITE_DEBUG)
+
    if( rc==SQLITE_OK ){
+
      rc = sqlite3_create_function(db, "regexp_bytecode", 1,
+
                            SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
+
                            0, re_bytecode_func, 0, 0);
+
    }
+
#endif /* SQLITE_DEBUG */
  }
  return rc;
}

/************************* End ../ext/misc/regexp.c ********************/
-
#ifndef SQLITE_SHELL_WASM_MODE
+
#ifndef SQLITE_SHELL_FIDDLE
/************************* Begin ../ext/misc/fileio.c ******************/
/*
** 2014-06-13
@@ -6767,8 +6895,8 @@ SQLITE_EXTENSION_INIT1
#endif
/* typedef sqlite3_int64 i64; */
/* typedef unsigned char u8; */
-
typedef UINT32_TYPE u32;           /* 4-byte unsigned integer */
-
typedef UINT16_TYPE u16;           /* 2-byte unsigned integer */
+
/* typedef UINT32_TYPE u32;           // 4-byte unsigned integer // */
+
/* typedef UINT16_TYPE u16;           // 2-byte unsigned integer // */
#define MIN(a,b) ((a)<(b) ? (a) : (b))

#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
@@ -10049,6 +10177,10 @@ static char *idxAppendText(int *pRc, char *zIn, const char *zFmt, ...){
*/
static int idxIdentifierRequiresQuotes(const char *zId){
  int i;
+
  int nId = STRLEN(zId);
+
  
+
  if( sqlite3_keyword_check(zId, nId) ) return 1;
+

  for(i=0; zId[i]; i++){
    if( !(zId[i]=='_')
     && !(zId[i]>='0' && zId[i]<='9')
@@ -11275,7 +11407,12 @@ void sqlite3_expert_destroy(sqlite3expert *p){
/************************* End ../ext/expert/sqlite3expert.c ********************/

#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
-
/************************* Begin ../ext/misc/dbdata.c ******************/
+
#define SQLITE_SHELL_HAVE_RECOVER 1
+
#else
+
#define SQLITE_SHELL_HAVE_RECOVER 0
+
#endif
+
#if SQLITE_SHELL_HAVE_RECOVER
+
/************************* Begin ../ext/recover/dbdata.c ******************/
/*
** 2019-04-17
**
@@ -11349,16 +11486,20 @@ void sqlite3_expert_destroy(sqlite3expert *p){
**   It contains one entry for each b-tree pointer between a parent and
**   child page in the database.
*/
+

#if !defined(SQLITEINT_H) 
/* #include "sqlite3ext.h" */

/* typedef unsigned char u8; */
+
/* typedef unsigned int u32; */

#endif
SQLITE_EXTENSION_INIT1
#include <string.h>
#include <assert.h>

+
#ifndef SQLITE_OMIT_VIRTUALTABLE
+

#define DBDATA_PADDING_BYTES 100 

typedef struct DbdataTable DbdataTable;
@@ -11380,11 +11521,12 @@ struct DbdataCursor {

  /* Only for the sqlite_dbdata table */
  u8 *pRec;                       /* Buffer containing current record */
-
  int nRec;                       /* Size of pRec[] in bytes */
-
  int nHdr;                       /* Size of header in bytes */
+
  sqlite3_int64 nRec;             /* Size of pRec[] in bytes */
+
  sqlite3_int64 nHdr;             /* Size of header in bytes */
  int iField;                     /* Current field number */
  u8 *pHdrPtr;
  u8 *pPtr;
+
  u32 enc;                        /* Text encoding */
  
  sqlite3_int64 iIntkey;          /* Integer key value */
};
@@ -11577,14 +11719,14 @@ static int dbdataClose(sqlite3_vtab_cursor *pCursor){
/* 
** Utility methods to decode 16 and 32-bit big-endian unsigned integers. 
*/
-
static unsigned int get_uint16(unsigned char *a){
+
static u32 get_uint16(unsigned char *a){
  return (a[0]<<8)|a[1];
}
-
static unsigned int get_uint32(unsigned char *a){
-
  return ((unsigned int)a[0]<<24)
-
       | ((unsigned int)a[1]<<16)
-
       | ((unsigned int)a[2]<<8)
-
       | ((unsigned int)a[3]);
+
static u32 get_uint32(unsigned char *a){
+
  return ((u32)a[0]<<24)
+
       | ((u32)a[1]<<16)
+
       | ((u32)a[2]<<8)
+
       | ((u32)a[3]);
}

/*
@@ -11599,7 +11741,7 @@ static unsigned int get_uint32(unsigned char *a){
*/
static int dbdataLoadPage(
  DbdataCursor *pCsr,             /* Cursor object */
-
  unsigned int pgno,              /* Page number of page to load */
+
  u32 pgno,                       /* Page number of page to load */
  u8 **ppPage,                    /* OUT: pointer to page buffer */
  int *pnPage                     /* OUT: Size of (*ppPage) in bytes */
){
@@ -11609,25 +11751,27 @@ static int dbdataLoadPage(

  *ppPage = 0;
  *pnPage = 0;
-
  sqlite3_bind_int64(pStmt, 2, pgno);
-
  if( SQLITE_ROW==sqlite3_step(pStmt) ){
-
    int nCopy = sqlite3_column_bytes(pStmt, 0);
-
    if( nCopy>0 ){
-
      u8 *pPage;
-
      pPage = (u8*)sqlite3_malloc64(nCopy + DBDATA_PADDING_BYTES);
-
      if( pPage==0 ){
-
        rc = SQLITE_NOMEM;
-
      }else{
-
        const u8 *pCopy = sqlite3_column_blob(pStmt, 0);
-
        memcpy(pPage, pCopy, nCopy);
-
        memset(&pPage[nCopy], 0, DBDATA_PADDING_BYTES);
+
  if( pgno>0 ){
+
    sqlite3_bind_int64(pStmt, 2, pgno);
+
    if( SQLITE_ROW==sqlite3_step(pStmt) ){
+
      int nCopy = sqlite3_column_bytes(pStmt, 0);
+
      if( nCopy>0 ){
+
        u8 *pPage;
+
        pPage = (u8*)sqlite3_malloc64(nCopy + DBDATA_PADDING_BYTES);
+
        if( pPage==0 ){
+
          rc = SQLITE_NOMEM;
+
        }else{
+
          const u8 *pCopy = sqlite3_column_blob(pStmt, 0);
+
          memcpy(pPage, pCopy, nCopy);
+
          memset(&pPage[nCopy], 0, DBDATA_PADDING_BYTES);
+
        }
+
        *ppPage = pPage;
+
        *pnPage = nCopy;
      }
-
      *ppPage = pPage;
-
      *pnPage = nCopy;
    }
+
    rc2 = sqlite3_reset(pStmt);
+
    if( rc==SQLITE_OK ) rc = rc2;
  }
-
  rc2 = sqlite3_reset(pStmt);
-
  if( rc==SQLITE_OK ) rc = rc2;

  return rc;
}
@@ -11636,18 +11780,31 @@ static int dbdataLoadPage(
** Read a varint.  Put the value in *pVal and return the number of bytes.
*/
static int dbdataGetVarint(const u8 *z, sqlite3_int64 *pVal){
-
  sqlite3_int64 v = 0;
+
  sqlite3_uint64 u = 0;
  int i;
  for(i=0; i<8; i++){
-
    v = (v<<7) + (z[i]&0x7f);
-
    if( (z[i]&0x80)==0 ){ *pVal = v; return i+1; }
+
    u = (u<<7) + (z[i]&0x7f);
+
    if( (z[i]&0x80)==0 ){ *pVal = (sqlite3_int64)u; return i+1; }
  }
-
  v = (v<<8) + (z[i]&0xff);
-
  *pVal = v;
+
  u = (u<<8) + (z[i]&0xff);
+
  *pVal = (sqlite3_int64)u;
  return 9;
}

/*
+
** Like dbdataGetVarint(), but set the output to 0 if it is less than 0
+
** or greater than 0xFFFFFFFF. This can be used for all varints in an
+
** SQLite database except for key values in intkey tables.
+
*/
+
static int dbdataGetVarintU32(const u8 *z, sqlite3_int64 *pVal){
+
  sqlite3_int64 val;
+
  int nRet = dbdataGetVarint(z, &val);
+
  if( val<0 || val>0xFFFFFFFF ) val = 0;
+
  *pVal = val;
+
  return nRet;
+
}
+

+
/*
** Return the number of bytes of space used by an SQLite value of type
** eType.
*/
@@ -11683,9 +11840,10 @@ static int dbdataValueBytes(int eType){
*/
static void dbdataValue(
  sqlite3_context *pCtx, 
+
  u32 enc,
  int eType, 
  u8 *pData,
-
  int nData
+
  sqlite3_int64 nData
){
  if( eType>=0 && dbdataValueBytes(eType)<=nData ){
    switch( eType ){
@@ -11727,7 +11885,19 @@ static void dbdataValue(
      default: {
        int n = ((eType-12) / 2);
        if( eType % 2 ){
-
          sqlite3_result_text(pCtx, (const char*)pData, n, SQLITE_TRANSIENT);
+
          switch( enc ){
+
#ifndef SQLITE_OMIT_UTF16
+
            case SQLITE_UTF16BE:
+
              sqlite3_result_text16be(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
+
              break;
+
            case SQLITE_UTF16LE:
+
              sqlite3_result_text16le(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
+
              break;
+
#endif
+
            default:
+
              sqlite3_result_text(pCtx, (char*)pData, n, SQLITE_TRANSIENT);
+
              break;
+
          }
        }else{
          sqlite3_result_blob(pCtx, pData, n, SQLITE_TRANSIENT);
        }
@@ -11755,6 +11925,7 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){
        rc = dbdataLoadPage(pCsr, pCsr->iPgno, &pCsr->aPage, &pCsr->nPage);
        if( rc!=SQLITE_OK ) return rc;
        if( pCsr->aPage ) break;
+
        if( pCsr->bOnePage ) return SQLITE_OK;
        pCsr->iPgno++;
      }
      pCsr->iCell = pTab->bPtr ? -2 : 0;
@@ -11818,7 +11989,7 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){
          if( bNextPage || iOff>pCsr->nPage ){
            bNextPage = 1;
          }else{
-
            iOff += dbdataGetVarint(&pCsr->aPage[iOff], &nPayload);
+
            iOff += dbdataGetVarintU32(&pCsr->aPage[iOff], &nPayload);
          }
    
          /* If this is a leaf intkey cell, load the rowid */
@@ -11865,7 +12036,7 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){
            /* Load content from overflow pages */
            if( nPayload>nLocal ){
              sqlite3_int64 nRem = nPayload - nLocal;
-
              unsigned int pgnoOvfl = get_uint32(&pCsr->aPage[iOff]);
+
              u32 pgnoOvfl = get_uint32(&pCsr->aPage[iOff]);
              while( nRem>0 ){
                u8 *aOvfl = 0;
                int nOvfl = 0;
@@ -11885,7 +12056,8 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){
              }
            }
    
-
            iHdr = dbdataGetVarint(pCsr->pRec, &nHdr);
+
            iHdr = dbdataGetVarintU32(pCsr->pRec, &nHdr);
+
            if( nHdr>nPayload ) nHdr = 0;
            pCsr->nHdr = nHdr;
            pCsr->pHdrPtr = &pCsr->pRec[iHdr];
            pCsr->pPtr = &pCsr->pRec[pCsr->nHdr];
@@ -11899,7 +12071,7 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){
          if( pCsr->pHdrPtr>&pCsr->pRec[pCsr->nRec] ){
            bNextPage = 1;
          }else{
-
            pCsr->pHdrPtr += dbdataGetVarint(pCsr->pHdrPtr, &iType);
+
            pCsr->pHdrPtr += dbdataGetVarintU32(pCsr->pHdrPtr, &iType);
            pCsr->pPtr += dbdataValueBytes(iType);
          }
        }
@@ -11938,6 +12110,18 @@ static int dbdataEof(sqlite3_vtab_cursor *pCursor){
  return pCsr->aPage==0;
}

+
/*
+
** Return true if nul-terminated string zSchema ends in "()". Or false
+
** otherwise.
+
*/
+
static int dbdataIsFunction(const char *zSchema){
+
  size_t n = strlen(zSchema);
+
  if( n>2 && zSchema[n-2]=='(' && zSchema[n-1]==')' ){
+
    return (int)n-2;
+
  }
+
  return 0;
+
}
+

/* 
** Determine the size in pages of database zSchema (where zSchema is
** "main", "temp" or the name of an attached database) and set 
@@ -11948,10 +12132,16 @@ static int dbdataDbsize(DbdataCursor *pCsr, const char *zSchema){
  DbdataTable *pTab = (DbdataTable*)pCsr->base.pVtab;
  char *zSql = 0;
  int rc, rc2;
+
  int nFunc = 0;
  sqlite3_stmt *pStmt = 0;

-
  zSql = sqlite3_mprintf("PRAGMA %Q.page_count", zSchema);
+
  if( (nFunc = dbdataIsFunction(zSchema))>0 ){
+
    zSql = sqlite3_mprintf("SELECT %.*s(0)", nFunc, zSchema);
+
  }else{
+
    zSql = sqlite3_mprintf("PRAGMA %Q.page_count", zSchema);
+
  }
  if( zSql==0 ) return SQLITE_NOMEM;
+

  rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pStmt, 0);
  sqlite3_free(zSql);
  if( rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW ){
@@ -11962,6 +12152,25 @@ static int dbdataDbsize(DbdataCursor *pCsr, const char *zSchema){
  return rc;
}

+
/*
+
** Attempt to figure out the encoding of the database by retrieving page 1
+
** and inspecting the header field. If successful, set the pCsr->enc variable
+
** and return SQLITE_OK. Otherwise, return an SQLite error code.
+
*/
+
static int dbdataGetEncoding(DbdataCursor *pCsr){
+
  int rc = SQLITE_OK;
+
  int nPg1 = 0;
+
  u8 *aPg1 = 0;
+
  rc = dbdataLoadPage(pCsr, 1, &aPg1, &nPg1);
+
  assert( rc!=SQLITE_OK || nPg1==0 || nPg1>=512 );
+
  if( rc==SQLITE_OK && nPg1>0 ){
+
    pCsr->enc = get_uint32(&aPg1[56]);
+
  }
+
  sqlite3_free(aPg1);
+
  return rc;
+
}
+

+

/* 
** xFilter method for sqlite_dbdata and sqlite_dbptr.
*/
@@ -11979,19 +12188,28 @@ static int dbdataFilter(
  assert( pCsr->iPgno==1 );
  if( idxNum & 0x01 ){
    zSchema = (const char*)sqlite3_value_text(argv[0]);
+
    if( zSchema==0 ) zSchema = "";
  }
  if( idxNum & 0x02 ){
    pCsr->iPgno = sqlite3_value_int(argv[(idxNum & 0x01)]);
    pCsr->bOnePage = 1;
  }else{
-
    pCsr->nPage = dbdataDbsize(pCsr, zSchema);
    rc = dbdataDbsize(pCsr, zSchema);
  }

  if( rc==SQLITE_OK ){
+
    int nFunc = 0;
    if( pTab->pStmt ){
      pCsr->pStmt = pTab->pStmt;
      pTab->pStmt = 0;
+
    }else if( (nFunc = dbdataIsFunction(zSchema))>0 ){
+
      char *zSql = sqlite3_mprintf("SELECT %.*s(?2)", nFunc, zSchema);
+
      if( zSql==0 ){
+
        rc = SQLITE_NOMEM;
+
      }else{
+
        rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pCsr->pStmt, 0);
+
        sqlite3_free(zSql);
+
      }
    }else{
      rc = sqlite3_prepare_v2(pTab->db, 
          "SELECT data FROM sqlite_dbpage(?) WHERE pgno=?", -1,
@@ -12004,13 +12222,20 @@ static int dbdataFilter(
  }else{
    pTab->base.zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pTab->db));
  }
+

+
  /* Try to determine the encoding of the db by inspecting the header
+
  ** field on page 1. */
+
  if( rc==SQLITE_OK ){
+
    rc = dbdataGetEncoding(pCsr);
+
  }
+

  if( rc==SQLITE_OK ){
    rc = dbdataNext(pCursor);
  }
  return rc;
}

-
/* 
+
/*
** Return a column for the sqlite_dbdata or sqlite_dbptr table.
*/
static int dbdataColumn(
@@ -12054,11 +12279,12 @@ static int dbdataColumn(
      case DBDATA_COLUMN_VALUE: {
        if( pCsr->iField<0 ){
          sqlite3_result_int64(ctx, pCsr->iIntkey);
-
        }else{
+
        }else if( &pCsr->pRec[pCsr->nRec] >= pCsr->pPtr ){
          sqlite3_int64 iType;
-
          dbdataGetVarint(pCsr->pHdrPtr, &iType);
+
          dbdataGetVarintU32(pCsr->pHdrPtr, &iType);
          dbdataValue(
-
              ctx, iType, pCsr->pPtr, &pCsr->pRec[pCsr->nRec] - pCsr->pPtr
+
              ctx, pCsr->enc, iType, pCsr->pPtr, 
+
              &pCsr->pRec[pCsr->nRec] - pCsr->pPtr
          );
        }
        break;
@@ -12128,56 +12354,3170 @@ int sqlite3_dbdata_init(
  return sqlite3DbdataRegister(db);
}

-
/************************* End ../ext/misc/dbdata.c ********************/
+
#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
+

+
/************************* End ../ext/recover/dbdata.c ********************/
+
/************************* Begin ../ext/recover/sqlite3recover.h ******************/
+
/*
+
** 2022-08-27
+
**
+
** The author disclaims copyright to this source code.  In place of
+
** a legal notice, here is a blessing:
+
**
+
**    May you do good and not evil.
+
**    May you find forgiveness for yourself and forgive others.
+
**    May you share freely, never taking more than you give.
+
**
+
*************************************************************************
+
**
+
** This file contains the public interface to the "recover" extension -
+
** an SQLite extension designed to recover data from corrupted database
+
** files.
+
*/
+

+
/*
+
** OVERVIEW:
+
**
+
** To use the API to recover data from a corrupted database, an
+
** application:
+
**
+
**   1) Creates an sqlite3_recover handle by calling either
+
**      sqlite3_recover_init() or sqlite3_recover_init_sql().
+
**
+
**   2) Configures the new handle using one or more calls to
+
**      sqlite3_recover_config().
+
**
+
**   3) Executes the recovery by repeatedly calling sqlite3_recover_step() on
+
**      the handle until it returns something other than SQLITE_OK. If it
+
**      returns SQLITE_DONE, then the recovery operation completed without 
+
**      error. If it returns some other non-SQLITE_OK value, then an error 
+
**      has occurred.
+
**
+
**   4) Retrieves any error code and English language error message using the
+
**      sqlite3_recover_errcode() and sqlite3_recover_errmsg() APIs,
+
**      respectively.
+
**
+
**   5) Destroys the sqlite3_recover handle and frees all resources
+
**      using sqlite3_recover_finish().
+
**
+
** The application may abandon the recovery operation at any point 
+
** before it is finished by passing the sqlite3_recover handle to
+
** sqlite3_recover_finish(). This is not an error, but the final state
+
** of the output database, or the results of running the partial script
+
** delivered to the SQL callback, are undefined.
+
*/
+

+
#ifndef _SQLITE_RECOVER_H
+
#define _SQLITE_RECOVER_H
+

+
/* #include "sqlite3.h" */
+

+
#ifdef __cplusplus
+
extern "C" {
#endif

-
#if defined(SQLITE_ENABLE_SESSION)
/*
-
** State information for a single open session
+
** An instance of the sqlite3_recover object represents a recovery
+
** operation in progress.
+
**
+
** Constructors:
+
**
+
**    sqlite3_recover_init()
+
**    sqlite3_recover_init_sql()
+
**
+
** Destructor:
+
**
+
**    sqlite3_recover_finish()
+
**
+
** Methods:
+
**
+
**    sqlite3_recover_config()
+
**    sqlite3_recover_errcode()
+
**    sqlite3_recover_errmsg()
+
**    sqlite3_recover_run()
+
**    sqlite3_recover_step()
*/
-
typedef struct OpenSession OpenSession;
-
struct OpenSession {
-
  char *zName;             /* Symbolic name for this session */
-
  int nFilter;             /* Number of xFilter rejection GLOB patterns */
-
  char **azFilter;         /* Array of xFilter rejection GLOB patterns */
-
  sqlite3_session *p;      /* The open session */
-
};
+
typedef struct sqlite3_recover sqlite3_recover;
+

+
/* 
+
** These two APIs attempt to create and return a new sqlite3_recover object.
+
** In both cases the first two arguments identify the (possibly
+
** corrupt) database to recover data from. The first argument is an open
+
** database handle and the second the name of a database attached to that
+
** handle (i.e. "main", "temp" or the name of an attached database).
+
**
+
** If sqlite3_recover_init() is used to create the new sqlite3_recover
+
** handle, then data is recovered into a new database, identified by
+
** string parameter zUri. zUri may be an absolute or relative file path,
+
** or may be an SQLite URI. If the identified database file already exists,
+
** it is overwritten.
+
**
+
** If sqlite3_recover_init_sql() is invoked, then any recovered data will
+
** be returned to the user as a series of SQL statements. Executing these
+
** SQL statements results in the same database as would have been created
+
** had sqlite3_recover_init() been used. For each SQL statement in the
+
** output, the callback function passed as the third argument (xSql) is 
+
** invoked once. The first parameter is a passed a copy of the fourth argument
+
** to this function (pCtx) as its first parameter, and a pointer to a
+
** nul-terminated buffer containing the SQL statement formated as UTF-8 as 
+
** the second. If the xSql callback returns any value other than SQLITE_OK,
+
** then processing is immediately abandoned and the value returned used as
+
** the recover handle error code (see below).
+
**
+
** If an out-of-memory error occurs, NULL may be returned instead of
+
** a valid handle. In all other cases, it is the responsibility of the
+
** application to avoid resource leaks by ensuring that
+
** sqlite3_recover_finish() is called on all allocated handles.
+
*/
+
sqlite3_recover *sqlite3_recover_init(
+
  sqlite3* db, 
+
  const char *zDb, 
+
  const char *zUri
+
);
+
sqlite3_recover *sqlite3_recover_init_sql(
+
  sqlite3* db, 
+
  const char *zDb, 
+
  int (*xSql)(void*, const char*),
+
  void *pCtx
+
);
+

+
/*
+
** Configure an sqlite3_recover object that has just been created using
+
** sqlite3_recover_init() or sqlite3_recover_init_sql(). This function
+
** may only be called before the first call to sqlite3_recover_step()
+
** or sqlite3_recover_run() on the object.
+
**
+
** The second argument passed to this function must be one of the
+
** SQLITE_RECOVER_* symbols defined below. Valid values for the third argument
+
** depend on the specific SQLITE_RECOVER_* symbol in use.
+
**
+
** SQLITE_OK is returned if the configuration operation was successful,
+
** or an SQLite error code otherwise.
+
*/
+
int sqlite3_recover_config(sqlite3_recover*, int op, void *pArg);
+

+
/*
+
** SQLITE_RECOVER_LOST_AND_FOUND:
+
**   The pArg argument points to a string buffer containing the name
+
**   of a "lost-and-found" table in the output database, or NULL. If
+
**   the argument is non-NULL and the database contains seemingly
+
**   valid pages that cannot be associated with any table in the
+
**   recovered part of the schema, data is extracted from these
+
**   pages to add to the lost-and-found table.
+
**
+
** SQLITE_RECOVER_FREELIST_CORRUPT:
+
**   The pArg value must actually be a pointer to a value of type
+
**   int containing value 0 or 1 cast as a (void*). If this option is set
+
**   (argument is 1) and a lost-and-found table has been configured using
+
**   SQLITE_RECOVER_LOST_AND_FOUND, then is assumed that the freelist is 
+
**   corrupt and an attempt is made to recover records from pages that
+
**   appear to be linked into the freelist. Otherwise, pages on the freelist
+
**   are ignored. Setting this option can recover more data from the
+
**   database, but often ends up "recovering" deleted records. The default 
+
**   value is 0 (clear).
+
**
+
** SQLITE_RECOVER_ROWIDS:
+
**   The pArg value must actually be a pointer to a value of type
+
**   int containing value 0 or 1 cast as a (void*). If this option is set
+
**   (argument is 1), then an attempt is made to recover rowid values
+
**   that are not also INTEGER PRIMARY KEY values. If this option is
+
**   clear, then new rowids are assigned to all recovered rows. The
+
**   default value is 1 (set).
+
**
+
** SQLITE_RECOVER_SLOWINDEXES:
+
**   The pArg value must actually be a pointer to a value of type
+
**   int containing value 0 or 1 cast as a (void*). If this option is clear
+
**   (argument is 0), then when creating an output database, the recover 
+
**   module creates and populates non-UNIQUE indexes right at the end of the
+
**   recovery operation - after all recoverable data has been inserted
+
**   into the new database. This is faster overall, but means that the
+
**   final call to sqlite3_recover_step() for a recovery operation may
+
**   be need to create a large number of indexes, which may be very slow.
+
**
+
**   Or, if this option is set (argument is 1), then non-UNIQUE indexes
+
**   are created in the output database before it is populated with 
+
**   recovered data. This is slower overall, but avoids the slow call
+
**   to sqlite3_recover_step() at the end of the recovery operation.
+
**
+
**   The default option value is 0.
+
*/
+
#define SQLITE_RECOVER_LOST_AND_FOUND   1
+
#define SQLITE_RECOVER_FREELIST_CORRUPT 2
+
#define SQLITE_RECOVER_ROWIDS           3
+
#define SQLITE_RECOVER_SLOWINDEXES      4
+

+
/*
+
** Perform a unit of work towards the recovery operation. This function 
+
** must normally be called multiple times to complete database recovery.
+
**
+
** If no error occurs but the recovery operation is not completed, this
+
** function returns SQLITE_OK. If recovery has been completed successfully
+
** then SQLITE_DONE is returned. If an error has occurred, then an SQLite
+
** error code (e.g. SQLITE_IOERR or SQLITE_NOMEM) is returned. It is not
+
** considered an error if some or all of the data cannot be recovered
+
** due to database corruption.
+
**
+
** Once sqlite3_recover_step() has returned a value other than SQLITE_OK,
+
** all further such calls on the same recover handle are no-ops that return
+
** the same non-SQLITE_OK value.
+
*/
+
int sqlite3_recover_step(sqlite3_recover*);
+

+
/* 
+
** Run the recovery operation to completion. Return SQLITE_OK if successful,
+
** or an SQLite error code otherwise. Calling this function is the same
+
** as executing:
+
**
+
**     while( SQLITE_OK==sqlite3_recover_step(p) );
+
**     return sqlite3_recover_errcode(p);
+
*/
+
int sqlite3_recover_run(sqlite3_recover*);
+

+
/*
+
** If an error has been encountered during a prior call to
+
** sqlite3_recover_step(), then this function attempts to return a 
+
** pointer to a buffer containing an English language explanation of 
+
** the error. If no error message is available, or if an out-of memory 
+
** error occurs while attempting to allocate a buffer in which to format
+
** the error message, NULL is returned.
+
**
+
** The returned buffer remains valid until the sqlite3_recover handle is
+
** destroyed using sqlite3_recover_finish().
+
*/
+
const char *sqlite3_recover_errmsg(sqlite3_recover*);
+

+
/*
+
** If this function is called on an sqlite3_recover handle after
+
** an error occurs, an SQLite error code is returned. Otherwise, SQLITE_OK.
+
*/
+
int sqlite3_recover_errcode(sqlite3_recover*);
+

+
/* 
+
** Clean up a recovery object created by a call to sqlite3_recover_init().
+
** The results of using a recovery object with any API after it has been
+
** passed to this function are undefined.
+
**
+
** This function returns the same value as sqlite3_recover_errcode().
+
*/
+
int sqlite3_recover_finish(sqlite3_recover*);
+

+

+
#ifdef __cplusplus
+
}  /* end of the 'extern "C"' block */
#endif

-
typedef struct ExpertInfo ExpertInfo;
-
struct ExpertInfo {
-
  sqlite3expert *pExpert;
-
  int bVerbose;
-
};
+
#endif /* ifndef _SQLITE_RECOVER_H */

-
/* A single line in the EQP output */
-
typedef struct EQPGraphRow EQPGraphRow;
-
struct EQPGraphRow {
-
  int iEqpId;           /* ID for this row */
-
  int iParentId;        /* ID of the parent row */
-
  EQPGraphRow *pNext;   /* Next row in sequence */
-
  char zText[1];        /* Text to display for this row */
+
/************************* End ../ext/recover/sqlite3recover.h ********************/
+
/************************* Begin ../ext/recover/sqlite3recover.c ******************/
+
/*
+
** 2022-08-27
+
**
+
** The author disclaims copyright to this source code.  In place of
+
** a legal notice, here is a blessing:
+
**
+
**    May you do good and not evil.
+
**    May you find forgiveness for yourself and forgive others.
+
**    May you share freely, never taking more than you give.
+
**
+
*************************************************************************
+
**
+
*/
+

+

+
/* #include "sqlite3recover.h" */
+
#include <assert.h>
+
#include <string.h>
+

+
#ifndef SQLITE_OMIT_VIRTUALTABLE
+

+
/*
+
** Declaration for public API function in file dbdata.c. This may be called
+
** with NULL as the final two arguments to register the sqlite_dbptr and
+
** sqlite_dbdata virtual tables with a database handle.
+
*/
+
#ifdef _WIN32
+

+
#endif
+
int sqlite3_dbdata_init(sqlite3*, char**, const sqlite3_api_routines*);
+

+
/* typedef unsigned int u32; */
+
/* typedef unsigned char u8; */
+
/* typedef sqlite3_int64 i64; */
+

+
typedef struct RecoverTable RecoverTable;
+
typedef struct RecoverColumn RecoverColumn;
+

+
/*
+
** When recovering rows of data that can be associated with table
+
** definitions recovered from the sqlite_schema table, each table is
+
** represented by an instance of the following object.
+
**
+
** iRoot:
+
**   The root page in the original database. Not necessarily (and usually
+
**   not) the same in the recovered database.
+
**
+
** zTab:
+
**   Name of the table.
+
**
+
** nCol/aCol[]:
+
**   aCol[] is an array of nCol columns. In the order in which they appear 
+
**   in the table.
+
**
+
** bIntkey:
+
**   Set to true for intkey tables, false for WITHOUT ROWID.
+
**
+
** iRowidBind:
+
**   Each column in the aCol[] array has associated with it the index of
+
**   the bind parameter its values will be bound to in the INSERT statement
+
**   used to construct the output database. If the table does has a rowid
+
**   but not an INTEGER PRIMARY KEY column, then iRowidBind contains the
+
**   index of the bind paramater to which the rowid value should be bound.
+
**   Otherwise, it contains -1. If the table does contain an INTEGER PRIMARY 
+
**   KEY column, then the rowid value should be bound to the index associated
+
**   with the column.
+
**
+
** pNext:
+
**   All RecoverTable objects used by the recovery operation are allocated
+
**   and populated as part of creating the recovered database schema in
+
**   the output database, before any non-schema data are recovered. They
+
**   are then stored in a singly-linked list linked by this variable beginning
+
**   at sqlite3_recover.pTblList.
+
*/
+
struct RecoverTable {
+
  u32 iRoot;                      /* Root page in original database */
+
  char *zTab;                     /* Name of table */
+
  int nCol;                       /* Number of columns in table */
+
  RecoverColumn *aCol;            /* Array of columns */
+
  int bIntkey;                    /* True for intkey, false for without rowid */
+
  int iRowidBind;                 /* If >0, bind rowid to INSERT here */
+
  RecoverTable *pNext;
};

-
/* All EQP output is collected into an instance of the following */
-
typedef struct EQPGraph EQPGraph;
-
struct EQPGraph {
-
  EQPGraphRow *pRow;    /* Linked list of all rows of the EQP output */
-
  EQPGraphRow *pLast;   /* Last element of the pRow list */
-
  char zPrefix[100];    /* Graph prefix */
+
/*
+
** Each database column is represented by an instance of the following object
+
** stored in the RecoverTable.aCol[] array of the associated table.
+
**
+
** iField:
+
**   The index of the associated field within database records. Or -1 if
+
**   there is no associated field (e.g. for virtual generated columns).
+
**
+
** iBind:
+
**   The bind index of the INSERT statement to bind this columns values
+
**   to. Or 0 if there is no such index (iff (iField<0)).
+
**
+
** bIPK:
+
**   True if this is the INTEGER PRIMARY KEY column.
+
**
+
** zCol:
+
**   Name of column.
+
**
+
** eHidden:
+
**   A RECOVER_EHIDDEN_* constant value (see below for interpretation of each).
+
*/
+
struct RecoverColumn {
+
  int iField;                     /* Field in record on disk */
+
  int iBind;                      /* Binding to use in INSERT */
+
  int bIPK;                       /* True for IPK column */
+
  char *zCol;
+
  int eHidden;
};

-
/* Parameters affecting columnar mode result display (defaulting together) */
-
typedef struct ColModeOpts {
-
  int iWrap;            /* In columnar modes, wrap lines reaching this limit */
-
  u8 bQuote;            /* Quote results for .mode box and table */
-
  u8 bWordWrap;         /* In columnar modes, wrap at word boundaries  */
-
} ColModeOpts;
-
#define ColModeOpts_default { 60, 0, 0 }
-
#define ColModeOpts_default_qbox { 60, 1, 0 }
+
#define RECOVER_EHIDDEN_NONE    0      /* Normal database column */
+
#define RECOVER_EHIDDEN_HIDDEN  1      /* Column is __HIDDEN__ */
+
#define RECOVER_EHIDDEN_VIRTUAL 2      /* Virtual generated column */
+
#define RECOVER_EHIDDEN_STORED  3      /* Stored generated column */

/*
-
** State information about the database connection is contained in an
+
** Bitmap object used to track pages in the input database. Allocated
+
** and manipulated only by the following functions:
+
**
+
**     recoverBitmapAlloc()
+
**     recoverBitmapFree()
+
**     recoverBitmapSet()
+
**     recoverBitmapQuery()
+
**
+
** nPg:
+
**   Largest page number that may be stored in the bitmap. The range
+
**   of valid keys is 1 to nPg, inclusive.
+
**
+
** aElem[]:
+
**   Array large enough to contain a bit for each key. For key value
+
**   iKey, the associated bit is the bit (iKey%32) of aElem[iKey/32].
+
**   In other words, the following is true if bit iKey is set, or 
+
**   false if it is clear:
+
**
+
**       (aElem[iKey/32] & (1 << (iKey%32))) ? 1 : 0
+
*/
+
typedef struct RecoverBitmap RecoverBitmap;
+
struct RecoverBitmap {
+
  i64 nPg;                        /* Size of bitmap */
+
  u32 aElem[1];                   /* Array of 32-bit bitmasks */
+
};
+

+
/*
+
** State variables (part of the sqlite3_recover structure) used while
+
** recovering data for tables identified in the recovered schema (state
+
** RECOVER_STATE_WRITING).
+
*/
+
typedef struct RecoverStateW1 RecoverStateW1;
+
struct RecoverStateW1 {
+
  sqlite3_stmt *pTbls;
+
  sqlite3_stmt *pSel;
+
  sqlite3_stmt *pInsert;
+
  int nInsert;
+

+
  RecoverTable *pTab;             /* Table currently being written */
+
  int nMax;                       /* Max column count in any schema table */
+
  sqlite3_value **apVal;          /* Array of nMax values */
+
  int nVal;                       /* Number of valid entries in apVal[] */
+
  int bHaveRowid;
+
  i64 iRowid;
+
  i64 iPrevPage;
+
  int iPrevCell;
+
};
+

+
/*
+
** State variables (part of the sqlite3_recover structure) used while
+
** recovering data destined for the lost and found table (states
+
** RECOVER_STATE_LOSTANDFOUND[123]).
+
*/
+
typedef struct RecoverStateLAF RecoverStateLAF;
+
struct RecoverStateLAF {
+
  RecoverBitmap *pUsed;
+
  i64 nPg;                        /* Size of db in pages */
+
  sqlite3_stmt *pAllAndParent;
+
  sqlite3_stmt *pMapInsert;
+
  sqlite3_stmt *pMaxField;
+
  sqlite3_stmt *pUsedPages;
+
  sqlite3_stmt *pFindRoot;
+
  sqlite3_stmt *pInsert;          /* INSERT INTO lost_and_found ... */
+
  sqlite3_stmt *pAllPage;
+
  sqlite3_stmt *pPageData;
+
  sqlite3_value **apVal;
+
  int nMaxField;
+
};
+

+
/*
+
** Main recover handle structure.
+
*/
+
struct sqlite3_recover {
+
  /* Copies of sqlite3_recover_init[_sql]() parameters */
+
  sqlite3 *dbIn;                  /* Input database */
+
  char *zDb;                      /* Name of input db ("main" etc.) */
+
  char *zUri;                     /* URI for output database */
+
  void *pSqlCtx;                  /* SQL callback context */
+
  int (*xSql)(void*,const char*); /* Pointer to SQL callback function */
+

+
  /* Values configured by sqlite3_recover_config() */
+
  char *zStateDb;                 /* State database to use (or NULL) */
+
  char *zLostAndFound;            /* Name of lost-and-found table (or NULL) */
+
  int bFreelistCorrupt;           /* SQLITE_RECOVER_FREELIST_CORRUPT setting */
+
  int bRecoverRowid;              /* SQLITE_RECOVER_ROWIDS setting */
+
  int bSlowIndexes;               /* SQLITE_RECOVER_SLOWINDEXES setting */
+

+
  int pgsz;
+
  int detected_pgsz;
+
  int nReserve;
+
  u8 *pPage1Disk;
+
  u8 *pPage1Cache;
+

+
  /* Error code and error message */
+
  int errCode;                    /* For sqlite3_recover_errcode() */
+
  char *zErrMsg;                  /* For sqlite3_recover_errmsg() */
+

+
  int eState;
+
  int bCloseTransaction;
+

+
  /* Variables used with eState==RECOVER_STATE_WRITING */
+
  RecoverStateW1 w1;
+

+
  /* Variables used with states RECOVER_STATE_LOSTANDFOUND[123] */
+
  RecoverStateLAF laf;
+

+
  /* Fields used within sqlite3_recover_run() */
+
  sqlite3 *dbOut;                 /* Output database */
+
  sqlite3_stmt *pGetPage;         /* SELECT against input db sqlite_dbdata */
+
  RecoverTable *pTblList;         /* List of tables recovered from schema */
+
};
+

+
/*
+
** The various states in which an sqlite3_recover object may exist:
+
**
+
**   RECOVER_STATE_INIT:
+
**    The object is initially created in this state. sqlite3_recover_step()
+
**    has yet to be called. This is the only state in which it is permitted
+
**    to call sqlite3_recover_config().
+
**
+
**   RECOVER_STATE_WRITING:
+
**
+
**   RECOVER_STATE_LOSTANDFOUND1:
+
**    State to populate the bitmap of pages used by other tables or the
+
**    database freelist.
+
**
+
**   RECOVER_STATE_LOSTANDFOUND2:
+
**    Populate the recovery.map table - used to figure out a "root" page
+
**    for each lost page from in the database from which records are
+
**    extracted.
+
**
+
**   RECOVER_STATE_LOSTANDFOUND3:
+
**    Populate the lost-and-found table itself.
+
*/
+
#define RECOVER_STATE_INIT           0
+
#define RECOVER_STATE_WRITING        1
+
#define RECOVER_STATE_LOSTANDFOUND1  2
+
#define RECOVER_STATE_LOSTANDFOUND2  3
+
#define RECOVER_STATE_LOSTANDFOUND3  4
+
#define RECOVER_STATE_SCHEMA2        5
+
#define RECOVER_STATE_DONE           6
+

+

+
/*
+
** Global variables used by this extension.
+
*/
+
typedef struct RecoverGlobal RecoverGlobal;
+
struct RecoverGlobal {
+
  const sqlite3_io_methods *pMethods;
+
  sqlite3_recover *p;
+
};
+
static RecoverGlobal recover_g;
+

+
/*
+
** Use this static SQLite mutex to protect the globals during the
+
** first call to sqlite3_recover_step().
+
*/ 
+
#define RECOVER_MUTEX_ID SQLITE_MUTEX_STATIC_APP2
+

+

+
/* 
+
** Default value for SQLITE_RECOVER_ROWIDS (sqlite3_recover.bRecoverRowid).
+
*/
+
#define RECOVER_ROWID_DEFAULT 1
+

+
/*
+
** Mutex handling:
+
**
+
**    recoverEnterMutex()       -   Enter the recovery mutex
+
**    recoverLeaveMutex()       -   Leave the recovery mutex
+
**    recoverAssertMutexHeld()  -   Assert that the recovery mutex is held
+
*/
+
#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE==0
+
# define recoverEnterMutex()
+
# define recoverLeaveMutex()
+
#else
+
static void recoverEnterMutex(void){
+
  sqlite3_mutex_enter(sqlite3_mutex_alloc(RECOVER_MUTEX_ID));
+
}
+
static void recoverLeaveMutex(void){
+
  sqlite3_mutex_leave(sqlite3_mutex_alloc(RECOVER_MUTEX_ID));
+
}
+
#endif
+
#if SQLITE_THREADSAFE+0>=1 && defined(SQLITE_DEBUG)
+
static void recoverAssertMutexHeld(void){
+
  assert( sqlite3_mutex_held(sqlite3_mutex_alloc(RECOVER_MUTEX_ID)) );
+
}
+
#else
+
# define recoverAssertMutexHeld()
+
#endif
+

+

+
/*
+
** Like strlen(). But handles NULL pointer arguments.
+
*/
+
static int recoverStrlen(const char *zStr){
+
  if( zStr==0 ) return 0;
+
  return (int)(strlen(zStr)&0x7fffffff);
+
}
+

+
/*
+
** This function is a no-op if the recover handle passed as the first 
+
** argument already contains an error (if p->errCode!=SQLITE_OK). 
+
**
+
** Otherwise, an attempt is made to allocate, zero and return a buffer nByte
+
** bytes in size. If successful, a pointer to the new buffer is returned. Or,
+
** if an OOM error occurs, NULL is returned and the handle error code
+
** (p->errCode) set to SQLITE_NOMEM.
+
*/
+
static void *recoverMalloc(sqlite3_recover *p, i64 nByte){
+
  void *pRet = 0;
+
  assert( nByte>0 );
+
  if( p->errCode==SQLITE_OK ){
+
    pRet = sqlite3_malloc64(nByte);
+
    if( pRet ){
+
      memset(pRet, 0, nByte);
+
    }else{
+
      p->errCode = SQLITE_NOMEM;
+
    }
+
  }
+
  return pRet;
+
}
+

+
/*
+
** Set the error code and error message for the recover handle passed as
+
** the first argument. The error code is set to the value of parameter
+
** errCode.
+
**
+
** Parameter zFmt must be a printf() style formatting string. The handle 
+
** error message is set to the result of using any trailing arguments for 
+
** parameter substitutions in the formatting string.
+
**
+
** For example:
+
**
+
**   recoverError(p, SQLITE_ERROR, "no such table: %s", zTablename);
+
*/
+
static int recoverError(
+
  sqlite3_recover *p, 
+
  int errCode, 
+
  const char *zFmt, ...
+
){
+
  char *z = 0;
+
  va_list ap;
+
  va_start(ap, zFmt);
+
  if( zFmt ){
+
    z = sqlite3_vmprintf(zFmt, ap);
+
    va_end(ap);
+
  }
+
  sqlite3_free(p->zErrMsg);
+
  p->zErrMsg = z;
+
  p->errCode = errCode;
+
  return errCode;
+
}
+

+

+
/*
+
** This function is a no-op if p->errCode is initially other than SQLITE_OK.
+
** In this case it returns NULL.
+
**
+
** Otherwise, an attempt is made to allocate and return a bitmap object
+
** large enough to store a bit for all page numbers between 1 and nPg,
+
** inclusive. The bitmap is initially zeroed.
+
*/
+
static RecoverBitmap *recoverBitmapAlloc(sqlite3_recover *p, i64 nPg){
+
  int nElem = (nPg+1+31) / 32;
+
  int nByte = sizeof(RecoverBitmap) + nElem*sizeof(u32);
+
  RecoverBitmap *pRet = (RecoverBitmap*)recoverMalloc(p, nByte);
+

+
  if( pRet ){
+
    pRet->nPg = nPg;
+
  }
+
  return pRet;
+
}
+

+
/*
+
** Free a bitmap object allocated by recoverBitmapAlloc().
+
*/
+
static void recoverBitmapFree(RecoverBitmap *pMap){
+
  sqlite3_free(pMap);
+
}
+

+
/*
+
** Set the bit associated with page iPg in bitvec pMap.
+
*/
+
static void recoverBitmapSet(RecoverBitmap *pMap, i64 iPg){
+
  if( iPg<=pMap->nPg ){
+
    int iElem = (iPg / 32);
+
    int iBit = (iPg % 32);
+
    pMap->aElem[iElem] |= (((u32)1) << iBit);
+
  }
+
}
+

+
/*
+
** Query bitmap object pMap for the state of the bit associated with page
+
** iPg. Return 1 if it is set, or 0 otherwise.
+
*/
+
static int recoverBitmapQuery(RecoverBitmap *pMap, i64 iPg){
+
  int ret = 1;
+
  if( iPg<=pMap->nPg && iPg>0 ){
+
    int iElem = (iPg / 32);
+
    int iBit = (iPg % 32);
+
    ret = (pMap->aElem[iElem] & (((u32)1) << iBit)) ? 1 : 0;
+
  }
+
  return ret;
+
}
+

+
/*
+
** Set the recover handle error to the error code and message returned by
+
** calling sqlite3_errcode() and sqlite3_errmsg(), respectively, on database
+
** handle db.
+
*/
+
static int recoverDbError(sqlite3_recover *p, sqlite3 *db){
+
  return recoverError(p, sqlite3_errcode(db), "%s", sqlite3_errmsg(db));
+
}
+

+
/*
+
** This function is a no-op if recover handle p already contains an error
+
** (if p->errCode!=SQLITE_OK). 
+
**
+
** Otherwise, it attempts to prepare the SQL statement in zSql against
+
** database handle db. If successful, the statement handle is returned.
+
** Or, if an error occurs, NULL is returned and an error left in the
+
** recover handle.
+
*/
+
static sqlite3_stmt *recoverPrepare(
+
  sqlite3_recover *p,
+
  sqlite3 *db, 
+
  const char *zSql
+
){
+
  sqlite3_stmt *pStmt = 0;
+
  if( p->errCode==SQLITE_OK ){
+
    if( sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0) ){
+
      recoverDbError(p, db);
+
    }
+
  }
+
  return pStmt;
+
}
+

+
/*
+
** This function is a no-op if recover handle p already contains an error
+
** (if p->errCode!=SQLITE_OK). 
+
**
+
** Otherwise, argument zFmt is used as a printf() style format string,
+
** along with any trailing arguments, to create an SQL statement. This
+
** SQL statement is prepared against database handle db and, if successful,
+
** the statment handle returned. Or, if an error occurs - either during
+
** the printf() formatting or when preparing the resulting SQL - an
+
** error code and message are left in the recover handle.
+
*/
+
static sqlite3_stmt *recoverPreparePrintf(
+
  sqlite3_recover *p,
+
  sqlite3 *db, 
+
  const char *zFmt, ...
+
){
+
  sqlite3_stmt *pStmt = 0;
+
  if( p->errCode==SQLITE_OK ){
+
    va_list ap;
+
    char *z;
+
    va_start(ap, zFmt);
+
    z = sqlite3_vmprintf(zFmt, ap);
+
    va_end(ap);
+
    if( z==0 ){
+
      p->errCode = SQLITE_NOMEM;
+
    }else{
+
      pStmt = recoverPrepare(p, db, z);
+
      sqlite3_free(z);
+
    }
+
  }
+
  return pStmt;
+
}
+

+
/*
+
** Reset SQLite statement handle pStmt. If the call to sqlite3_reset() 
+
** indicates that an error occurred, and there is not already an error
+
** in the recover handle passed as the first argument, set the error
+
** code and error message appropriately.
+
**
+
** This function returns a copy of the statement handle pointer passed
+
** as the second argument.
+
*/
+
static sqlite3_stmt *recoverReset(sqlite3_recover *p, sqlite3_stmt *pStmt){
+
  int rc = sqlite3_reset(pStmt);
+
  if( rc!=SQLITE_OK && rc!=SQLITE_CONSTRAINT && p->errCode==SQLITE_OK ){
+
    recoverDbError(p, sqlite3_db_handle(pStmt));
+
  }
+
  return pStmt;
+
}
+

+
/*
+
** Finalize SQLite statement handle pStmt. If the call to sqlite3_reset() 
+
** indicates that an error occurred, and there is not already an error
+
** in the recover handle passed as the first argument, set the error
+
** code and error message appropriately.
+
*/
+
static void recoverFinalize(sqlite3_recover *p, sqlite3_stmt *pStmt){
+
  sqlite3 *db = sqlite3_db_handle(pStmt);
+
  int rc = sqlite3_finalize(pStmt);
+
  if( rc!=SQLITE_OK && p->errCode==SQLITE_OK ){
+
    recoverDbError(p, db);
+
  }
+
}
+

+
/*
+
** This function is a no-op if recover handle p already contains an error
+
** (if p->errCode!=SQLITE_OK). A copy of p->errCode is returned in this 
+
** case.
+
**
+
** Otherwise, execute SQL script zSql. If successful, return SQLITE_OK.
+
** Or, if an error occurs, leave an error code and message in the recover
+
** handle and return a copy of the error code.
+
*/
+
static int recoverExec(sqlite3_recover *p, sqlite3 *db, const char *zSql){
+
  if( p->errCode==SQLITE_OK ){
+
    int rc = sqlite3_exec(db, zSql, 0, 0, 0);
+
    if( rc ){
+
      recoverDbError(p, db);
+
    }
+
  }
+
  return p->errCode;
+
}
+

+
/*
+
** Bind the value pVal to parameter iBind of statement pStmt. Leave an
+
** error in the recover handle passed as the first argument if an error
+
** (e.g. an OOM) occurs.
+
*/
+
static void recoverBindValue(
+
  sqlite3_recover *p, 
+
  sqlite3_stmt *pStmt, 
+
  int iBind, 
+
  sqlite3_value *pVal
+
){
+
  if( p->errCode==SQLITE_OK ){
+
    int rc = sqlite3_bind_value(pStmt, iBind, pVal);
+
    if( rc ) recoverError(p, rc, 0);
+
  }
+
}
+

+
/*
+
** This function is a no-op if recover handle p already contains an error
+
** (if p->errCode!=SQLITE_OK). NULL is returned in this case.
+
**
+
** Otherwise, an attempt is made to interpret zFmt as a printf() style
+
** formatting string and the result of using the trailing arguments for
+
** parameter substitution with it written into a buffer obtained from
+
** sqlite3_malloc(). If successful, a pointer to the buffer is returned.
+
** It is the responsibility of the caller to eventually free the buffer
+
** using sqlite3_free().
+
**
+
** Or, if an error occurs, an error code and message is left in the recover
+
** handle and NULL returned.
+
*/
+
static char *recoverMPrintf(sqlite3_recover *p, const char *zFmt, ...){
+
  va_list ap;
+
  char *z;
+
  va_start(ap, zFmt);
+
  z = sqlite3_vmprintf(zFmt, ap);
+
  va_end(ap);
+
  if( p->errCode==SQLITE_OK ){
+
    if( z==0 ) p->errCode = SQLITE_NOMEM;
+
  }else{
+
    sqlite3_free(z);
+
    z = 0;
+
  }
+
  return z;
+
}
+

+
/*
+
** This function is a no-op if recover handle p already contains an error
+
** (if p->errCode!=SQLITE_OK). Zero is returned in this case.
+
**
+
** Otherwise, execute "PRAGMA page_count" against the input database. If
+
** successful, return the integer result. Or, if an error occurs, leave an
+
** error code and error message in the sqlite3_recover handle and return
+
** zero.
+
*/
+
static i64 recoverPageCount(sqlite3_recover *p){
+
  i64 nPg = 0;
+
  if( p->errCode==SQLITE_OK ){
+
    sqlite3_stmt *pStmt = 0;
+
    pStmt = recoverPreparePrintf(p, p->dbIn, "PRAGMA %Q.page_count", p->zDb);
+
    if( pStmt ){
+
      sqlite3_step(pStmt);
+
      nPg = sqlite3_column_int64(pStmt, 0);
+
    }
+
    recoverFinalize(p, pStmt);
+
  }
+
  return nPg;
+
}
+

+
/*
+
** Implementation of SQL scalar function "read_i32". The first argument to 
+
** this function must be a blob. The second a non-negative integer. This 
+
** function reads and returns a 32-bit big-endian integer from byte
+
** offset (4*<arg2>) of the blob.
+
**
+
**     SELECT read_i32(<blob>, <idx>)
+
*/
+
static void recoverReadI32(
+
  sqlite3_context *context, 
+
  int argc, 
+
  sqlite3_value **argv
+
){
+
  const unsigned char *pBlob;
+
  int nBlob;
+
  int iInt;
+

+
  assert( argc==2 );
+
  nBlob = sqlite3_value_bytes(argv[0]);
+
  pBlob = (const unsigned char*)sqlite3_value_blob(argv[0]);
+
  iInt = sqlite3_value_int(argv[1]) & 0xFFFF;
+

+
  if( (iInt+1)*4<=nBlob ){
+
    const unsigned char *a = &pBlob[iInt*4];
+
    i64 iVal = ((i64)a[0]<<24)
+
             + ((i64)a[1]<<16)
+
             + ((i64)a[2]<< 8)
+
             + ((i64)a[3]<< 0);
+
    sqlite3_result_int64(context, iVal);
+
  }
+
}
+

+
/*
+
** Implementation of SQL scalar function "page_is_used". This function
+
** is used as part of the procedure for locating orphan rows for the
+
** lost-and-found table, and it depends on those routines having populated
+
** the sqlite3_recover.laf.pUsed variable.
+
**
+
** The only argument to this function is a page-number. It returns true 
+
** if the page has already been used somehow during data recovery, or false
+
** otherwise.
+
**
+
**     SELECT page_is_used(<pgno>);
+
*/
+
static void recoverPageIsUsed(
+
  sqlite3_context *pCtx,
+
  int nArg,
+
  sqlite3_value **apArg
+
){
+
  sqlite3_recover *p = (sqlite3_recover*)sqlite3_user_data(pCtx);
+
  i64 pgno = sqlite3_value_int64(apArg[0]);
+
  assert( nArg==1 );
+
  sqlite3_result_int(pCtx, recoverBitmapQuery(p->laf.pUsed, pgno));
+
}
+

+
/*
+
** The implementation of a user-defined SQL function invoked by the 
+
** sqlite_dbdata and sqlite_dbptr virtual table modules to access pages
+
** of the database being recovered.
+
**
+
** This function always takes a single integer argument. If the argument
+
** is zero, then the value returned is the number of pages in the db being
+
** recovered. If the argument is greater than zero, it is a page number. 
+
** The value returned in this case is an SQL blob containing the data for 
+
** the identified page of the db being recovered. e.g.
+
**
+
**     SELECT getpage(0);       -- return number of pages in db
+
**     SELECT getpage(4);       -- return page 4 of db as a blob of data 
+
*/
+
static void recoverGetPage(
+
  sqlite3_context *pCtx,
+
  int nArg,
+
  sqlite3_value **apArg
+
){
+
  sqlite3_recover *p = (sqlite3_recover*)sqlite3_user_data(pCtx);
+
  i64 pgno = sqlite3_value_int64(apArg[0]);
+
  sqlite3_stmt *pStmt = 0;
+

+
  assert( nArg==1 );
+
  if( pgno==0 ){
+
    i64 nPg = recoverPageCount(p);
+
    sqlite3_result_int64(pCtx, nPg);
+
    return;
+
  }else{
+
    if( p->pGetPage==0 ){
+
      pStmt = p->pGetPage = recoverPreparePrintf(
+
          p, p->dbIn, "SELECT data FROM sqlite_dbpage(%Q) WHERE pgno=?", p->zDb
+
      );
+
    }else if( p->errCode==SQLITE_OK ){
+
      pStmt = p->pGetPage;
+
    }
+

+
    if( pStmt ){
+
      sqlite3_bind_int64(pStmt, 1, pgno);
+
      if( SQLITE_ROW==sqlite3_step(pStmt) ){
+
        const u8 *aPg;
+
        int nPg;
+
        assert( p->errCode==SQLITE_OK );
+
        aPg = sqlite3_column_blob(pStmt, 0);
+
        nPg = sqlite3_column_bytes(pStmt, 0);
+
        if( pgno==1 && nPg==p->pgsz && 0==memcmp(p->pPage1Cache, aPg, nPg) ){
+
          aPg = p->pPage1Disk;
+
        }
+
        sqlite3_result_blob(pCtx, aPg, nPg-p->nReserve, SQLITE_TRANSIENT);
+
      }
+
      recoverReset(p, pStmt);
+
    }
+
  }
+

+
  if( p->errCode ){
+
    if( p->zErrMsg ) sqlite3_result_error(pCtx, p->zErrMsg, -1);
+
    sqlite3_result_error_code(pCtx, p->errCode);
+
  }
+
}
+

+
/*
+
** Find a string that is not found anywhere in z[].  Return a pointer
+
** to that string.
+
**
+
** Try to use zA and zB first.  If both of those are already found in z[]
+
** then make up some string and store it in the buffer zBuf.
+
*/
+
static const char *recoverUnusedString(
+
  const char *z,                    /* Result must not appear anywhere in z */
+
  const char *zA, const char *zB,   /* Try these first */
+
  char *zBuf                        /* Space to store a generated string */
+
){
+
  unsigned i = 0;
+
  if( strstr(z, zA)==0 ) return zA;
+
  if( strstr(z, zB)==0 ) return zB;
+
  do{
+
    sqlite3_snprintf(20,zBuf,"(%s%u)", zA, i++);
+
  }while( strstr(z,zBuf)!=0 );
+
  return zBuf;
+
}
+

+
/*
+
** Implementation of scalar SQL function "escape_crnl".  The argument passed to
+
** this function is the output of built-in function quote(). If the first
+
** character of the input is "'", indicating that the value passed to quote()
+
** was a text value, then this function searches the input for "\n" and "\r"
+
** characters and adds a wrapper similar to the following:
+
**
+
**   replace(replace(<input>, '\n', char(10), '\r', char(13));
+
**
+
** Or, if the first character of the input is not "'", then a copy of the input
+
** is returned.
+
*/
+
static void recoverEscapeCrnl(
+
  sqlite3_context *context, 
+
  int argc, 
+
  sqlite3_value **argv
+
){
+
  const char *zText = (const char*)sqlite3_value_text(argv[0]);
+
  if( zText && zText[0]=='\'' ){
+
    int nText = sqlite3_value_bytes(argv[0]);
+
    int i;
+
    char zBuf1[20];
+
    char zBuf2[20];
+
    const char *zNL = 0;
+
    const char *zCR = 0;
+
    int nCR = 0;
+
    int nNL = 0;
+

+
    for(i=0; zText[i]; i++){
+
      if( zNL==0 && zText[i]=='\n' ){
+
        zNL = recoverUnusedString(zText, "\\n", "\\012", zBuf1);
+
        nNL = (int)strlen(zNL);
+
      }
+
      if( zCR==0 && zText[i]=='\r' ){
+
        zCR = recoverUnusedString(zText, "\\r", "\\015", zBuf2);
+
        nCR = (int)strlen(zCR);
+
      }
+
    }
+

+
    if( zNL || zCR ){
+
      int iOut = 0;
+
      i64 nMax = (nNL > nCR) ? nNL : nCR;
+
      i64 nAlloc = nMax * nText + (nMax+64)*2;
+
      char *zOut = (char*)sqlite3_malloc64(nAlloc);
+
      if( zOut==0 ){
+
        sqlite3_result_error_nomem(context);
+
        return;
+
      }
+

+
      if( zNL && zCR ){
+
        memcpy(&zOut[iOut], "replace(replace(", 16);
+
        iOut += 16;
+
      }else{
+
        memcpy(&zOut[iOut], "replace(", 8);
+
        iOut += 8;
+
      }
+
      for(i=0; zText[i]; i++){
+
        if( zText[i]=='\n' ){
+
          memcpy(&zOut[iOut], zNL, nNL);
+
          iOut += nNL;
+
        }else if( zText[i]=='\r' ){
+
          memcpy(&zOut[iOut], zCR, nCR);
+
          iOut += nCR;
+
        }else{
+
          zOut[iOut] = zText[i];
+
          iOut++;
+
        }
+
      }
+

+
      if( zNL ){
+
        memcpy(&zOut[iOut], ",'", 2); iOut += 2;
+
        memcpy(&zOut[iOut], zNL, nNL); iOut += nNL;
+
        memcpy(&zOut[iOut], "', char(10))", 12); iOut += 12;
+
      }
+
      if( zCR ){
+
        memcpy(&zOut[iOut], ",'", 2); iOut += 2;
+
        memcpy(&zOut[iOut], zCR, nCR); iOut += nCR;
+
        memcpy(&zOut[iOut], "', char(13))", 12); iOut += 12;
+
      }
+

+
      sqlite3_result_text(context, zOut, iOut, SQLITE_TRANSIENT);
+
      sqlite3_free(zOut);
+
      return;
+
    }
+
  }
+

+
  sqlite3_result_value(context, argv[0]);
+
}
+

+
/*
+
** This function is a no-op if recover handle p already contains an error
+
** (if p->errCode!=SQLITE_OK). A copy of the error code is returned in
+
** this case. 
+
**
+
** Otherwise, attempt to populate temporary table "recovery.schema" with the
+
** parts of the database schema that can be extracted from the input database.
+
**
+
** If no error occurs, SQLITE_OK is returned. Otherwise, an error code
+
** and error message are left in the recover handle and a copy of the
+
** error code returned. It is not considered an error if part of all of
+
** the database schema cannot be recovered due to corruption.
+
*/
+
static int recoverCacheSchema(sqlite3_recover *p){
+
  return recoverExec(p, p->dbOut,
+
    "WITH RECURSIVE pages(p) AS ("
+
    "  SELECT 1"
+
    "    UNION"
+
    "  SELECT child FROM sqlite_dbptr('getpage()'), pages WHERE pgno=p"
+
    ")"
+
    "INSERT INTO recovery.schema SELECT"
+
    "  max(CASE WHEN field=0 THEN value ELSE NULL END),"
+
    "  max(CASE WHEN field=1 THEN value ELSE NULL END),"
+
    "  max(CASE WHEN field=2 THEN value ELSE NULL END),"
+
    "  max(CASE WHEN field=3 THEN value ELSE NULL END),"
+
    "  max(CASE WHEN field=4 THEN value ELSE NULL END)"
+
    "FROM sqlite_dbdata('getpage()') WHERE pgno IN ("
+
    "  SELECT p FROM pages"
+
    ") GROUP BY pgno, cell"
+
  );
+
}
+

+
/*
+
** If this recover handle is not in SQL callback mode (i.e. was not created 
+
** using sqlite3_recover_init_sql()) of if an error has already occurred, 
+
** this function is a no-op. Otherwise, issue a callback with SQL statement
+
** zSql as the parameter. 
+
**
+
** If the callback returns non-zero, set the recover handle error code to
+
** the value returned (so that the caller will abandon processing).
+
*/
+
static void recoverSqlCallback(sqlite3_recover *p, const char *zSql){
+
  if( p->errCode==SQLITE_OK && p->xSql ){
+
    int res = p->xSql(p->pSqlCtx, zSql);
+
    if( res ){
+
      recoverError(p, SQLITE_ERROR, "callback returned an error - %d", res);
+
    }
+
  }
+
}
+

+
/*
+
** Transfer the following settings from the input database to the output
+
** database:
+
**
+
**   + page-size,
+
**   + auto-vacuum settings,
+
**   + database encoding,
+
**   + user-version (PRAGMA user_version), and
+
**   + application-id (PRAGMA application_id), and
+
*/
+
static void recoverTransferSettings(sqlite3_recover *p){
+
  const char *aPragma[] = {
+
    "encoding",
+
    "page_size",
+
    "auto_vacuum",
+
    "user_version",
+
    "application_id"
+
  };
+
  int ii;
+

+
  /* Truncate the output database to 0 pages in size. This is done by 
+
  ** opening a new, empty, temp db, then using the backup API to clobber 
+
  ** any existing output db with a copy of it. */
+
  if( p->errCode==SQLITE_OK ){
+
    sqlite3 *db2 = 0;
+
    int rc = sqlite3_open("", &db2);
+
    if( rc!=SQLITE_OK ){
+
      recoverDbError(p, db2);
+
      return;
+
    }
+

+
    for(ii=0; ii<sizeof(aPragma)/sizeof(aPragma[0]); ii++){
+
      const char *zPrag = aPragma[ii];
+
      sqlite3_stmt *p1 = 0;
+
      p1 = recoverPreparePrintf(p, p->dbIn, "PRAGMA %Q.%s", p->zDb, zPrag);
+
      if( p->errCode==SQLITE_OK && sqlite3_step(p1)==SQLITE_ROW ){
+
        const char *zArg = (const char*)sqlite3_column_text(p1, 0);
+
        char *z2 = recoverMPrintf(p, "PRAGMA %s = %Q", zPrag, zArg);
+
        recoverSqlCallback(p, z2);
+
        recoverExec(p, db2, z2);
+
        sqlite3_free(z2);
+
        if( zArg==0 ){
+
          recoverError(p, SQLITE_NOMEM, 0);
+
        }
+
      }
+
      recoverFinalize(p, p1);
+
    }
+
    recoverExec(p, db2, "CREATE TABLE t1(a); DROP TABLE t1;");
+

+
    if( p->errCode==SQLITE_OK ){
+
      sqlite3 *db = p->dbOut;
+
      sqlite3_backup *pBackup = sqlite3_backup_init(db, "main", db2, "main");
+
      if( pBackup ){
+
        sqlite3_backup_step(pBackup, -1);
+
        p->errCode = sqlite3_backup_finish(pBackup);
+
      }else{
+
        recoverDbError(p, db);
+
      }
+
    }
+

+
    sqlite3_close(db2);
+
  }
+
}
+

+
/*
+
** This function is a no-op if recover handle p already contains an error
+
** (if p->errCode!=SQLITE_OK). A copy of the error code is returned in
+
** this case. 
+
**
+
** Otherwise, an attempt is made to open the output database, attach
+
** and create the schema of the temporary database used to store
+
** intermediate data, and to register all required user functions and
+
** virtual table modules with the output handle.
+
**
+
** If no error occurs, SQLITE_OK is returned. Otherwise, an error code
+
** and error message are left in the recover handle and a copy of the
+
** error code returned.
+
*/
+
static int recoverOpenOutput(sqlite3_recover *p){
+
  struct Func {
+
    const char *zName;
+
    int nArg;
+
    void (*xFunc)(sqlite3_context*,int,sqlite3_value **);
+
  } aFunc[] = {
+
    { "getpage", 1, recoverGetPage },
+
    { "page_is_used", 1, recoverPageIsUsed },
+
    { "read_i32", 2, recoverReadI32 },
+
    { "escape_crnl", 1, recoverEscapeCrnl },
+
  };
+

+
  const int flags = SQLITE_OPEN_URI|SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE;
+
  sqlite3 *db = 0;                /* New database handle */
+
  int ii;                         /* For iterating through aFunc[] */
+

+
  assert( p->dbOut==0 );
+

+
  if( sqlite3_open_v2(p->zUri, &db, flags, 0) ){
+
    recoverDbError(p, db);
+
  }
+

+
  /* Register the sqlite_dbdata and sqlite_dbptr virtual table modules.
+
  ** These two are registered with the output database handle - this
+
  ** module depends on the input handle supporting the sqlite_dbpage
+
  ** virtual table only.  */
+
  if( p->errCode==SQLITE_OK ){
+
    p->errCode = sqlite3_dbdata_init(db, 0, 0);
+
  }
+

+
  /* Register the custom user-functions with the output handle. */
+
  for(ii=0; p->errCode==SQLITE_OK && ii<sizeof(aFunc)/sizeof(aFunc[0]); ii++){
+
    p->errCode = sqlite3_create_function(db, aFunc[ii].zName, 
+
        aFunc[ii].nArg, SQLITE_UTF8, (void*)p, aFunc[ii].xFunc, 0, 0
+
    );
+
  }
+

+
  p->dbOut = db;
+
  return p->errCode;
+
}
+

+
/*
+
** Attach the auxiliary database 'recovery' to the output database handle.
+
** This temporary database is used during the recovery process and then 
+
** discarded.
+
*/
+
static void recoverOpenRecovery(sqlite3_recover *p){
+
  char *zSql = recoverMPrintf(p, "ATTACH %Q AS recovery;", p->zStateDb);
+
  recoverExec(p, p->dbOut, zSql);
+
  recoverExec(p, p->dbOut,
+
      "PRAGMA writable_schema = 1;"
+
      "CREATE TABLE recovery.map(pgno INTEGER PRIMARY KEY, parent INT);" 
+
      "CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql);"
+
  );
+
  sqlite3_free(zSql);
+
}
+

+

+
/*
+
** This function is a no-op if recover handle p already contains an error
+
** (if p->errCode!=SQLITE_OK).
+
**
+
** Otherwise, argument zName must be the name of a table that has just been
+
** created in the output database. This function queries the output db
+
** for the schema of said table, and creates a RecoverTable object to
+
** store the schema in memory. The new RecoverTable object is linked into
+
** the list at sqlite3_recover.pTblList.
+
**
+
** Parameter iRoot must be the root page of table zName in the INPUT 
+
** database.
+
*/
+
static void recoverAddTable(
+
  sqlite3_recover *p, 
+
  const char *zName,              /* Name of table created in output db */
+
  i64 iRoot                       /* Root page of same table in INPUT db */
+
){
+
  sqlite3_stmt *pStmt = recoverPreparePrintf(p, p->dbOut, 
+
      "PRAGMA table_xinfo(%Q)", zName
+
  );
+

+
  if( pStmt ){
+
    int iPk = -1;
+
    int iBind = 1;
+
    RecoverTable *pNew = 0;
+
    int nCol = 0;
+
    int nName = recoverStrlen(zName);
+
    int nByte = 0;
+
    while( sqlite3_step(pStmt)==SQLITE_ROW ){
+
      nCol++;
+
      nByte += (sqlite3_column_bytes(pStmt, 1)+1);
+
    }
+
    nByte += sizeof(RecoverTable) + nCol*sizeof(RecoverColumn) + nName+1;
+
    recoverReset(p, pStmt);
+

+
    pNew = recoverMalloc(p, nByte);
+
    if( pNew ){
+
      int i = 0;
+
      int iField = 0;
+
      char *csr = 0;
+
      pNew->aCol = (RecoverColumn*)&pNew[1];
+
      pNew->zTab = csr = (char*)&pNew->aCol[nCol];
+
      pNew->nCol = nCol;
+
      pNew->iRoot = iRoot;
+
      memcpy(csr, zName, nName);
+
      csr += nName+1;
+

+
      for(i=0; sqlite3_step(pStmt)==SQLITE_ROW; i++){
+
        int iPKF = sqlite3_column_int(pStmt, 5);
+
        int n = sqlite3_column_bytes(pStmt, 1);
+
        const char *z = (const char*)sqlite3_column_text(pStmt, 1);
+
        const char *zType = (const char*)sqlite3_column_text(pStmt, 2);
+
        int eHidden = sqlite3_column_int(pStmt, 6);
+

+
        if( iPk==-1 && iPKF==1 && !sqlite3_stricmp("integer", zType) ) iPk = i;
+
        if( iPKF>1 ) iPk = -2;
+
        pNew->aCol[i].zCol = csr;
+
        pNew->aCol[i].eHidden = eHidden;
+
        if( eHidden==RECOVER_EHIDDEN_VIRTUAL ){
+
          pNew->aCol[i].iField = -1;
+
        }else{
+
          pNew->aCol[i].iField = iField++;
+
        }
+
        if( eHidden!=RECOVER_EHIDDEN_VIRTUAL
+
         && eHidden!=RECOVER_EHIDDEN_STORED
+
        ){
+
          pNew->aCol[i].iBind = iBind++;
+
        }
+
        memcpy(csr, z, n);
+
        csr += (n+1);
+
      }
+

+
      pNew->pNext = p->pTblList;
+
      p->pTblList = pNew;
+
      pNew->bIntkey = 1;
+
    }
+

+
    recoverFinalize(p, pStmt);
+

+
    pStmt = recoverPreparePrintf(p, p->dbOut, "PRAGMA index_xinfo(%Q)", zName);
+
    while( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
+
      int iField = sqlite3_column_int(pStmt, 0);
+
      int iCol = sqlite3_column_int(pStmt, 1);
+

+
      assert( iField<pNew->nCol && iCol<pNew->nCol );
+
      pNew->aCol[iCol].iField = iField;
+

+
      pNew->bIntkey = 0;
+
      iPk = -2;
+
    }
+
    recoverFinalize(p, pStmt);
+

+
    if( p->errCode==SQLITE_OK ){
+
      if( iPk>=0 ){
+
        pNew->aCol[iPk].bIPK = 1;
+
      }else if( pNew->bIntkey ){
+
        pNew->iRowidBind = iBind++;
+
      }
+
    }
+
  }
+
}
+

+
/*
+
** This function is called after recoverCacheSchema() has cached those parts
+
** of the input database schema that could be recovered in temporary table
+
** "recovery.schema". This function creates in the output database copies
+
** of all parts of that schema that must be created before the tables can
+
** be populated. Specifically, this means:
+
**
+
**     * all tables that are not VIRTUAL, and
+
**     * UNIQUE indexes.
+
**
+
** If the recovery handle uses SQL callbacks, then callbacks containing
+
** the associated "CREATE TABLE" and "CREATE INDEX" statements are made.
+
**
+
** Additionally, records are added to the sqlite_schema table of the
+
** output database for any VIRTUAL tables. The CREATE VIRTUAL TABLE
+
** records are written directly to sqlite_schema, not actually executed.
+
** If the handle is in SQL callback mode, then callbacks are invoked 
+
** with equivalent SQL statements.
+
*/
+
static int recoverWriteSchema1(sqlite3_recover *p){
+
  sqlite3_stmt *pSelect = 0;
+
  sqlite3_stmt *pTblname = 0;
+

+
  pSelect = recoverPrepare(p, p->dbOut,
+
      "WITH dbschema(rootpage, name, sql, tbl, isVirtual, isIndex) AS ("
+
      "  SELECT rootpage, name, sql, "
+
      "    type='table', "
+
      "    sql LIKE 'create virtual%',"
+
      "    (type='index' AND (sql LIKE '%unique%' OR ?1))"
+
      "  FROM recovery.schema"
+
      ")"
+
      "SELECT rootpage, tbl, isVirtual, name, sql"
+
      " FROM dbschema "
+
      "  WHERE tbl OR isIndex"
+
      "  ORDER BY tbl DESC, name=='sqlite_sequence' DESC"
+
  );
+

+
  pTblname = recoverPrepare(p, p->dbOut,
+
      "SELECT name FROM sqlite_schema "
+
      "WHERE type='table' ORDER BY rowid DESC LIMIT 1"
+
  );
+

+
  if( pSelect ){
+
    sqlite3_bind_int(pSelect, 1, p->bSlowIndexes);
+
    while( sqlite3_step(pSelect)==SQLITE_ROW ){
+
      i64 iRoot = sqlite3_column_int64(pSelect, 0);
+
      int bTable = sqlite3_column_int(pSelect, 1);
+
      int bVirtual = sqlite3_column_int(pSelect, 2);
+
      const char *zName = (const char*)sqlite3_column_text(pSelect, 3);
+
      const char *zSql = (const char*)sqlite3_column_text(pSelect, 4);
+
      char *zFree = 0;
+
      int rc = SQLITE_OK;
+

+
      if( bVirtual ){
+
        zSql = (const char*)(zFree = recoverMPrintf(p,
+
            "INSERT INTO sqlite_schema VALUES('table', %Q, %Q, 0, %Q)",
+
            zName, zName, zSql
+
        ));
+
      }
+
      rc = sqlite3_exec(p->dbOut, zSql, 0, 0, 0);
+
      if( rc==SQLITE_OK ){
+
        recoverSqlCallback(p, zSql);
+
        if( bTable && !bVirtual ){
+
          if( SQLITE_ROW==sqlite3_step(pTblname) ){
+
            const char *zTbl = (const char*)sqlite3_column_text(pTblname, 0);
+
            recoverAddTable(p, zTbl, iRoot);
+
          }
+
          recoverReset(p, pTblname);
+
        }
+
      }else if( rc!=SQLITE_ERROR ){
+
        recoverDbError(p, p->dbOut);
+
      }
+
      sqlite3_free(zFree);
+
    }
+
  }
+
  recoverFinalize(p, pSelect);
+
  recoverFinalize(p, pTblname);
+

+
  return p->errCode;
+
}
+

+
/*
+
** This function is called after the output database has been populated. It
+
** adds all recovered schema elements that were not created in the output
+
** database by recoverWriteSchema1() - everything except for tables and
+
** UNIQUE indexes. Specifically:
+
**
+
**     * views,
+
**     * triggers,
+
**     * non-UNIQUE indexes.
+
**
+
** If the recover handle is in SQL callback mode, then equivalent callbacks
+
** are issued to create the schema elements.
+
*/
+
static int recoverWriteSchema2(sqlite3_recover *p){
+
  sqlite3_stmt *pSelect = 0;
+

+
  pSelect = recoverPrepare(p, p->dbOut,
+
      p->bSlowIndexes ?
+
      "SELECT rootpage, sql FROM recovery.schema "
+
      "  WHERE type!='table' AND type!='index'"
+
      :
+
      "SELECT rootpage, sql FROM recovery.schema "
+
      "  WHERE type!='table' AND (type!='index' OR sql NOT LIKE '%unique%')"
+
  );
+

+
  if( pSelect ){
+
    while( sqlite3_step(pSelect)==SQLITE_ROW ){
+
      const char *zSql = (const char*)sqlite3_column_text(pSelect, 1);
+
      int rc = sqlite3_exec(p->dbOut, zSql, 0, 0, 0);
+
      if( rc==SQLITE_OK ){
+
        recoverSqlCallback(p, zSql);
+
      }else if( rc!=SQLITE_ERROR ){
+
        recoverDbError(p, p->dbOut);
+
      }
+
    }
+
  }
+
  recoverFinalize(p, pSelect);
+

+
  return p->errCode;
+
}
+

+
/*
+
** This function is a no-op if recover handle p already contains an error
+
** (if p->errCode!=SQLITE_OK). In this case it returns NULL.
+
**
+
** Otherwise, if the recover handle is configured to create an output
+
** database (was created by sqlite3_recover_init()), then this function
+
** prepares and returns an SQL statement to INSERT a new record into table
+
** pTab, assuming the first nField fields of a record extracted from disk
+
** are valid.
+
**
+
** For example, if table pTab is:
+
**
+
**     CREATE TABLE name(a, b GENERATED ALWAYS AS (a+1) STORED, c, d, e);
+
**
+
** And nField is 4, then the SQL statement prepared and returned is:
+
**
+
**     INSERT INTO (a, c, d) VALUES (?1, ?2, ?3);
+
**
+
** In this case even though 4 values were extracted from the input db,
+
** only 3 are written to the output, as the generated STORED column 
+
** cannot be written.
+
**
+
** If the recover handle is in SQL callback mode, then the SQL statement
+
** prepared is such that evaluating it returns a single row containing
+
** a single text value - itself an SQL statement similar to the above,
+
** except with SQL literals in place of the variables. For example:
+
**
+
**     SELECT 'INSERT INTO (a, c, d) VALUES (' 
+
**          || quote(?1) || ', '
+
**          || quote(?2) || ', '
+
**          || quote(?3) || ')';
+
**
+
** In either case, it is the responsibility of the caller to eventually
+
** free the statement handle using sqlite3_finalize().
+
*/
+
static sqlite3_stmt *recoverInsertStmt(
+
  sqlite3_recover *p, 
+
  RecoverTable *pTab,
+
  int nField
+
){
+
  sqlite3_stmt *pRet = 0;
+
  const char *zSep = "";
+
  const char *zSqlSep = "";
+
  char *zSql = 0;
+
  char *zFinal = 0;
+
  char *zBind = 0;
+
  int ii;
+
  int bSql = p->xSql ? 1 : 0;
+

+
  if( nField<=0 ) return 0;
+

+
  assert( nField<=pTab->nCol );
+

+
  zSql = recoverMPrintf(p, "INSERT OR IGNORE INTO %Q(", pTab->zTab);
+

+
  if( pTab->iRowidBind ){
+
    assert( pTab->bIntkey );
+
    zSql = recoverMPrintf(p, "%z_rowid_", zSql);
+
    if( bSql ){
+
      zBind = recoverMPrintf(p, "%zquote(?%d)", zBind, pTab->iRowidBind);
+
    }else{
+
      zBind = recoverMPrintf(p, "%z?%d", zBind, pTab->iRowidBind);
+
    }
+
    zSqlSep = "||', '||";
+
    zSep = ", ";
+
  }
+

+
  for(ii=0; ii<nField; ii++){
+
    int eHidden = pTab->aCol[ii].eHidden;
+
    if( eHidden!=RECOVER_EHIDDEN_VIRTUAL
+
     && eHidden!=RECOVER_EHIDDEN_STORED
+
    ){
+
      assert( pTab->aCol[ii].iField>=0 && pTab->aCol[ii].iBind>=1 );
+
      zSql = recoverMPrintf(p, "%z%s%Q", zSql, zSep, pTab->aCol[ii].zCol);
+

+
      if( bSql ){
+
        zBind = recoverMPrintf(p, 
+
            "%z%sescape_crnl(quote(?%d))", zBind, zSqlSep, pTab->aCol[ii].iBind
+
        );
+
        zSqlSep = "||', '||";
+
      }else{
+
        zBind = recoverMPrintf(p, "%z%s?%d", zBind, zSep, pTab->aCol[ii].iBind);
+
      }
+
      zSep = ", ";
+
    }
+
  }
+

+
  if( bSql ){
+
    zFinal = recoverMPrintf(p, "SELECT %Q || ') VALUES (' || %s || ')'", 
+
        zSql, zBind
+
    );
+
  }else{
+
    zFinal = recoverMPrintf(p, "%s) VALUES (%s)", zSql, zBind);
+
  }
+

+
  pRet = recoverPrepare(p, p->dbOut, zFinal);
+
  sqlite3_free(zSql);
+
  sqlite3_free(zBind);
+
  sqlite3_free(zFinal);
+
  
+
  return pRet;
+
}
+

+

+
/*
+
** Search the list of RecoverTable objects at p->pTblList for one that
+
** has root page iRoot in the input database. If such an object is found,
+
** return a pointer to it. Otherwise, return NULL.
+
*/
+
static RecoverTable *recoverFindTable(sqlite3_recover *p, u32 iRoot){
+
  RecoverTable *pRet = 0;
+
  for(pRet=p->pTblList; pRet && pRet->iRoot!=iRoot; pRet=pRet->pNext);
+
  return pRet;
+
}
+

+
/*
+
** This function attempts to create a lost and found table within the 
+
** output db. If successful, it returns a pointer to a buffer containing
+
** the name of the new table. It is the responsibility of the caller to
+
** eventually free this buffer using sqlite3_free().
+
**
+
** If an error occurs, NULL is returned and an error code and error 
+
** message left in the recover handle.
+
*/
+
static char *recoverLostAndFoundCreate(
+
  sqlite3_recover *p,             /* Recover object */
+
  int nField                      /* Number of column fields in new table */
+
){
+
  char *zTbl = 0;
+
  sqlite3_stmt *pProbe = 0;
+
  int ii = 0;
+

+
  pProbe = recoverPrepare(p, p->dbOut,
+
    "SELECT 1 FROM sqlite_schema WHERE name=?"
+
  );
+
  for(ii=-1; zTbl==0 && p->errCode==SQLITE_OK && ii<1000; ii++){
+
    int bFail = 0;
+
    if( ii<0 ){
+
      zTbl = recoverMPrintf(p, "%s", p->zLostAndFound);
+
    }else{
+
      zTbl = recoverMPrintf(p, "%s_%d", p->zLostAndFound, ii);
+
    }
+

+
    if( p->errCode==SQLITE_OK ){
+
      sqlite3_bind_text(pProbe, 1, zTbl, -1, SQLITE_STATIC);
+
      if( SQLITE_ROW==sqlite3_step(pProbe) ){
+
        bFail = 1;
+
      }
+
      recoverReset(p, pProbe);
+
    }
+

+
    if( bFail ){
+
      sqlite3_clear_bindings(pProbe);
+
      sqlite3_free(zTbl);
+
      zTbl = 0;
+
    }
+
  }
+
  recoverFinalize(p, pProbe);
+

+
  if( zTbl ){
+
    const char *zSep = 0;
+
    char *zField = 0;
+
    char *zSql = 0;
+

+
    zSep = "rootpgno INTEGER, pgno INTEGER, nfield INTEGER, id INTEGER, ";
+
    for(ii=0; p->errCode==SQLITE_OK && ii<nField; ii++){
+
      zField = recoverMPrintf(p, "%z%sc%d", zField, zSep, ii);
+
      zSep = ", ";
+
    }
+

+
    zSql = recoverMPrintf(p, "CREATE TABLE %s(%s)", zTbl, zField);
+
    sqlite3_free(zField);
+

+
    recoverExec(p, p->dbOut, zSql);
+
    recoverSqlCallback(p, zSql);
+
    sqlite3_free(zSql);
+
  }else if( p->errCode==SQLITE_OK ){
+
    recoverError(
+
        p, SQLITE_ERROR, "failed to create %s output table", p->zLostAndFound
+
    );
+
  }
+

+
  return zTbl;
+
}
+

+
/*
+
** Synthesize and prepare an INSERT statement to write to the lost_and_found
+
** table in the output database. The name of the table is zTab, and it has
+
** nField c* fields.
+
*/
+
static sqlite3_stmt *recoverLostAndFoundInsert(
+
  sqlite3_recover *p,
+
  const char *zTab,
+
  int nField
+
){
+
  int nTotal = nField + 4;
+
  int ii;
+
  char *zBind = 0;
+
  sqlite3_stmt *pRet = 0;
+

+
  if( p->xSql==0 ){
+
    for(ii=0; ii<nTotal; ii++){
+
      zBind = recoverMPrintf(p, "%z%s?", zBind, zBind?", ":"", ii);
+
    }
+
    pRet = recoverPreparePrintf(
+
        p, p->dbOut, "INSERT INTO %s VALUES(%s)", zTab, zBind
+
    );
+
  }else{
+
    const char *zSep = "";
+
    for(ii=0; ii<nTotal; ii++){
+
      zBind = recoverMPrintf(p, "%z%squote(?)", zBind, zSep);
+
      zSep = "|| ', ' ||";
+
    }
+
    pRet = recoverPreparePrintf(
+
        p, p->dbOut, "SELECT 'INSERT INTO %s VALUES(' || %s || ')'", zTab, zBind
+
    );
+
  }
+

+
  sqlite3_free(zBind);
+
  return pRet;
+
}
+

+
/*
+
** Input database page iPg contains data that will be written to the
+
** lost-and-found table of the output database. This function attempts
+
** to identify the root page of the tree that page iPg belonged to.
+
** If successful, it sets output variable (*piRoot) to the page number
+
** of the root page and returns SQLITE_OK. Otherwise, if an error occurs,
+
** an SQLite error code is returned and the final value of *piRoot 
+
** undefined.
+
*/
+
static int recoverLostAndFoundFindRoot(
+
  sqlite3_recover *p, 
+
  i64 iPg,
+
  i64 *piRoot
+
){
+
  RecoverStateLAF *pLaf = &p->laf;
+

+
  if( pLaf->pFindRoot==0 ){
+
    pLaf->pFindRoot = recoverPrepare(p, p->dbOut,
+
        "WITH RECURSIVE p(pgno) AS ("
+
        "  SELECT ?"
+
        "    UNION"
+
        "  SELECT parent FROM recovery.map AS m, p WHERE m.pgno=p.pgno"
+
        ") "
+
        "SELECT p.pgno FROM p, recovery.map m WHERE m.pgno=p.pgno "
+
        "    AND m.parent IS NULL"
+
    );
+
  }
+
  if( p->errCode==SQLITE_OK ){
+
    sqlite3_bind_int64(pLaf->pFindRoot, 1, iPg);
+
    if( sqlite3_step(pLaf->pFindRoot)==SQLITE_ROW ){
+
      *piRoot = sqlite3_column_int64(pLaf->pFindRoot, 0);
+
    }else{
+
      *piRoot = iPg;
+
    }
+
    recoverReset(p, pLaf->pFindRoot);
+
  }
+
  return p->errCode;
+
}
+

+
/*
+
** Recover data from page iPage of the input database and write it to
+
** the lost-and-found table in the output database.
+
*/
+
static void recoverLostAndFoundOnePage(sqlite3_recover *p, i64 iPage){
+
  RecoverStateLAF *pLaf = &p->laf;
+
  sqlite3_value **apVal = pLaf->apVal;
+
  sqlite3_stmt *pPageData = pLaf->pPageData;
+
  sqlite3_stmt *pInsert = pLaf->pInsert;
+

+
  int nVal = -1;
+
  int iPrevCell = 0;
+
  i64 iRoot = 0;
+
  int bHaveRowid = 0;
+
  i64 iRowid = 0;
+
  int ii = 0;
+

+
  if( recoverLostAndFoundFindRoot(p, iPage, &iRoot) ) return;
+
  sqlite3_bind_int64(pPageData, 1, iPage);
+
  while( p->errCode==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPageData) ){
+
    int iCell = sqlite3_column_int64(pPageData, 0);
+
    int iField = sqlite3_column_int64(pPageData, 1);
+

+
    if( iPrevCell!=iCell && nVal>=0 ){
+
      /* Insert the new row */
+
      sqlite3_bind_int64(pInsert, 1, iRoot);      /* rootpgno */
+
      sqlite3_bind_int64(pInsert, 2, iPage);      /* pgno */
+
      sqlite3_bind_int(pInsert, 3, nVal);         /* nfield */
+
      if( bHaveRowid ){
+
        sqlite3_bind_int64(pInsert, 4, iRowid);   /* id */
+
      }
+
      for(ii=0; ii<nVal; ii++){
+
        recoverBindValue(p, pInsert, 5+ii, apVal[ii]);
+
      }
+
      if( sqlite3_step(pInsert)==SQLITE_ROW ){
+
        recoverSqlCallback(p, (const char*)sqlite3_column_text(pInsert, 0));
+
      }
+
      recoverReset(p, pInsert);
+

+
      /* Discard the accumulated row data */
+
      for(ii=0; ii<nVal; ii++){
+
        sqlite3_value_free(apVal[ii]);
+
        apVal[ii] = 0;
+
      }
+
      sqlite3_clear_bindings(pInsert);
+
      bHaveRowid = 0;
+
      nVal = -1;
+
    }
+

+
    if( iCell<0 ) break;
+

+
    if( iField<0 ){
+
      assert( nVal==-1 );
+
      iRowid = sqlite3_column_int64(pPageData, 2);
+
      bHaveRowid = 1;
+
      nVal = 0;
+
    }else if( iField<pLaf->nMaxField ){
+
      sqlite3_value *pVal = sqlite3_column_value(pPageData, 2);
+
      apVal[iField] = sqlite3_value_dup(pVal);
+
      assert( iField==nVal || (nVal==-1 && iField==0) );
+
      nVal = iField+1;
+
      if( apVal[iField]==0 ){
+
        recoverError(p, SQLITE_NOMEM, 0);
+
      }
+
    }
+

+
    iPrevCell = iCell;
+
  }
+
  recoverReset(p, pPageData);
+

+
  for(ii=0; ii<nVal; ii++){
+
    sqlite3_value_free(apVal[ii]);
+
    apVal[ii] = 0;
+
  }
+
}
+

+
/*
+
** Perform one step (sqlite3_recover_step()) of work for the connection 
+
** passed as the only argument, which is guaranteed to be in
+
** RECOVER_STATE_LOSTANDFOUND3 state - during which the lost-and-found 
+
** table of the output database is populated with recovered data that can 
+
** not be assigned to any recovered schema object.
+
*/ 
+
static int recoverLostAndFound3Step(sqlite3_recover *p){
+
  RecoverStateLAF *pLaf = &p->laf;
+
  if( p->errCode==SQLITE_OK ){
+
    if( pLaf->pInsert==0 ){
+
      return SQLITE_DONE;
+
    }else{
+
      if( p->errCode==SQLITE_OK ){
+
        int res = sqlite3_step(pLaf->pAllPage);
+
        if( res==SQLITE_ROW ){
+
          i64 iPage = sqlite3_column_int64(pLaf->pAllPage, 0);
+
          if( recoverBitmapQuery(pLaf->pUsed, iPage)==0 ){
+
            recoverLostAndFoundOnePage(p, iPage);
+
          }
+
        }else{
+
          recoverReset(p, pLaf->pAllPage);
+
          return SQLITE_DONE;
+
        }
+
      }
+
    }
+
  }
+
  return SQLITE_OK;
+
}
+

+
/*
+
** Initialize resources required in RECOVER_STATE_LOSTANDFOUND3 
+
** state - during which the lost-and-found table of the output database 
+
** is populated with recovered data that can not be assigned to any 
+
** recovered schema object.
+
*/ 
+
static void recoverLostAndFound3Init(sqlite3_recover *p){
+
  RecoverStateLAF *pLaf = &p->laf;
+

+
  if( pLaf->nMaxField>0 ){
+
    char *zTab = 0;               /* Name of lost_and_found table */
+

+
    zTab = recoverLostAndFoundCreate(p, pLaf->nMaxField);
+
    pLaf->pInsert = recoverLostAndFoundInsert(p, zTab, pLaf->nMaxField);
+
    sqlite3_free(zTab);
+

+
    pLaf->pAllPage = recoverPreparePrintf(p, p->dbOut,
+
        "WITH RECURSIVE seq(ii) AS ("
+
        "  SELECT 1 UNION ALL SELECT ii+1 FROM seq WHERE ii<%lld"
+
        ")"
+
        "SELECT ii FROM seq" , p->laf.nPg
+
    );
+
    pLaf->pPageData = recoverPrepare(p, p->dbOut,
+
        "SELECT cell, field, value "
+
        "FROM sqlite_dbdata('getpage()') d WHERE d.pgno=? "
+
        "UNION ALL "
+
        "SELECT -1, -1, -1"
+
    );
+

+
    pLaf->apVal = (sqlite3_value**)recoverMalloc(p, 
+
        pLaf->nMaxField*sizeof(sqlite3_value*)
+
    );
+
  }
+
}
+

+
/*
+
** Initialize resources required in RECOVER_STATE_WRITING state - during which
+
** tables recovered from the schema of the input database are populated with
+
** recovered data.
+
*/ 
+
static int recoverWriteDataInit(sqlite3_recover *p){
+
  RecoverStateW1 *p1 = &p->w1;
+
  RecoverTable *pTbl = 0;
+
  int nByte = 0;
+

+
  /* Figure out the maximum number of columns for any table in the schema */
+
  assert( p1->nMax==0 );
+
  for(pTbl=p->pTblList; pTbl; pTbl=pTbl->pNext){
+
    if( pTbl->nCol>p1->nMax ) p1->nMax = pTbl->nCol;
+
  }
+

+
  /* Allocate an array of (sqlite3_value*) in which to accumulate the values
+
  ** that will be written to the output database in a single row. */
+
  nByte = sizeof(sqlite3_value*) * (p1->nMax+1);
+
  p1->apVal = (sqlite3_value**)recoverMalloc(p, nByte);
+
  if( p1->apVal==0 ) return p->errCode;
+

+
  /* Prepare the SELECT to loop through schema tables (pTbls) and the SELECT
+
  ** to loop through cells that appear to belong to a single table (pSel). */
+
  p1->pTbls = recoverPrepare(p, p->dbOut,
+
      "SELECT rootpage FROM recovery.schema "
+
      "  WHERE type='table' AND (sql NOT LIKE 'create virtual%')"
+
      "  ORDER BY (tbl_name='sqlite_sequence') ASC"
+
  );
+
  p1->pSel = recoverPrepare(p, p->dbOut, 
+
      "WITH RECURSIVE pages(page) AS ("
+
      "  SELECT ?1"
+
      "    UNION"
+
      "  SELECT child FROM sqlite_dbptr('getpage()'), pages "
+
      "    WHERE pgno=page"
+
      ") "
+
      "SELECT page, cell, field, value "
+
      "FROM sqlite_dbdata('getpage()') d, pages p WHERE p.page=d.pgno "
+
      "UNION ALL "
+
      "SELECT 0, 0, 0, 0"
+
  );
+

+
  return p->errCode;
+
}
+

+
/*
+
** Clean up resources allocated by recoverWriteDataInit() (stuff in 
+
** sqlite3_recover.w1).
+
*/
+
static void recoverWriteDataCleanup(sqlite3_recover *p){
+
  RecoverStateW1 *p1 = &p->w1;
+
  int ii;
+
  for(ii=0; ii<p1->nVal; ii++){
+
    sqlite3_value_free(p1->apVal[ii]);
+
  }
+
  sqlite3_free(p1->apVal);
+
  recoverFinalize(p, p1->pInsert);
+
  recoverFinalize(p, p1->pTbls);
+
  recoverFinalize(p, p1->pSel);
+
  memset(p1, 0, sizeof(*p1));
+
}
+

+
/*
+
** Perform one step (sqlite3_recover_step()) of work for the connection 
+
** passed as the only argument, which is guaranteed to be in
+
** RECOVER_STATE_WRITING state - during which tables recovered from the
+
** schema of the input database are populated with recovered data.
+
*/ 
+
static int recoverWriteDataStep(sqlite3_recover *p){
+
  RecoverStateW1 *p1 = &p->w1;
+
  sqlite3_stmt *pSel = p1->pSel;
+
  sqlite3_value **apVal = p1->apVal;
+

+
  if( p->errCode==SQLITE_OK && p1->pTab==0 ){
+
    if( sqlite3_step(p1->pTbls)==SQLITE_ROW ){
+
      i64 iRoot = sqlite3_column_int64(p1->pTbls, 0);
+
      p1->pTab = recoverFindTable(p, iRoot);
+

+
      recoverFinalize(p, p1->pInsert);
+
      p1->pInsert = 0;
+

+
      /* If this table is unknown, return early. The caller will invoke this
+
      ** function again and it will move on to the next table.  */
+
      if( p1->pTab==0 ) return p->errCode;
+

+
      /* If this is the sqlite_sequence table, delete any rows added by
+
      ** earlier INSERT statements on tables with AUTOINCREMENT primary
+
      ** keys before recovering its contents. The p1->pTbls SELECT statement
+
      ** is rigged to deliver "sqlite_sequence" last of all, so we don't
+
      ** worry about it being modified after it is recovered. */
+
      if( sqlite3_stricmp("sqlite_sequence", p1->pTab->zTab)==0 ){
+
        recoverExec(p, p->dbOut, "DELETE FROM sqlite_sequence");
+
        recoverSqlCallback(p, "DELETE FROM sqlite_sequence");
+
      }
+

+
      /* Bind the root page of this table within the original database to 
+
      ** SELECT statement p1->pSel. The SELECT statement will then iterate
+
      ** through cells that look like they belong to table pTab.  */
+
      sqlite3_bind_int64(pSel, 1, iRoot);
+

+
      p1->nVal = 0;
+
      p1->bHaveRowid = 0;
+
      p1->iPrevPage = -1;
+
      p1->iPrevCell = -1;
+
    }else{
+
      return SQLITE_DONE;
+
    }
+
  }
+
  assert( p->errCode!=SQLITE_OK || p1->pTab );
+

+
  if( p->errCode==SQLITE_OK && sqlite3_step(pSel)==SQLITE_ROW ){
+
    RecoverTable *pTab = p1->pTab;
+

+
    i64 iPage = sqlite3_column_int64(pSel, 0);
+
    int iCell = sqlite3_column_int(pSel, 1);
+
    int iField = sqlite3_column_int(pSel, 2);
+
    sqlite3_value *pVal = sqlite3_column_value(pSel, 3);
+
    int bNewCell = (p1->iPrevPage!=iPage || p1->iPrevCell!=iCell);
+

+
    assert( bNewCell==0 || (iField==-1 || iField==0) );
+
    assert( bNewCell || iField==p1->nVal || p1->nVal==pTab->nCol );
+

+
    if( bNewCell ){
+
      int ii = 0;
+
      if( p1->nVal>=0 ){
+
        if( p1->pInsert==0 || p1->nVal!=p1->nInsert ){
+
          recoverFinalize(p, p1->pInsert);
+
          p1->pInsert = recoverInsertStmt(p, pTab, p1->nVal);
+
          p1->nInsert = p1->nVal;
+
        }
+
        if( p1->nVal>0 ){
+
          sqlite3_stmt *pInsert = p1->pInsert;
+
          for(ii=0; ii<pTab->nCol; ii++){
+
            RecoverColumn *pCol = &pTab->aCol[ii];
+
            int iBind = pCol->iBind;
+
            if( iBind>0 ){
+
              if( pCol->bIPK ){
+
                sqlite3_bind_int64(pInsert, iBind, p1->iRowid);
+
              }else if( pCol->iField<p1->nVal ){
+
                recoverBindValue(p, pInsert, iBind, apVal[pCol->iField]);
+
              }
+
            }
+
          }
+
          if( p->bRecoverRowid && pTab->iRowidBind>0 && p1->bHaveRowid ){
+
            sqlite3_bind_int64(pInsert, pTab->iRowidBind, p1->iRowid);
+
          }
+
          if( SQLITE_ROW==sqlite3_step(pInsert) ){
+
            const char *z = (const char*)sqlite3_column_text(pInsert, 0);
+
            recoverSqlCallback(p, z);
+
          }
+
          recoverReset(p, pInsert);
+
          assert( p->errCode || pInsert );
+
          if( pInsert ) sqlite3_clear_bindings(pInsert);
+
        }
+
      }
+

+
      for(ii=0; ii<p1->nVal; ii++){
+
        sqlite3_value_free(apVal[ii]);
+
        apVal[ii] = 0;
+
      }
+
      p1->nVal = -1;
+
      p1->bHaveRowid = 0;
+
    }
+

+
    if( iPage!=0 ){
+
      if( iField<0 ){
+
        p1->iRowid = sqlite3_column_int64(pSel, 3);
+
        assert( p1->nVal==-1 );
+
        p1->nVal = 0;
+
        p1->bHaveRowid = 1;
+
      }else if( iField<pTab->nCol ){
+
        assert( apVal[iField]==0 );
+
        apVal[iField] = sqlite3_value_dup( pVal );
+
        if( apVal[iField]==0 ){
+
          recoverError(p, SQLITE_NOMEM, 0);
+
        }
+
        p1->nVal = iField+1;
+
      }
+
      p1->iPrevCell = iCell;
+
      p1->iPrevPage = iPage;
+
    }
+
  }else{
+
    recoverReset(p, pSel);
+
    p1->pTab = 0;
+
  }
+

+
  return p->errCode;
+
}
+

+
/*
+
** Initialize resources required by sqlite3_recover_step() in
+
** RECOVER_STATE_LOSTANDFOUND1 state - during which the set of pages not
+
** already allocated to a recovered schema element is determined.
+
*/ 
+
static void recoverLostAndFound1Init(sqlite3_recover *p){
+
  RecoverStateLAF *pLaf = &p->laf;
+
  sqlite3_stmt *pStmt = 0;
+

+
  assert( p->laf.pUsed==0 );
+
  pLaf->nPg = recoverPageCount(p);
+
  pLaf->pUsed = recoverBitmapAlloc(p, pLaf->nPg);
+

+
  /* Prepare a statement to iterate through all pages that are part of any tree
+
  ** in the recoverable part of the input database schema to the bitmap. And,
+
  ** if !p->bFreelistCorrupt, add all pages that appear to be part of the
+
  ** freelist.  */
+
  pStmt = recoverPrepare(
+
      p, p->dbOut,
+
      "WITH trunk(pgno) AS ("
+
      "  SELECT read_i32(getpage(1), 8) AS x WHERE x>0"
+
      "    UNION"
+
      "  SELECT read_i32(getpage(trunk.pgno), 0) AS x FROM trunk WHERE x>0"
+
      "),"
+
      "trunkdata(pgno, data) AS ("
+
      "  SELECT pgno, getpage(pgno) FROM trunk"
+
      "),"
+
      "freelist(data, n, freepgno) AS ("
+
      "  SELECT data, min(16384, read_i32(data, 1)-1), pgno FROM trunkdata"
+
      "    UNION ALL"
+
      "  SELECT data, n-1, read_i32(data, 2+n) FROM freelist WHERE n>=0"
+
      "),"
+
      ""
+
      "roots(r) AS ("
+
      "  SELECT 1 UNION ALL"
+
      "  SELECT rootpage FROM recovery.schema WHERE rootpage>0"
+
      "),"
+
      "used(page) AS ("
+
      "  SELECT r FROM roots"
+
      "    UNION"
+
      "  SELECT child FROM sqlite_dbptr('getpage()'), used "
+
      "    WHERE pgno=page"
+
      ") "
+
      "SELECT page FROM used"
+
      " UNION ALL "
+
      "SELECT freepgno FROM freelist WHERE NOT ?"
+
  );
+
  if( pStmt ) sqlite3_bind_int(pStmt, 1, p->bFreelistCorrupt);
+
  pLaf->pUsedPages = pStmt;
+
}
+

+
/*
+
** Perform one step (sqlite3_recover_step()) of work for the connection 
+
** passed as the only argument, which is guaranteed to be in
+
** RECOVER_STATE_LOSTANDFOUND1 state - during which the set of pages not
+
** already allocated to a recovered schema element is determined.
+
*/ 
+
static int recoverLostAndFound1Step(sqlite3_recover *p){
+
  RecoverStateLAF *pLaf = &p->laf;
+
  int rc = p->errCode;
+
  if( rc==SQLITE_OK ){
+
    rc = sqlite3_step(pLaf->pUsedPages);
+
    if( rc==SQLITE_ROW ){
+
      i64 iPg = sqlite3_column_int64(pLaf->pUsedPages, 0);
+
      recoverBitmapSet(pLaf->pUsed, iPg);
+
      rc = SQLITE_OK;
+
    }else{
+
      recoverFinalize(p, pLaf->pUsedPages);
+
      pLaf->pUsedPages = 0;
+
    }
+
  }
+
  return rc;
+
}
+

+
/*
+
** Initialize resources required by RECOVER_STATE_LOSTANDFOUND2 
+
** state - during which the pages identified in RECOVER_STATE_LOSTANDFOUND1
+
** are sorted into sets that likely belonged to the same database tree.
+
*/ 
+
static void recoverLostAndFound2Init(sqlite3_recover *p){
+
  RecoverStateLAF *pLaf = &p->laf;
+

+
  assert( p->laf.pAllAndParent==0 );
+
  assert( p->laf.pMapInsert==0 );
+
  assert( p->laf.pMaxField==0 );
+
  assert( p->laf.nMaxField==0 );
+

+
  pLaf->pMapInsert = recoverPrepare(p, p->dbOut,
+
      "INSERT OR IGNORE INTO recovery.map(pgno, parent) VALUES(?, ?)"
+
  );
+
  pLaf->pAllAndParent = recoverPreparePrintf(p, p->dbOut,
+
      "WITH RECURSIVE seq(ii) AS ("
+
      "  SELECT 1 UNION ALL SELECT ii+1 FROM seq WHERE ii<%lld"
+
      ")"
+
      "SELECT pgno, child FROM sqlite_dbptr('getpage()') "
+
      " UNION ALL "
+
      "SELECT NULL, ii FROM seq", p->laf.nPg
+
  );
+
  pLaf->pMaxField = recoverPreparePrintf(p, p->dbOut,
+
      "SELECT max(field)+1 FROM sqlite_dbdata('getpage') WHERE pgno = ?"
+
  );
+
}
+

+
/*
+
** Perform one step (sqlite3_recover_step()) of work for the connection 
+
** passed as the only argument, which is guaranteed to be in
+
** RECOVER_STATE_LOSTANDFOUND2 state - during which the pages identified 
+
** in RECOVER_STATE_LOSTANDFOUND1 are sorted into sets that likely belonged 
+
** to the same database tree.
+
*/ 
+
static int recoverLostAndFound2Step(sqlite3_recover *p){
+
  RecoverStateLAF *pLaf = &p->laf;
+
  if( p->errCode==SQLITE_OK ){
+
    int res = sqlite3_step(pLaf->pAllAndParent);
+
    if( res==SQLITE_ROW ){
+
      i64 iChild = sqlite3_column_int(pLaf->pAllAndParent, 1);
+
      if( recoverBitmapQuery(pLaf->pUsed, iChild)==0 ){
+
        sqlite3_bind_int64(pLaf->pMapInsert, 1, iChild);
+
        sqlite3_bind_value(pLaf->pMapInsert, 2, 
+
            sqlite3_column_value(pLaf->pAllAndParent, 0)
+
        );
+
        sqlite3_step(pLaf->pMapInsert);
+
        recoverReset(p, pLaf->pMapInsert);
+
        sqlite3_bind_int64(pLaf->pMaxField, 1, iChild);
+
        if( SQLITE_ROW==sqlite3_step(pLaf->pMaxField) ){
+
          int nMax = sqlite3_column_int(pLaf->pMaxField, 0);
+
          if( nMax>pLaf->nMaxField ) pLaf->nMaxField = nMax;
+
        }
+
        recoverReset(p, pLaf->pMaxField);
+
      }
+
    }else{
+
      recoverFinalize(p, pLaf->pAllAndParent);
+
      pLaf->pAllAndParent =0;
+
      return SQLITE_DONE;
+
    }
+
  }
+
  return p->errCode;
+
}
+

+
/*
+
** Free all resources allocated as part of sqlite3_recover_step() calls
+
** in one of the RECOVER_STATE_LOSTANDFOUND[123] states.
+
*/
+
static void recoverLostAndFoundCleanup(sqlite3_recover *p){
+
  recoverBitmapFree(p->laf.pUsed);
+
  p->laf.pUsed = 0;
+
  sqlite3_finalize(p->laf.pUsedPages);
+
  sqlite3_finalize(p->laf.pAllAndParent);
+
  sqlite3_finalize(p->laf.pMapInsert);
+
  sqlite3_finalize(p->laf.pMaxField);
+
  sqlite3_finalize(p->laf.pFindRoot);
+
  sqlite3_finalize(p->laf.pInsert);
+
  sqlite3_finalize(p->laf.pAllPage);
+
  sqlite3_finalize(p->laf.pPageData);
+
  p->laf.pUsedPages = 0;
+
  p->laf.pAllAndParent = 0;
+
  p->laf.pMapInsert = 0;
+
  p->laf.pMaxField = 0;
+
  p->laf.pFindRoot = 0;
+
  p->laf.pInsert = 0;
+
  p->laf.pAllPage = 0;
+
  p->laf.pPageData = 0;
+
  sqlite3_free(p->laf.apVal);
+
  p->laf.apVal = 0;
+
}
+

+
/*
+
** Free all resources allocated as part of sqlite3_recover_step() calls.
+
*/
+
static void recoverFinalCleanup(sqlite3_recover *p){
+
  RecoverTable *pTab = 0;
+
  RecoverTable *pNext = 0;
+

+
  recoverWriteDataCleanup(p);
+
  recoverLostAndFoundCleanup(p);
+

+
  for(pTab=p->pTblList; pTab; pTab=pNext){
+
    pNext = pTab->pNext;
+
    sqlite3_free(pTab);
+
  }
+
  p->pTblList = 0;
+
  sqlite3_finalize(p->pGetPage);
+
  p->pGetPage = 0;
+

+
  {
+
#ifndef NDEBUG
+
    int res = 
+
#endif
+
       sqlite3_close(p->dbOut);
+
    assert( res==SQLITE_OK );
+
  }
+
  p->dbOut = 0;
+
}
+

+
/*
+
** Decode and return an unsigned 16-bit big-endian integer value from 
+
** buffer a[].
+
*/
+
static u32 recoverGetU16(const u8 *a){
+
  return (((u32)a[0])<<8) + ((u32)a[1]);
+
}
+

+
/*
+
** Decode and return an unsigned 32-bit big-endian integer value from 
+
** buffer a[].
+
*/
+
static u32 recoverGetU32(const u8 *a){
+
  return (((u32)a[0])<<24) + (((u32)a[1])<<16) + (((u32)a[2])<<8) + ((u32)a[3]);
+
}
+

+
/*
+
** Decode an SQLite varint from buffer a[]. Write the decoded value to (*pVal)
+
** and return the number of bytes consumed.
+
*/
+
static int recoverGetVarint(const u8 *a, i64 *pVal){
+
  sqlite3_uint64 u = 0;
+
  int i;
+
  for(i=0; i<8; i++){
+
    u = (u<<7) + (a[i]&0x7f);
+
    if( (a[i]&0x80)==0 ){ *pVal = (sqlite3_int64)u; return i+1; }
+
  }
+
  u = (u<<8) + (a[i]&0xff);
+
  *pVal = (sqlite3_int64)u;
+
  return 9;
+
}
+

+
/*
+
** The second argument points to a buffer n bytes in size. If this buffer
+
** or a prefix thereof appears to contain a well-formed SQLite b-tree page, 
+
** return the page-size in bytes. Otherwise, if the buffer does not 
+
** appear to contain a well-formed b-tree page, return 0.
+
*/
+
static int recoverIsValidPage(u8 *aTmp, const u8 *a, int n){
+
  u8 *aUsed = aTmp;
+
  int nFrag = 0;
+
  int nActual = 0;
+
  int iFree = 0;
+
  int nCell = 0;                  /* Number of cells on page */
+
  int iCellOff = 0;               /* Offset of cell array in page */
+
  int iContent = 0;
+
  int eType = 0;
+
  int ii = 0;
+

+
  eType = (int)a[0];
+
  if( eType!=0x02 && eType!=0x05 && eType!=0x0A && eType!=0x0D ) return 0;
+

+
  iFree = (int)recoverGetU16(&a[1]);
+
  nCell = (int)recoverGetU16(&a[3]);
+
  iContent = (int)recoverGetU16(&a[5]);
+
  if( iContent==0 ) iContent = 65536;
+
  nFrag = (int)a[7];
+

+
  if( iContent>n ) return 0;
+

+
  memset(aUsed, 0, n);
+
  memset(aUsed, 0xFF, iContent);
+

+
  /* Follow the free-list. This is the same format for all b-tree pages. */
+
  if( iFree && iFree<=iContent ) return 0;
+
  while( iFree ){
+
    int iNext = 0;
+
    int nByte = 0;
+
    if( iFree>(n-4) ) return 0;
+
    iNext = recoverGetU16(&a[iFree]);
+
    nByte = recoverGetU16(&a[iFree+2]);
+
    if( iFree+nByte>n ) return 0;
+
    if( iNext && iNext<iFree+nByte ) return 0;
+
    memset(&aUsed[iFree], 0xFF, nByte);
+
    iFree = iNext;
+
  }
+

+
  /* Run through the cells */
+
  if( eType==0x02 || eType==0x05 ){
+
    iCellOff = 12;
+
  }else{
+
    iCellOff = 8;
+
  }
+
  if( (iCellOff + 2*nCell)>iContent ) return 0;
+
  for(ii=0; ii<nCell; ii++){
+
    int iByte;
+
    i64 nPayload = 0;
+
    int nByte = 0;
+
    int iOff = recoverGetU16(&a[iCellOff + 2*ii]);
+
    if( iOff<iContent || iOff>n ){
+
      return 0;
+
    }
+
    if( eType==0x05 || eType==0x02 ) nByte += 4;
+
    nByte += recoverGetVarint(&a[iOff+nByte], &nPayload);
+
    if( eType==0x0D ){
+
      i64 dummy = 0;
+
      nByte += recoverGetVarint(&a[iOff+nByte], &dummy);
+
    }
+
    if( eType!=0x05 ){
+
      int X = (eType==0x0D) ? n-35 : (((n-12)*64/255)-23);
+
      int M = ((n-12)*32/255)-23;
+
      int K = M+((nPayload-M)%(n-4));
+

+
      if( nPayload<X ){
+
        nByte += nPayload;
+
      }else if( K<=X ){
+
        nByte += K+4;
+
      }else{
+
        nByte += M+4;
+
      }
+
    }
+

+
    if( iOff+nByte>n ){
+
      return 0;
+
    }
+
    for(iByte=iOff; iByte<(iOff+nByte); iByte++){
+
      if( aUsed[iByte]!=0 ){
+
        return 0;
+
      }
+
      aUsed[iByte] = 0xFF;
+
    }
+
  }
+

+
  nActual = 0;
+
  for(ii=0; ii<n; ii++){
+
    if( aUsed[ii]==0 ) nActual++;
+
  }
+
  return (nActual==nFrag);
+
}
+

+

+
static int recoverVfsClose(sqlite3_file*);
+
static int recoverVfsRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
+
static int recoverVfsWrite(sqlite3_file*, const void*, int, sqlite3_int64);
+
static int recoverVfsTruncate(sqlite3_file*, sqlite3_int64 size);
+
static int recoverVfsSync(sqlite3_file*, int flags);
+
static int recoverVfsFileSize(sqlite3_file*, sqlite3_int64 *pSize);
+
static int recoverVfsLock(sqlite3_file*, int);
+
static int recoverVfsUnlock(sqlite3_file*, int);
+
static int recoverVfsCheckReservedLock(sqlite3_file*, int *pResOut);
+
static int recoverVfsFileControl(sqlite3_file*, int op, void *pArg);
+
static int recoverVfsSectorSize(sqlite3_file*);
+
static int recoverVfsDeviceCharacteristics(sqlite3_file*);
+
static int recoverVfsShmMap(sqlite3_file*, int, int, int, void volatile**);
+
static int recoverVfsShmLock(sqlite3_file*, int offset, int n, int flags);
+
static void recoverVfsShmBarrier(sqlite3_file*);
+
static int recoverVfsShmUnmap(sqlite3_file*, int deleteFlag);
+
static int recoverVfsFetch(sqlite3_file*, sqlite3_int64, int, void**);
+
static int recoverVfsUnfetch(sqlite3_file *pFd, sqlite3_int64 iOff, void *p);
+

+
static sqlite3_io_methods recover_methods = {
+
  2, /* iVersion */
+
  recoverVfsClose,
+
  recoverVfsRead,
+
  recoverVfsWrite,
+
  recoverVfsTruncate,
+
  recoverVfsSync,
+
  recoverVfsFileSize,
+
  recoverVfsLock,
+
  recoverVfsUnlock,
+
  recoverVfsCheckReservedLock,
+
  recoverVfsFileControl,
+
  recoverVfsSectorSize,
+
  recoverVfsDeviceCharacteristics,
+
  recoverVfsShmMap,
+
  recoverVfsShmLock,
+
  recoverVfsShmBarrier,
+
  recoverVfsShmUnmap,
+
  recoverVfsFetch,
+
  recoverVfsUnfetch
+
};
+

+
static int recoverVfsClose(sqlite3_file *pFd){
+
  assert( pFd->pMethods!=&recover_methods );
+
  return pFd->pMethods->xClose(pFd);
+
}
+

+
/*
+
** Write value v to buffer a[] as a 16-bit big-endian unsigned integer.
+
*/
+
static void recoverPutU16(u8 *a, u32 v){
+
  a[0] = (v>>8) & 0x00FF;
+
  a[1] = (v>>0) & 0x00FF;
+
}
+

+
/*
+
** Write value v to buffer a[] as a 32-bit big-endian unsigned integer.
+
*/
+
static void recoverPutU32(u8 *a, u32 v){
+
  a[0] = (v>>24) & 0x00FF;
+
  a[1] = (v>>16) & 0x00FF;
+
  a[2] = (v>>8) & 0x00FF;
+
  a[3] = (v>>0) & 0x00FF;
+
}
+

+
/*
+
** Detect the page-size of the database opened by file-handle pFd by 
+
** searching the first part of the file for a well-formed SQLite b-tree 
+
** page. If parameter nReserve is non-zero, then as well as searching for
+
** a b-tree page with zero reserved bytes, this function searches for one
+
** with nReserve reserved bytes at the end of it.
+
**
+
** If successful, set variable p->detected_pgsz to the detected page-size
+
** in bytes and return SQLITE_OK. Or, if no error occurs but no valid page
+
** can be found, return SQLITE_OK but leave p->detected_pgsz set to 0. Or,
+
** if an error occurs (e.g. an IO or OOM error), then an SQLite error code
+
** is returned. The final value of p->detected_pgsz is undefined in this
+
** case.
+
*/
+
static int recoverVfsDetectPagesize(
+
  sqlite3_recover *p,             /* Recover handle */
+
  sqlite3_file *pFd,              /* File-handle open on input database */
+
  u32 nReserve,                   /* Possible nReserve value */
+
  i64 nSz                         /* Size of database file in bytes */
+
){
+
  int rc = SQLITE_OK;
+
  const int nMin = 512;
+
  const int nMax = 65536;
+
  const int nMaxBlk = 4;
+
  u32 pgsz = 0;
+
  int iBlk = 0;
+
  u8 *aPg = 0;
+
  u8 *aTmp = 0;
+
  int nBlk = 0;
+

+
  aPg = (u8*)sqlite3_malloc(2*nMax);
+
  if( aPg==0 ) return SQLITE_NOMEM;
+
  aTmp = &aPg[nMax];
+

+
  nBlk = (nSz+nMax-1)/nMax;
+
  if( nBlk>nMaxBlk ) nBlk = nMaxBlk;
+

+
  do {
+
    for(iBlk=0; rc==SQLITE_OK && iBlk<nBlk; iBlk++){
+
      int nByte = (nSz>=((iBlk+1)*nMax)) ? nMax : (nSz % nMax);
+
      memset(aPg, 0, nMax);
+
      rc = pFd->pMethods->xRead(pFd, aPg, nByte, iBlk*nMax);
+
      if( rc==SQLITE_OK ){
+
        int pgsz2;
+
        for(pgsz2=(pgsz ? pgsz*2 : nMin); pgsz2<=nMax; pgsz2=pgsz2*2){
+
          int iOff;
+
          for(iOff=0; iOff<nMax; iOff+=pgsz2){
+
            if( recoverIsValidPage(aTmp, &aPg[iOff], pgsz2-nReserve) ){
+
              pgsz = pgsz2;
+
              break;
+
            }
+
          }
+
        }
+
      }
+
    }
+
    if( pgsz>(u32)p->detected_pgsz ){
+
      p->detected_pgsz = pgsz;
+
      p->nReserve = nReserve;
+
    }
+
    if( nReserve==0 ) break;
+
    nReserve = 0;
+
  }while( 1 );
+

+
  p->detected_pgsz = pgsz;
+
  sqlite3_free(aPg);
+
  return rc;
+
}
+

+
/*
+
** The xRead() method of the wrapper VFS. This is used to intercept calls
+
** to read page 1 of the input database.
+
*/
+
static int recoverVfsRead(sqlite3_file *pFd, void *aBuf, int nByte, i64 iOff){
+
  int rc = SQLITE_OK;
+
  if( pFd->pMethods==&recover_methods ){
+
    pFd->pMethods = recover_g.pMethods;
+
    rc = pFd->pMethods->xRead(pFd, aBuf, nByte, iOff);
+
    if( nByte==16 ){
+
      sqlite3_randomness(16, aBuf);
+
    }else
+
    if( rc==SQLITE_OK && iOff==0 && nByte>=108 ){
+
      /* Ensure that the database has a valid header file. The only fields
+
      ** that really matter to recovery are:
+
      **
+
      **   + Database page size (16-bits at offset 16)
+
      **   + Size of db in pages (32-bits at offset 28)
+
      **   + Database encoding (32-bits at offset 56)
+
      **
+
      ** Also preserved are:
+
      **
+
      **   + first freelist page (32-bits at offset 32)
+
      **   + size of freelist (32-bits at offset 36)
+
      **
+
      ** We also try to preserve the auto-vacuum, incr-value, user-version
+
      ** and application-id fields - all 32 bit quantities at offsets 
+
      ** 52, 60, 64 and 68. All other fields are set to known good values.
+
      **
+
      ** Byte offset 105 should also contain the page-size as a 16-bit 
+
      ** integer.
+
      */
+
      const int aPreserve[] = {32, 36, 52, 60, 64, 68};
+
      u8 aHdr[108] = {
+
        0x53, 0x51, 0x4c, 0x69, 0x74, 0x65, 0x20, 0x66, 
+
        0x6f, 0x72, 0x6d, 0x61, 0x74, 0x20, 0x33, 0x00,
+
        0xFF, 0xFF, 0x01, 0x01, 0x00, 0x40, 0x20, 0x20,
+
        0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
+
        0x00, 0x00, 0x10, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
        0x00, 0x2e, 0x5b, 0x30,
+

+
        0x0D, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00
+
      };
+
      u8 *a = (u8*)aBuf;
+

+
      u32 pgsz = recoverGetU16(&a[16]);
+
      u32 nReserve = a[20];
+
      u32 enc = recoverGetU32(&a[56]);
+
      u32 dbsz = 0;
+
      i64 dbFileSize = 0;
+
      int ii;
+
      sqlite3_recover *p = recover_g.p;
+

+
      if( pgsz==0x01 ) pgsz = 65536;
+
      rc = pFd->pMethods->xFileSize(pFd, &dbFileSize);
+

+
      if( rc==SQLITE_OK && p->detected_pgsz==0 ){
+
        rc = recoverVfsDetectPagesize(p, pFd, nReserve, dbFileSize);
+
      }
+
      if( p->detected_pgsz ){
+
        pgsz = p->detected_pgsz;
+
        nReserve = p->nReserve;
+
      }
+

+
      if( pgsz ){
+
        dbsz = dbFileSize / pgsz;
+
      }
+
      if( enc!=SQLITE_UTF8 && enc!=SQLITE_UTF16BE && enc!=SQLITE_UTF16LE ){
+
        enc = SQLITE_UTF8;
+
      }
+

+
      sqlite3_free(p->pPage1Cache);
+
      p->pPage1Cache = 0;
+
      p->pPage1Disk = 0;
+

+
      p->pgsz = nByte;
+
      p->pPage1Cache = (u8*)recoverMalloc(p, nByte*2);
+
      if( p->pPage1Cache ){
+
        p->pPage1Disk = &p->pPage1Cache[nByte];
+
        memcpy(p->pPage1Disk, aBuf, nByte);
+

+
        recoverPutU32(&aHdr[28], dbsz);
+
        recoverPutU32(&aHdr[56], enc);
+
        recoverPutU16(&aHdr[105], pgsz-nReserve);
+
        if( pgsz==65536 ) pgsz = 1;
+
        recoverPutU16(&aHdr[16], pgsz);
+
        aHdr[20] = nReserve;
+
        for(ii=0; ii<sizeof(aPreserve)/sizeof(aPreserve[0]); ii++){
+
          memcpy(&aHdr[aPreserve[ii]], &a[aPreserve[ii]], 4);
+
        }
+
        memcpy(aBuf, aHdr, sizeof(aHdr));
+
        memset(&((u8*)aBuf)[sizeof(aHdr)], 0, nByte-sizeof(aHdr));
+

+
        memcpy(p->pPage1Cache, aBuf, nByte);
+
      }else{
+
        rc = p->errCode;
+
      }
+

+
    }
+
    pFd->pMethods = &recover_methods;
+
  }else{
+
    rc = pFd->pMethods->xRead(pFd, aBuf, nByte, iOff);
+
  }
+
  return rc;
+
}
+

+
/*
+
** Used to make sqlite3_io_methods wrapper methods less verbose.
+
*/
+
#define RECOVER_VFS_WRAPPER(code)                         \
+
  int rc = SQLITE_OK;                                     \
+
  if( pFd->pMethods==&recover_methods ){                  \
+
    pFd->pMethods = recover_g.pMethods;                   \
+
    rc = code;                                            \
+
    pFd->pMethods = &recover_methods;                     \
+
  }else{                                                  \
+
    rc = code;                                            \
+
  }                                                       \
+
  return rc;                                              
+

+
/*
+
** Methods of the wrapper VFS. All methods except for xRead() and xClose()
+
** simply uninstall the sqlite3_io_methods wrapper, invoke the equivalent
+
** method on the lower level VFS, then reinstall the wrapper before returning.
+
** Those that return an integer value use the RECOVER_VFS_WRAPPER macro.
+
*/
+
static int recoverVfsWrite(
+
  sqlite3_file *pFd, const void *aBuf, int nByte, i64 iOff
+
){
+
  RECOVER_VFS_WRAPPER (
+
      pFd->pMethods->xWrite(pFd, aBuf, nByte, iOff)
+
  );
+
}
+
static int recoverVfsTruncate(sqlite3_file *pFd, sqlite3_int64 size){
+
  RECOVER_VFS_WRAPPER (
+
      pFd->pMethods->xTruncate(pFd, size)
+
  );
+
}
+
static int recoverVfsSync(sqlite3_file *pFd, int flags){
+
  RECOVER_VFS_WRAPPER (
+
      pFd->pMethods->xSync(pFd, flags)
+
  );
+
}
+
static int recoverVfsFileSize(sqlite3_file *pFd, sqlite3_int64 *pSize){
+
  RECOVER_VFS_WRAPPER (
+
      pFd->pMethods->xFileSize(pFd, pSize)
+
  );
+
}
+
static int recoverVfsLock(sqlite3_file *pFd, int eLock){
+
  RECOVER_VFS_WRAPPER (
+
      pFd->pMethods->xLock(pFd, eLock)
+
  );
+
}
+
static int recoverVfsUnlock(sqlite3_file *pFd, int eLock){
+
  RECOVER_VFS_WRAPPER (
+
      pFd->pMethods->xUnlock(pFd, eLock)
+
  );
+
}
+
static int recoverVfsCheckReservedLock(sqlite3_file *pFd, int *pResOut){
+
  RECOVER_VFS_WRAPPER (
+
      pFd->pMethods->xCheckReservedLock(pFd, pResOut)
+
  );
+
}
+
static int recoverVfsFileControl(sqlite3_file *pFd, int op, void *pArg){
+
  RECOVER_VFS_WRAPPER (
+
    (pFd->pMethods ?  pFd->pMethods->xFileControl(pFd, op, pArg) : SQLITE_NOTFOUND)
+
  );
+
}
+
static int recoverVfsSectorSize(sqlite3_file *pFd){
+
  RECOVER_VFS_WRAPPER (
+
      pFd->pMethods->xSectorSize(pFd)
+
  );
+
}
+
static int recoverVfsDeviceCharacteristics(sqlite3_file *pFd){
+
  RECOVER_VFS_WRAPPER (
+
      pFd->pMethods->xDeviceCharacteristics(pFd)
+
  );
+
}
+
static int recoverVfsShmMap(
+
  sqlite3_file *pFd, int iPg, int pgsz, int bExtend, void volatile **pp
+
){
+
  RECOVER_VFS_WRAPPER (
+
      pFd->pMethods->xShmMap(pFd, iPg, pgsz, bExtend, pp)
+
  );
+
}
+
static int recoverVfsShmLock(sqlite3_file *pFd, int offset, int n, int flags){
+
  RECOVER_VFS_WRAPPER (
+
      pFd->pMethods->xShmLock(pFd, offset, n, flags)
+
  );
+
}
+
static void recoverVfsShmBarrier(sqlite3_file *pFd){
+
  if( pFd->pMethods==&recover_methods ){
+
    pFd->pMethods = recover_g.pMethods;
+
    pFd->pMethods->xShmBarrier(pFd);
+
    pFd->pMethods = &recover_methods;
+
  }else{
+
    pFd->pMethods->xShmBarrier(pFd);
+
  }
+
}
+
static int recoverVfsShmUnmap(sqlite3_file *pFd, int deleteFlag){
+
  RECOVER_VFS_WRAPPER (
+
      pFd->pMethods->xShmUnmap(pFd, deleteFlag)
+
  );
+
}
+

+
static int recoverVfsFetch(
+
  sqlite3_file *pFd, 
+
  sqlite3_int64 iOff, 
+
  int iAmt, 
+
  void **pp
+
){
+
  *pp = 0;
+
  return SQLITE_OK;
+
}
+
static int recoverVfsUnfetch(sqlite3_file *pFd, sqlite3_int64 iOff, void *p){
+
  return SQLITE_OK;
+
}
+

+
/*
+
** Install the VFS wrapper around the file-descriptor open on the input
+
** database for recover handle p. Mutex RECOVER_MUTEX_ID must be held
+
** when this function is called.
+
*/
+
static void recoverInstallWrapper(sqlite3_recover *p){
+
  sqlite3_file *pFd = 0;
+
  assert( recover_g.pMethods==0 );
+
  recoverAssertMutexHeld();
+
  sqlite3_file_control(p->dbIn, p->zDb, SQLITE_FCNTL_FILE_POINTER, (void*)&pFd);
+
  assert( pFd==0 || pFd->pMethods!=&recover_methods );
+
  if( pFd && pFd->pMethods ){
+
    int iVersion = 1 + (pFd->pMethods->iVersion>1 && pFd->pMethods->xShmMap!=0);
+
    recover_g.pMethods = pFd->pMethods;
+
    recover_g.p = p;
+
    recover_methods.iVersion = iVersion;
+
    pFd->pMethods = &recover_methods;
+
  }
+
}
+

+
/*
+
** Uninstall the VFS wrapper that was installed around the file-descriptor open
+
** on the input database for recover handle p. Mutex RECOVER_MUTEX_ID must be
+
** held when this function is called.
+
*/
+
static void recoverUninstallWrapper(sqlite3_recover *p){
+
  sqlite3_file *pFd = 0;
+
  recoverAssertMutexHeld();
+
  sqlite3_file_control(p->dbIn, p->zDb,SQLITE_FCNTL_FILE_POINTER,(void*)&pFd);
+
  if( pFd && pFd->pMethods ){
+
    pFd->pMethods = recover_g.pMethods;
+
    recover_g.pMethods = 0;
+
    recover_g.p = 0;
+
  }
+
}
+

+
/*
+
** This function does the work of a single sqlite3_recover_step() call. It
+
** is guaranteed that the handle is not in an error state when this
+
** function is called.
+
*/
+
static void recoverStep(sqlite3_recover *p){
+
  assert( p && p->errCode==SQLITE_OK );
+
  switch( p->eState ){
+
    case RECOVER_STATE_INIT:
+
      /* This is the very first call to sqlite3_recover_step() on this object.
+
      */
+
      recoverSqlCallback(p, "BEGIN");
+
      recoverSqlCallback(p, "PRAGMA writable_schema = on");
+

+
      recoverEnterMutex();
+
      recoverInstallWrapper(p);
+

+
      /* Open the output database. And register required virtual tables and 
+
      ** user functions with the new handle. */
+
      recoverOpenOutput(p);
+

+
      /* Open transactions on both the input and output databases. */
+
      recoverExec(p, p->dbIn, "PRAGMA writable_schema = on");
+
      recoverExec(p, p->dbIn, "BEGIN");
+
      if( p->errCode==SQLITE_OK ) p->bCloseTransaction = 1;
+
      recoverExec(p, p->dbIn, "SELECT 1 FROM sqlite_schema");
+
      recoverTransferSettings(p);
+
      recoverOpenRecovery(p);
+
      recoverCacheSchema(p);
+

+
      recoverUninstallWrapper(p);
+
      recoverLeaveMutex();
+

+
      recoverExec(p, p->dbOut, "BEGIN");
+

+
      recoverWriteSchema1(p);
+
      p->eState = RECOVER_STATE_WRITING;
+
      break;
+
      
+
    case RECOVER_STATE_WRITING: {
+
      if( p->w1.pTbls==0 ){
+
        recoverWriteDataInit(p);
+
      }
+
      if( SQLITE_DONE==recoverWriteDataStep(p) ){
+
        recoverWriteDataCleanup(p);
+
        if( p->zLostAndFound ){
+
          p->eState = RECOVER_STATE_LOSTANDFOUND1;
+
        }else{
+
          p->eState = RECOVER_STATE_SCHEMA2;
+
        }
+
      }
+
      break;
+
    }
+

+
    case RECOVER_STATE_LOSTANDFOUND1: {
+
      if( p->laf.pUsed==0 ){
+
        recoverLostAndFound1Init(p);
+
      }
+
      if( SQLITE_DONE==recoverLostAndFound1Step(p) ){
+
        p->eState = RECOVER_STATE_LOSTANDFOUND2;
+
      }
+
      break;
+
    }
+
    case RECOVER_STATE_LOSTANDFOUND2: {
+
      if( p->laf.pAllAndParent==0 ){
+
        recoverLostAndFound2Init(p);
+
      }
+
      if( SQLITE_DONE==recoverLostAndFound2Step(p) ){
+
        p->eState = RECOVER_STATE_LOSTANDFOUND3;
+
      }
+
      break;
+
    }
+

+
    case RECOVER_STATE_LOSTANDFOUND3: {
+
      if( p->laf.pInsert==0 ){
+
        recoverLostAndFound3Init(p);
+
      }
+
      if( SQLITE_DONE==recoverLostAndFound3Step(p) ){
+
        p->eState = RECOVER_STATE_SCHEMA2;
+
      }
+
      break;
+
    }
+

+
    case RECOVER_STATE_SCHEMA2: {
+
      int rc = SQLITE_OK;
+

+
      recoverWriteSchema2(p);
+
      p->eState = RECOVER_STATE_DONE;
+

+
      /* If no error has occurred, commit the write transaction on the output
+
      ** database. Regardless of whether or not an error has occurred, make
+
      ** an attempt to end the read transaction on the input database.  */
+
      recoverExec(p, p->dbOut, "COMMIT");
+
      rc = sqlite3_exec(p->dbIn, "END", 0, 0, 0);
+
      if( p->errCode==SQLITE_OK ) p->errCode = rc;
+

+
      recoverSqlCallback(p, "PRAGMA writable_schema = off");
+
      recoverSqlCallback(p, "COMMIT");
+
      p->eState = RECOVER_STATE_DONE;
+
      recoverFinalCleanup(p);
+
      break;
+
    };
+

+
    case RECOVER_STATE_DONE: {
+
      /* no-op */
+
      break;
+
    };
+
  }
+
}
+

+

+
/*
+
** This is a worker function that does the heavy lifting for both init
+
** functions:
+
**
+
**     sqlite3_recover_init()
+
**     sqlite3_recover_init_sql()
+
**
+
** All this function does is allocate space for the recover handle and
+
** take copies of the input parameters. All the real work is done within
+
** sqlite3_recover_run().
+
*/
+
sqlite3_recover *recoverInit(
+
  sqlite3* db, 
+
  const char *zDb, 
+
  const char *zUri,               /* Output URI for _recover_init() */
+
  int (*xSql)(void*, const char*),/* SQL callback for _recover_init_sql() */
+
  void *pSqlCtx                   /* Context arg for _recover_init_sql() */
+
){
+
  sqlite3_recover *pRet = 0;
+
  int nDb = 0;
+
  int nUri = 0;
+
  int nByte = 0;
+

+
  if( zDb==0 ){ zDb = "main"; }
+

+
  nDb = recoverStrlen(zDb);
+
  nUri = recoverStrlen(zUri);
+

+
  nByte = sizeof(sqlite3_recover) + nDb+1 + nUri+1;
+
  pRet = (sqlite3_recover*)sqlite3_malloc(nByte);
+
  if( pRet ){
+
    memset(pRet, 0, nByte);
+
    pRet->dbIn = db;
+
    pRet->zDb = (char*)&pRet[1];
+
    pRet->zUri = &pRet->zDb[nDb+1];
+
    memcpy(pRet->zDb, zDb, nDb);
+
    if( nUri>0 && zUri ) memcpy(pRet->zUri, zUri, nUri);
+
    pRet->xSql = xSql;
+
    pRet->pSqlCtx = pSqlCtx;
+
    pRet->bRecoverRowid = RECOVER_ROWID_DEFAULT;
+
  }
+

+
  return pRet;
+
}
+

+
/*
+
** Initialize a recovery handle that creates a new database containing
+
** the recovered data.
+
*/
+
sqlite3_recover *sqlite3_recover_init(
+
  sqlite3* db, 
+
  const char *zDb, 
+
  const char *zUri
+
){
+
  return recoverInit(db, zDb, zUri, 0, 0);
+
}
+

+
/*
+
** Initialize a recovery handle that returns recovered data in the
+
** form of SQL statements via a callback.
+
*/
+
sqlite3_recover *sqlite3_recover_init_sql(
+
  sqlite3* db, 
+
  const char *zDb, 
+
  int (*xSql)(void*, const char*),
+
  void *pSqlCtx
+
){
+
  return recoverInit(db, zDb, 0, xSql, pSqlCtx);
+
}
+

+
/*
+
** Return the handle error message, if any.
+
*/
+
const char *sqlite3_recover_errmsg(sqlite3_recover *p){
+
  return (p && p->errCode!=SQLITE_NOMEM) ? p->zErrMsg : "out of memory";
+
}
+

+
/*
+
** Return the handle error code.
+
*/
+
int sqlite3_recover_errcode(sqlite3_recover *p){
+
  return p ? p->errCode : SQLITE_NOMEM;
+
}
+

+
/*
+
** Configure the handle.
+
*/
+
int sqlite3_recover_config(sqlite3_recover *p, int op, void *pArg){
+
  int rc = SQLITE_OK;
+
  if( p==0 ){
+
    rc = SQLITE_NOMEM;
+
  }else if( p->eState!=RECOVER_STATE_INIT ){
+
    rc = SQLITE_MISUSE;
+
  }else{
+
    switch( op ){
+
      case 789:
+
        /* This undocumented magic configuration option is used to set the
+
        ** name of the auxiliary database that is ATTACH-ed to the database
+
        ** connection and used to hold state information during the
+
        ** recovery process.  This option is for debugging use only and
+
        ** is subject to change or removal at any time. */
+
        sqlite3_free(p->zStateDb);
+
        p->zStateDb = recoverMPrintf(p, "%s", (char*)pArg);
+
        break;
+

+
      case SQLITE_RECOVER_LOST_AND_FOUND: {
+
        const char *zArg = (const char*)pArg;
+
        sqlite3_free(p->zLostAndFound);
+
        if( zArg ){
+
          p->zLostAndFound = recoverMPrintf(p, "%s", zArg);
+
        }else{
+
          p->zLostAndFound = 0;
+
        }
+
        break;
+
      }
+

+
      case SQLITE_RECOVER_FREELIST_CORRUPT:
+
        p->bFreelistCorrupt = *(int*)pArg;
+
        break;
+

+
      case SQLITE_RECOVER_ROWIDS:
+
        p->bRecoverRowid = *(int*)pArg;
+
        break;
+

+
      case SQLITE_RECOVER_SLOWINDEXES:
+
        p->bSlowIndexes = *(int*)pArg;
+
        break;
+

+
      default:
+
        rc = SQLITE_NOTFOUND;
+
        break;
+
    }
+
  }
+

+
  return rc;
+
}
+

+
/*
+
** Do a unit of work towards the recovery job. Return SQLITE_OK if
+
** no error has occurred but database recovery is not finished, SQLITE_DONE
+
** if database recovery has been successfully completed, or an SQLite
+
** error code if an error has occurred.
+
*/
+
int sqlite3_recover_step(sqlite3_recover *p){
+
  if( p==0 ) return SQLITE_NOMEM;
+
  if( p->errCode==SQLITE_OK ) recoverStep(p);
+
  if( p->eState==RECOVER_STATE_DONE && p->errCode==SQLITE_OK ){
+
    return SQLITE_DONE;
+
  }
+
  return p->errCode;
+
}
+

+
/*
+
** Do the configured recovery operation. Return SQLITE_OK if successful, or
+
** else an SQLite error code.
+
*/
+
int sqlite3_recover_run(sqlite3_recover *p){
+
  while( SQLITE_OK==sqlite3_recover_step(p) );
+
  return sqlite3_recover_errcode(p);
+
}
+

+

+
/*
+
** Free all resources associated with the recover handle passed as the only
+
** argument. The results of using a handle with any sqlite3_recover_**
+
** API function after it has been passed to this function are undefined.
+
**
+
** A copy of the value returned by the first call made to sqlite3_recover_run()
+
** on this handle is returned, or SQLITE_OK if sqlite3_recover_run() has
+
** not been called on this handle.
+
*/
+
int sqlite3_recover_finish(sqlite3_recover *p){
+
  int rc;
+
  if( p==0 ){
+
    rc = SQLITE_NOMEM;
+
  }else{
+
    recoverFinalCleanup(p);
+
    if( p->bCloseTransaction && sqlite3_get_autocommit(p->dbIn)==0 ){
+
      rc = sqlite3_exec(p->dbIn, "END", 0, 0, 0);
+
      if( p->errCode==SQLITE_OK ) p->errCode = rc;
+
    }
+
    rc = p->errCode;
+
    sqlite3_free(p->zErrMsg);
+
    sqlite3_free(p->zStateDb);
+
    sqlite3_free(p->zLostAndFound);
+
    sqlite3_free(p->pPage1Cache);
+
    sqlite3_free(p);
+
  }
+
  return rc;
+
}
+

+
#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
+

+
/************************* End ../ext/recover/sqlite3recover.c ********************/
+
#endif
+

+
#if defined(SQLITE_ENABLE_SESSION)
+
/*
+
** State information for a single open session
+
*/
+
typedef struct OpenSession OpenSession;
+
struct OpenSession {
+
  char *zName;             /* Symbolic name for this session */
+
  int nFilter;             /* Number of xFilter rejection GLOB patterns */
+
  char **azFilter;         /* Array of xFilter rejection GLOB patterns */
+
  sqlite3_session *p;      /* The open session */
+
};
+
#endif
+

+
typedef struct ExpertInfo ExpertInfo;
+
struct ExpertInfo {
+
  sqlite3expert *pExpert;
+
  int bVerbose;
+
};
+

+
/* A single line in the EQP output */
+
typedef struct EQPGraphRow EQPGraphRow;
+
struct EQPGraphRow {
+
  int iEqpId;           /* ID for this row */
+
  int iParentId;        /* ID of the parent row */
+
  EQPGraphRow *pNext;   /* Next row in sequence */
+
  char zText[1];        /* Text to display for this row */
+
};
+

+
/* All EQP output is collected into an instance of the following */
+
typedef struct EQPGraph EQPGraph;
+
struct EQPGraph {
+
  EQPGraphRow *pRow;    /* Linked list of all rows of the EQP output */
+
  EQPGraphRow *pLast;   /* Last element of the pRow list */
+
  char zPrefix[100];    /* Graph prefix */
+
};
+

+
/* Parameters affecting columnar mode result display (defaulting together) */
+
typedef struct ColModeOpts {
+
  int iWrap;            /* In columnar modes, wrap lines reaching this limit */
+
  u8 bQuote;            /* Quote results for .mode box and table */
+
  u8 bWordWrap;         /* In columnar modes, wrap at word boundaries  */
+
} ColModeOpts;
+
#define ColModeOpts_default { 60, 0, 0 }
+
#define ColModeOpts_default_qbox { 60, 1, 0 }
+

+
/*
+
** State information about the database connection is contained in an
** instance of the following structure.
*/
typedef struct ShellState ShellState;
@@ -12250,15 +15590,16 @@ struct ShellState {
  char *zNonce;          /* Nonce for temporary safe-mode excapes */
  EQPGraph sGraph;       /* Information for the graphical EXPLAIN QUERY PLAN */
  ExpertInfo expert;     /* Valid if previous command was ".expert OPT..." */
-
#ifdef SQLITE_SHELL_WASM_MODE
+
#ifdef SQLITE_SHELL_FIDDLE
  struct {
    const char * zInput; /* Input string from wasm/JS proxy */
    const char * zPos;   /* Cursor pos into zInput */
+
    const char * zDefaultDbName; /* Default name for db file */
  } wasm;
#endif
};

-
#ifdef SQLITE_SHELL_WASM_MODE
+
#ifdef SQLITE_SHELL_FIDDLE
static ShellState shellState;
#endif

@@ -12590,10 +15931,23 @@ static void outputModePop(ShellState *p){
*/
static void output_hex_blob(FILE *out, const void *pBlob, int nBlob){
  int i;
-
  char *zBlob = (char *)pBlob;
-
  raw_printf(out,"X'");
-
  for(i=0; i<nBlob; i++){ raw_printf(out,"%02x",zBlob[i]&0xff); }
-
  raw_printf(out,"'");
+
  unsigned char *aBlob = (unsigned char*)pBlob;
+

+
  char *zStr = sqlite3_malloc(nBlob*2 + 1);
+
  shell_check_oom(zStr);
+

+
  for(i=0; i<nBlob; i++){
+
    static const char aHex[] = {
+
        '0', '1', '2', '3', '4', '5', '6', '7',
+
        '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
+
    };
+
    zStr[i*2] = aHex[ (aBlob[i] >> 4) ];
+
    zStr[i*2+1] = aHex[ (aBlob[i] & 0x0F) ];
+
  }
+
  zStr[i*2] = '\0';
+

+
  raw_printf(out,"X'%s'", zStr);
+
  sqlite3_free(zStr);
}

/*
@@ -12753,9 +16107,9 @@ 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){
+
static void output_json_string(FILE *out, const char *z, i64 n){
  unsigned int c;
-
  if( n<0 ) n = (int)strlen(z);
+
  if( n<0 ) n = strlen(z);
  fputc('"', out);
  while( n-- ){
    c = *(z++);
@@ -12926,7 +16280,7 @@ static int safeModeAuth(
  UNUSED_PARAMETER(zA4);
  switch( op ){
    case SQLITE_ATTACH: {
-
#ifndef SQLITE_SHELL_WASM_MODE
+
#ifndef SQLITE_SHELL_FIDDLE
      /* In WASM builds the filesystem is a virtual sandbox, so
      ** there's no harm in using ATTACH. */
      failIfSafeMode(p, "cannot run ATTACH in safe mode");
@@ -12999,15 +16353,37 @@ static int shellAuth(
**
** This routine converts some CREATE TABLE statements for shadow tables
** in FTS3/4/5 into CREATE TABLE IF NOT EXISTS statements.
+
**
+
** If the schema statement in z[] contains a start-of-comment and if
+
** sqlite3_complete() returns false, try to terminate the comment before
+
** printing the result.  https://sqlite.org/forum/forumpost/d7be961c5c
*/
static void printSchemaLine(FILE *out, const char *z, const char *zTail){
+
  char *zToFree = 0;
  if( z==0 ) return;
  if( zTail==0 ) return;
+
  if( zTail[0]==';' && (strstr(z, "/*")!=0 || strstr(z,"--")!=0) ){
+
    const char *zOrig = z;
+
    static const char *azTerm[] = { "", "*/", "\n" };
+
    int i;
+
    for(i=0; i<ArraySize(azTerm); i++){
+
      char *zNew = sqlite3_mprintf("%s%s;", zOrig, azTerm[i]);
+
      if( sqlite3_complete(zNew) ){
+
        size_t n = strlen(zNew);
+
        zNew[n-1] = 0;
+
        zToFree = zNew;
+
        z = zNew;
+
        break;
+
      }
+
      sqlite3_free(zNew);
+
    }
+
  }
  if( sqlite3_strglob("CREATE TABLE ['\"]*", z)==0 ){
    utf8_printf(out, "CREATE TABLE IF NOT EXISTS %s%s", z+13, zTail);
  }else{
    utf8_printf(out, "%s%s", z, zTail);
  }
+
  sqlite3_free(zToFree);
}
static void printSchemaLineN(FILE *out, char *z, int n, const char *zTail){
  char c = z[n];
@@ -13036,7 +16412,9 @@ static int wsToEol(const char *z){
*/
static void eqp_append(ShellState *p, int iEqpId, int p2, const char *zText){
  EQPGraphRow *pNew;
-
  int nText = strlen30(zText);
+
  i64 nText;
+
  if( zText==0 ) return;
+
  nText = strlen(zText);
  if( p->autoEQPtest ){
    utf8_printf(p->out, "%d,%d,%s\n", iEqpId, p2, zText);
  }
@@ -13081,14 +16459,14 @@ static EQPGraphRow *eqp_next_row(ShellState *p, int iEqpId, EQPGraphRow *pOld){
*/
static void eqp_render_level(ShellState *p, int iEqpId){
  EQPGraphRow *pRow, *pNext;
-
  int n = strlen30(p->sGraph.zPrefix);
+
  i64 n = strlen(p->sGraph.zPrefix);
  char *z;
  for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){
    pNext = eqp_next_row(p, iEqpId, pRow);
    z = pRow->zText;
    utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix,
                pNext ? "|--" : "`--", z);
-
    if( n<(int)sizeof(p->sGraph.zPrefix)-7 ){
+
    if( n<(i64)sizeof(p->sGraph.zPrefix)-7 ){
      memcpy(&p->sGraph.zPrefix[n], pNext ? "|  " : "   ", 4);
      eqp_render_level(p, pRow->iEqpId);
      p->sGraph.zPrefix[n] = 0;
@@ -13688,6 +17066,7 @@ static char *shell_error_context(const char *zSql, sqlite3 *db){
    while( (zSql[len]&0xc0)==0x80 ) len--;
  }
  zCode = sqlite3_mprintf("%.*s", len, zSql);
+
  shell_check_oom(zCode);
  for(i=0; zCode[i]; i++){ if( IsSpace(zSql[i]) ) zCode[i] = ' '; }
  if( iOffset<25 ){
    zMsg = sqlite3_mprintf("\n  %z\n  %*s^--- error here", zCode, iOffset, "");
@@ -13804,7 +17183,7 @@ static void displayLinuxIoStats(FILE *out){
    int i;
    for(i=0; i<ArraySize(aTrans); i++){
      int n = strlen30(aTrans[i].zPattern);
-
      if( strncmp(aTrans[i].zPattern, z, n)==0 ){
+
      if( cli_strncmp(aTrans[i].zPattern, z, n)==0 ){
        utf8_printf(out, "%-36s %s", aTrans[i].zDesc, &z[n]);
        break;
      }
@@ -14043,7 +17422,7 @@ static void display_scanstats(
static int str_in_array(const char *zStr, const char **azArray){
  int i;
  for(i=0; azArray[i]; i++){
-
    if( 0==strcmp(zStr, azArray[i]) ) return 1;
+
    if( 0==cli_strcmp(zStr, azArray[i]) ) return 1;
  }
  return 0;
}
@@ -14118,7 +17497,7 @@ static void explain_data_prepare(ShellState *p, sqlite3_stmt *pSql){
           "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment" };
        int jj;
        for(jj=0; jj<ArraySize(explainCols); jj++){
-
          if( strcmp(sqlite3_column_name(pSql,jj),explainCols[jj])!=0 ){
+
          if( cli_strcmp(sqlite3_column_name(pSql,jj),explainCols[jj])!=0 ){
            p->cMode = p->mode;
            sqlite3_reset(pSql);
            return;
@@ -14842,10 +18221,10 @@ static int expertDotCommand(
    int n;
    if( z[0]=='-' && z[1]=='-' ) z++;
    n = strlen30(z);
-
    if( n>=2 && 0==strncmp(z, "-verbose", n) ){
+
    if( n>=2 && 0==cli_strncmp(z, "-verbose", n) ){
      pState->expert.bVerbose = 1;
    }
-
    else if( n>=2 && 0==strncmp(z, "-sample", n) ){
+
    else if( n>=2 && 0==cli_strncmp(z, "-sample", n) ){
      if( i==(nArg-1) ){
        raw_printf(stderr, "option requires an argument: %s\n", z);
        rc = SQLITE_ERROR;
@@ -15193,18 +18572,20 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
  zTable = azArg[0];
  zType = azArg[1];
  zSql = azArg[2];
+
  if( zTable==0 ) return 0;
+
  if( zType==0 ) return 0;
  dataOnly = (p->shellFlgs & SHFLG_DumpDataOnly)!=0;
  noSys    = (p->shellFlgs & SHFLG_DumpNoSys)!=0;

-
  if( strcmp(zTable, "sqlite_sequence")==0 && !noSys ){
+
  if( cli_strcmp(zTable, "sqlite_sequence")==0 && !noSys ){
    if( !dataOnly ) raw_printf(p->out, "DELETE FROM sqlite_sequence;\n");
  }else if( sqlite3_strglob("sqlite_stat?", zTable)==0 && !noSys ){
    if( !dataOnly ) raw_printf(p->out, "ANALYZE sqlite_schema;\n");
-
  }else if( strncmp(zTable, "sqlite_", 7)==0 ){
+
  }else if( cli_strncmp(zTable, "sqlite_", 7)==0 ){
    return 0;
  }else if( dataOnly ){
    /* no-op */
-
  }else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
+
  }else if( cli_strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
    char *zIns;
    if( !p->writableSchema ){
      raw_printf(p->out, "PRAGMA writable_schema=ON;\n");
@@ -15222,7 +18603,7 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
    printSchemaLine(p->out, zSql, ";\n");
  }

-
  if( strcmp(zType, "table")==0 ){
+
  if( cli_strcmp(zType, "table")==0 ){
    ShellText sSelect;
    ShellText sTable;
    char **azCol;
@@ -15340,7 +18721,7 @@ static int run_schema_dump_query(
*/
static const char *(azHelp[]) = {
#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE) \
-
  && !defined(SQLITE_SHELL_WASM_MODE)
+
  && !defined(SQLITE_SHELL_FIDDLE)
  ".archive ...             Manage SQL archives",
  "   Each command must have exactly one of the following options:",
  "     -c, --create               Create a new archive",
@@ -15366,7 +18747,7 @@ static const char *(azHelp[]) = {
#ifndef SQLITE_OMIT_AUTHORIZATION
  ".auth ON|OFF             Show authorizer callbacks",
#endif
-
#ifndef SQLITE_SHELL_WASM_MODE
+
#ifndef SQLITE_SHELL_FIDDLE
  ".backup ?DB? FILE        Backup DB (default \"main\") to FILE",
  "   Options:",
  "       --append            Use the appendvfs",
@@ -15374,18 +18755,18 @@ static const char *(azHelp[]) = {
#endif
  ".bail on|off             Stop after hitting an error.  Default OFF",
  ".binary on|off           Turn binary output on or off.  Default OFF",
-
#ifndef SQLITE_SHELL_WASM_MODE
+
#ifndef SQLITE_SHELL_FIDDLE
  ".cd DIRECTORY            Change the working directory to DIRECTORY",
#endif
  ".changes on|off          Show number of rows changed by SQL",
-
#ifndef SQLITE_SHELL_WASM_MODE
+
#ifndef SQLITE_SHELL_FIDDLE
  ".check GLOB              Fail if output since .testcase does not match",
  ".clone NEWDB             Clone data into NEWDB from the existing database",
#endif
  ".connection [close] [#]  Open or close an auxiliary database connection",
  ".databases               List names and files of attached databases",
  ".dbconfig ?op? ?val?     List or change sqlite3_db_config() options",
-
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
+
#if SQLITE_SHELL_HAVE_RECOVER
  ".dbinfo ?DB?             Show status information about the database",
#endif
  ".dump ?OBJECTS?          Render database content as SQL",
@@ -15404,11 +18785,11 @@ static const char *(azHelp[]) = {
  "      trace                 Like \"full\" but enable \"PRAGMA vdbe_trace\"",
#endif
  "      trigger               Like \"full\" but also show trigger bytecode",
-
#ifndef SQLITE_SHELL_WASM_MODE
+
#ifndef SQLITE_SHELL_FIDDLE
  ".excel                   Display the output of next command in spreadsheet",
  "   --bom                   Put a UTF8 byte-order mark on intermediate file",
#endif
-
#ifndef SQLITE_SHELL_WASM_MODE
+
#ifndef SQLITE_SHELL_FIDDLE
  ".exit ?CODE?             Exit this program with return-code CODE",
#endif
  ".expert                  EXPERIMENTAL. Suggest indexes for queries",
@@ -15419,7 +18800,7 @@ static const char *(azHelp[]) = {
  ".fullschema ?--indent?   Show schema and the content of sqlite_stat tables",
  ".headers on|off          Turn display of headers on or off",
  ".help ?-all? ?PATTERN?   Show help text for PATTERN",
-
#ifndef SQLITE_SHELL_WASM_MODE
+
#ifndef SQLITE_SHELL_FIDDLE
  ".import FILE TABLE       Import data from FILE into TABLE",
  "   Options:",
  "     --ascii               Use \\037 and \\036 as column and row separators",
@@ -15448,10 +18829,10 @@ static const char *(azHelp[]) = {
  ".lint OPTIONS            Report potential schema issues.",
  "     Options:",
  "        fkey-indexes     Find missing foreign key indexes",
-
#if !defined(SQLITE_OMIT_LOAD_EXTENSION) && !defined(SQLITE_SHELL_WASM_MODE)
+
#if !defined(SQLITE_OMIT_LOAD_EXTENSION) && !defined(SQLITE_SHELL_FIDDLE)
  ".load FILE ?ENTRY?       Load an extension library",
#endif
-
#ifndef SQLITE_SHELL_WASM_MODE
+
#ifndef SQLITE_SHELL_FIDDLE
  ".log FILE|off            Turn logging on or off.  FILE can be stderr/stdout",
#endif
  ".mode MODE ?OPTIONS?     Set output mode",
@@ -15466,7 +18847,7 @@ static const char *(azHelp[]) = {
  "     line        One value per line",
  "     list        Values delimited by \"|\"",
  "     markdown    Markdown table format",
-
  "     qbox        Shorthand for \"box --width 60 --quote\"",
+
  "     qbox        Shorthand for \"box --wrap 60 --quote\"",
  "     quote       Escape answers as for SQL",
  "     table       ASCII-art table",
  "     tabs        Tab-separated values",
@@ -15478,11 +18859,11 @@ static const char *(azHelp[]) = {
  "     --quote        Quote output text as SQL literals",
  "     --noquote      Do not quote output text",
  "     TABLE          The name of SQL table used for \"insert\" mode",
-
#ifndef SQLITE_SHELL_WASM_MODE
+
#ifndef SQLITE_SHELL_FIDDLE
  ".nonce STRING            Suspend safe mode for one command if nonce matches",
#endif
  ".nullvalue STRING        Use STRING in place of NULL values",
-
#ifndef SQLITE_SHELL_WASM_MODE
+
#ifndef SQLITE_SHELL_FIDDLE
  ".once ?OPTIONS? ?FILE?   Output for the next SQL command only to FILE",
  "     If FILE begins with '|' then open as a pipe",
  "       --bom  Put a UTF8 byte-order mark at the beginning",
@@ -15504,7 +18885,7 @@ static const char *(azHelp[]) = {
  "        --nofollow      Do not follow symbolic links",
  "        --readonly      Open FILE readonly",
  "        --zip           FILE is a ZIP archive",
-
#ifndef SQLITE_SHELL_WASM_MODE
+
#ifndef SQLITE_SHELL_FIDDLE
  ".output ?FILE?           Send output to FILE or stdout if FILE is omitted",
  "   If FILE begins with '|' then open it as a pipe.",
  "   Options:",
@@ -15528,20 +18909,19 @@ static const char *(azHelp[]) = {
  "   --reset                   Reset the count for each input and interrupt",
#endif
  ".prompt MAIN CONTINUE    Replace the standard prompts",
-
#ifndef SQLITE_SHELL_WASM_MODE
+
#ifndef SQLITE_SHELL_FIDDLE
  ".quit                    Exit this program",
  ".read FILE               Read input from FILE or command output",
  "    If FILE begins with \"|\", it is a command that generates the input.",
#endif
-
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
+
#if SQLITE_SHELL_HAVE_RECOVER
  ".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",
+
  "   --ignore-freelist        Ignore pages that appear to be on db freelist",
  "   --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
-
#ifndef SQLITE_SHELL_WASM_MODE
+
#ifndef SQLITE_SHELL_FIDDLE
  ".restore ?DB? FILE       Restore content of DB (default \"main\") from FILE",
  ".save ?OPTIONS? FILE     Write database to FILE (an alias for .backup ...)",
#endif
@@ -15578,7 +18958,7 @@ static const char *(azHelp[]) = {
  "      --sha3-384            Use the sha3-384 algorithm",
  "      --sha3-512            Use the sha3-512 algorithm",
  "    Any other argument is a LIKE pattern for tables to hash",
-
#if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_WASM_MODE)
+
#if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE)
  ".shell CMD ARGS...       Run CMD ARGS... in a system shell",
#endif
  ".show                    Show the current values for various settings",
@@ -15587,11 +18967,11 @@ static const char *(azHelp[]) = {
  "   on                       Turn on automatic stat display",
  "   stmt                     Show statement stats",
  "   vmstep                   Show the virtual machine step count only",
-
#if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_WASM_MODE)
+
#if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE)
  ".system CMD ARGS...      Run CMD ARGS... in a system shell",
#endif
  ".tables ?TABLE?          List names of tables matching LIKE pattern TABLE",
-
#ifndef SQLITE_SHELL_WASM_MODE
+
#ifndef SQLITE_SHELL_FIDDLE
  ".testcase NAME           Begin redirecting output to 'testcase-out.txt'",
#endif
  ".testctrl CMD ...        Run various sqlite3_test_control() operations",
@@ -15641,9 +19021,9 @@ static int showHelp(FILE *out, const char *zPattern){
  char *zPat;
  if( zPattern==0
   || zPattern[0]=='0'
-
   || strcmp(zPattern,"-a")==0
-
   || strcmp(zPattern,"-all")==0
-
   || strcmp(zPattern,"--all")==0
+
   || cli_strcmp(zPattern,"-a")==0
+
   || cli_strcmp(zPattern,"-all")==0
+
   || cli_strcmp(zPattern,"--all")==0
  ){
    /* Show all commands, but only one line per command */
    if( zPattern==0 ) zPattern = "";
@@ -15880,7 +19260,7 @@ static unsigned char *readHexDb(ShellState *p, int *pnData){
      iOffset = k;
      continue;
    }
-
    if( strncmp(zLine, "| end ", 6)==0 ){
+
    if( cli_strncmp(zLine, "| end ", 6)==0 ){
      break;
    }
    rc = sscanf(zLine,"| %d: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
@@ -15908,7 +19288,7 @@ readHexDb_error:
  }else{
    while( fgets(zLine, sizeof(zLine), p->in)!=0 ){
      nLine++;
-
      if(strncmp(zLine, "| end ", 6)==0 ) break;
+
      if(cli_strncmp(zLine, "| end ", 6)==0 ) break;
    }
    p->lineno = nLine;
  }
@@ -16000,28 +19380,28 @@ static void shellEscapeCrnl(
  const char *zText = (const char*)sqlite3_value_text(argv[0]);
  UNUSED_PARAMETER(argc);
  if( zText && zText[0]=='\'' ){
-
    int nText = sqlite3_value_bytes(argv[0]);
-
    int i;
+
    i64 nText = sqlite3_value_bytes(argv[0]);
+
    i64 i;
    char zBuf1[20];
    char zBuf2[20];
    const char *zNL = 0;
    const char *zCR = 0;
-
    int nCR = 0;
-
    int nNL = 0;
+
    i64 nCR = 0;
+
    i64 nNL = 0;

    for(i=0; zText[i]; i++){
      if( zNL==0 && zText[i]=='\n' ){
        zNL = unused_string(zText, "\\n", "\\012", zBuf1);
-
        nNL = (int)strlen(zNL);
+
        nNL = strlen(zNL);
      }
      if( zCR==0 && zText[i]=='\r' ){
        zCR = unused_string(zText, "\\r", "\\015", zBuf2);
-
        nCR = (int)strlen(zCR);
+
        nCR = strlen(zCR);
      }
    }

    if( zNL || zCR ){
-
      int iOut = 0;
+
      i64 iOut = 0;
      i64 nMax = (nNL > nCR) ? nNL : nCR;
      i64 nAlloc = nMax * nText + (nMax+64)*2;
      char *zOut = (char*)sqlite3_malloc64(nAlloc);
@@ -16144,11 +19524,11 @@ static void open_db(ShellState *p, int openFlags){
    sqlite3_regexp_init(p->db, 0, 0);
    sqlite3_ieee_init(p->db, 0, 0);
    sqlite3_series_init(p->db, 0, 0);
-
#ifndef SQLITE_SHELL_WASM_MODE
+
#ifndef SQLITE_SHELL_FIDDLE
    sqlite3_fileio_init(p->db, 0, 0);
    sqlite3_completion_init(p->db, 0, 0);
#endif
-
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
+
#if SQLITE_SHELL_HAVE_RECOVER
    sqlite3_dbdata_init(p->db, 0, 0);
#endif
#ifdef SQLITE_HAVE_ZLIB
@@ -16262,8 +19642,8 @@ static char **readline_completion(const char *zText, int iStart, int iEnd){
** Linenoise completion callback
*/
static void linenoise_completion(const char *zLine, linenoiseCompletions *lc){
-
  int nLine = strlen30(zLine);
-
  int i, iStart;
+
  i64 nLine = strlen(zLine);
+
  i64 i, iStart;
  sqlite3_stmt *pStmt = 0;
  char *zSql;
  char zBuf[1000];
@@ -16401,11 +19781,11 @@ static void output_file_close(FILE *f){
*/
static FILE *output_file_open(const char *zFile, int bTextMode){
  FILE *f;
-
  if( strcmp(zFile,"stdout")==0 ){
+
  if( cli_strcmp(zFile,"stdout")==0 ){
    f = stdout;
-
  }else if( strcmp(zFile, "stderr")==0 ){
+
  }else if( cli_strcmp(zFile, "stderr")==0 ){
    f = stderr;
-
  }else if( strcmp(zFile, "off")==0 ){
+
  }else if( cli_strcmp(zFile, "off")==0 ){
    f = 0;
  }else{
    f = fopen(zFile, bTextMode ? "w" : "wb");
@@ -16429,7 +19809,7 @@ static int sql_trace_callback(
  ShellState *p = (ShellState*)pArg;
  sqlite3_stmt *pStmt;
  const char *zSql;
-
  int nSql;
+
  i64 nSql;
  if( p->traceOut==0 ) return 0;
  if( mType==SQLITE_TRACE_CLOSE ){
    utf8_printf(p->traceOut, "-- closing database connection\n");
@@ -16457,17 +19837,18 @@ static int sql_trace_callback(
    }
  }
  if( zSql==0 ) return 0;
-
  nSql = strlen30(zSql);
+
  nSql = strlen(zSql);
+
  if( nSql>1000000000 ) nSql = 1000000000;
  while( nSql>0 && zSql[nSql-1]==';' ){ nSql--; }
  switch( mType ){
    case SQLITE_TRACE_ROW:
    case SQLITE_TRACE_STMT: {
-
      utf8_printf(p->traceOut, "%.*s;\n", nSql, zSql);
+
      utf8_printf(p->traceOut, "%.*s;\n", (int)nSql, zSql);
      break;
    }
    case SQLITE_TRACE_PROFILE: {
      sqlite3_int64 nNanosec = *(sqlite3_int64*)pX;
-
      utf8_printf(p->traceOut, "%.*s; -- %lld ns\n", nSql, zSql, nNanosec);
+
      utf8_printf(p->traceOut, "%.*s; -- %lld ns\n", (int)nSql, zSql, nNanosec);
      break;
    }
  }
@@ -17016,7 +20397,7 @@ static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
  }
  if( zDb==0 ){
    zSchemaTab = sqlite3_mprintf("main.sqlite_schema");
-
  }else if( strcmp(zDb,"temp")==0 ){
+
  }else if( cli_strcmp(zDb,"temp")==0 ){
    zSchemaTab = sqlite3_mprintf("%s", "sqlite_temp_schema");
  }else{
    zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_schema", zDb);
@@ -17032,8 +20413,7 @@ static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
  utf8_printf(p->out, "%-20s %u\n", "data version", iDataVersion);
  return 0;
}
-
#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE)
-
          && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
+
#endif /* SQLITE_SHELL_HAVE_RECOVER */

/*
** Print the current sqlite3_errmsg() value to stderr and return 1.
@@ -17150,7 +20530,7 @@ static int optionMatch(const char *zStr, const char *zOpt){
  if( zStr[0]!='-' ) return 0;
  zStr++;
  if( zStr[0]=='-' ) zStr++;
-
  return strcmp(zStr, zOpt)==0;
+
  return cli_strcmp(zStr, zOpt)==0;
}

/*
@@ -18306,364 +21686,16 @@ end_ar_command:
*******************************************************************************/
#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */

-
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
-
/*
-
** If (*pRc) is not SQLITE_OK when this function is called, it is a no-op.
-
** Otherwise, the SQL statement or statements in zSql are executed using
-
** database connection db and the error code written to *pRc before
-
** this function returns.
-
*/
-
static void shellExec(sqlite3 *db, int *pRc, const char *zSql){
-
  int rc = *pRc;
-
  if( rc==SQLITE_OK ){
-
    char *zErr = 0;
-
    rc = sqlite3_exec(db, zSql, 0, 0, &zErr);
-
    if( rc!=SQLITE_OK ){
-
      raw_printf(stderr, "SQL error: %s\n", zErr);
-
    }
-
    sqlite3_free(zErr);
-
    *pRc = rc;
-
  }
-
}
-

-
/*
-
** Like shellExec(), except that zFmt is a printf() style format string.
-
*/
-
static void shellExecPrintf(sqlite3 *db, int *pRc, const char *zFmt, ...){
-
  char *z = 0;
-
  if( *pRc==SQLITE_OK ){
-
    va_list ap;
-
    va_start(ap, zFmt);
-
    z = sqlite3_vmprintf(zFmt, ap);
-
    va_end(ap);
-
    if( z==0 ){
-
      *pRc = SQLITE_NOMEM;
-
    }else{
-
      shellExec(db, pRc, z);
-
    }
-
    sqlite3_free(z);
-
  }
-
}
-

-
/*
-
** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
-
** Otherwise, an attempt is made to allocate, zero and return a pointer
-
** to a buffer nByte bytes in size. If an OOM error occurs, *pRc is set
-
** to SQLITE_NOMEM and NULL returned.
-
*/
-
static void *shellMalloc(int *pRc, sqlite3_int64 nByte){
-
  void *pRet = 0;
-
  if( *pRc==SQLITE_OK ){
-
    pRet = sqlite3_malloc64(nByte);
-
    if( pRet==0 ){
-
      *pRc = SQLITE_NOMEM;
-
    }else{
-
      memset(pRet, 0, nByte);
-
    }
-
  }
-
  return pRet;
-
}
-

-
/*
-
** If *pRc is not SQLITE_OK when this function is called, it is a no-op.
-
** Otherwise, zFmt is treated as a printf() style string. The result of
-
** formatting it along with any trailing arguments is written into a 
-
** buffer obtained from sqlite3_malloc(), and pointer to which is returned.
-
** It is the responsibility of the caller to eventually free this buffer
-
** using a call to sqlite3_free().
-
** 
-
** If an OOM error occurs, (*pRc) is set to SQLITE_NOMEM and a NULL 
-
** pointer returned.
-
*/
-
static char *shellMPrintf(int *pRc, const char *zFmt, ...){
-
  char *z = 0;
-
  if( *pRc==SQLITE_OK ){
-
    va_list ap;
-
    va_start(ap, zFmt);
-
    z = sqlite3_vmprintf(zFmt, ap);
-
    va_end(ap);
-
    if( z==0 ){
-
      *pRc = SQLITE_NOMEM;
-
    }
-
  }
-
  return z;
-
}
-

-

-
/*
-
** When running the ".recover" command, each output table, and the special
-
** orphaned row table if it is required, is represented by an instance
-
** of the following struct.
-
*/
-
typedef struct RecoverTable RecoverTable;
-
struct RecoverTable {
-
  char *zQuoted;                  /* Quoted version of table name */
-
  int nCol;                       /* Number of columns in table */
-
  char **azlCol;                  /* Array of column lists */
-
  int iPk;                        /* Index of IPK column */
-
};
-

-
/*
-
** Free a RecoverTable object allocated by recoverFindTable() or
-
** recoverOrphanTable().
-
*/
-
static void recoverFreeTable(RecoverTable *pTab){
-
  if( pTab ){
-
    sqlite3_free(pTab->zQuoted);
-
    if( pTab->azlCol ){
-
      int i;
-
      for(i=0; i<=pTab->nCol; i++){
-
        sqlite3_free(pTab->azlCol[i]);
-
      }
-
      sqlite3_free(pTab->azlCol);
-
    }
-
    sqlite3_free(pTab);
-
  }
-
}
-

-
/*
-
** This function is a no-op if (*pRc) is not SQLITE_OK when it is called.
-
** Otherwise, it allocates and returns a RecoverTable object based on the
-
** final four arguments passed to this function. It is the responsibility
-
** of the caller to eventually free the returned object using
-
** recoverFreeTable().
-
*/
-
static RecoverTable *recoverNewTable(
-
  int *pRc,                       /* IN/OUT: Error code */
-
  const char *zName,              /* Name of table */
-
  const char *zSql,               /* CREATE TABLE statement */
-
  int bIntkey, 
-
  int nCol
-
){
-
  sqlite3 *dbtmp = 0;             /* sqlite3 handle for testing CREATE TABLE */
-
  int rc = *pRc;
-
  RecoverTable *pTab = 0;
-

-
  pTab = (RecoverTable*)shellMalloc(&rc, sizeof(RecoverTable));
-
  if( rc==SQLITE_OK ){
-
    int nSqlCol = 0;
-
    int bSqlIntkey = 0;
-
    sqlite3_stmt *pStmt = 0;
-
    
-
    rc = sqlite3_open("", &dbtmp);
-
    if( rc==SQLITE_OK ){
-
      sqlite3_create_function(dbtmp, "shell_idquote", 1, SQLITE_UTF8, 0,
-
                              shellIdQuote, 0, 0);
-
    }
-
    if( rc==SQLITE_OK ){
-
      rc = sqlite3_exec(dbtmp, "PRAGMA writable_schema = on", 0, 0, 0);
-
    }
-
    if( rc==SQLITE_OK ){
-
      rc = sqlite3_exec(dbtmp, zSql, 0, 0, 0);
-
      if( rc==SQLITE_ERROR ){
-
        rc = SQLITE_OK;
-
        goto finished;
-
      }
-
    }
-
    shellPreparePrintf(dbtmp, &rc, &pStmt, 
-
        "SELECT count(*) FROM pragma_table_info(%Q)", zName
-
    );
-
    if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
-
      nSqlCol = sqlite3_column_int(pStmt, 0);
-
    }
-
    shellFinalize(&rc, pStmt);
-

-
    if( rc!=SQLITE_OK || nSqlCol<nCol ){
-
      goto finished;
-
    }
-

-
    shellPreparePrintf(dbtmp, &rc, &pStmt, 
-
      "SELECT ("
-
      "  SELECT substr(data,1,1)==X'0D' FROM sqlite_dbpage WHERE pgno=rootpage"
-
      ") FROM sqlite_schema WHERE name = %Q", zName
-
    );
-
    if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
-
      bSqlIntkey = sqlite3_column_int(pStmt, 0);
-
    }
-
    shellFinalize(&rc, pStmt);
-

-
    if( bIntkey==bSqlIntkey ){
-
      int i;
-
      const char *zPk = "_rowid_";
-
      sqlite3_stmt *pPkFinder = 0;
-

-
      /* If this is an intkey table and there is an INTEGER PRIMARY KEY,
-
      ** set zPk to the name of the PK column, and pTab->iPk to the index
-
      ** of the column, where columns are 0-numbered from left to right.
-
      ** Or, if this is a WITHOUT ROWID table or if there is no IPK column,
-
      ** leave zPk as "_rowid_" and pTab->iPk at -2.  */
-
      pTab->iPk = -2;
-
      if( bIntkey ){
-
        shellPreparePrintf(dbtmp, &rc, &pPkFinder, 
-
          "SELECT cid, name FROM pragma_table_info(%Q) "
-
          "  WHERE pk=1 AND type='integer' COLLATE nocase"
-
          "  AND NOT EXISTS (SELECT cid FROM pragma_table_info(%Q) WHERE pk=2)"
-
          , zName, zName
-
        );
-
        if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPkFinder) ){
-
          pTab->iPk = sqlite3_column_int(pPkFinder, 0);
-
          zPk = (const char*)sqlite3_column_text(pPkFinder, 1);
-
          if( zPk==0 ){ zPk = "_";  /* Defensive.  Should never happen */ }
-
        }
-
      }
-

-
      pTab->zQuoted = shellMPrintf(&rc, "\"%w\"", zName);
-
      pTab->azlCol = (char**)shellMalloc(&rc, sizeof(char*) * (nSqlCol+1));
-
      pTab->nCol = nSqlCol;
-

-
      if( bIntkey ){
-
        pTab->azlCol[0] = shellMPrintf(&rc, "\"%w\"", zPk);
-
      }else{
-
        pTab->azlCol[0] = shellMPrintf(&rc, "");
-
      }
-
      i = 1;
-
      shellPreparePrintf(dbtmp, &rc, &pStmt, 
-
          "SELECT %Q || group_concat(shell_idquote(name), ', ') "
-
          "  FILTER (WHERE cid!=%d) OVER (ORDER BY %s cid) "
-
          "FROM pragma_table_info(%Q)", 
-
          bIntkey ? ", " : "", pTab->iPk, 
-
          bIntkey ? "" : "(CASE WHEN pk=0 THEN 1000000 ELSE pk END), ",
-
          zName
-
      );
-
      while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
-
        const char *zText = (const char*)sqlite3_column_text(pStmt, 0);
-
        pTab->azlCol[i] = shellMPrintf(&rc, "%s%s", pTab->azlCol[0], zText);
-
        i++;
-
      }
-
      shellFinalize(&rc, pStmt);
-

-
      shellFinalize(&rc, pPkFinder);
-
    }
-
  }
-

-
 finished:
-
  sqlite3_close(dbtmp);
-
  *pRc = rc;
-
  if( rc!=SQLITE_OK || (pTab && pTab->zQuoted==0) ){
-
    recoverFreeTable(pTab);
-
    pTab = 0;
-
  }
-
  return pTab;
-
}
-

-
/*
-
** This function is called to search the schema recovered from the
-
** sqlite_schema table of the (possibly) corrupt database as part
-
** of a ".recover" command. Specifically, for a table with root page
-
** iRoot and at least nCol columns. Additionally, if bIntkey is 0, the
-
** table must be a WITHOUT ROWID table, or if non-zero, not one of
-
** those.
-
**
-
** If a table is found, a (RecoverTable*) object is returned. Or, if
-
** no such table is found, but bIntkey is false and iRoot is the 
-
** root page of an index in the recovered schema, then (*pbNoop) is
-
** set to true and NULL returned. Or, if there is no such table or
-
** index, NULL is returned and (*pbNoop) set to 0, indicating that
-
** the caller should write data to the orphans table.
-
*/
-
static RecoverTable *recoverFindTable(
-
  ShellState *pState,             /* Shell state object */
-
  int *pRc,                       /* IN/OUT: Error code */
-
  int iRoot,                      /* Root page of table */
-
  int bIntkey,                    /* True for an intkey table */
-
  int nCol,                       /* Number of columns in table */
-
  int *pbNoop                     /* OUT: True if iRoot is root of index */
-
){
-
  sqlite3_stmt *pStmt = 0;
-
  RecoverTable *pRet = 0;
-
  int bNoop = 0;
-
  const char *zSql = 0;
-
  const char *zName = 0;
-

-
  /* Search the recovered schema for an object with root page iRoot. */
-
  shellPreparePrintf(pState->db, pRc, &pStmt,
-
      "SELECT type, name, sql FROM recovery.schema WHERE rootpage=%d", iRoot
-
  );
-
  while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
-
    const char *zType = (const char*)sqlite3_column_text(pStmt, 0);
-
    if( bIntkey==0 && sqlite3_stricmp(zType, "index")==0 ){
-
      bNoop = 1;
-
      break;
-
    }
-
    if( sqlite3_stricmp(zType, "table")==0 ){
-
      zName = (const char*)sqlite3_column_text(pStmt, 1);
-
      zSql = (const char*)sqlite3_column_text(pStmt, 2);
-
      if( zName!=0 && zSql!=0 ){
-
        pRet = recoverNewTable(pRc, zName, zSql, bIntkey, nCol);
-
        break;
-
      }
-
    }
-
  }
-

-
  shellFinalize(pRc, pStmt);
-
  *pbNoop = bNoop;
-
  return pRet;
-
}
+
#if SQLITE_SHELL_HAVE_RECOVER

/*
-
** Return a RecoverTable object representing the orphans table.
+
** This function is used as a callback by the recover extension. Simply
+
** print the supplied SQL statement to stdout.
*/
-
static RecoverTable *recoverOrphanTable(
-
  ShellState *pState,             /* Shell state object */
-
  int *pRc,                       /* IN/OUT: Error code */
-
  const char *zLostAndFound,      /* Base name for orphans table */
-
  int nCol                        /* Number of user data columns */
-
){
-
  RecoverTable *pTab = 0;
-
  if( nCol>=0 && *pRc==SQLITE_OK ){
-
    int i;
-

-
    /* This block determines the name of the orphan table. The prefered
-
    ** name is zLostAndFound. But if that clashes with another name
-
    ** in the recovered schema, try zLostAndFound_0, zLostAndFound_1
-
    ** and so on until a non-clashing name is found.  */
-
    int iTab = 0;
-
    char *zTab = shellMPrintf(pRc, "%s", zLostAndFound);
-
    sqlite3_stmt *pTest = 0;
-
    shellPrepare(pState->db, pRc,
-
        "SELECT 1 FROM recovery.schema WHERE name=?", &pTest
-
    );
-
    if( pTest ) sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT);
-
    while( *pRc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pTest) ){
-
      shellReset(pRc, pTest);
-
      sqlite3_free(zTab);
-
      zTab = shellMPrintf(pRc, "%s_%d", zLostAndFound, iTab++);
-
      sqlite3_bind_text(pTest, 1, zTab, -1, SQLITE_TRANSIENT);
-
    }
-
    shellFinalize(pRc, pTest);
-

-
    pTab = (RecoverTable*)shellMalloc(pRc, sizeof(RecoverTable));
-
    if( pTab ){
-
      pTab->zQuoted = shellMPrintf(pRc, "\"%w\"", zTab);
-
      pTab->nCol = nCol;
-
      pTab->iPk = -2;
-
      if( nCol>0 ){
-
        pTab->azlCol = (char**)shellMalloc(pRc, sizeof(char*) * (nCol+1));
-
        if( pTab->azlCol ){
-
          pTab->azlCol[nCol] = shellMPrintf(pRc, "");
-
          for(i=nCol-1; i>=0; i--){
-
            pTab->azlCol[i] = shellMPrintf(pRc, "%s, NULL", pTab->azlCol[i+1]);
-
          }
-
        }
-
      }
-

-
      if( *pRc!=SQLITE_OK ){
-
        recoverFreeTable(pTab);
-
        pTab = 0;
-
      }else{
-
        raw_printf(pState->out, 
-
            "CREATE TABLE %s(rootpgno INTEGER, "
-
            "pgno INTEGER, nfield INTEGER, id INTEGER", pTab->zQuoted
-
        );
-
        for(i=0; i<nCol; i++){
-
          raw_printf(pState->out, ", c%d", i);
-
        }
-
        raw_printf(pState->out, ");\n");
-
      }
-
    }
-
    sqlite3_free(zTab);
-
  }
-
  return pTab;
+
static int recoverSqlCb(void *pCtx, const char *zSql){
+
  ShellState *pState = (ShellState*)pCtx;
+
  utf8_printf(pState->out, "%s;\n", zSql);
+
  return SQLITE_OK;
}

/*
@@ -18673,32 +21705,33 @@ static RecoverTable *recoverOrphanTable(
*/
static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
  int rc = SQLITE_OK;
-
  sqlite3_stmt *pLoop = 0;        /* Loop through all root pages */
-
  sqlite3_stmt *pPages = 0;       /* Loop through all pages in a group */
-
  sqlite3_stmt *pCells = 0;       /* Loop through all cells in a page */
-
  const char *zRecoveryDb = "";   /* Name of "recovery" database */
-
  const char *zLostAndFound = "lost_and_found";
-
  int i;
-
  int nOrphan = -1;
-
  RecoverTable *pOrphan = 0;
-

-
  int bFreelist = 1;              /* 0 if --freelist-corrupt is specified */
+
  const char *zRecoveryDb = "";   /* Name of "recovery" database.  Debug only */
+
  const char *zLAF = "lost_and_found";
+
  int bFreelist = 1;              /* 0 if --ignore-freelist is specified */
  int bRowids = 1;                /* 0 if --no-rowids */
+
  sqlite3_recover *p = 0;
+
  int i = 0;
+

  for(i=1; i<nArg; i++){
    char *z = azArg[i];
    int n;
    if( z[0]=='-' && z[1]=='-' ) z++;
    n = strlen30(z);
-
    if( n<=17 && memcmp("-freelist-corrupt", z, n)==0 ){
+
    if( n<=17 && memcmp("-ignore-freelist", z, n)==0 ){
      bFreelist = 0;
    }else
    if( n<=12 && memcmp("-recovery-db", z, n)==0 && i<(nArg-1) ){
+
      /* This option determines the name of the ATTACH-ed database used
+
      ** internally by the recovery extension.  The default is "" which
+
      ** means to use a temporary database that is automatically deleted
+
      ** when closed.  This option is undocumented and might disappear at
+
      ** any moment. */
      i++;
      zRecoveryDb = azArg[i];
    }else
    if( n<=15 && memcmp("-lost-and-found", z, n)==0 && i<(nArg-1) ){
      i++;
-
      zLostAndFound = azArg[i];
+
      zLAF = azArg[i];
    }else
    if( n<=10 && memcmp("-no-rowids", z, n)==0 ){
      bRowids = 0;
@@ -18710,281 +21743,25 @@ static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
    }
  }

-
  shellExecPrintf(pState->db, &rc,
-
    /* Attach an in-memory database named 'recovery'. Create an indexed 
-
    ** cache of the sqlite_dbptr virtual table. */
-
    "PRAGMA writable_schema = on;"
-
    "ATTACH %Q AS recovery;"
-
    "DROP TABLE IF EXISTS recovery.dbptr;"
-
    "DROP TABLE IF EXISTS recovery.freelist;"
-
    "DROP TABLE IF EXISTS recovery.map;"
-
    "DROP TABLE IF EXISTS recovery.schema;"
-
    "CREATE TABLE recovery.freelist(pgno INTEGER PRIMARY KEY);", zRecoveryDb
-
  );
-

-
  if( bFreelist ){
-
    shellExec(pState->db, &rc,
-
      "WITH trunk(pgno) AS ("
-
      "  SELECT shell_int32("
-
      "      (SELECT data FROM sqlite_dbpage WHERE pgno=1), 8) AS x "
-
      "      WHERE x>0"
-
      "    UNION"
-
      "  SELECT shell_int32("
-
      "      (SELECT data FROM sqlite_dbpage WHERE pgno=trunk.pgno), 0) AS x "
-
      "      FROM trunk WHERE x>0"
-
      "),"
-
      "freelist(data, n, freepgno) AS ("
-
      "  SELECT data, min(16384, shell_int32(data, 1)-1), t.pgno "
-
      "      FROM trunk t, sqlite_dbpage s WHERE s.pgno=t.pgno"
-
      "    UNION ALL"
-
      "  SELECT data, n-1, shell_int32(data, 2+n) "
-
      "      FROM freelist WHERE n>=0"
-
      ")"
-
      "REPLACE INTO recovery.freelist SELECT freepgno FROM freelist;"
-
    );
-
  }
-

-
  /* If this is an auto-vacuum database, add all pointer-map pages to
-
  ** the freelist table. Do this regardless of whether or not 
-
  ** --freelist-corrupt was specified.  */
-
  shellExec(pState->db, &rc, 
-
    "WITH ptrmap(pgno) AS ("
-
    "  SELECT 2 WHERE shell_int32("
-
    "    (SELECT data FROM sqlite_dbpage WHERE pgno=1), 13"
-
    "  )"
-
    "    UNION ALL "
-
    "  SELECT pgno+1+(SELECT page_size FROM pragma_page_size)/5 AS pp "
-
    "  FROM ptrmap WHERE pp<=(SELECT page_count FROM pragma_page_count)"
-
    ")"
-
    "REPLACE INTO recovery.freelist SELECT pgno FROM ptrmap"
-
  );
-

-
  shellExec(pState->db, &rc, 
-
    "CREATE TABLE recovery.dbptr("
-
    "      pgno, child, PRIMARY KEY(child, pgno)"
-
    ") WITHOUT ROWID;"
-
    "INSERT OR IGNORE INTO recovery.dbptr(pgno, child) "
-
    "    SELECT * FROM sqlite_dbptr"
-
    "      WHERE pgno NOT IN freelist AND child NOT IN freelist;"
-

-
    /* Delete any pointer to page 1. This ensures that page 1 is considered
-
    ** a root page, regardless of how corrupt the db is. */
-
    "DELETE FROM recovery.dbptr WHERE child = 1;"
-

-
    /* Delete all pointers to any pages that have more than one pointer
-
    ** to them. Such pages will be treated as root pages when recovering
-
    ** data.  */
-
    "DELETE FROM recovery.dbptr WHERE child IN ("
-
    "  SELECT child FROM recovery.dbptr GROUP BY child HAVING count(*)>1"
-
    ");"
-

-
    /* Create the "map" table that will (eventually) contain instructions
-
    ** for dealing with each page in the db that contains one or more 
-
    ** records. */
-
    "CREATE TABLE recovery.map("
-
      "pgno INTEGER PRIMARY KEY, maxlen INT, intkey, root INT"
-
    ");"
-

-
    /* Populate table [map]. If there are circular loops of pages in the
-
    ** database, the following adds all pages in such a loop to the map
-
    ** as individual root pages. This could be handled better.  */
-
    "WITH pages(i, maxlen) AS ("
-
    "  SELECT page_count, ("
-
    "    SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=page_count"
-
    "  ) FROM pragma_page_count WHERE page_count>0"
-
    "    UNION ALL"
-
    "  SELECT i-1, ("
-
    "    SELECT max(field+1) FROM sqlite_dbdata WHERE pgno=i-1"
-
    "  ) FROM pages WHERE i>=2"
-
    ")"
-
    "INSERT INTO recovery.map(pgno, maxlen, intkey, root) "
-
    "  SELECT i, maxlen, NULL, ("
-
    "    WITH p(orig, pgno, parent) AS ("
-
    "      SELECT 0, i, (SELECT pgno FROM recovery.dbptr WHERE child=i)"
-
    "        UNION "
-
    "      SELECT i, p.parent, "
-
    "        (SELECT pgno FROM recovery.dbptr WHERE child=p.parent) FROM p"
-
    "    )"
-
    "    SELECT pgno FROM p WHERE (parent IS NULL OR pgno = orig)"
-
    ") "
-
    "FROM pages WHERE maxlen IS NOT NULL AND i NOT IN freelist;"
-
    "UPDATE recovery.map AS o SET intkey = ("
-
    "  SELECT substr(data, 1, 1)==X'0D' FROM sqlite_dbpage WHERE pgno=o.pgno"
-
    ");"
-

-
    /* Extract data from page 1 and any linked pages into table
-
    ** recovery.schema. With the same schema as an sqlite_schema table.  */
-
    "CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql);"
-
    "INSERT INTO recovery.schema SELECT "
-
    "  max(CASE WHEN field=0 THEN value ELSE NULL END),"
-
    "  max(CASE WHEN field=1 THEN value ELSE NULL END),"
-
    "  max(CASE WHEN field=2 THEN value ELSE NULL END),"
-
    "  max(CASE WHEN field=3 THEN value ELSE NULL END),"
-
    "  max(CASE WHEN field=4 THEN value ELSE NULL END)"
-
    "FROM sqlite_dbdata WHERE pgno IN ("
-
    "  SELECT pgno FROM recovery.map WHERE root=1"
-
    ")"
-
    "GROUP BY pgno, cell;"
-
    "CREATE INDEX recovery.schema_rootpage ON schema(rootpage);"
-
  );
-

-
  /* Open a transaction, then print out all non-virtual, non-"sqlite_%" 
-
  ** CREATE TABLE statements that extracted from the existing schema.  */
-
  if( rc==SQLITE_OK ){
-
    sqlite3_stmt *pStmt = 0;
-
    /* ".recover" might output content in an order which causes immediate
-
    ** foreign key constraints to be violated. So disable foreign-key
-
    ** constraint enforcement to prevent problems when running the output
-
    ** script. */
-
    raw_printf(pState->out, "PRAGMA foreign_keys=OFF;\n");
-
    raw_printf(pState->out, "BEGIN;\n");
-
    raw_printf(pState->out, "PRAGMA writable_schema = on;\n");
-
    shellPrepare(pState->db, &rc,
-
        "SELECT sql FROM recovery.schema "
-
        "WHERE type='table' AND sql LIKE 'create table%'", &pStmt
-
    );
-
    while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
-
      const char *zCreateTable = (const char*)sqlite3_column_text(pStmt, 0);
-
      raw_printf(pState->out, "CREATE TABLE IF NOT EXISTS %s;\n", 
-
          &zCreateTable[12]
-
      );
-
    }
-
    shellFinalize(&rc, pStmt);
-
  }
-

-
  /* Figure out if an orphan table will be required. And if so, how many
-
  ** user columns it should contain */
-
  shellPrepare(pState->db, &rc, 
-
      "SELECT coalesce(max(maxlen), -2) FROM recovery.map WHERE root>1"
-
      , &pLoop
-
  );
-
  if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){
-
    nOrphan = sqlite3_column_int(pLoop, 0);
-
  }
-
  shellFinalize(&rc, pLoop);
-
  pLoop = 0;
-

-
  shellPrepare(pState->db, &rc,
-
      "SELECT pgno FROM recovery.map WHERE root=?", &pPages
-
  );
-

-
  shellPrepare(pState->db, &rc,
-
      "SELECT max(field), group_concat(shell_escape_crnl(quote"
-
      "(case when (? AND field<0) then NULL else value end)"
-
      "), ', ')"
-
      ", min(field) "
-
      "FROM sqlite_dbdata WHERE pgno = ? AND field != ?"
-
      "GROUP BY cell", &pCells
+
  p = sqlite3_recover_init_sql(
+
      pState->db, "main", recoverSqlCb, (void*)pState
  );

-
  /* Loop through each root page. */
-
  shellPrepare(pState->db, &rc, 
-
      "SELECT root, intkey, max(maxlen) FROM recovery.map" 
-
      " WHERE root>1 GROUP BY root, intkey ORDER BY root=("
-
      "  SELECT rootpage FROM recovery.schema WHERE name='sqlite_sequence'"
-
      ")", &pLoop
-
  );
-
  while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pLoop) ){
-
    int iRoot = sqlite3_column_int(pLoop, 0);
-
    int bIntkey = sqlite3_column_int(pLoop, 1);
-
    int nCol = sqlite3_column_int(pLoop, 2);
-
    int bNoop = 0;
-
    RecoverTable *pTab;
-

-
    assert( bIntkey==0 || bIntkey==1 );
-
    pTab = recoverFindTable(pState, &rc, iRoot, bIntkey, nCol, &bNoop);
-
    if( bNoop || rc ) continue;
-
    if( pTab==0 ){
-
      if( pOrphan==0 ){
-
        pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan);
-
      }
-
      pTab = pOrphan;
-
      if( pTab==0 ) break;
-
    }
-

-
    if( 0==sqlite3_stricmp(pTab->zQuoted, "\"sqlite_sequence\"") ){
-
      raw_printf(pState->out, "DELETE FROM sqlite_sequence;\n");
-
    }
-
    sqlite3_bind_int(pPages, 1, iRoot);
-
    if( bRowids==0 && pTab->iPk<0 ){
-
      sqlite3_bind_int(pCells, 1, 1);
-
    }else{
-
      sqlite3_bind_int(pCells, 1, 0);
-
    }
-
    sqlite3_bind_int(pCells, 3, pTab->iPk);
-

-
    while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPages) ){
-
      int iPgno = sqlite3_column_int(pPages, 0);
-
      sqlite3_bind_int(pCells, 2, iPgno);
-
      while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pCells) ){
-
        int nField = sqlite3_column_int(pCells, 0);
-
        int iMin = sqlite3_column_int(pCells, 2);
-
        const char *zVal = (const char*)sqlite3_column_text(pCells, 1);
-

-
        RecoverTable *pTab2 = pTab;
-
        if( pTab!=pOrphan && (iMin<0)!=bIntkey ){
-
          if( pOrphan==0 ){
-
            pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan);
-
          }
-
          pTab2 = pOrphan;
-
          if( pTab2==0 ) break;
-
        }
-

-
        nField = nField+1;
-
        if( pTab2==pOrphan ){
-
          raw_printf(pState->out, 
-
              "INSERT INTO %s VALUES(%d, %d, %d, %s%s%s);\n",
-
              pTab2->zQuoted, iRoot, iPgno, nField,
-
              iMin<0 ? "" : "NULL, ", zVal, pTab2->azlCol[nField]
-
          );
-
        }else{
-
          raw_printf(pState->out, "INSERT INTO %s(%s) VALUES( %s );\n", 
-
              pTab2->zQuoted, pTab2->azlCol[nField], zVal
-
          );
-
        }
-
      }
-
      shellReset(&rc, pCells);
-
    }
-
    shellReset(&rc, pPages);
-
    if( pTab!=pOrphan ) recoverFreeTable(pTab);
-
  }
-
  shellFinalize(&rc, pLoop);
-
  shellFinalize(&rc, pPages);
-
  shellFinalize(&rc, pCells);
-
  recoverFreeTable(pOrphan);
-

-
  /* The rest of the schema */
-
  if( rc==SQLITE_OK ){
-
    sqlite3_stmt *pStmt = 0;
-
    shellPrepare(pState->db, &rc, 
-
        "SELECT sql, name FROM recovery.schema "
-
        "WHERE sql NOT LIKE 'create table%'", &pStmt
-
    );
-
    while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
-
      const char *zSql = (const char*)sqlite3_column_text(pStmt, 0);
-
      if( sqlite3_strnicmp(zSql, "create virt", 11)==0 ){
-
        const char *zName = (const char*)sqlite3_column_text(pStmt, 1);
-
        char *zPrint = shellMPrintf(&rc, 
-
          "INSERT INTO sqlite_schema VALUES('table', %Q, %Q, 0, %Q)",
-
          zName, zName, zSql
-
        );
-
        raw_printf(pState->out, "%s;\n", zPrint);
-
        sqlite3_free(zPrint);
-
      }else{
-
        raw_printf(pState->out, "%s;\n", zSql);
-
      }
-
    }
-
    shellFinalize(&rc, pStmt);
-
  }
+
  sqlite3_recover_config(p, 789, (void*)zRecoveryDb);  /* Debug use only */
+
  sqlite3_recover_config(p, SQLITE_RECOVER_LOST_AND_FOUND, (void*)zLAF);
+
  sqlite3_recover_config(p, SQLITE_RECOVER_ROWIDS, (void*)&bRowids);
+
  sqlite3_recover_config(p, SQLITE_RECOVER_FREELIST_CORRUPT,(void*)&bFreelist);

-
  if( rc==SQLITE_OK ){
-
    raw_printf(pState->out, "PRAGMA writable_schema = off;\n");
-
    raw_printf(pState->out, "COMMIT;\n");
+
  sqlite3_recover_run(p);
+
  if( sqlite3_recover_errcode(p)!=SQLITE_OK ){
+
    const char *zErr = sqlite3_recover_errmsg(p);
+
    int errCode = sqlite3_recover_errcode(p);
+
    raw_printf(stderr, "sql error: %s (%d)\n", zErr, errCode);
  }
-
  sqlite3_exec(pState->db, "DETACH recovery", 0, 0, 0);
+
  rc = sqlite3_recover_finish(p);
  return rc;
}
-
#endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
+
#endif /* SQLITE_SHELL_HAVE_RECOVER */


/*
@@ -19256,7 +22033,7 @@ static int do_meta_command(char *zLine, ShellState *p){
  clearTempFile(p);

#ifndef SQLITE_OMIT_AUTHORIZATION
-
  if( c=='a' && strncmp(azArg[0], "auth", n)==0 ){
+
  if( c=='a' && cli_strncmp(azArg[0], "auth", n)==0 ){
    if( nArg!=2 ){
      raw_printf(stderr, "Usage: .auth ON|OFF\n");
      rc = 1;
@@ -19274,17 +22051,17 @@ static int do_meta_command(char *zLine, ShellState *p){
#endif

#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) \
-
  && !defined(SQLITE_SHELL_WASM_MODE)
-
  if( c=='a' && strncmp(azArg[0], "archive", n)==0 ){
+
  && !defined(SQLITE_SHELL_FIDDLE)
+
  if( c=='a' && cli_strncmp(azArg[0], "archive", n)==0 ){
    open_db(p, 0);
    failIfSafeMode(p, "cannot run .archive in safe mode");
    rc = arDotCommand(p, 0, azArg, nArg);
  }else
#endif

-
#ifndef SQLITE_SHELL_WASM_MODE
-
  if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0)
-
   || (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0)
+
#ifndef SQLITE_SHELL_FIDDLE
+
  if( (c=='b' && n>=3 && cli_strncmp(azArg[0], "backup", n)==0)
+
   || (c=='s' && n>=3 && cli_strncmp(azArg[0], "save", n)==0)
  ){
    const char *zDestFile = 0;
    const char *zDb = 0;
@@ -19298,10 +22075,10 @@ static int do_meta_command(char *zLine, ShellState *p){
      const char *z = azArg[j];
      if( z[0]=='-' ){
        if( z[1]=='-' ) z++;
-
        if( strcmp(z, "-append")==0 ){
+
        if( cli_strcmp(z, "-append")==0 ){
          zVfs = "apndvfs";
        }else
-
        if( strcmp(z, "-async")==0 ){
+
        if( cli_strcmp(z, "-async")==0 ){
          bAsync = 1;
        }else
        {
@@ -19351,9 +22128,9 @@ static int do_meta_command(char *zLine, ShellState *p){
    }
    close_db(pDest);
  }else
-
#endif /* !defined(SQLITE_SHELL_WASM_MODE) */
+
#endif /* !defined(SQLITE_SHELL_FIDDLE) */

-
  if( c=='b' && n>=3 && strncmp(azArg[0], "bail", n)==0 ){
+
  if( c=='b' && n>=3 && cli_strncmp(azArg[0], "bail", n)==0 ){
    if( nArg==2 ){
      bail_on_error = booleanValue(azArg[1]);
    }else{
@@ -19362,7 +22139,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    }
  }else

-
  if( c=='b' && n>=3 && strncmp(azArg[0], "binary", n)==0 ){
+
  if( c=='b' && n>=3 && cli_strncmp(azArg[0], "binary", n)==0 ){
    if( nArg==2 ){
      if( booleanValue(azArg[1]) ){
        setBinaryMode(p->out, 1);
@@ -19378,12 +22155,12 @@ static int do_meta_command(char *zLine, ShellState *p){
  /* The undocumented ".breakpoint" command causes a call to the no-op
  ** routine named test_breakpoint().
  */
-
  if( c=='b' && n>=3 && strncmp(azArg[0], "breakpoint", n)==0 ){
+
  if( c=='b' && n>=3 && cli_strncmp(azArg[0], "breakpoint", n)==0 ){
    test_breakpoint();
  }else

-
#ifndef SQLITE_SHELL_WASM_MODE
-
  if( c=='c' && strcmp(azArg[0],"cd")==0 ){
+
#ifndef SQLITE_SHELL_FIDDLE
+
  if( c=='c' && cli_strcmp(azArg[0],"cd")==0 ){
    failIfSafeMode(p, "cannot run .cd in safe mode");
    if( nArg==2 ){
#if defined(_WIN32) || defined(WIN32)
@@ -19402,9 +22179,9 @@ static int do_meta_command(char *zLine, ShellState *p){
      rc = 1;
    }
  }else
-
#endif /* !defined(SQLITE_SHELL_WASM_MODE) */
+
#endif /* !defined(SQLITE_SHELL_FIDDLE) */

-
  if( c=='c' && n>=3 && strncmp(azArg[0], "changes", n)==0 ){
+
  if( c=='c' && n>=3 && cli_strncmp(azArg[0], "changes", n)==0 ){
    if( nArg==2 ){
      setOrClearFlag(p, SHFLG_CountChanges, azArg[1]);
    }else{
@@ -19413,12 +22190,12 @@ static int do_meta_command(char *zLine, ShellState *p){
    }
  }else

-
#ifndef SQLITE_SHELL_WASM_MODE
+
#ifndef SQLITE_SHELL_FIDDLE
  /* Cancel output redirection, if it is currently set (by .testcase)
  ** Then read the content of the testcase-out.txt file and compare against
  ** azArg[1].  If there are differences, report an error and exit.
  */
-
  if( c=='c' && n>=3 && strncmp(azArg[0], "check", n)==0 ){
+
  if( c=='c' && n>=3 && cli_strncmp(azArg[0], "check", n)==0 ){
    char *zRes = 0;
    output_reset(p);
    if( nArg!=2 ){
@@ -19438,10 +22215,10 @@ static int do_meta_command(char *zLine, ShellState *p){
    }
    sqlite3_free(zRes);
  }else
-
#endif /* !defined(SQLITE_SHELL_WASM_MODE) */
+
#endif /* !defined(SQLITE_SHELL_FIDDLE) */

-
#ifndef SQLITE_SHELL_WASM_MODE
-
  if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){
+
#ifndef SQLITE_SHELL_FIDDLE
+
  if( c=='c' && cli_strncmp(azArg[0], "clone", n)==0 ){
    failIfSafeMode(p, "cannot run .clone in safe mode");
    if( nArg==2 ){
      tryToClone(p, azArg[1]);
@@ -19450,9 +22227,9 @@ static int do_meta_command(char *zLine, ShellState *p){
      rc = 1;
    }
  }else
-
#endif /* !defined(SQLITE_SHELL_WASM_MODE) */
+
#endif /* !defined(SQLITE_SHELL_FIDDLE) */

-
  if( c=='c' && strncmp(azArg[0], "connection", n)==0 ){
+
  if( c=='c' && cli_strncmp(azArg[0], "connection", n)==0 ){
    if( nArg==1 ){
      /* List available connections */
      int i;
@@ -19479,7 +22256,7 @@ static int do_meta_command(char *zLine, ShellState *p){
        globalDb = p->db = p->pAuxDb->db;
        p->pAuxDb->db = 0;
      }
-
    }else if( nArg==3 && strcmp(azArg[1], "close")==0
+
    }else if( nArg==3 && cli_strcmp(azArg[1], "close")==0
           && IsDigit(azArg[2][0]) && azArg[2][1]==0 ){
      int i = azArg[2][0] - '0';
      if( i<0 || i>=ArraySize(p->aAuxDb) ){
@@ -19498,7 +22275,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    }
  }else

-
  if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){
+
  if( c=='d' && n>1 && cli_strncmp(azArg[0], "databases", n)==0 ){
    char **azName = 0;
    int nName = 0;
    sqlite3_stmt *pStmt;
@@ -19537,7 +22314,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    sqlite3_free(azName);
  }else

-
  if( c=='d' && n>=3 && strncmp(azArg[0], "dbconfig", n)==0 ){
+
  if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbconfig", n)==0 ){
    static const struct DbConfigChoices {
      const char *zName;
      int op;
@@ -19562,7 +22339,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    int ii, v;
    open_db(p, 0);
    for(ii=0; ii<ArraySize(aDbConfig); ii++){
-
      if( nArg>1 && strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue;
+
      if( nArg>1 && cli_strcmp(azArg[1], aDbConfig[ii].zName)!=0 ) continue;
      if( nArg>=3 ){
        sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0);
      }
@@ -19576,18 +22353,18 @@ static int do_meta_command(char *zLine, ShellState *p){
    }   
  }else

-
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
-
  if( c=='d' && n>=3 && strncmp(azArg[0], "dbinfo", n)==0 ){
+
#if SQLITE_SHELL_HAVE_RECOVER
+
  if( c=='d' && n>=3 && cli_strncmp(azArg[0], "dbinfo", n)==0 ){
    rc = shell_dbinfo_command(p, nArg, azArg);
  }else

-
  if( c=='r' && strncmp(azArg[0], "recover", n)==0 ){
+
  if( c=='r' && cli_strncmp(azArg[0], "recover", n)==0 ){
    open_db(p, 0);
    rc = recoverDatabaseCmd(p, nArg, azArg);
  }else
-
#endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
+
#endif /* SQLITE_SHELL_HAVE_RECOVER */

-
  if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
+
  if( c=='d' && cli_strncmp(azArg[0], "dump", n)==0 ){
    char *zLike = 0;
    char *zSql;
    int i;
@@ -19600,7 +22377,7 @@ static int do_meta_command(char *zLine, ShellState *p){
      if( azArg[i][0]=='-' ){
        const char *z = azArg[i]+1;
        if( z[0]=='-' ) z++;
-
        if( strcmp(z,"preserve-rowids")==0 ){
+
        if( cli_strcmp(z,"preserve-rowids")==0 ){
#ifdef SQLITE_OMIT_VIRTUALTABLE
          raw_printf(stderr, "The --preserve-rowids option is not compatible"
                             " with SQLITE_OMIT_VIRTUALTABLE\n");
@@ -19611,13 +22388,13 @@ static int do_meta_command(char *zLine, ShellState *p){
          ShellSetFlag(p, SHFLG_PreserveRowid);
#endif
        }else
-
        if( strcmp(z,"newlines")==0 ){
+
        if( cli_strcmp(z,"newlines")==0 ){
          ShellSetFlag(p, SHFLG_Newlines);
        }else
-
        if( strcmp(z,"data-only")==0 ){
+
        if( cli_strcmp(z,"data-only")==0 ){
          ShellSetFlag(p, SHFLG_DumpDataOnly);
        }else
-
        if( strcmp(z,"nosys")==0 ){
+
        if( cli_strcmp(z,"nosys")==0 ){
          ShellSetFlag(p, SHFLG_DumpNoSys);
        }else
        {
@@ -19699,7 +22476,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    p->shellFlgs = savedShellFlags;
  }else

-
  if( c=='e' && strncmp(azArg[0], "echo", n)==0 ){
+
  if( c=='e' && cli_strncmp(azArg[0], "echo", n)==0 ){
    if( nArg==2 ){
      setOrClearFlag(p, SHFLG_Echo, azArg[1]);
    }else{
@@ -19708,22 +22485,22 @@ static int do_meta_command(char *zLine, ShellState *p){
    }
  }else

-
  if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){
+
  if( c=='e' && cli_strncmp(azArg[0], "eqp", n)==0 ){
    if( nArg==2 ){
      p->autoEQPtest = 0;
      if( p->autoEQPtrace ){
        if( p->db ) sqlite3_exec(p->db, "PRAGMA vdbe_trace=OFF;", 0, 0, 0);
        p->autoEQPtrace = 0;
      }
-
      if( strcmp(azArg[1],"full")==0 ){
+
      if( cli_strcmp(azArg[1],"full")==0 ){
        p->autoEQP = AUTOEQP_full;
-
      }else if( strcmp(azArg[1],"trigger")==0 ){
+
      }else if( cli_strcmp(azArg[1],"trigger")==0 ){
        p->autoEQP = AUTOEQP_trigger;
#ifdef SQLITE_DEBUG
-
      }else if( strcmp(azArg[1],"test")==0 ){
+
      }else if( cli_strcmp(azArg[1],"test")==0 ){
        p->autoEQP = AUTOEQP_on;
        p->autoEQPtest = 1;
-
      }else if( strcmp(azArg[1],"trace")==0 ){
+
      }else if( cli_strcmp(azArg[1],"trace")==0 ){
        p->autoEQP = AUTOEQP_full;
        p->autoEQPtrace = 1;
        open_db(p, 0);
@@ -19739,8 +22516,8 @@ static int do_meta_command(char *zLine, ShellState *p){
    }
  }else

-
#ifndef SQLITE_SHELL_WASM_MODE
-
  if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
+
#ifndef SQLITE_SHELL_FIDDLE
+
  if( c=='e' && cli_strncmp(azArg[0], "exit", n)==0 ){
    if( nArg>1 && (rc = (int)integerValue(azArg[1]))!=0 ) exit(rc);
    rc = 2;
  }else
@@ -19748,10 +22525,10 @@ static int do_meta_command(char *zLine, ShellState *p){

  /* The ".explain" command is automatic now.  It is largely pointless.  It
  ** retained purely for backwards compatibility */
-
  if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
+
  if( c=='e' && cli_strncmp(azArg[0], "explain", n)==0 ){
    int val = 1;
    if( nArg>=2 ){
-
      if( strcmp(azArg[1],"auto")==0 ){
+
      if( cli_strcmp(azArg[1],"auto")==0 ){
        val = 99;
      }else{
        val =  booleanValue(azArg[1]);
@@ -19771,7 +22548,7 @@ static int do_meta_command(char *zLine, ShellState *p){
  }else

#ifndef SQLITE_OMIT_VIRTUALTABLE
-
  if( c=='e' && strncmp(azArg[0], "expert", n)==0 ){
+
  if( c=='e' && cli_strncmp(azArg[0], "expert", n)==0 ){
    if( p->bSafeMode ){
      raw_printf(stderr, 
        "Cannot run experimental commands such as \"%s\" in safe mode\n",
@@ -19784,7 +22561,7 @@ static int do_meta_command(char *zLine, ShellState *p){
  }else
#endif

-
  if( c=='f' && strncmp(azArg[0], "filectrl", n)==0 ){
+
  if( c=='f' && cli_strncmp(azArg[0], "filectrl", n)==0 ){
    static const struct {
       const char *zCtrlName;   /* Name of a test-control option */
       int ctrlCode;            /* Integer code for that option */
@@ -19814,7 +22591,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    zCmd = nArg>=2 ? azArg[1] : "help";

    if( zCmd[0]=='-' 
-
     && (strcmp(zCmd,"--schema")==0 || strcmp(zCmd,"-schema")==0)
+
     && (cli_strcmp(zCmd,"--schema")==0 || cli_strcmp(zCmd,"-schema")==0)
     && nArg>=4
    ){
      zSchema = azArg[2];
@@ -19830,7 +22607,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    }

    /* --help lists all file-controls */
-
    if( strcmp(zCmd,"help")==0 ){
+
    if( cli_strcmp(zCmd,"help")==0 ){
      utf8_printf(p->out, "Available file-controls:\n");
      for(i=0; i<ArraySize(aCtrl); i++){
        utf8_printf(p->out, "  .filectrl %s %s\n",
@@ -19844,7 +22621,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    ** of the option name, or a numerical value. */
    n2 = strlen30(zCmd);
    for(i=0; i<ArraySize(aCtrl); i++){
-
      if( strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
+
      if( cli_strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
        if( filectrl<0 ){
          filectrl = aCtrl[i].ctrlCode;
          iCtrl = i;
@@ -19931,7 +22708,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    }
  }else

-
  if( c=='f' && strncmp(azArg[0], "fullschema", n)==0 ){
+
  if( c=='f' && cli_strncmp(azArg[0], "fullschema", n)==0 ){
    ShellState data;
    int doStats = 0;
    memcpy(&data, p, sizeof(data));
@@ -19978,7 +22755,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    }
  }else

-
  if( c=='h' && strncmp(azArg[0], "headers", n)==0 ){
+
  if( c=='h' && cli_strncmp(azArg[0], "headers", n)==0 ){
    if( nArg==2 ){
      p->showHeader = booleanValue(azArg[1]);
      p->shellFlgs |= SHFLG_HeaderSet;
@@ -19988,7 +22765,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    }
  }else

-
  if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
+
  if( c=='h' && cli_strncmp(azArg[0], "help", n)==0 ){
    if( nArg>=2 ){
      n = showHelp(p->out, azArg[1]);
      if( n==0 ){
@@ -19999,8 +22776,8 @@ static int do_meta_command(char *zLine, ShellState *p){
    }
  }else

-
#ifndef SQLITE_SHELL_WASM_MODE
-
  if( c=='i' && strncmp(azArg[0], "import", n)==0 ){
+
#ifndef SQLITE_SHELL_FIDDLE
+
  if( c=='i' && cli_strncmp(azArg[0], "import", n)==0 ){
    char *zTable = 0;           /* Insert data into this table */
    char *zSchema = 0;          /* within this schema (may default to "main") */
    char *zFile = 0;            /* Name of file to extra content from */
@@ -20040,18 +22817,18 @@ static int do_meta_command(char *zLine, ShellState *p){
          showHelp(p->out, "import");
          goto meta_command_exit;
        }
-
      }else if( strcmp(z,"-v")==0 ){
+
      }else if( cli_strcmp(z,"-v")==0 ){
        eVerbose++;
-
      }else if( strcmp(z,"-schema")==0 && i<nArg-1 ){
+
      }else if( cli_strcmp(z,"-schema")==0 && i<nArg-1 ){
        zSchema = azArg[++i];
-
      }else if( strcmp(z,"-skip")==0 && i<nArg-1 ){
+
      }else if( cli_strcmp(z,"-skip")==0 && i<nArg-1 ){
        nSkip = integerValue(azArg[++i]);
-
      }else if( strcmp(z,"-ascii")==0 ){
+
      }else if( cli_strcmp(z,"-ascii")==0 ){
        sCtx.cColSep = SEP_Unit[0];
        sCtx.cRowSep = SEP_Record[0];
        xRead = ascii_read_one_field;
        useOutputMode = 0;
-
      }else if( strcmp(z,"-csv")==0 ){
+
      }else if( cli_strcmp(z,"-csv")==0 ){
        sCtx.cColSep = ',';
        sCtx.cRowSep = '\n';
        xRead = csv_read_one_field;
@@ -20091,7 +22868,9 @@ static int do_meta_command(char *zLine, ShellState *p){
            "Error: non-null row separator required for import\n");
        goto meta_command_exit;
      }
-
      if( nSep==2 && p->mode==MODE_Csv && strcmp(p->rowSeparator,SEP_CrLf)==0 ){
+
      if( nSep==2 && p->mode==MODE_Csv
+
       && cli_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
@@ -20290,10 +23069,10 @@ static int do_meta_command(char *zLine, ShellState *p){
          sCtx.nRow, sCtx.nErr, sCtx.nLine-1);
    }
  }else
-
#endif /* !defined(SQLITE_SHELL_WASM_MODE) */
+
#endif /* !defined(SQLITE_SHELL_FIDDLE) */

#ifndef SQLITE_UNTESTABLE
-
  if( c=='i' && strncmp(azArg[0], "imposter", n)==0 ){
+
  if( c=='i' && cli_strncmp(azArg[0], "imposter", n)==0 ){
    char *zSql;
    char *zCollist = 0;
    sqlite3_stmt *pStmt;
@@ -20394,13 +23173,13 @@ static int do_meta_command(char *zLine, ShellState *p){
#endif /* !defined(SQLITE_OMIT_TEST_CONTROL) */

#ifdef SQLITE_ENABLE_IOTRACE
-
  if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){
+
  if( c=='i' && cli_strncmp(azArg[0], "iotrace", n)==0 ){
    SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...);
    if( iotrace && iotrace!=stdout ) fclose(iotrace);
    iotrace = 0;
    if( nArg<2 ){
      sqlite3IoTrace = 0;
-
    }else if( strcmp(azArg[1], "-")==0 ){
+
    }else if( cli_strcmp(azArg[1], "-")==0 ){
      sqlite3IoTrace = iotracePrintf;
      iotrace = stdout;
    }else{
@@ -20416,7 +23195,7 @@ static int do_meta_command(char *zLine, ShellState *p){
  }else
#endif

-
  if( c=='l' && n>=5 && strncmp(azArg[0], "limits", n)==0 ){
+
  if( c=='l' && n>=5 && cli_strncmp(azArg[0], "limits", n)==0 ){
    static const struct {
       const char *zLimitName;   /* Name of a limit */
       int limitCode;            /* Integer code for that limit */
@@ -20475,13 +23254,13 @@ static int do_meta_command(char *zLine, ShellState *p){
    }
  }else

-
  if( c=='l' && n>2 && strncmp(azArg[0], "lint", n)==0 ){
+
  if( c=='l' && n>2 && cli_strncmp(azArg[0], "lint", n)==0 ){
    open_db(p, 0);
    lintDotCommand(p, azArg, nArg);
  }else

-
#if !defined(SQLITE_OMIT_LOAD_EXTENSION) && !defined(SQLITE_SHELL_WASM_MODE)
-
  if( c=='l' && strncmp(azArg[0], "load", n)==0 ){
+
#if !defined(SQLITE_OMIT_LOAD_EXTENSION) && !defined(SQLITE_SHELL_FIDDLE)
+
  if( c=='l' && cli_strncmp(azArg[0], "load", n)==0 ){
    const char *zFile, *zProc;
    char *zErrMsg = 0;
    failIfSafeMode(p, "cannot run .load in safe mode");
@@ -20502,8 +23281,8 @@ static int do_meta_command(char *zLine, ShellState *p){
  }else
#endif

-
#ifndef SQLITE_SHELL_WASM_MODE
-
  if( c=='l' && strncmp(azArg[0], "log", n)==0 ){
+
#ifndef SQLITE_SHELL_FIDDLE
+
  if( c=='l' && cli_strncmp(azArg[0], "log", n)==0 ){
    failIfSafeMode(p, "cannot run .log in safe mode");
    if( nArg!=2 ){
      raw_printf(stderr, "Usage: .log FILENAME\n");
@@ -20516,7 +23295,7 @@ static int do_meta_command(char *zLine, ShellState *p){
  }else
#endif

-
  if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){
+
  if( c=='m' && cli_strncmp(azArg[0], "mode", n)==0 ){
    const char *zMode = 0;
    const char *zTabname = 0;
    int i, n2;
@@ -20535,10 +23314,10 @@ static int do_meta_command(char *zLine, ShellState *p){
        cmOpts.bQuote = 0;
      }else if( zMode==0 ){
        zMode = z;
-
        /* Apply defaults for qbox pseudo-mods. If that
+
        /* Apply defaults for qbox pseudo-mode.  If that
         * overwrites already-set values, user was informed of this.
         */
-
        if( strcmp(z, "qbox")==0 ){
+
        if( cli_strcmp(z, "qbox")==0 ){
          ColModeOpts cmo = ColModeOpts_default_qbox;
          zMode = "box";
          cmOpts = cmo;
@@ -20577,58 +23356,58 @@ static int do_meta_command(char *zLine, ShellState *p){
      zMode = modeDescr[p->mode];
    }
    n2 = strlen30(zMode);
-
    if( strncmp(zMode,"lines",n2)==0 ){
+
    if( cli_strncmp(zMode,"lines",n2)==0 ){
      p->mode = MODE_Line;
      sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
-
    }else if( strncmp(zMode,"columns",n2)==0 ){
+
    }else if( cli_strncmp(zMode,"columns",n2)==0 ){
      p->mode = MODE_Column;
      if( (p->shellFlgs & SHFLG_HeaderSet)==0 ){
        p->showHeader = 1;
      }
      sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
      p->cmOpts = cmOpts;
-
    }else if( strncmp(zMode,"list",n2)==0 ){
+
    }else if( cli_strncmp(zMode,"list",n2)==0 ){
      p->mode = MODE_List;
      sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Column);
      sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
-
    }else if( strncmp(zMode,"html",n2)==0 ){
+
    }else if( cli_strncmp(zMode,"html",n2)==0 ){
      p->mode = MODE_Html;
-
    }else if( strncmp(zMode,"tcl",n2)==0 ){
+
    }else if( cli_strncmp(zMode,"tcl",n2)==0 ){
      p->mode = MODE_Tcl;
      sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Space);
      sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
-
    }else if( strncmp(zMode,"csv",n2)==0 ){
+
    }else if( cli_strncmp(zMode,"csv",n2)==0 ){
      p->mode = MODE_Csv;
      sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
      sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
-
    }else if( strncmp(zMode,"tabs",n2)==0 ){
+
    }else if( cli_strncmp(zMode,"tabs",n2)==0 ){
      p->mode = MODE_List;
      sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Tab);
-
    }else if( strncmp(zMode,"insert",n2)==0 ){
+
    }else if( cli_strncmp(zMode,"insert",n2)==0 ){
      p->mode = MODE_Insert;
      set_table_name(p, zTabname ? zTabname : "table");
-
    }else if( strncmp(zMode,"quote",n2)==0 ){
+
    }else if( cli_strncmp(zMode,"quote",n2)==0 ){
      p->mode = MODE_Quote;
      sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
      sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
-
    }else if( strncmp(zMode,"ascii",n2)==0 ){
+
    }else if( cli_strncmp(zMode,"ascii",n2)==0 ){
      p->mode = MODE_Ascii;
      sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Unit);
      sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Record);
-
    }else if( strncmp(zMode,"markdown",n2)==0 ){
+
    }else if( cli_strncmp(zMode,"markdown",n2)==0 ){
      p->mode = MODE_Markdown;
      p->cmOpts = cmOpts;
-
    }else if( strncmp(zMode,"table",n2)==0 ){
+
    }else if( cli_strncmp(zMode,"table",n2)==0 ){
      p->mode = MODE_Table;
      p->cmOpts = cmOpts;
-
    }else if( strncmp(zMode,"box",n2)==0 ){
+
    }else if( cli_strncmp(zMode,"box",n2)==0 ){
      p->mode = MODE_Box;
      p->cmOpts = cmOpts;
-
    }else if( strncmp(zMode,"count",n2)==0 ){
+
    }else if( cli_strncmp(zMode,"count",n2)==0 ){
      p->mode = MODE_Count;
-
    }else if( strncmp(zMode,"off",n2)==0 ){
+
    }else if( cli_strncmp(zMode,"off",n2)==0 ){
      p->mode = MODE_Off;
-
    }else if( strncmp(zMode,"json",n2)==0 ){
+
    }else if( cli_strncmp(zMode,"json",n2)==0 ){
      p->mode = MODE_Json;
    }else{
      raw_printf(stderr, "Error: mode should be one of: "
@@ -20639,12 +23418,12 @@ static int do_meta_command(char *zLine, ShellState *p){
    p->cMode = p->mode;
  }else

-
#ifndef SQLITE_SHELL_WASM_MODE
-
  if( c=='n' && strcmp(azArg[0], "nonce")==0 ){
+
#ifndef SQLITE_SHELL_FIDDLE
+
  if( c=='n' && cli_strcmp(azArg[0], "nonce")==0 ){
    if( nArg!=2 ){
      raw_printf(stderr, "Usage: .nonce NONCE\n");
      rc = 1;
-
    }else if( p->zNonce==0 || strcmp(azArg[1],p->zNonce)!=0 ){
+
    }else if( p->zNonce==0 || cli_strcmp(azArg[1],p->zNonce)!=0 ){
      raw_printf(stderr, "line %d: incorrect nonce: \"%s\"\n",
                 p->lineno, azArg[1]);
      exit(1);
@@ -20654,9 +23433,9 @@ static int do_meta_command(char *zLine, ShellState *p){
                 ** at the end of this procedure */
    }
  }else
-
#endif /* !defined(SQLITE_SHELL_WASM_MODE) */
+
#endif /* !defined(SQLITE_SHELL_FIDDLE) */

-
  if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 ){
+
  if( c=='n' && cli_strncmp(azArg[0], "nullvalue", n)==0 ){
    if( nArg==2 ){
      sqlite3_snprintf(sizeof(p->nullValue), p->nullValue,
                       "%.*s", (int)ArraySize(p->nullValue)-1, azArg[1]);
@@ -20666,7 +23445,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    }
  }else

-
  if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
+
  if( c=='o' && cli_strncmp(azArg[0], "open", n)==0 && n>=2 ){
    const char *zFN = 0;     /* Pointer to constant filename */
    char *zNewFilename = 0;  /* Name of the database file to open */
    int iName = 1;           /* Index in azArg[] of the filename */
@@ -20676,7 +23455,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    /* Check for command-line arguments */
    for(iName=1; iName<nArg; iName++){
      const char *z = azArg[iName];
-
#ifndef SQLITE_SHELL_WASM_MODE
+
#ifndef SQLITE_SHELL_FIDDLE
      if( optionMatch(z,"new") ){
        newFlag = 1;
#ifdef SQLITE_HAVE_ZLIB
@@ -20698,7 +23477,7 @@ static int do_meta_command(char *zLine, ShellState *p){
        p->szMax = integerValue(azArg[++iName]);
#endif /* SQLITE_OMIT_DESERIALIZE */
      }else
-
#endif /* !SQLITE_SHELL_WASM_MODE */
+
#endif /* !SQLITE_SHELL_FIDDLE */
      if( z[0]=='-' ){
        utf8_printf(stderr, "unknown option: %s\n", z);
        rc = 1;
@@ -20726,11 +23505,11 @@ static int do_meta_command(char *zLine, ShellState *p){
    /* If a filename is specified, try to open it first */
    if( zFN || p->openMode==SHELL_OPEN_HEXDB ){
      if( newFlag && zFN && !p->bSafeMode ) shellDeleteFile(zFN);
-
#ifndef SQLITE_SHELL_WASM_MODE
+
#ifndef SQLITE_SHELL_FIDDLE
      if( p->bSafeMode
       && p->openMode!=SHELL_OPEN_HEXDB
       && zFN
-
       && strcmp(zFN,":memory:")!=0
+
       && cli_strcmp(zFN,":memory:")!=0
      ){
        failIfSafeMode(p, "cannot open disk-based database files in safe mode");
      }
@@ -20759,10 +23538,11 @@ static int do_meta_command(char *zLine, ShellState *p){
    }
  }else

-
#ifndef SQLITE_SHELL_WASM_MODE
+
#ifndef SQLITE_SHELL_FIDDLE
  if( (c=='o'
-
        && (strncmp(azArg[0], "output", n)==0||strncmp(azArg[0], "once", n)==0))
-
   || (c=='e' && n==5 && strcmp(azArg[0],"excel")==0)
+
        && (cli_strncmp(azArg[0], "output", n)==0
+
            || cli_strncmp(azArg[0], "once", n)==0))
+
   || (c=='e' && n==5 && cli_strcmp(azArg[0],"excel")==0)
  ){
    char *zFile = 0;
    int bTxtMode = 0;
@@ -20776,21 +23556,21 @@ static int do_meta_command(char *zLine, ShellState *p){
    if( c=='e' ){
      eMode = 'x';
      bOnce = 2;
-
    }else if( strncmp(azArg[0],"once",n)==0 ){
+
    }else if( cli_strncmp(azArg[0],"once",n)==0 ){
      bOnce = 1;
    }
    for(i=1; i<nArg; i++){
      char *z = azArg[i];
      if( z[0]=='-' ){
        if( z[1]=='-' ) z++;
-
        if( strcmp(z,"-bom")==0 ){
+
        if( cli_strcmp(z,"-bom")==0 ){
          zBOM[0] = 0xef;
          zBOM[1] = 0xbb;
          zBOM[2] = 0xbf;
          zBOM[3] = 0;
-
        }else if( c!='e' && strcmp(z,"-x")==0 ){
+
        }else if( c!='e' && cli_strcmp(z,"-x")==0 ){
          eMode = 'x';  /* spreadsheet */
-
        }else if( c!='e' && strcmp(z,"-e")==0 ){
+
        }else if( c!='e' && cli_strcmp(z,"-e")==0 ){
          eMode = 'e';  /* text editor */
        }else{
          utf8_printf(p->out, "ERROR: unknown option: \"%s\".  Usage:\n",
@@ -20863,7 +23643,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    }else{
      p->out = output_file_open(zFile, bTxtMode);
      if( p->out==0 ){
-
        if( strcmp(zFile,"off")!=0 ){
+
        if( cli_strcmp(zFile,"off")!=0 ){
          utf8_printf(stderr,"Error: cannot write to \"%s\"\n", zFile);
        }
        p->out = stdout;
@@ -20875,16 +23655,16 @@ static int do_meta_command(char *zLine, ShellState *p){
    }
    sqlite3_free(zFile);
  }else
-
#endif /* !defined(SQLITE_SHELL_WASM_MODE) */
+
#endif /* !defined(SQLITE_SHELL_FIDDLE) */

-
  if( c=='p' && n>=3 && strncmp(azArg[0], "parameter", n)==0 ){
+
  if( c=='p' && n>=3 && cli_strncmp(azArg[0], "parameter", n)==0 ){
    open_db(p,0);
    if( nArg<=1 ) goto parameter_syntax_error;

    /* .parameter clear
    ** Clear all bind parameters by dropping the TEMP table that holds them.
    */
-
    if( nArg==2 && strcmp(azArg[1],"clear")==0 ){
+
    if( nArg==2 && cli_strcmp(azArg[1],"clear")==0 ){
      sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp.sqlite_parameters;",
                   0, 0, 0);
    }else
@@ -20892,7 +23672,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    /* .parameter list
    ** List all bind parameters.
    */
-
    if( nArg==2 && strcmp(azArg[1],"list")==0 ){
+
    if( nArg==2 && cli_strcmp(azArg[1],"list")==0 ){
      sqlite3_stmt *pStmt = 0;
      int rx;
      int len = 0;
@@ -20921,7 +23701,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    ** Make sure the TEMP table used to hold bind parameters exists.
    ** Create it if necessary.
    */
-
    if( nArg==2 && strcmp(azArg[1],"init")==0 ){
+
    if( nArg==2 && cli_strcmp(azArg[1],"init")==0 ){
      bind_table_init(p);
    }else

@@ -20931,7 +23711,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    ** VALUE can be in either SQL literal notation, or if not it will be
    ** understood to be a text string.
    */
-
    if( nArg==4 && strcmp(azArg[1],"set")==0 ){
+
    if( nArg==4 && cli_strcmp(azArg[1],"set")==0 ){
      int rx;
      char *zSql;
      sqlite3_stmt *pStmt;
@@ -20969,7 +23749,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    ** Remove the NAME binding from the parameter binding table, if it
    ** exists.
    */
-
    if( nArg==3 && strcmp(azArg[1],"unset")==0 ){
+
    if( nArg==3 && cli_strcmp(azArg[1],"unset")==0 ){
      char *zSql = sqlite3_mprintf(
          "DELETE FROM temp.sqlite_parameters WHERE key=%Q", azArg[2]);
      shell_check_oom(zSql);
@@ -20981,7 +23761,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    showHelp(p->out, "parameter");
  }else

-
  if( c=='p' && n>=3 && strncmp(azArg[0], "print", n)==0 ){
+
  if( c=='p' && n>=3 && cli_strncmp(azArg[0], "print", n)==0 ){
    int i;
    for(i=1; i<nArg; i++){
      if( i>1 ) raw_printf(p->out, " ");
@@ -20991,7 +23771,7 @@ static int do_meta_command(char *zLine, ShellState *p){
  }else

#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
-
  if( c=='p' && n>=3 && strncmp(azArg[0], "progress", n)==0 ){
+
  if( c=='p' && n>=3 && cli_strncmp(azArg[0], "progress", n)==0 ){
    int i;
    int nn = 0;
    p->flgProgress = 0;
@@ -21002,19 +23782,19 @@ static int do_meta_command(char *zLine, ShellState *p){
      if( z[0]=='-' ){
        z++;
        if( z[0]=='-' ) z++;
-
        if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){
+
        if( cli_strcmp(z,"quiet")==0 || cli_strcmp(z,"q")==0 ){
          p->flgProgress |= SHELL_PROGRESS_QUIET;
          continue;
        }
-
        if( strcmp(z,"reset")==0 ){
+
        if( cli_strcmp(z,"reset")==0 ){
          p->flgProgress |= SHELL_PROGRESS_RESET;
          continue;
        }
-
        if( strcmp(z,"once")==0 ){
+
        if( cli_strcmp(z,"once")==0 ){
          p->flgProgress |= SHELL_PROGRESS_ONCE;
          continue;
        }
-
        if( strcmp(z,"limit")==0 ){
+
        if( cli_strcmp(z,"limit")==0 ){
          if( i+1>=nArg ){
            utf8_printf(stderr, "Error: missing argument on --limit\n");
            rc = 1;
@@ -21036,7 +23816,7 @@ static int do_meta_command(char *zLine, ShellState *p){
  }else
#endif /* SQLITE_OMIT_PROGRESS_CALLBACK */

-
  if( c=='p' && strncmp(azArg[0], "prompt", n)==0 ){
+
  if( c=='p' && cli_strncmp(azArg[0], "prompt", n)==0 ){
    if( nArg >= 2) {
      strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1);
    }
@@ -21045,14 +23825,14 @@ static int do_meta_command(char *zLine, ShellState *p){
    }
  }else

-
#ifndef SQLITE_SHELL_WASM_MODE
-
  if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){
+
#ifndef SQLITE_SHELL_FIDDLE
+
  if( c=='q' && cli_strncmp(azArg[0], "quit", n)==0 ){
    rc = 2;
  }else
#endif

-
#ifndef SQLITE_SHELL_WASM_MODE
-
  if( c=='r' && n>=3 && strncmp(azArg[0], "read", n)==0 ){
+
#ifndef SQLITE_SHELL_FIDDLE
+
  if( c=='r' && n>=3 && cli_strncmp(azArg[0], "read", n)==0 ){
    FILE *inSaved = p->in;
    int savedLineno = p->lineno;
    failIfSafeMode(p, "cannot run .read in safe mode");
@@ -21086,10 +23866,10 @@ static int do_meta_command(char *zLine, ShellState *p){
    p->in = inSaved;
    p->lineno = savedLineno;
  }else
-
#endif /* !defined(SQLITE_SHELL_WASM_MODE) */
+
#endif /* !defined(SQLITE_SHELL_FIDDLE) */

-
#ifndef SQLITE_SHELL_WASM_MODE
-
  if( c=='r' && n>=3 && strncmp(azArg[0], "restore", n)==0 ){
+
#ifndef SQLITE_SHELL_FIDDLE
+
  if( c=='r' && n>=3 && cli_strncmp(azArg[0], "restore", n)==0 ){
    const char *zSrcFile;
    const char *zDb;
    sqlite3 *pSrc;
@@ -21140,9 +23920,9 @@ static int do_meta_command(char *zLine, ShellState *p){
    }
    close_db(pSrc);
  }else
-
#endif /* !defined(SQLITE_SHELL_WASM_MODE) */
+
#endif /* !defined(SQLITE_SHELL_FIDDLE) */

-
  if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){
+
  if( c=='s' && cli_strncmp(azArg[0], "scanstats", n)==0 ){
    if( nArg==2 ){
      p->scanstatsOn = (u8)booleanValue(azArg[1]);
#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
@@ -21154,7 +23934,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    }
  }else

-
  if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
+
  if( c=='s' && cli_strncmp(azArg[0], "schema", n)==0 ){
    ShellText sSelect;
    ShellState data;
    char *zErrMsg = 0;
@@ -21297,15 +24077,15 @@ static int do_meta_command(char *zLine, ShellState *p){
    }
  }else

-
  if( (c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0)
-
   || (c=='t' && n==9  && strncmp(azArg[0], "treetrace", n)==0)
+
  if( (c=='s' && n==11 && cli_strncmp(azArg[0], "selecttrace", n)==0)
+
   || (c=='t' && n==9  && cli_strncmp(azArg[0], "treetrace", n)==0)
  ){
    unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
    sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 1, &x);
  }else

#if defined(SQLITE_ENABLE_SESSION)
-
  if( c=='s' && strncmp(azArg[0],"session",n)==0 && n>=3 ){
+
  if( c=='s' && cli_strncmp(azArg[0],"session",n)==0 && n>=3 ){
    struct AuxDb *pAuxDb = p->pAuxDb;
    OpenSession *pSession = &pAuxDb->aSession[0];
    char **azCmd = &azArg[1];
@@ -21316,7 +24096,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    open_db(p, 0);
    if( nArg>=3 ){
      for(iSes=0; iSes<pAuxDb->nSession; iSes++){
-
        if( strcmp(pAuxDb->aSession[iSes].zName, azArg[1])==0 ) break;
+
        if( cli_strcmp(pAuxDb->aSession[iSes].zName, azArg[1])==0 ) break;
      }
      if( iSes<pAuxDb->nSession ){
        pSession = &pAuxDb->aSession[iSes];
@@ -21332,7 +24112,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    ** Invoke the sqlite3session_attach() interface to attach a particular
    ** table so that it is never filtered.
    */
-
    if( strcmp(azCmd[0],"attach")==0 ){
+
    if( cli_strcmp(azCmd[0],"attach")==0 ){
      if( nCmd!=2 ) goto session_syntax_error;
      if( pSession->p==0 ){
        session_not_open:
@@ -21350,7 +24130,9 @@ static int do_meta_command(char *zLine, ShellState *p){
    ** .session patchset FILE
    ** Write a changeset or patchset into a file.  The file is overwritten.
    */
-
    if( strcmp(azCmd[0],"changeset")==0 || strcmp(azCmd[0],"patchset")==0 ){
+
    if( cli_strcmp(azCmd[0],"changeset")==0
+
     || cli_strcmp(azCmd[0],"patchset")==0
+
    ){
      FILE *out = 0;
      failIfSafeMode(p, "cannot run \".session %s\" in safe mode", azCmd[0]);
      if( nCmd!=2 ) goto session_syntax_error;
@@ -21384,7 +24166,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    /* .session close
    ** Close the identified session
    */
-
    if( strcmp(azCmd[0], "close")==0 ){
+
    if( cli_strcmp(azCmd[0], "close")==0 ){
      if( nCmd!=1 ) goto session_syntax_error;
      if( pAuxDb->nSession ){
        session_close(pSession);
@@ -21395,7 +24177,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    /* .session enable ?BOOLEAN?
    ** Query or set the enable flag
    */
-
    if( strcmp(azCmd[0], "enable")==0 ){
+
    if( cli_strcmp(azCmd[0], "enable")==0 ){
      int ii;
      if( nCmd>2 ) goto session_syntax_error;
      ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
@@ -21409,7 +24191,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    /* .session filter GLOB ....
    ** Set a list of GLOB patterns of table names to be excluded.
    */
-
    if( strcmp(azCmd[0], "filter")==0 ){
+
    if( cli_strcmp(azCmd[0], "filter")==0 ){
      int ii, nByte;
      if( nCmd<2 ) goto session_syntax_error;
      if( pAuxDb->nSession ){
@@ -21434,7 +24216,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    /* .session indirect ?BOOLEAN?
    ** Query or set the indirect flag
    */
-
    if( strcmp(azCmd[0], "indirect")==0 ){
+
    if( cli_strcmp(azCmd[0], "indirect")==0 ){
      int ii;
      if( nCmd>2 ) goto session_syntax_error;
      ii = nCmd==1 ? -1 : booleanValue(azCmd[1]);
@@ -21448,7 +24230,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    /* .session isempty
    ** Determine if the session is empty
    */
-
    if( strcmp(azCmd[0], "isempty")==0 ){
+
    if( cli_strcmp(azCmd[0], "isempty")==0 ){
      int ii;
      if( nCmd!=1 ) goto session_syntax_error;
      if( pAuxDb->nSession ){
@@ -21461,7 +24243,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    /* .session list
    ** List all currently open sessions
    */
-
    if( strcmp(azCmd[0],"list")==0 ){
+
    if( cli_strcmp(azCmd[0],"list")==0 ){
      for(i=0; i<pAuxDb->nSession; i++){
        utf8_printf(p->out, "%d %s\n", i, pAuxDb->aSession[i].zName);
      }
@@ -21471,13 +24253,13 @@ static int do_meta_command(char *zLine, ShellState *p){
    ** Open a new session called NAME on the attached database DB.
    ** DB is normally "main".
    */
-
    if( strcmp(azCmd[0],"open")==0 ){
+
    if( cli_strcmp(azCmd[0],"open")==0 ){
      char *zName;
      if( nCmd!=3 ) goto session_syntax_error;
      zName = azCmd[2];
      if( zName[0]==0 ) goto session_syntax_error;
      for(i=0; i<pAuxDb->nSession; i++){
-
        if( strcmp(pAuxDb->aSession[i].zName,zName)==0 ){
+
        if( cli_strcmp(pAuxDb->aSession[i].zName,zName)==0 ){
          utf8_printf(stderr, "Session \"%s\" already exists\n", zName);
          goto meta_command_exit;
        }
@@ -21508,15 +24290,15 @@ static int do_meta_command(char *zLine, ShellState *p){
#ifdef SQLITE_DEBUG
  /* Undocumented commands for internal testing.  Subject to change
  ** without notice. */
-
  if( c=='s' && n>=10 && strncmp(azArg[0], "selftest-", 9)==0 ){
-
    if( strncmp(azArg[0]+9, "boolean", n-9)==0 ){
+
  if( c=='s' && n>=10 && cli_strncmp(azArg[0], "selftest-", 9)==0 ){
+
    if( cli_strncmp(azArg[0]+9, "boolean", n-9)==0 ){
      int i, v;
      for(i=1; i<nArg; i++){
        v = booleanValue(azArg[i]);
        utf8_printf(p->out, "%s: %d 0x%x\n", azArg[i], v, v);
      }
    }
-
    if( strncmp(azArg[0]+9, "integer", n-9)==0 ){
+
    if( cli_strncmp(azArg[0]+9, "integer", n-9)==0 ){
      int i; sqlite3_int64 v;
      for(i=1; i<nArg; i++){
        char zBuf[200];
@@ -21528,7 +24310,7 @@ static int do_meta_command(char *zLine, ShellState *p){
  }else
#endif

-
  if( c=='s' && n>=4 && strncmp(azArg[0],"selftest",n)==0 ){
+
  if( c=='s' && n>=4 && cli_strncmp(azArg[0],"selftest",n)==0 ){
    int bIsInit = 0;         /* True to initialize the SELFTEST table */
    int bVerbose = 0;        /* Verbose output */
    int bSelftestExists;     /* True if SELFTEST already exists */
@@ -21542,10 +24324,10 @@ static int do_meta_command(char *zLine, ShellState *p){
    for(i=1; i<nArg; i++){
      const char *z = azArg[i];
      if( z[0]=='-' && z[1]=='-' ) z++;
-
      if( strcmp(z,"-init")==0 ){
+
      if( cli_strcmp(z,"-init")==0 ){
        bIsInit = 1;
      }else
-
      if( strcmp(z,"-v")==0 ){
+
      if( cli_strcmp(z,"-v")==0 ){
        bVerbose++;
      }else
      {
@@ -21598,10 +24380,10 @@ static int do_meta_command(char *zLine, ShellState *p){
        if( bVerbose>0 ){
          printf("%d: %s %s\n", tno, zOp, zSql);
        }
-
        if( strcmp(zOp,"memo")==0 ){
+
        if( cli_strcmp(zOp,"memo")==0 ){
          utf8_printf(p->out, "%s\n", zSql);
        }else
-
        if( strcmp(zOp,"run")==0 ){
+
        if( cli_strcmp(zOp,"run")==0 ){
          char *zErrMsg = 0;
          str.n = 0;
          str.z[0] = 0;
@@ -21615,7 +24397,7 @@ static int do_meta_command(char *zLine, ShellState *p){
            rc = 1;
            utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg);
            sqlite3_free(zErrMsg);
-
          }else if( strcmp(zAns,str.z)!=0 ){
+
          }else if( cli_strcmp(zAns,str.z)!=0 ){
            nErr++;
            rc = 1;
            utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns);
@@ -21635,7 +24417,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    utf8_printf(p->out, "%d errors out of %d tests\n", nErr, nTest);
  }else

-
  if( c=='s' && strncmp(azArg[0], "separator", n)==0 ){
+
  if( c=='s' && cli_strncmp(azArg[0], "separator", n)==0 ){
    if( nArg<2 || nArg>3 ){
      raw_printf(stderr, "Usage: .separator COL ?ROW?\n");
      rc = 1;
@@ -21650,7 +24432,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    }
  }else

-
  if( c=='s' && n>=4 && strncmp(azArg[0],"sha3sum",n)==0 ){
+
  if( c=='s' && n>=4 && cli_strncmp(azArg[0],"sha3sum",n)==0 ){
    const char *zLike = 0;   /* Which table to checksum. 0 means everything */
    int i;                   /* Loop counter */
    int bSchema = 0;         /* Also hash the schema */
@@ -21668,15 +24450,15 @@ static int do_meta_command(char *zLine, ShellState *p){
      if( z[0]=='-' ){
        z++;
        if( z[0]=='-' ) z++;
-
        if( strcmp(z,"schema")==0 ){
+
        if( cli_strcmp(z,"schema")==0 ){
          bSchema = 1;
        }else
-
        if( strcmp(z,"sha3-224")==0 || strcmp(z,"sha3-256")==0
-
         || strcmp(z,"sha3-384")==0 || strcmp(z,"sha3-512")==0
+
        if( cli_strcmp(z,"sha3-224")==0 || cli_strcmp(z,"sha3-256")==0
+
         || cli_strcmp(z,"sha3-384")==0 || cli_strcmp(z,"sha3-512")==0
        ){
          iSize = atoi(&z[5]);
        }else
-
        if( strcmp(z,"debug")==0 ){
+
        if( cli_strcmp(z,"debug")==0 ){
          bDebug = 1;
        }else
        {
@@ -21716,20 +24498,20 @@ static int do_meta_command(char *zLine, ShellState *p){
      const char *zTab = (const char*)sqlite3_column_text(pStmt,0);
      if( zTab==0 ) continue;
      if( zLike && sqlite3_strlike(zLike, zTab, 0)!=0 ) continue;
-
      if( strncmp(zTab, "sqlite_",7)!=0 ){
+
      if( cli_strncmp(zTab, "sqlite_",7)!=0 ){
        appendText(&sQuery,"SELECT * FROM ", 0);
        appendText(&sQuery,zTab,'"');
        appendText(&sQuery," NOT INDEXED;", 0);
-
      }else if( strcmp(zTab, "sqlite_schema")==0 ){
+
      }else if( cli_strcmp(zTab, "sqlite_schema")==0 ){
        appendText(&sQuery,"SELECT type,name,tbl_name,sql FROM sqlite_schema"
                           " ORDER BY name;", 0);
-
      }else if( strcmp(zTab, "sqlite_sequence")==0 ){
+
      }else if( cli_strcmp(zTab, "sqlite_sequence")==0 ){
        appendText(&sQuery,"SELECT name,seq FROM sqlite_sequence"
                           " ORDER BY name;", 0);
-
      }else if( strcmp(zTab, "sqlite_stat1")==0 ){
+
      }else if( cli_strcmp(zTab, "sqlite_stat1")==0 ){
        appendText(&sQuery,"SELECT tbl,idx,stat FROM sqlite_stat1"
                           " ORDER BY tbl,idx;", 0);
-
      }else if( strcmp(zTab, "sqlite_stat4")==0 ){
+
      }else if( cli_strcmp(zTab, "sqlite_stat4")==0 ){
        appendText(&sQuery, "SELECT * FROM ", 0);
        appendText(&sQuery, zTab, 0);
        appendText(&sQuery, " ORDER BY tbl, idx, rowid;\n", 0);
@@ -21766,9 +24548,10 @@ static int do_meta_command(char *zLine, ShellState *p){
    sqlite3_free(zSql);
  }else

-
#if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_WASM_MODE)
+
#if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE)
  if( c=='s'
-
   && (strncmp(azArg[0], "shell", n)==0 || strncmp(azArg[0],"system",n)==0)
+
   && (cli_strncmp(azArg[0], "shell", n)==0
+
       || cli_strncmp(azArg[0],"system",n)==0)
  ){
    char *zCmd;
    int i, x;
@@ -21787,9 +24570,9 @@ static int do_meta_command(char *zLine, ShellState *p){
    sqlite3_free(zCmd);
    if( x ) raw_printf(stderr, "System command returns %d\n", x);
  }else
-
#endif /* !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_WASM_MODE) */
+
#endif /* !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE) */

-
  if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
+
  if( c=='s' && cli_strncmp(azArg[0], "show", n)==0 ){
    static const char *azBool[] = { "off", "on", "trigger", "full"};
    const char *zOut;
    int i;
@@ -21842,11 +24625,11 @@ static int do_meta_command(char *zLine, ShellState *p){
                p->pAuxDb->zDbFilename ? p->pAuxDb->zDbFilename : "");
  }else

-
  if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){
+
  if( c=='s' && cli_strncmp(azArg[0], "stats", n)==0 ){
    if( nArg==2 ){
-
      if( strcmp(azArg[1],"stmt")==0 ){
+
      if( cli_strcmp(azArg[1],"stmt")==0 ){
        p->statsOn = 2;
-
      }else if( strcmp(azArg[1],"vmstep")==0 ){
+
      }else if( cli_strcmp(azArg[1],"vmstep")==0 ){
        p->statsOn = 3;
      }else{
        p->statsOn = (u8)booleanValue(azArg[1]);
@@ -21859,9 +24642,9 @@ static int do_meta_command(char *zLine, ShellState *p){
    }
  }else

-
  if( (c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0)
-
   || (c=='i' && (strncmp(azArg[0], "indices", n)==0
-
                 || strncmp(azArg[0], "indexes", n)==0) )
+
  if( (c=='t' && n>1 && cli_strncmp(azArg[0], "tables", n)==0)
+
   || (c=='i' && (cli_strncmp(azArg[0], "indices", n)==0
+
                 || cli_strncmp(azArg[0], "indexes", n)==0) )
  ){
    sqlite3_stmt *pStmt;
    char **azResult;
@@ -21967,9 +24750,9 @@ static int do_meta_command(char *zLine, ShellState *p){
    sqlite3_free(azResult);
  }else

-
#ifndef SQLITE_SHELL_WASM_MODE
+
#ifndef SQLITE_SHELL_FIDDLE
  /* Begin redirecting output to the file "testcase-out.txt" */
-
  if( c=='t' && strcmp(azArg[0],"testcase")==0 ){
+
  if( c=='t' && cli_strcmp(azArg[0],"testcase")==0 ){
    output_reset(p);
    p->out = output_file_open("testcase-out.txt", 0);
    if( p->out==0 ){
@@ -21981,10 +24764,10 @@ static int do_meta_command(char *zLine, ShellState *p){
      sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?");
    }
  }else
-
#endif /* !defined(SQLITE_SHELL_WASM_MODE) */
+
#endif /* !defined(SQLITE_SHELL_FIDDLE) */

#ifndef SQLITE_UNTESTABLE
-
  if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 ){
+
  if( c=='t' && n>=8 && cli_strncmp(azArg[0], "testctrl", n)==0 ){
    static const struct {
       const char *zCtrlName;   /* Name of a test-control option */
       int ctrlCode;            /* Integer code for that option */
@@ -22031,7 +24814,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    }

    /* --help lists all test-controls */
-
    if( strcmp(zCmd,"help")==0 ){
+
    if( cli_strcmp(zCmd,"help")==0 ){
      utf8_printf(p->out, "Available test-controls:\n");
      for(i=0; i<ArraySize(aCtrl); i++){
        utf8_printf(p->out, "  .testctrl %s %s\n",
@@ -22045,7 +24828,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    ** of the option name, or a numerical value. */
    n2 = strlen30(zCmd);
    for(i=0; i<ArraySize(aCtrl); i++){
-
      if( strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
+
      if( cli_strncmp(zCmd, aCtrl[i].zCtrlName, n2)==0 ){
        if( testctrl<0 ){
          testctrl = aCtrl[i].ctrlCode;
          iCtrl = i;
@@ -22101,7 +24884,7 @@ static int do_meta_command(char *zLine, ShellState *p){
          if( nArg==3 || nArg==4 ){
            int ii = (int)integerValue(azArg[2]);
            sqlite3 *db;
-
            if( ii==0 && strcmp(azArg[2],"random")==0 ){
+
            if( ii==0 && cli_strcmp(azArg[2],"random")==0 ){
              sqlite3_randomness(sizeof(ii),&ii);
              printf("-- random seed: %d\n", ii);
            }
@@ -22217,12 +25000,12 @@ static int do_meta_command(char *zLine, ShellState *p){
  }else
#endif /* !defined(SQLITE_UNTESTABLE) */

-
  if( c=='t' && n>4 && strncmp(azArg[0], "timeout", n)==0 ){
+
  if( c=='t' && n>4 && cli_strncmp(azArg[0], "timeout", n)==0 ){
    open_db(p, 0);
    sqlite3_busy_timeout(p->db, nArg>=2 ? (int)integerValue(azArg[1]) : 0);
  }else

-
  if( c=='t' && n>=5 && strncmp(azArg[0], "timer", n)==0 ){
+
  if( c=='t' && n>=5 && cli_strncmp(azArg[0], "timer", n)==0 ){
    if( nArg==2 ){
      enableTimer = booleanValue(azArg[1]);
      if( enableTimer && !HAS_TIMER ){
@@ -22236,7 +25019,7 @@ static int do_meta_command(char *zLine, ShellState *p){
  }else

#ifndef SQLITE_OMIT_TRACE
-
  if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){
+
  if( c=='t' && cli_strncmp(azArg[0], "trace", n)==0 ){
    int mType = 0;
    int jj;
    open_db(p, 0);
@@ -22286,7 +25069,7 @@ static int do_meta_command(char *zLine, ShellState *p){
#endif /* !defined(SQLITE_OMIT_TRACE) */

#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_VIRTUALTABLE)
-
  if( c=='u' && strncmp(azArg[0], "unmodule", n)==0 ){
+
  if( c=='u' && cli_strncmp(azArg[0], "unmodule", n)==0 ){
    int ii;
    int lenOpt;
    char *zOpt;
@@ -22299,7 +25082,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    zOpt = azArg[1];
    if( zOpt[0]=='-' && zOpt[1]=='-' && zOpt[2]!=0 ) zOpt++;
    lenOpt = (int)strlen(zOpt);
-
    if( lenOpt>=3 && strncmp(zOpt, "-allexcept",lenOpt)==0 ){
+
    if( lenOpt>=3 && cli_strncmp(zOpt, "-allexcept",lenOpt)==0 ){
      assert( azArg[nArg]==0 );
      sqlite3_drop_modules(p->db, nArg>2 ? (const char**)(azArg+2) : 0);
    }else{
@@ -22311,14 +25094,14 @@ static int do_meta_command(char *zLine, ShellState *p){
#endif

#if SQLITE_USER_AUTHENTICATION
-
  if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
+
  if( c=='u' && cli_strncmp(azArg[0], "user", n)==0 ){
    if( nArg<2 ){
      raw_printf(stderr, "Usage: .user SUBCOMMAND ...\n");
      rc = 1;
      goto meta_command_exit;
    }
    open_db(p, 0);
-
    if( strcmp(azArg[1],"login")==0 ){
+
    if( cli_strcmp(azArg[1],"login")==0 ){
      if( nArg!=4 ){
        raw_printf(stderr, "Usage: .user login USER PASSWORD\n");
        rc = 1;
@@ -22330,7 +25113,7 @@ static int do_meta_command(char *zLine, ShellState *p){
        utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]);
        rc = 1;
      }
-
    }else if( strcmp(azArg[1],"add")==0 ){
+
    }else if( cli_strcmp(azArg[1],"add")==0 ){
      if( nArg!=5 ){
        raw_printf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n");
        rc = 1;
@@ -22342,7 +25125,7 @@ static int do_meta_command(char *zLine, ShellState *p){
        raw_printf(stderr, "User-Add failed: %d\n", rc);
        rc = 1;
      }
-
    }else if( strcmp(azArg[1],"edit")==0 ){
+
    }else if( cli_strcmp(azArg[1],"edit")==0 ){
      if( nArg!=5 ){
        raw_printf(stderr, "Usage: .user edit USER PASSWORD ISADMIN\n");
        rc = 1;
@@ -22354,7 +25137,7 @@ static int do_meta_command(char *zLine, ShellState *p){
        raw_printf(stderr, "User-Edit failed: %d\n", rc);
        rc = 1;
      }
-
    }else if( strcmp(azArg[1],"delete")==0 ){
+
    }else if( cli_strcmp(azArg[1],"delete")==0 ){
      if( nArg!=3 ){
        raw_printf(stderr, "Usage: .user delete USER\n");
        rc = 1;
@@ -22373,7 +25156,7 @@ static int do_meta_command(char *zLine, ShellState *p){
  }else
#endif /* SQLITE_USER_AUTHENTICATION */

-
  if( c=='v' && strncmp(azArg[0], "version", n)==0 ){
+
  if( c=='v' && cli_strncmp(azArg[0], "version", n)==0 ){
    utf8_printf(p->out, "SQLite %s %s\n" /*extra-version-info*/,
        sqlite3_libversion(), sqlite3_sourceid());
#if SQLITE_HAVE_ZLIB
@@ -22392,7 +25175,7 @@ static int do_meta_command(char *zLine, ShellState *p){
#endif
  }else

-
  if( c=='v' && strncmp(azArg[0], "vfsinfo", n)==0 ){
+
  if( c=='v' && cli_strncmp(azArg[0], "vfsinfo", n)==0 ){
    const char *zDbName = nArg==2 ? azArg[1] : "main";
    sqlite3_vfs *pVfs = 0;
    if( p->db ){
@@ -22406,7 +25189,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    }
  }else

-
  if( c=='v' && strncmp(azArg[0], "vfslist", n)==0 ){
+
  if( c=='v' && cli_strncmp(azArg[0], "vfslist", n)==0 ){
    sqlite3_vfs *pVfs;
    sqlite3_vfs *pCurrent = 0;
    if( p->db ){
@@ -22424,7 +25207,7 @@ static int do_meta_command(char *zLine, ShellState *p){
    }
  }else

-
  if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){
+
  if( c=='v' && cli_strncmp(azArg[0], "vfsname", n)==0 ){
    const char *zDbName = nArg==2 ? azArg[1] : "main";
    char *zVfsName = 0;
    if( p->db ){
@@ -22436,12 +25219,12 @@ static int do_meta_command(char *zLine, ShellState *p){
    }
  }else

-
  if( c=='w' && strncmp(azArg[0], "wheretrace", n)==0 ){
+
  if( c=='w' && cli_strncmp(azArg[0], "wheretrace", n)==0 ){
    unsigned int x = nArg>=2 ? (unsigned int)integerValue(azArg[1]) : 0xffffffff;
    sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, 3, &x);
  }else

-
  if( c=='w' && strncmp(azArg[0], "width", n)==0 ){
+
  if( c=='w' && cli_strncmp(azArg[0], "width", n)==0 ){
    int j;
    assert( nArg<=ArraySize(azArg) );
    p->nWidth = nArg-1;
@@ -22619,10 +25402,10 @@ static int runOneSqlLine(ShellState *p, char *zSql, FILE *in, int startline){
    if( zErrMsg==0 ){
      zErrorType = "Error";
      zErrorTail = sqlite3_errmsg(p->db);
-
    }else if( strncmp(zErrMsg, "in prepare, ",12)==0 ){
+
    }else if( cli_strncmp(zErrMsg, "in prepare, ",12)==0 ){
      zErrorType = "Parse error";
      zErrorTail = &zErrMsg[12];
-
    }else if( strncmp(zErrMsg, "stepping, ", 10)==0 ){
+
    }else if( cli_strncmp(zErrMsg, "stepping, ", 10)==0 ){
      zErrorType = "Runtime error";
      zErrorTail = &zErrMsg[10];
    }else{
@@ -22653,7 +25436,7 @@ static void echo_group_input(ShellState *p, const char *zDo){
  if( ShellHasFlag(p, SHFLG_Echo) ) utf8_printf(p->out, "%s\n", zDo);
}

-
#ifdef SQLITE_SHELL_WASM_MODE
+
#ifdef SQLITE_SHELL_FIDDLE
/*
** Alternate one_input_line() impl for wasm mode. This is not in the primary impl
** because we need the global shellState and cannot access it from that function
@@ -22664,7 +25447,7 @@ static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
  const char *zBegin = shellState.wasm.zPos;
  const char *z = zBegin;
  char *zLine = 0;
-
  int nZ = 0;
+
  i64 nZ = 0;

  UNUSED_PARAMETER(in);
  UNUSED_PARAMETER(isContinuation);
@@ -22680,11 +25463,11 @@ static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
  shellState.wasm.zPos = z;
  zLine = realloc(zPrior, nZ+1);
  shell_check_oom(zLine);
-
  memcpy(zLine, zBegin, (size_t)nZ);
+
  memcpy(zLine, zBegin, nZ);
  zLine[nZ] = 0;
  return zLine;
}
-
#endif /* SQLITE_SHELL_WASM_MODE */
+
#endif /* SQLITE_SHELL_FIDDLE */

/*
** Read input from *in and process it.  If *in==0 then input
@@ -22698,12 +25481,12 @@ static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
static int process_input(ShellState *p){
  char *zLine = 0;          /* A single input line */
  char *zSql = 0;           /* Accumulated SQL text */
-
  int nLine;                /* Length of current line */
-
  int nSql = 0;             /* Bytes of zSql[] used */
-
  int nAlloc = 0;           /* Allocated zSql[] space */
+
  i64 nLine;                /* Length of current line */
+
  i64 nSql = 0;             /* Bytes of zSql[] used */
+
  i64 nAlloc = 0;           /* Allocated zSql[] space */
  int rc;                   /* Error code */
  int errCnt = 0;           /* Number of errors seen */
-
  int startline = 0;        /* Line number for start of current input */
+
  i64 startline = 0;        /* Line number for start of current input */
  QuickScanState qss = QSS_Start; /* Accumulated line status (so far) */

  if( p->inputNesting==MAX_INPUT_NESTING ){
@@ -22753,7 +25536,7 @@ static int process_input(ShellState *p){
      continue;
    }
    /* No single-line dispositions remain; accumulate line(s). */
-
    nLine = strlen30(zLine);
+
    nLine = strlen(zLine);
    if( nSql+nLine+2>=nAlloc ){
      /* Grow buffer by half-again increments when big. */
      nAlloc = nSql+(nSql>>1)+nLine+100;
@@ -22761,7 +25544,7 @@ static int process_input(ShellState *p){
      shell_check_oom(zSql);
    }
    if( nSql==0 ){
-
      int i;
+
      i64 i;
      for(i=0; zLine[i] && IsSpace(zLine[i]); i++){}
      assert( nAlloc>0 && zSql!=0 );
      memcpy(zSql, zLine+i, nLine+1-i);
@@ -22861,7 +25644,7 @@ static char *find_home_dir(int clearFlag){
#endif /* !_WIN32_WCE */

  if( home_dir ){
-
    int n = strlen30(home_dir) + 1;
+
    i64 n = strlen(home_dir) + 1;
    char *z = malloc( n );
    if( z ) memcpy(z, home_dir, n);
    home_dir = z;
@@ -23067,7 +25850,7 @@ static char *cmdline_option_value(int argc, char **argv, int i){
#  endif
#endif

-
#ifdef SQLITE_SHELL_WASM_MODE
+
#ifdef SQLITE_SHELL_FIDDLE
#  define main fiddle_main
#endif

@@ -23081,7 +25864,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
  sqlite3_int64 mem_main_enter = sqlite3_memory_used();
#endif
  char *zErrMsg = 0;
-
#ifdef SQLITE_SHELL_WASM_MODE
+
#ifdef SQLITE_SHELL_FIDDLE
#  define data shellState
#else
  ShellState data;
@@ -23101,9 +25884,10 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){

  setBinaryMode(stdin, 0);
  setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
-
#ifdef SQLITE_SHELL_WASM_MODE
+
#ifdef SQLITE_SHELL_FIDDLE
  stdin_is_interactive = 0;
  stdout_is_console = 1;
+
  data.wasm.zDefaultDbName = "/fiddle.sqlite3";
#else
  stdin_is_interactive = isatty(0);
  stdout_is_console = isatty(1);
@@ -23131,7 +25915,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
#endif

#if USE_SYSTEM_SQLITE+0!=1
-
  if( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){
+
  if( cli_strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){
    utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
            sqlite3_sourceid(), SQLITE_SOURCE_ID);
    exit(1);
@@ -23153,9 +25937,9 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
  argv = argvToFree + argc;
  for(i=0; i<argc; i++){
    char *z = sqlite3_win32_unicode_to_utf8(wargv[i]);
-
    int n;
+
    i64 n;
    shell_check_oom(z);
-
    n = (int)strlen(z);
+
    n = strlen(z);
    argv[i] = malloc( n+1 );
    shell_check_oom(argv[i]);
    memcpy(argv[i], z, n+1);
@@ -23212,21 +25996,21 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
      }
    }
    if( z[1]=='-' ) z++;
-
    if( strcmp(z,"-separator")==0
-
     || strcmp(z,"-nullvalue")==0
-
     || strcmp(z,"-newline")==0
-
     || strcmp(z,"-cmd")==0
+
    if( cli_strcmp(z,"-separator")==0
+
     || cli_strcmp(z,"-nullvalue")==0
+
     || cli_strcmp(z,"-newline")==0
+
     || cli_strcmp(z,"-cmd")==0
    ){
      (void)cmdline_option_value(argc, argv, ++i);
-
    }else if( strcmp(z,"-init")==0 ){
+
    }else if( cli_strcmp(z,"-init")==0 ){
      zInitFile = cmdline_option_value(argc, argv, ++i);
-
    }else if( strcmp(z,"-batch")==0 ){
+
    }else if( cli_strcmp(z,"-batch")==0 ){
      /* Need to check for batch mode here to so we can avoid printing
      ** informational messages (like from process_sqliterc) before
      ** we do the actual processing of arguments later in a second pass.
      */
      stdin_is_interactive = 0;
-
    }else if( strcmp(z,"-heap")==0 ){
+
    }else if( cli_strcmp(z,"-heap")==0 ){
#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
      const char *zSize;
      sqlite3_int64 szHeap;
@@ -23238,7 +26022,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
#else
      (void)cmdline_option_value(argc, argv, ++i);
#endif
-
    }else if( strcmp(z,"-pagecache")==0 ){
+
    }else if( cli_strcmp(z,"-pagecache")==0 ){
      sqlite3_int64 n, sz;
      sz = integerValue(cmdline_option_value(argc,argv,++i));
      if( sz>70000 ) sz = 70000;
@@ -23250,7 +26034,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
      sqlite3_config(SQLITE_CONFIG_PAGECACHE,
                    (n>0 && sz>0) ? malloc(n*sz) : 0, sz, n);
      data.shellFlgs |= SHFLG_Pagecache;
-
    }else if( strcmp(z,"-lookaside")==0 ){
+
    }else if( cli_strcmp(z,"-lookaside")==0 ){
      int n, sz;
      sz = (int)integerValue(cmdline_option_value(argc,argv,++i));
      if( sz<0 ) sz = 0;
@@ -23258,7 +26042,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
      if( n<0 ) n = 0;
      sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, n);
      if( sz*n==0 ) data.shellFlgs &= ~SHFLG_Lookaside;
-
    }else if( strcmp(z,"-threadsafe")==0 ){
+
    }else if( cli_strcmp(z,"-threadsafe")==0 ){
      int n;
      n = (int)integerValue(cmdline_option_value(argc,argv,++i));
      switch( n ){
@@ -23267,7 +26051,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
         default: sqlite3_config(SQLITE_CONFIG_SERIALIZED);    break;
      }
#ifdef SQLITE_ENABLE_VFSTRACE
-
    }else if( strcmp(z,"-vfstrace")==0 ){
+
    }else if( cli_strcmp(z,"-vfstrace")==0 ){
      extern int vfstrace_register(
         const char *zTraceName,
         const char *zOldVfsName,
@@ -23278,50 +26062,50 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
      vfstrace_register("trace",0,(int(*)(const char*,void*))fputs,stderr,1);
#endif
#ifdef SQLITE_ENABLE_MULTIPLEX
-
    }else if( strcmp(z,"-multiplex")==0 ){
+
    }else if( cli_strcmp(z,"-multiplex")==0 ){
      extern int sqlite3_multiple_initialize(const char*,int);
      sqlite3_multiplex_initialize(0, 1);
#endif
-
    }else if( strcmp(z,"-mmap")==0 ){
+
    }else if( cli_strcmp(z,"-mmap")==0 ){
      sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
      sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, sz, sz);
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
-
    }else if( strcmp(z,"-sorterref")==0 ){
+
    }else if( cli_strcmp(z,"-sorterref")==0 ){
      sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i));
      sqlite3_config(SQLITE_CONFIG_SORTERREF_SIZE, (int)sz);
#endif
-
    }else if( strcmp(z,"-vfs")==0 ){
+
    }else if( cli_strcmp(z,"-vfs")==0 ){
      zVfs = cmdline_option_value(argc, argv, ++i);
#ifdef SQLITE_HAVE_ZLIB
-
    }else if( strcmp(z,"-zip")==0 ){
+
    }else if( cli_strcmp(z,"-zip")==0 ){
      data.openMode = SHELL_OPEN_ZIPFILE;
#endif
-
    }else if( strcmp(z,"-append")==0 ){
+
    }else if( cli_strcmp(z,"-append")==0 ){
      data.openMode = SHELL_OPEN_APPENDVFS;
#ifndef SQLITE_OMIT_DESERIALIZE
-
    }else if( strcmp(z,"-deserialize")==0 ){
+
    }else if( cli_strcmp(z,"-deserialize")==0 ){
      data.openMode = SHELL_OPEN_DESERIALIZE;
-
    }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
+
    }else if( cli_strcmp(z,"-maxsize")==0 && i+1<argc ){
      data.szMax = integerValue(argv[++i]);
#endif
-
    }else if( strcmp(z,"-readonly")==0 ){
+
    }else if( cli_strcmp(z,"-readonly")==0 ){
      data.openMode = SHELL_OPEN_READONLY;
-
    }else if( strcmp(z,"-nofollow")==0 ){
+
    }else if( cli_strcmp(z,"-nofollow")==0 ){
      data.openFlags = SQLITE_OPEN_NOFOLLOW;
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
-
    }else if( strncmp(z, "-A",2)==0 ){
+
    }else if( cli_strncmp(z, "-A",2)==0 ){
      /* All remaining command-line arguments are passed to the ".archive"
      ** command, so ignore them */
      break;
#endif
-
    }else if( strcmp(z, "-memtrace")==0 ){
+
    }else if( cli_strcmp(z, "-memtrace")==0 ){
      sqlite3MemTraceActivate(stderr);
-
    }else if( strcmp(z,"-bail")==0 ){
+
    }else if( cli_strcmp(z,"-bail")==0 ){
      bail_on_error = 1;
-
    }else if( strcmp(z,"-nonce")==0 ){
+
    }else if( cli_strcmp(z,"-nonce")==0 ){
      free(data.zNonce);
      data.zNonce = strdup(argv[++i]);
-
    }else if( strcmp(z,"-safe")==0 ){
+
    }else if( cli_strcmp(z,"-safe")==0 ){
      /* no-op - catch this on the second pass */
    }
  }
@@ -23363,7 +26147,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
#endif
  }
  data.out = stdout;
-
#ifndef SQLITE_SHELL_WASM_MODE
+
#ifndef SQLITE_SHELL_FIDDLE
  sqlite3_appendvfs_init(0,0,0);
#endif

@@ -23391,127 +26175,127 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
    char *z = argv[i];
    if( z[0]!='-' ) continue;
    if( z[1]=='-' ){ z++; }
-
    if( strcmp(z,"-init")==0 ){
+
    if( cli_strcmp(z,"-init")==0 ){
      i++;
-
    }else if( strcmp(z,"-html")==0 ){
+
    }else if( cli_strcmp(z,"-html")==0 ){
      data.mode = MODE_Html;
-
    }else if( strcmp(z,"-list")==0 ){
+
    }else if( cli_strcmp(z,"-list")==0 ){
      data.mode = MODE_List;
-
    }else if( strcmp(z,"-quote")==0 ){
+
    }else if( cli_strcmp(z,"-quote")==0 ){
      data.mode = MODE_Quote;
      sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Comma);
      sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
-
    }else if( strcmp(z,"-line")==0 ){
+
    }else if( cli_strcmp(z,"-line")==0 ){
      data.mode = MODE_Line;
-
    }else if( strcmp(z,"-column")==0 ){
+
    }else if( cli_strcmp(z,"-column")==0 ){
      data.mode = MODE_Column;
-
    }else if( strcmp(z,"-json")==0 ){
+
    }else if( cli_strcmp(z,"-json")==0 ){
      data.mode = MODE_Json;
-
    }else if( strcmp(z,"-markdown")==0 ){
+
    }else if( cli_strcmp(z,"-markdown")==0 ){
      data.mode = MODE_Markdown;
-
    }else if( strcmp(z,"-table")==0 ){
+
    }else if( cli_strcmp(z,"-table")==0 ){
      data.mode = MODE_Table;
-
    }else if( strcmp(z,"-box")==0 ){
+
    }else if( cli_strcmp(z,"-box")==0 ){
      data.mode = MODE_Box;
-
    }else if( strcmp(z,"-csv")==0 ){
+
    }else if( cli_strcmp(z,"-csv")==0 ){
      data.mode = MODE_Csv;
      memcpy(data.colSeparator,",",2);
#ifdef SQLITE_HAVE_ZLIB
-
    }else if( strcmp(z,"-zip")==0 ){
+
    }else if( cli_strcmp(z,"-zip")==0 ){
      data.openMode = SHELL_OPEN_ZIPFILE;
#endif
-
    }else if( strcmp(z,"-append")==0 ){
+
    }else if( cli_strcmp(z,"-append")==0 ){
      data.openMode = SHELL_OPEN_APPENDVFS;
#ifndef SQLITE_OMIT_DESERIALIZE
-
    }else if( strcmp(z,"-deserialize")==0 ){
+
    }else if( cli_strcmp(z,"-deserialize")==0 ){
      data.openMode = SHELL_OPEN_DESERIALIZE;
-
    }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
+
    }else if( cli_strcmp(z,"-maxsize")==0 && i+1<argc ){
      data.szMax = integerValue(argv[++i]);
#endif
-
    }else if( strcmp(z,"-readonly")==0 ){
+
    }else if( cli_strcmp(z,"-readonly")==0 ){
      data.openMode = SHELL_OPEN_READONLY;
-
    }else if( strcmp(z,"-nofollow")==0 ){
+
    }else if( cli_strcmp(z,"-nofollow")==0 ){
      data.openFlags |= SQLITE_OPEN_NOFOLLOW;
-
    }else if( strcmp(z,"-ascii")==0 ){
+
    }else if( cli_strcmp(z,"-ascii")==0 ){
      data.mode = MODE_Ascii;
      sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Unit);
      sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Record);
-
    }else if( strcmp(z,"-tabs")==0 ){
+
    }else if( cli_strcmp(z,"-tabs")==0 ){
      data.mode = MODE_List;
      sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator, SEP_Tab);
      sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator, SEP_Row);
-
    }else if( strcmp(z,"-separator")==0 ){
+
    }else if( cli_strcmp(z,"-separator")==0 ){
      sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
                       "%s",cmdline_option_value(argc,argv,++i));
-
    }else if( strcmp(z,"-newline")==0 ){
+
    }else if( cli_strcmp(z,"-newline")==0 ){
      sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
                       "%s",cmdline_option_value(argc,argv,++i));
-
    }else if( strcmp(z,"-nullvalue")==0 ){
+
    }else if( cli_strcmp(z,"-nullvalue")==0 ){
      sqlite3_snprintf(sizeof(data.nullValue), data.nullValue,
                       "%s",cmdline_option_value(argc,argv,++i));
-
    }else if( strcmp(z,"-header")==0 ){
+
    }else if( cli_strcmp(z,"-header")==0 ){
      data.showHeader = 1;
      ShellSetFlag(&data, SHFLG_HeaderSet);
-
     }else if( strcmp(z,"-noheader")==0 ){
+
     }else if( cli_strcmp(z,"-noheader")==0 ){
      data.showHeader = 0;
      ShellSetFlag(&data, SHFLG_HeaderSet);
-
    }else if( strcmp(z,"-echo")==0 ){
+
    }else if( cli_strcmp(z,"-echo")==0 ){
      ShellSetFlag(&data, SHFLG_Echo);
-
    }else if( strcmp(z,"-eqp")==0 ){
+
    }else if( cli_strcmp(z,"-eqp")==0 ){
      data.autoEQP = AUTOEQP_on;
-
    }else if( strcmp(z,"-eqpfull")==0 ){
+
    }else if( cli_strcmp(z,"-eqpfull")==0 ){
      data.autoEQP = AUTOEQP_full;
-
    }else if( strcmp(z,"-stats")==0 ){
+
    }else if( cli_strcmp(z,"-stats")==0 ){
      data.statsOn = 1;
-
    }else if( strcmp(z,"-scanstats")==0 ){
+
    }else if( cli_strcmp(z,"-scanstats")==0 ){
      data.scanstatsOn = 1;
-
    }else if( strcmp(z,"-backslash")==0 ){
+
    }else if( cli_strcmp(z,"-backslash")==0 ){
      /* Undocumented command-line option: -backslash
      ** Causes C-style backslash escapes to be evaluated in SQL statements
      ** prior to sending the SQL into SQLite.  Useful for injecting
      ** crazy bytes in the middle of SQL statements for testing and debugging.
      */
      ShellSetFlag(&data, SHFLG_Backslash);
-
    }else if( strcmp(z,"-bail")==0 ){
+
    }else if( cli_strcmp(z,"-bail")==0 ){
      /* No-op.  The bail_on_error flag should already be set. */
-
    }else if( strcmp(z,"-version")==0 ){
+
    }else if( cli_strcmp(z,"-version")==0 ){
      printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid());
      return 0;
-
    }else if( strcmp(z,"-interactive")==0 ){
+
    }else if( cli_strcmp(z,"-interactive")==0 ){
      stdin_is_interactive = 1;
-
    }else if( strcmp(z,"-batch")==0 ){
+
    }else if( cli_strcmp(z,"-batch")==0 ){
      stdin_is_interactive = 0;
-
    }else if( strcmp(z,"-heap")==0 ){
+
    }else if( cli_strcmp(z,"-heap")==0 ){
      i++;
-
    }else if( strcmp(z,"-pagecache")==0 ){
+
    }else if( cli_strcmp(z,"-pagecache")==0 ){
      i+=2;
-
    }else if( strcmp(z,"-lookaside")==0 ){
+
    }else if( cli_strcmp(z,"-lookaside")==0 ){
      i+=2;
-
    }else if( strcmp(z,"-threadsafe")==0 ){
+
    }else if( cli_strcmp(z,"-threadsafe")==0 ){
      i+=2;
-
    }else if( strcmp(z,"-nonce")==0 ){
+
    }else if( cli_strcmp(z,"-nonce")==0 ){
      i += 2;
-
    }else if( strcmp(z,"-mmap")==0 ){
+
    }else if( cli_strcmp(z,"-mmap")==0 ){
      i++;
-
    }else if( strcmp(z,"-memtrace")==0 ){
+
    }else if( cli_strcmp(z,"-memtrace")==0 ){
      i++;
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
-
    }else if( strcmp(z,"-sorterref")==0 ){
+
    }else if( cli_strcmp(z,"-sorterref")==0 ){
      i++;
#endif
-
    }else if( strcmp(z,"-vfs")==0 ){
+
    }else if( cli_strcmp(z,"-vfs")==0 ){
      i++;
#ifdef SQLITE_ENABLE_VFSTRACE
-
    }else if( strcmp(z,"-vfstrace")==0 ){
+
    }else if( cli_strcmp(z,"-vfstrace")==0 ){
      i++;
#endif
#ifdef SQLITE_ENABLE_MULTIPLEX
-
    }else if( strcmp(z,"-multiplex")==0 ){
+
    }else if( cli_strcmp(z,"-multiplex")==0 ){
      i++;
#endif
-
    }else if( strcmp(z,"-help")==0 ){
+
    }else if( cli_strcmp(z,"-help")==0 ){
      usage(1);
-
    }else if( strcmp(z,"-cmd")==0 ){
+
    }else if( cli_strcmp(z,"-cmd")==0 ){
      /* Run commands that follow -cmd first and separately from commands
      ** that simply appear on the command-line.  This seems goofy.  It would
      ** be better if all commands ran in the order that they appear.  But
@@ -23533,7 +26317,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
        }
      }
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
-
    }else if( strncmp(z, "-A", 2)==0 ){
+
    }else if( cli_strncmp(z, "-A", 2)==0 ){
      if( nCmd>0 ){
        utf8_printf(stderr, "Error: cannot mix regular SQL or dot-commands"
                            " with \"%s\"\n", z);
@@ -23549,7 +26333,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
      readStdin = 0;
      break;
#endif
-
    }else if( strcmp(z,"-safe")==0 ){
+
    }else if( cli_strcmp(z,"-safe")==0 ){
      data.bSafeMode = data.bSafeModePersist = 1;
    }else{
      utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z);
@@ -23631,7 +26415,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
      rc = process_input(&data);
    }
  }
-
#ifndef SQLITE_SHELL_WASM_MODE
+
#ifndef SQLITE_SHELL_FIDDLE
  /* In WASM mode we have to leave the db state in place so that
  ** client code can "push" SQL into it after this call returns. */
  free(azCmd);
@@ -23666,38 +26450,38 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
                (unsigned int)(sqlite3_memory_used()-mem_main_enter));
  }
#endif
-
#endif /* !SQLITE_SHELL_WASM_MODE */
+
#endif /* !SQLITE_SHELL_FIDDLE */
  return rc;
}


-
#ifdef SQLITE_SHELL_WASM_MODE
+
#ifdef SQLITE_SHELL_FIDDLE
/* Only for emcc experimentation purposes. */
int fiddle_experiment(int a,int b){
-
   return a + b;
+
  return a + b;
}

-
/* Only for emcc experimentation purposes.
-

-
  Define this function in JS using:
-

-
  emcc ... --js-library somefile.js
-

-
  containing:
+
/*
+
** Returns a pointer to the current DB handle.
+
*/
+
sqlite3 * fiddle_db_handle(){
+
  return globalDb;
+
}

-
mergeInto(LibraryManager.library, {
-
    my_foo: function(){
-
        console.debug("my_foo()",arguments);
-
    }
-
});
+
/*
+
** Returns a pointer to the given DB name's VFS. If zDbName is 0 then
+
** "main" is assumed. Returns 0 if no db with the given name is
+
** open.
*/
-
/*extern void my_foo(sqlite3 *);*/
-
/* Only for emcc experimentation purposes. */
-
sqlite3 * fiddle_the_db(){
-
    printf("fiddle_the_db(%p)\n", (const void*)globalDb);
-
    /*my_foo(globalDb);*/
-
    return globalDb;
+
sqlite3_vfs * fiddle_db_vfs(const char *zDbName){
+
  sqlite3_vfs * pVfs = 0;
+
  if(globalDb){
+
    sqlite3_file_control(globalDb, zDbName ? zDbName : "main",
+
                         SQLITE_FCNTL_VFS_POINTER, &pVfs);
+
  }
+
  return pVfs;
}
+

/* Only for emcc experimentation purposes. */
sqlite3 * fiddle_db_arg(sqlite3 *arg){
    printf("fiddle_db_arg(%p)\n", (const void*)arg);
@@ -23711,7 +26495,7 @@ sqlite3 * fiddle_db_arg(sqlite3 *arg){
** portable enough to make real use of.
*/
void fiddle_interrupt(void){
-
  if(globalDb) sqlite3_interrupt(globalDb);
+
  if( globalDb ) sqlite3_interrupt(globalDb);
}

/*
@@ -23725,71 +26509,72 @@ const char * fiddle_db_filename(const char * zDbName){
}

/*
-
** Closes, unlinks, and reopens the db using its current filename (or
-
** the default if the db is currently closed). It is assumed, for
-
** purposes of the fiddle build, that the file is in a transient
-
** virtual filesystem within the browser.
+
** Completely wipes out the contents of the currently-opened database
+
** but leaves its storage intact for reuse.
*/
void fiddle_reset_db(void){
-
  char *zFilename = 0;
-
  if(0==globalDb){
-
    shellState.pAuxDb->zDbFilename = "/fiddle.sqlite3";
-
  }else{
-
    zFilename =
-
      sqlite3_mprintf("%s", sqlite3_db_filename(globalDb, "main"));
-
    shell_check_oom(zFilename);
-
    close_db(globalDb);
-
    shellDeleteFile(zFilename);
-
    shellState.db = 0;
-
    shellState.pAuxDb->zDbFilename = zFilename;
+
  if( globalDb ){
+
    int rc = sqlite3_db_config(globalDb, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0);
+
    if( 0==rc ) rc = sqlite3_exec(globalDb, "VACUUM", 0, 0, 0);
+
    sqlite3_db_config(globalDb, SQLITE_DBCONFIG_RESET_DATABASE, 0, 0);
+
  }
+
}
+

+
/*
+
** Uses the current database's VFS xRead to stream the db file's
+
** contents out to the given callback. The callback gets a single
+
** chunk of size n (its 2nd argument) on each call and must return 0
+
** on success, non-0 on error. This function returns 0 on success,
+
** SQLITE_NOTFOUND if no db is open, or propagates any other non-0
+
** code from the callback. Note that this is not thread-friendly: it
+
** expects that it will be the only thread reading the db file and
+
** takes no measures to ensure that is the case.
+
*/
+
int fiddle_export_db( int (*xCallback)(unsigned const char *zOut, int n) ){
+
  sqlite3_int64 nSize = 0;
+
  sqlite3_int64 nPos = 0;
+
  sqlite3_file * pFile = 0;
+
  unsigned char buf[1024 * 8];
+
  int nBuf = (int)sizeof(buf);
+
  int rc = shellState.db
+
    ? sqlite3_file_control(shellState.db, "main",
+
                           SQLITE_FCNTL_FILE_POINTER, &pFile)
+
    : SQLITE_NOTFOUND;
+
  if( rc ) return rc;
+
  rc = pFile->pMethods->xFileSize(pFile, &nSize);
+
  if( rc ) return rc;
+
  if(nSize % nBuf){
+
    /* DB size is not an even multiple of the buffer size. Reduce
+
    ** buffer size so that we do not unduly inflate the db size when
+
    ** exporting. */
+
    if(0 == nSize % 4096) nBuf = 4096;
+
    else if(0 == nSize % 2048) nBuf = 2048;
+
    else if(0 == nSize % 1024) nBuf = 1024;
+
    else nBuf = 512;
+
  }
+
  for( ; 0==rc && nPos<nSize; nPos += nBuf ){
+
    rc = pFile->pMethods->xRead(pFile, buf, nBuf, nPos);
+
    if(SQLITE_IOERR_SHORT_READ == rc){
+
      rc = (nPos + nBuf) < nSize ? rc : 0/*assume EOF*/;
+
    }
+
    if( 0==rc ) rc = xCallback(buf, nBuf);
  }
-
  open_db(&shellState, 0);
-
  sqlite3_free(zFilename);
+
  return rc;
}

/*
-
** Trivial exportable function for emscripten. Needs to be exported using:
-
**
-
** emcc ..flags... -sEXPORTED_FUNCTIONS=_fiddle_exec -sEXPORTED_RUNTIME_METHODS=ccall,cwrap
-
**
-
** (Note the underscore before the function name.) It processes zSql
-
** as if it were input to the sqlite3 shell and redirects all output
-
** to the wasm binding.
+
** Trivial exportable function for emscripten. It processes zSql as if
+
** it were input to the sqlite3 shell and redirects all output to the
+
** wasm binding. fiddle_main() must have been called before this
+
** is called, or results are undefined.
*/
void fiddle_exec(const char * zSql){
-
  static int once = 0;
-
  int rc = 0;
-
  if(!once){
-
    /* Simulate an argv array for main() */
-
    static char * argv[] = {"fiddle",
-
                            "-bail",
-
                            "-safe"};
-
    rc = fiddle_main((int)(sizeof(argv)/sizeof(argv[0])), argv);
-
    once = rc ? -1 : 1;
-
    memset(&shellState.wasm, 0, sizeof(shellState.wasm));
-
    printf(
-
        "SQLite version %s %.19s\n" /*extra-version-info*/,
-
        sqlite3_libversion(), sqlite3_sourceid()
-
    );
-
    puts("WASM shell");
-
    puts("Enter \".help\" for usage hints.");
-
    if(once>0){
-
      fiddle_reset_db();
-
    }
-
    if(shellState.db){
-
      printf("Connected to %s.\n", fiddle_db_filename(NULL));
-
    }else{
-
      fprintf(stderr,"ERROR initializing db!\n");
-
      return;
-
    }
-
  }
-
  if(once<0){
-
    puts("DB init failed. Not executing SQL.");
-
  }else if(zSql && *zSql){
+
  if(zSql && *zSql){
+
    if('.'==*zSql) puts(zSql);
    shellState.wasm.zInput = zSql;
    shellState.wasm.zPos = zSql;
    process_input(&shellState);
-
    memset(&shellState.wasm, 0, sizeof(shellState.wasm));
+
    shellState.wasm.zInput = shellState.wasm.zPos = 0;
  }
}
-
#endif /* SQLITE_SHELL_WASM_MODE */
+
#endif /* SQLITE_SHELL_FIDDLE */
modified external/sqlite/sqlite3.c
@@ -1,6 +1,6 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-
** version 3.39.3.  By combining all the individual C code files into this
+
** version 3.40.0.  By combining all the individual C code files into this
** single large file, the entire code can be compiled as a single translation
** unit.  This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately.  Performance improvements
@@ -452,9 +452,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-
#define SQLITE_VERSION        "3.39.3"
-
#define SQLITE_VERSION_NUMBER 3039003
-
#define SQLITE_SOURCE_ID      "2022-09-05 11:02:23 4635f4a69c8c2a8df242b384a992aea71224e39a2ccab42d8c0b0602f1e826e8"
+
#define SQLITE_VERSION        "3.40.0"
+
#define SQLITE_VERSION_NUMBER 3040000
+
#define SQLITE_SOURCE_ID      "2022-11-16 12:10:08 89c459e766ea7e9165d0beeb124708b955a4950d0f4792f457465d71b158d318"

/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -976,13 +976,17 @@ SQLITE_API int sqlite3_exec(
**
** SQLite uses one of these integer values as the second
** argument to calls it makes to the xLock() and xUnlock() methods
-
** of an [sqlite3_io_methods] object.
+
** of an [sqlite3_io_methods] object.  These values are ordered from
+
** lest restrictive to most restrictive.
+
**
+
** The argument to xLock() is always SHARED or higher.  The argument to
+
** xUnlock is either SHARED or NONE.
*/
-
#define SQLITE_LOCK_NONE          0
-
#define SQLITE_LOCK_SHARED        1
-
#define SQLITE_LOCK_RESERVED      2
-
#define SQLITE_LOCK_PENDING       3
-
#define SQLITE_LOCK_EXCLUSIVE     4
+
#define SQLITE_LOCK_NONE          0       /* xUnlock() only */
+
#define SQLITE_LOCK_SHARED        1       /* xLock() or xUnlock() */
+
#define SQLITE_LOCK_RESERVED      2       /* xLock() only */
+
#define SQLITE_LOCK_PENDING       3       /* xLock() only */
+
#define SQLITE_LOCK_EXCLUSIVE     4       /* xLock() only */

/*
** CAPI3REF: Synchronization Type Flags
@@ -1060,7 +1064,14 @@ struct sqlite3_file {
** <li> [SQLITE_LOCK_PENDING], or
** <li> [SQLITE_LOCK_EXCLUSIVE].
** </ul>
-
** xLock() increases the lock. xUnlock() decreases the lock.
+
** xLock() upgrades the database file lock.  In other words, xLock() moves the
+
** database file lock in the direction NONE toward EXCLUSIVE. The argument to
+
** xLock() is always on of SHARED, RESERVED, PENDING, or EXCLUSIVE, never
+
** SQLITE_LOCK_NONE.  If the database file lock is already at or above the
+
** requested lock, then the call to xLock() is a no-op.
+
** xUnlock() downgrades the database file lock to either SHARED or NONE.
+
*  If the lock is already at or below the requested lock state, then the call
+
** to xUnlock() is a no-op.
** The xCheckReservedLock() method checks whether any database connection,
** either in this process or in some other process, is holding a RESERVED,
** PENDING, or EXCLUSIVE lock on the file.  It returns true
@@ -1165,9 +1176,8 @@ struct sqlite3_io_methods {
** opcode causes the xFileControl method to write the current state of
** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED],
** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE])
-
** into an integer that the pArg argument points to. This capability
-
** is used during testing and is only available when the SQLITE_TEST
-
** compile-time option is used.
+
** into an integer that the pArg argument points to.
+
** This capability is only available if SQLite is compiled with [SQLITE_DEBUG].
**
** <li>[[SQLITE_FCNTL_SIZE_HINT]]
** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS
@@ -1560,6 +1570,26 @@ typedef struct sqlite3_mutex sqlite3_mutex;
typedef struct sqlite3_api_routines sqlite3_api_routines;

/*
+
** CAPI3REF: File Name
+
**
+
** Type [sqlite3_filename] is used by SQLite to pass filenames to the
+
** xOpen method of a [VFS]. It may be cast to (const char*) and treated
+
** as a normal, nul-terminated, UTF-8 buffer containing the filename, but
+
** may also be passed to special APIs such as:
+
**
+
** <ul>
+
** <li>  sqlite3_filename_database()
+
** <li>  sqlite3_filename_journal()
+
** <li>  sqlite3_filename_wal()
+
** <li>  sqlite3_uri_parameter()
+
** <li>  sqlite3_uri_boolean()
+
** <li>  sqlite3_uri_int64()
+
** <li>  sqlite3_uri_key()
+
** </ul>
+
*/
+
typedef const char *sqlite3_filename;
+

+
/*
** CAPI3REF: OS Interface Object
**
** An instance of the sqlite3_vfs object defines the interface between
@@ -1737,7 +1767,7 @@ struct sqlite3_vfs {
  sqlite3_vfs *pNext;      /* Next registered VFS */
  const char *zName;       /* Name of this virtual file system */
  void *pAppData;          /* Pointer to application-specific data */
-
  int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*,
+
  int (*xOpen)(sqlite3_vfs*, sqlite3_filename zName, sqlite3_file*,
               int flags, int *pOutFlags);
  int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir);
  int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut);
@@ -2615,6 +2645,7 @@ struct sqlite3_mem_methods {
** <ul>
** <li> The [PRAGMA writable_schema=ON] statement.
** <li> The [PRAGMA journal_mode=OFF] statement.
+
** <li> The [PRAGMA schema_version=N] statement.
** <li> Writes to the [sqlite_dbpage] virtual table.
** <li> Direct writes to [shadow tables].
** </ul>
@@ -3730,6 +3761,9 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** <dd>The database is opened [shared cache] enabled, overriding
** the default shared cache setting provided by
** [sqlite3_enable_shared_cache()].)^
+
** The [use of shared cache mode is discouraged] and hence shared cache
+
** capabilities may be omitted from many builds of SQLite.  In such cases,
+
** this option is a no-op.
**
** ^(<dt>[SQLITE_OPEN_PRIVATECACHE]</dt>
** <dd>The database is opened [shared cache] disabled, overriding
@@ -3745,7 +3779,7 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** to return an extended result code.</dd>
**
** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt>
-
** <dd>The database filename is not allowed to be a symbolic link</dd>
+
** <dd>The database filename is not allowed to contain a symbolic link</dd>
** </dl>)^
**
** If the 3rd parameter to sqlite3_open_v2() is not one of the
@@ -4004,10 +4038,10 @@ SQLITE_API int sqlite3_open_v2(
**
** See the [URI filename] documentation for additional information.
*/
-
SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam);
-
SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault);
-
SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64);
-
SQLITE_API const char *sqlite3_uri_key(const char *zFilename, int N);
+
SQLITE_API const char *sqlite3_uri_parameter(sqlite3_filename z, const char *zParam);
+
SQLITE_API int sqlite3_uri_boolean(sqlite3_filename z, const char *zParam, int bDefault);
+
SQLITE_API sqlite3_int64 sqlite3_uri_int64(sqlite3_filename, const char*, sqlite3_int64);
+
SQLITE_API const char *sqlite3_uri_key(sqlite3_filename z, int N);

/*
** CAPI3REF:  Translate filenames
@@ -4036,9 +4070,9 @@ SQLITE_API const char *sqlite3_uri_key(const char *zFilename, int N);
** return value from [sqlite3_db_filename()], then the result is
** undefined and is likely a memory access violation.
*/
-
SQLITE_API const char *sqlite3_filename_database(const char*);
-
SQLITE_API const char *sqlite3_filename_journal(const char*);
-
SQLITE_API const char *sqlite3_filename_wal(const char*);
+
SQLITE_API const char *sqlite3_filename_database(sqlite3_filename);
+
SQLITE_API const char *sqlite3_filename_journal(sqlite3_filename);
+
SQLITE_API const char *sqlite3_filename_wal(sqlite3_filename);

/*
** CAPI3REF:  Database File Corresponding To A Journal
@@ -4104,14 +4138,14 @@ SQLITE_API sqlite3_file *sqlite3_database_file_object(const char*);
** then the corresponding [sqlite3_module.xClose() method should also be
** invoked prior to calling sqlite3_free_filename(Y).
*/
-
SQLITE_API char *sqlite3_create_filename(
+
SQLITE_API sqlite3_filename sqlite3_create_filename(
  const char *zDatabase,
  const char *zJournal,
  const char *zWal,
  int nParam,
  const char **azParam
);
-
SQLITE_API void sqlite3_free_filename(char*);
+
SQLITE_API void sqlite3_free_filename(sqlite3_filename);

/*
** CAPI3REF: Error Codes And Messages
@@ -5814,6 +5848,16 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
** then the conversion is performed.  Otherwise no conversion occurs.
** The [SQLITE_INTEGER | datatype] after conversion is returned.)^
**
+
** ^(The sqlite3_value_encoding(X) interface returns one of [SQLITE_UTF8],
+
** [SQLITE_UTF16BE], or [SQLITE_UTF16LE] according to the current encoding
+
** of the value X, assuming that X has type TEXT.)^  If sqlite3_value_type(X)
+
** returns something other than SQLITE_TEXT, then the return value from
+
** sqlite3_value_encoding(X) is meaningless.  ^Calls to
+
** sqlite3_value_text(X), sqlite3_value_text16(X), sqlite3_value_text16be(X),
+
** sqlite3_value_text16le(X), sqlite3_value_bytes(X), or
+
** sqlite3_value_bytes16(X) might change the encoding of the value X and
+
** thus change the return from subsequent calls to sqlite3_value_encoding(X).
+
**
** ^Within the [xUpdate] method of a [virtual table], the
** sqlite3_value_nochange(X) interface returns true if and only if
** the column corresponding to X is unchanged by the UPDATE operation
@@ -5878,6 +5922,7 @@ SQLITE_API int sqlite3_value_type(sqlite3_value*);
SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*);
SQLITE_API int sqlite3_value_nochange(sqlite3_value*);
SQLITE_API int sqlite3_value_frombind(sqlite3_value*);
+
SQLITE_API int sqlite3_value_encoding(sqlite3_value*);

/*
** CAPI3REF: Finding The Subtype Of SQL Values
@@ -5931,7 +5976,7 @@ SQLITE_API void sqlite3_value_free(sqlite3_value*);
**
** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer
** when first called if N is less than or equal to zero or if a memory
-
** allocate error occurs.
+
** allocation error occurs.
**
** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is
** determined by the N parameter on first successful call.  Changing the
@@ -6136,9 +6181,10 @@ typedef void (*sqlite3_destructor_type)(void*);
** of [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE].
** ^SQLite takes the text result from the application from
** the 2nd parameter of the sqlite3_result_text* interfaces.
-
** ^If the 3rd parameter to the sqlite3_result_text* interfaces
-
** is negative, then SQLite takes result text from the 2nd parameter
-
** through the first zero character.
+
** ^If the 3rd parameter to any of the sqlite3_result_text* interfaces
+
** other than sqlite3_result_text64() is negative, then SQLite computes
+
** the string length itself by searching the 2nd parameter for the first
+
** zero character.
** ^If the 3rd parameter to the sqlite3_result_text* interfaces
** is non-negative, then as many bytes (not characters) of the text
** pointed to by the 2nd parameter are taken as the application-defined
@@ -6634,7 +6680,7 @@ SQLITE_API const char *sqlite3_db_name(sqlite3 *db, int N);
** <li> [sqlite3_filename_wal()]
** </ul>
*/
-
SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
+
SQLITE_API sqlite3_filename sqlite3_db_filename(sqlite3 *db, const char *zDbName);

/*
** CAPI3REF: Determine if a database is read-only
@@ -6771,7 +6817,7 @@ SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
** function C that is invoked prior to each autovacuum of the database
** file.  ^The callback is passed a copy of the generic data pointer (P),
** the schema-name of the attached database that is being autovacuumed,
-
** the the size of the database file in pages, the number of free pages,
+
** the size of the database file in pages, the number of free pages,
** and the number of bytes per page, respectively.  The callback should
** return the number of free pages that should be removed by the
** autovacuum.  ^If the callback returns zero, then no autovacuum happens.
@@ -6892,6 +6938,11 @@ SQLITE_API void *sqlite3_update_hook(
** to the same database. Sharing is enabled if the argument is true
** and disabled if the argument is false.)^
**
+
** This interface is omitted if SQLite is compiled with
+
** [-DSQLITE_OMIT_SHARED_CACHE].  The [-DSQLITE_OMIT_SHARED_CACHE]
+
** compile-time option is recommended because the
+
** [use of shared cache mode is discouraged].
+
**
** ^Cache sharing is enabled and disabled for an entire process.
** This is a change as of SQLite [version 3.5.0] ([dateof:3.5.0]).
** In prior versions of SQLite,
@@ -6990,7 +7041,7 @@ SQLITE_API int sqlite3_db_release_memory(sqlite3*);
** ^The soft heap limit may not be greater than the hard heap limit.
** ^If the hard heap limit is enabled and if sqlite3_soft_heap_limit(N)
** is invoked with a value of N that is greater than the hard heap limit,
-
** the the soft heap limit is set to the value of the hard heap limit.
+
** the soft heap limit is set to the value of the hard heap limit.
** ^The soft heap limit is automatically enabled whenever the hard heap
** limit is enabled. ^When sqlite3_hard_heap_limit64(N) is invoked and
** the soft heap limit is outside the range of 1..N, then the soft heap
@@ -9285,7 +9336,7 @@ typedef struct sqlite3_backup sqlite3_backup;
** if the application incorrectly accesses the destination [database connection]
** and so no error code is reported, but the operations may malfunction
** nevertheless.  Use of the destination database connection while a
-
** backup is in progress might also also cause a mutex deadlock.
+
** backup is in progress might also cause a mutex deadlock.
**
** If running in [shared cache mode], the application must
** guarantee that the shared cache used by the destination database
@@ -9713,7 +9764,7 @@ SQLITE_API int sqlite3_wal_checkpoint_v2(
*/
#define SQLITE_CHECKPOINT_PASSIVE  0  /* Do as much as possible w/o blocking */
#define SQLITE_CHECKPOINT_FULL     1  /* Wait for writers, then checkpoint */
-
#define SQLITE_CHECKPOINT_RESTART  2  /* Like FULL but wait for for readers */
+
#define SQLITE_CHECKPOINT_RESTART  2  /* Like FULL but wait for readers */
#define SQLITE_CHECKPOINT_TRUNCATE 3  /* Like RESTART but also truncate WAL */

/*
@@ -13154,7 +13205,7 @@ struct fts5_api {
** autoconf-based build
*/
#if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H)
-
#include "config.h"
+
#include "sqlite_cfg.h"
#define SQLITECONFIG_H 1
#endif

@@ -14637,6 +14688,7 @@ typedef struct FuncDef FuncDef;
typedef struct FuncDefHash FuncDefHash;
typedef struct IdList IdList;
typedef struct Index Index;
+
typedef struct IndexedExpr IndexedExpr;
typedef struct IndexSample IndexSample;
typedef struct KeyClass KeyClass;
typedef struct KeyInfo KeyInfo;
@@ -14702,6 +14754,7 @@ typedef struct With With;
#define MASKBIT32(n)  (((unsigned int)1)<<(n))
#define SMASKBIT32(n) ((n)<=31?((unsigned int)1)<<(n):0)
#define ALLBITS       ((Bitmask)-1)
+
#define TOPBIT        (((Bitmask)1)<<(BMS-1))

/* A VList object records a mapping between parameters/variables/wildcards
** in the SQL statement (such as $abc, @pqr, or :xyz) and the integer
@@ -14716,6 +14769,331 @@ typedef int VList;
** "BusyHandler" typedefs. vdbe.h also requires a few of the opaque
** pointer types (i.e. FuncDef) defined above.
*/
+
/************** Include os.h in the middle of sqliteInt.h ********************/
+
/************** Begin file os.h **********************************************/
+
/*
+
** 2001 September 16
+
**
+
** 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 header file (together with is companion C source-code file
+
** "os.c") attempt to abstract the underlying operating system so that
+
** the SQLite library will work on both POSIX and windows systems.
+
**
+
** This header file is #include-ed by sqliteInt.h and thus ends up
+
** being included by every source file.
+
*/
+
#ifndef _SQLITE_OS_H_
+
#define _SQLITE_OS_H_
+

+
/*
+
** Attempt to automatically detect the operating system and setup the
+
** necessary pre-processor macros for it.
+
*/
+
/************** Include os_setup.h in the middle of os.h *********************/
+
/************** Begin file os_setup.h ****************************************/
+
/*
+
** 2013 November 25
+
**
+
** The author disclaims copyright to this source code.  In place of
+
** a legal notice, here is a blessing:
+
**
+
**    May you do good and not evil.
+
**    May you find forgiveness for yourself and forgive others.
+
**    May you share freely, never taking more than you give.
+
**
+
******************************************************************************
+
**
+
** This file contains pre-processor directives related to operating system
+
** detection and/or setup.
+
*/
+
#ifndef SQLITE_OS_SETUP_H
+
#define SQLITE_OS_SETUP_H
+

+
/*
+
** Figure out if we are dealing with Unix, Windows, or some other operating
+
** system.
+
**
+
** After the following block of preprocess macros, all of
+
**
+
**    SQLITE_OS_KV
+
**    SQLITE_OS_OTHER
+
**    SQLITE_OS_UNIX
+
**    SQLITE_OS_WIN
+
**
+
** will defined to either 1 or 0. One of them will be 1. The others will be 0.
+
** If none of the macros are initially defined, then select either
+
** SQLITE_OS_UNIX or SQLITE_OS_WIN depending on the target platform.
+
**
+
** If SQLITE_OS_OTHER=1 is specified at compile-time, then the application
+
** must provide its own VFS implementation together with sqlite3_os_init()
+
** and sqlite3_os_end() routines.
+
*/
+
#if !defined(SQLITE_OS_KV) && !defined(SQLITE_OS_OTHER) && \
+
       !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_WIN)
+
#  if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || \
+
          defined(__MINGW32__) || defined(__BORLANDC__)
+
#    define SQLITE_OS_WIN 1
+
#    define SQLITE_OS_UNIX 0
+
#  else
+
#    define SQLITE_OS_WIN 0
+
#    define SQLITE_OS_UNIX 1
+
#  endif
+
#endif
+
#if SQLITE_OS_OTHER+1>1
+
#  undef SQLITE_OS_KV
+
#  define SQLITE_OS_KV 0
+
#  undef SQLITE_OS_UNIX
+
#  define SQLITE_OS_UNIX 0
+
#  undef SQLITE_OS_WIN
+
#  define SQLITE_OS_WIN 0
+
#endif
+
#if SQLITE_OS_KV+1>1
+
#  undef SQLITE_OS_OTHER
+
#  define SQLITE_OS_OTHER 0
+
#  undef SQLITE_OS_UNIX
+
#  define SQLITE_OS_UNIX 0
+
#  undef SQLITE_OS_WIN
+
#  define SQLITE_OS_WIN 0
+
#  define SQLITE_OMIT_LOAD_EXTENSION 1
+
#  define SQLITE_OMIT_WAL 1
+
#  define SQLITE_OMIT_DEPRECATED 1
+
#  undef SQLITE_TEMP_STORE
+
#  define SQLITE_TEMP_STORE 3  /* Always use memory for temporary storage */
+
#  define SQLITE_DQS 0
+
#  define SQLITE_OMIT_SHARED_CACHE 1
+
#  define SQLITE_OMIT_AUTOINIT 1
+
#endif
+
#if SQLITE_OS_UNIX+1>1
+
#  undef SQLITE_OS_KV
+
#  define SQLITE_OS_KV 0
+
#  undef SQLITE_OS_OTHER
+
#  define SQLITE_OS_OTHER 0
+
#  undef SQLITE_OS_WIN
+
#  define SQLITE_OS_WIN 0
+
#endif
+
#if SQLITE_OS_WIN+1>1
+
#  undef SQLITE_OS_KV
+
#  define SQLITE_OS_KV 0
+
#  undef SQLITE_OS_OTHER
+
#  define SQLITE_OS_OTHER 0
+
#  undef SQLITE_OS_UNIX
+
#  define SQLITE_OS_UNIX 0
+
#endif
+

+

+
#endif /* SQLITE_OS_SETUP_H */
+

+
/************** End of os_setup.h ********************************************/
+
/************** Continuing where we left off in os.h *************************/
+

+
/* If the SET_FULLSYNC macro is not defined above, then make it
+
** a no-op
+
*/
+
#ifndef SET_FULLSYNC
+
# define SET_FULLSYNC(x,y)
+
#endif
+

+
/* Maximum pathname length.  Note: FILENAME_MAX defined by stdio.h
+
*/
+
#ifndef SQLITE_MAX_PATHLEN
+
# define SQLITE_MAX_PATHLEN FILENAME_MAX
+
#endif
+

+
/* Maximum number of symlinks that will be resolved while trying to
+
** expand a filename in xFullPathname() in the VFS.
+
*/
+
#ifndef SQLITE_MAX_SYMLINK
+
# define SQLITE_MAX_SYMLINK 200
+
#endif
+

+
/*
+
** The default size of a disk sector
+
*/
+
#ifndef SQLITE_DEFAULT_SECTOR_SIZE
+
# define SQLITE_DEFAULT_SECTOR_SIZE 4096
+
#endif
+

+
/*
+
** Temporary files are named starting with this prefix followed by 16 random
+
** alphanumeric characters, and no file extension. They are stored in the
+
** OS's standard temporary file directory, and are deleted prior to exit.
+
** If sqlite is being embedded in another program, you may wish to change the
+
** prefix to reflect your program's name, so that if your program exits
+
** prematurely, old temporary files can be easily identified. This can be done
+
** using -DSQLITE_TEMP_FILE_PREFIX=myprefix_ on the compiler command line.
+
**
+
** 2006-10-31:  The default prefix used to be "sqlite_".  But then
+
** Mcafee started using SQLite in their anti-virus product and it
+
** started putting files with the "sqlite" name in the c:/temp folder.
+
** This annoyed many windows users.  Those users would then do a
+
** Google search for "sqlite", find the telephone numbers of the
+
** developers and call to wake them up at night and complain.
+
** For this reason, the default name prefix is changed to be "sqlite"
+
** spelled backwards.  So the temp files are still identified, but
+
** anybody smart enough to figure out the code is also likely smart
+
** enough to know that calling the developer will not help get rid
+
** of the file.
+
*/
+
#ifndef SQLITE_TEMP_FILE_PREFIX
+
# define SQLITE_TEMP_FILE_PREFIX "etilqs_"
+
#endif
+

+
/*
+
** The following values may be passed as the second argument to
+
** sqlite3OsLock(). The various locks exhibit the following semantics:
+
**
+
** SHARED:    Any number of processes may hold a SHARED lock simultaneously.
+
** RESERVED:  A single process may hold a RESERVED lock on a file at
+
**            any time. Other processes may hold and obtain new SHARED locks.
+
** PENDING:   A single process may hold a PENDING lock on a file at
+
**            any one time. Existing SHARED locks may persist, but no new
+
**            SHARED locks may be obtained by other processes.
+
** EXCLUSIVE: An EXCLUSIVE lock precludes all other locks.
+
**
+
** PENDING_LOCK may not be passed directly to sqlite3OsLock(). Instead, a
+
** process that requests an EXCLUSIVE lock may actually obtain a PENDING
+
** lock. This can be upgraded to an EXCLUSIVE lock by a subsequent call to
+
** sqlite3OsLock().
+
*/
+
#define NO_LOCK         0
+
#define SHARED_LOCK     1
+
#define RESERVED_LOCK   2
+
#define PENDING_LOCK    3
+
#define EXCLUSIVE_LOCK  4
+

+
/*
+
** File Locking Notes:  (Mostly about windows but also some info for Unix)
+
**
+
** We cannot use LockFileEx() or UnlockFileEx() on Win95/98/ME because
+
** those functions are not available.  So we use only LockFile() and
+
** UnlockFile().
+
**
+
** LockFile() prevents not just writing but also reading by other processes.
+
** A SHARED_LOCK is obtained by locking a single randomly-chosen
+
** byte out of a specific range of bytes. The lock byte is obtained at
+
** random so two separate readers can probably access the file at the
+
** same time, unless they are unlucky and choose the same lock byte.
+
** An EXCLUSIVE_LOCK is obtained by locking all bytes in the range.
+
** There can only be one writer.  A RESERVED_LOCK is obtained by locking
+
** a single byte of the file that is designated as the reserved lock byte.
+
** A PENDING_LOCK is obtained by locking a designated byte different from
+
** the RESERVED_LOCK byte.
+
**
+
** On WinNT/2K/XP systems, LockFileEx() and UnlockFileEx() are available,
+
** which means we can use reader/writer locks.  When reader/writer locks
+
** are used, the lock is placed on the same range of bytes that is used
+
** for probabilistic locking in Win95/98/ME.  Hence, the locking scheme
+
** will support two or more Win95 readers or two or more WinNT readers.
+
** But a single Win95 reader will lock out all WinNT readers and a single
+
** WinNT reader will lock out all other Win95 readers.
+
**
+
** The following #defines specify the range of bytes used for locking.
+
** SHARED_SIZE is the number of bytes available in the pool from which
+
** a random byte is selected for a shared lock.  The pool of bytes for
+
** shared locks begins at SHARED_FIRST.
+
**
+
** The same locking strategy and
+
** byte ranges are used for Unix.  This leaves open the possibility of having
+
** clients on win95, winNT, and unix all talking to the same shared file
+
** and all locking correctly.  To do so would require that samba (or whatever
+
** tool is being used for file sharing) implements locks correctly between
+
** windows and unix.  I'm guessing that isn't likely to happen, but by
+
** using the same locking range we are at least open to the possibility.
+
**
+
** Locking in windows is manditory.  For this reason, we cannot store
+
** actual data in the bytes used for locking.  The pager never allocates
+
** the pages involved in locking therefore.  SHARED_SIZE is selected so
+
** that all locks will fit on a single page even at the minimum page size.
+
** PENDING_BYTE defines the beginning of the locks.  By default PENDING_BYTE
+
** is set high so that we don't have to allocate an unused page except
+
** for very large databases.  But one should test the page skipping logic
+
** by setting PENDING_BYTE low and running the entire regression suite.
+
**
+
** Changing the value of PENDING_BYTE results in a subtly incompatible
+
** file format.  Depending on how it is changed, you might not notice
+
** the incompatibility right away, even running a full regression test.
+
** The default location of PENDING_BYTE is the first byte past the
+
** 1GB boundary.
+
**
+
*/
+
#ifdef SQLITE_OMIT_WSD
+
# define PENDING_BYTE     (0x40000000)
+
#else
+
# define PENDING_BYTE      sqlite3PendingByte
+
#endif
+
#define RESERVED_BYTE     (PENDING_BYTE+1)
+
#define SHARED_FIRST      (PENDING_BYTE+2)
+
#define SHARED_SIZE       510
+

+
/*
+
** Wrapper around OS specific sqlite3_os_init() function.
+
*/
+
SQLITE_PRIVATE int sqlite3OsInit(void);
+

+
/*
+
** Functions for accessing sqlite3_file methods
+
*/
+
SQLITE_PRIVATE void sqlite3OsClose(sqlite3_file*);
+
SQLITE_PRIVATE int sqlite3OsRead(sqlite3_file*, void*, int amt, i64 offset);
+
SQLITE_PRIVATE int sqlite3OsWrite(sqlite3_file*, const void*, int amt, i64 offset);
+
SQLITE_PRIVATE int sqlite3OsTruncate(sqlite3_file*, i64 size);
+
SQLITE_PRIVATE int sqlite3OsSync(sqlite3_file*, int);
+
SQLITE_PRIVATE int sqlite3OsFileSize(sqlite3_file*, i64 *pSize);
+
SQLITE_PRIVATE int sqlite3OsLock(sqlite3_file*, int);
+
SQLITE_PRIVATE int sqlite3OsUnlock(sqlite3_file*, int);
+
SQLITE_PRIVATE int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut);
+
SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file*,int,void*);
+
SQLITE_PRIVATE void sqlite3OsFileControlHint(sqlite3_file*,int,void*);
+
#define SQLITE_FCNTL_DB_UNCHANGED 0xca093fa0
+
SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id);
+
SQLITE_PRIVATE int sqlite3OsDeviceCharacteristics(sqlite3_file *id);
+
#ifndef SQLITE_OMIT_WAL
+
SQLITE_PRIVATE int sqlite3OsShmMap(sqlite3_file *,int,int,int,void volatile **);
+
SQLITE_PRIVATE int sqlite3OsShmLock(sqlite3_file *id, int, int, int);
+
SQLITE_PRIVATE void sqlite3OsShmBarrier(sqlite3_file *id);
+
SQLITE_PRIVATE int sqlite3OsShmUnmap(sqlite3_file *id, int);
+
#endif /* SQLITE_OMIT_WAL */
+
SQLITE_PRIVATE int sqlite3OsFetch(sqlite3_file *id, i64, int, void **);
+
SQLITE_PRIVATE int sqlite3OsUnfetch(sqlite3_file *, i64, void *);
+

+

+
/*
+
** Functions for accessing sqlite3_vfs methods
+
*/
+
SQLITE_PRIVATE int sqlite3OsOpen(sqlite3_vfs *, const char *, sqlite3_file*, int, int *);
+
SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *, const char *, int);
+
SQLITE_PRIVATE int sqlite3OsAccess(sqlite3_vfs *, const char *, int, int *pResOut);
+
SQLITE_PRIVATE int sqlite3OsFullPathname(sqlite3_vfs *, const char *, int, char *);
+
#ifndef SQLITE_OMIT_LOAD_EXTENSION
+
SQLITE_PRIVATE void *sqlite3OsDlOpen(sqlite3_vfs *, const char *);
+
SQLITE_PRIVATE void sqlite3OsDlError(sqlite3_vfs *, int, char *);
+
SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *, void *, const char *))(void);
+
SQLITE_PRIVATE void sqlite3OsDlClose(sqlite3_vfs *, void *);
+
#endif /* SQLITE_OMIT_LOAD_EXTENSION */
+
SQLITE_PRIVATE int sqlite3OsRandomness(sqlite3_vfs *, int, char *);
+
SQLITE_PRIVATE int sqlite3OsSleep(sqlite3_vfs *, int);
+
SQLITE_PRIVATE int sqlite3OsGetLastError(sqlite3_vfs*);
+
SQLITE_PRIVATE int sqlite3OsCurrentTimeInt64(sqlite3_vfs *, sqlite3_int64*);
+

+
/*
+
** Convenience functions for opening and closing files using
+
** sqlite3_malloc() to obtain space for the file-handle structure.
+
*/
+
SQLITE_PRIVATE int sqlite3OsOpenMalloc(sqlite3_vfs *, const char *, sqlite3_file **, int,int*);
+
SQLITE_PRIVATE void sqlite3OsCloseFree(sqlite3_file *);
+

+
#endif /* _SQLITE_OS_H_ */
+

+
/************** End of os.h **************************************************/
+
/************** Continuing where we left off in sqliteInt.h ******************/
/************** Include pager.h in the middle of sqliteInt.h *****************/
/************** Begin file pager.h *******************************************/
/*
@@ -15560,48 +15938,48 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_Vacuum          5
#define OP_VFilter         6 /* jump, synopsis: iplan=r[P3] zplan='P4'     */
#define OP_VUpdate         7 /* synopsis: data=r[P3@P2]                    */
-
#define OP_Goto            8 /* jump                                       */
-
#define OP_Gosub           9 /* jump                                       */
-
#define OP_InitCoroutine  10 /* jump                                       */
-
#define OP_Yield          11 /* jump                                       */
-
#define OP_MustBeInt      12 /* jump                                       */
-
#define OP_Jump           13 /* jump                                       */
-
#define OP_Once           14 /* jump                                       */
-
#define OP_If             15 /* jump                                       */
-
#define OP_IfNot          16 /* jump                                       */
-
#define OP_IsNullOrType   17 /* jump, synopsis: if typeof(r[P1]) IN (P3,5) goto P2 */
-
#define OP_IfNullRow      18 /* jump, synopsis: if P1.nullRow then r[P3]=NULL, goto P2 */
+
#define OP_Init            8 /* jump, synopsis: Start at P2                */
+
#define OP_Goto            9 /* jump                                       */
+
#define OP_Gosub          10 /* jump                                       */
+
#define OP_InitCoroutine  11 /* jump                                       */
+
#define OP_Yield          12 /* jump                                       */
+
#define OP_MustBeInt      13 /* jump                                       */
+
#define OP_Jump           14 /* jump                                       */
+
#define OP_Once           15 /* jump                                       */
+
#define OP_If             16 /* jump                                       */
+
#define OP_IfNot          17 /* jump                                       */
+
#define OP_IsType         18 /* jump, synopsis: if typeof(P1.P3) in P5 goto P2 */
#define OP_Not            19 /* same as TK_NOT, synopsis: r[P2]= !r[P1]    */
-
#define OP_SeekLT         20 /* jump, synopsis: key=r[P3@P4]               */
-
#define OP_SeekLE         21 /* jump, synopsis: key=r[P3@P4]               */
-
#define OP_SeekGE         22 /* jump, synopsis: key=r[P3@P4]               */
-
#define OP_SeekGT         23 /* jump, synopsis: key=r[P3@P4]               */
-
#define OP_IfNotOpen      24 /* jump, synopsis: if( !csr[P1] ) goto P2     */
-
#define OP_IfNoHope       25 /* jump, synopsis: key=r[P3@P4]               */
-
#define OP_NoConflict     26 /* jump, synopsis: key=r[P3@P4]               */
-
#define OP_NotFound       27 /* jump, synopsis: key=r[P3@P4]               */
-
#define OP_Found          28 /* jump, synopsis: key=r[P3@P4]               */
-
#define OP_SeekRowid      29 /* jump, synopsis: intkey=r[P3]               */
-
#define OP_NotExists      30 /* jump, synopsis: intkey=r[P3]               */
-
#define OP_Last           31 /* jump                                       */
-
#define OP_IfSmaller      32 /* jump                                       */
-
#define OP_SorterSort     33 /* jump                                       */
-
#define OP_Sort           34 /* jump                                       */
-
#define OP_Rewind         35 /* jump                                       */
-
#define OP_SorterNext     36 /* jump                                       */
-
#define OP_Prev           37 /* jump                                       */
-
#define OP_Next           38 /* jump                                       */
-
#define OP_IdxLE          39 /* jump, synopsis: key=r[P3@P4]               */
-
#define OP_IdxGT          40 /* jump, synopsis: key=r[P3@P4]               */
-
#define OP_IdxLT          41 /* jump, synopsis: key=r[P3@P4]               */
-
#define OP_IdxGE          42 /* jump, synopsis: key=r[P3@P4]               */
+
#define OP_IfNullRow      20 /* jump, synopsis: if P1.nullRow then r[P3]=NULL, goto P2 */
+
#define OP_SeekLT         21 /* jump, synopsis: key=r[P3@P4]               */
+
#define OP_SeekLE         22 /* jump, synopsis: key=r[P3@P4]               */
+
#define OP_SeekGE         23 /* jump, synopsis: key=r[P3@P4]               */
+
#define OP_SeekGT         24 /* jump, synopsis: key=r[P3@P4]               */
+
#define OP_IfNotOpen      25 /* jump, synopsis: if( !csr[P1] ) goto P2     */
+
#define OP_IfNoHope       26 /* jump, synopsis: key=r[P3@P4]               */
+
#define OP_NoConflict     27 /* jump, synopsis: key=r[P3@P4]               */
+
#define OP_NotFound       28 /* jump, synopsis: key=r[P3@P4]               */
+
#define OP_Found          29 /* jump, synopsis: key=r[P3@P4]               */
+
#define OP_SeekRowid      30 /* jump, synopsis: intkey=r[P3]               */
+
#define OP_NotExists      31 /* jump, synopsis: intkey=r[P3]               */
+
#define OP_Last           32 /* jump                                       */
+
#define OP_IfSmaller      33 /* jump                                       */
+
#define OP_SorterSort     34 /* jump                                       */
+
#define OP_Sort           35 /* jump                                       */
+
#define OP_Rewind         36 /* jump                                       */
+
#define OP_SorterNext     37 /* jump                                       */
+
#define OP_Prev           38 /* jump                                       */
+
#define OP_Next           39 /* jump                                       */
+
#define OP_IdxLE          40 /* jump, synopsis: key=r[P3@P4]               */
+
#define OP_IdxGT          41 /* jump, synopsis: key=r[P3@P4]               */
+
#define OP_IdxLT          42 /* jump, synopsis: key=r[P3@P4]               */
#define OP_Or             43 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */
#define OP_And            44 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */
-
#define OP_RowSetRead     45 /* jump, synopsis: r[P3]=rowset(P1)           */
-
#define OP_RowSetTest     46 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */
-
#define OP_Program        47 /* jump                                       */
-
#define OP_FkIfZero       48 /* jump, synopsis: if fkctr[P1]==0 goto P2    */
-
#define OP_IfPos          49 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
+
#define OP_IdxGE          45 /* jump, synopsis: key=r[P3@P4]               */
+
#define OP_RowSetRead     46 /* jump, synopsis: r[P3]=rowset(P1)           */
+
#define OP_RowSetTest     47 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */
+
#define OP_Program        48 /* jump                                       */
+
#define OP_FkIfZero       49 /* jump, synopsis: if fkctr[P1]==0 goto P2    */
#define OP_IsNull         50 /* jump, same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
#define OP_NotNull        51 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
#define OP_Ne             52 /* jump, same as TK_NE, synopsis: IF r[P3]!=r[P1] */
@@ -15611,12 +15989,12 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_Lt             56 /* jump, same as TK_LT, synopsis: IF r[P3]<r[P1] */
#define OP_Ge             57 /* jump, same as TK_GE, synopsis: IF r[P3]>=r[P1] */
#define OP_ElseEq         58 /* jump, same as TK_ESCAPE                    */
-
#define OP_IfNotZero      59 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */
-
#define OP_DecrJumpZero   60 /* jump, synopsis: if (--r[P1])==0 goto P2    */
-
#define OP_IncrVacuum     61 /* jump                                       */
-
#define OP_VNext          62 /* jump                                       */
-
#define OP_Filter         63 /* jump, synopsis: if key(P3@P4) not in filter(P1) goto P2 */
-
#define OP_Init           64 /* jump, synopsis: Start at P2                */
+
#define OP_IfPos          59 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
+
#define OP_IfNotZero      60 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */
+
#define OP_DecrJumpZero   61 /* jump, synopsis: if (--r[P1])==0 goto P2    */
+
#define OP_IncrVacuum     62 /* jump                                       */
+
#define OP_VNext          63 /* jump                                       */
+
#define OP_Filter         64 /* jump, synopsis: if key(P3@P4) not in filter(P1) goto P2 */
#define OP_PureFunc       65 /* synopsis: r[P3]=func(r[P2@NP])             */
#define OP_Function       66 /* synopsis: r[P3]=func(r[P2@NP])             */
#define OP_Return         67
@@ -15752,13 +16130,13 @@ typedef struct VdbeOpList VdbeOpList;
#define OPFLG_OUT3        0x20  /* out3:  P3 is an output */
#define OPFLG_INITIALIZER {\
/*   0 */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,\
-
/*   8 */ 0x01, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01, 0x03,\
-
/*  16 */ 0x03, 0x03, 0x01, 0x12, 0x09, 0x09, 0x09, 0x09,\
-
/*  24 */ 0x01, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x01,\
+
/*   8 */ 0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01,\
+
/*  16 */ 0x03, 0x03, 0x01, 0x12, 0x01, 0x09, 0x09, 0x09,\
+
/*  24 */ 0x09, 0x01, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,\
/*  32 */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\
-
/*  40 */ 0x01, 0x01, 0x01, 0x26, 0x26, 0x23, 0x0b, 0x01,\
-
/*  48 */ 0x01, 0x03, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\
-
/*  56 */ 0x0b, 0x0b, 0x01, 0x03, 0x03, 0x01, 0x01, 0x01,\
+
/*  40 */ 0x01, 0x01, 0x01, 0x26, 0x26, 0x01, 0x23, 0x0b,\
+
/*  48 */ 0x01, 0x01, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\
+
/*  56 */ 0x0b, 0x0b, 0x01, 0x03, 0x03, 0x03, 0x01, 0x01,\
/*  64 */ 0x01, 0x00, 0x00, 0x02, 0x02, 0x08, 0x00, 0x10,\
/*  72 */ 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x10, 0x00,\
/*  80 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x02, 0x02,\
@@ -15850,6 +16228,7 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1);
SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2);
SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, int addr, int P3);
SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u16 P5);
+
SQLITE_PRIVATE void sqlite3VdbeTypeofColumn(Vdbe*, int);
SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe*, int addr);
SQLITE_PRIVATE void sqlite3VdbeJumpHereOrPopInst(Vdbe*, int addr);
SQLITE_PRIVATE int sqlite3VdbeChangeToNoop(Vdbe*, int addr);
@@ -15864,6 +16243,7 @@ SQLITE_PRIVATE void sqlite3VdbeAppendP4(Vdbe*, void *pP4, int p4type);
SQLITE_PRIVATE void sqlite3VdbeSetP4KeyInfo(Parse*, Index*);
SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int);
SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
+
SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetLastOp(Vdbe*);
SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Parse*);
SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeReusable(Vdbe*);
@@ -16212,297 +16592,6 @@ SQLITE_PRIVATE int sqlite3PCacheIsDirty(PCache *pCache);

/************** End of pcache.h **********************************************/
/************** Continuing where we left off in sqliteInt.h ******************/
-
/************** Include os.h in the middle of sqliteInt.h ********************/
-
/************** Begin file os.h **********************************************/
-
/*
-
** 2001 September 16
-
**
-
** 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 header file (together with is companion C source-code file
-
** "os.c") attempt to abstract the underlying operating system so that
-
** the SQLite library will work on both POSIX and windows systems.
-
**
-
** This header file is #include-ed by sqliteInt.h and thus ends up
-
** being included by every source file.
-
*/
-
#ifndef _SQLITE_OS_H_
-
#define _SQLITE_OS_H_
-

-
/*
-
** Attempt to automatically detect the operating system and setup the
-
** necessary pre-processor macros for it.
-
*/
-
/************** Include os_setup.h in the middle of os.h *********************/
-
/************** Begin file os_setup.h ****************************************/
-
/*
-
** 2013 November 25
-
**
-
** The author disclaims copyright to this source code.  In place of
-
** a legal notice, here is a blessing:
-
**
-
**    May you do good and not evil.
-
**    May you find forgiveness for yourself and forgive others.
-
**    May you share freely, never taking more than you give.
-
**
-
******************************************************************************
-
**
-
** This file contains pre-processor directives related to operating system
-
** detection and/or setup.
-
*/
-
#ifndef SQLITE_OS_SETUP_H
-
#define SQLITE_OS_SETUP_H
-

-
/*
-
** Figure out if we are dealing with Unix, Windows, or some other operating
-
** system.
-
**
-
** After the following block of preprocess macros, all of SQLITE_OS_UNIX,
-
** SQLITE_OS_WIN, and SQLITE_OS_OTHER will defined to either 1 or 0.  One of
-
** the three will be 1.  The other two will be 0.
-
*/
-
#if defined(SQLITE_OS_OTHER)
-
#  if SQLITE_OS_OTHER==1
-
#    undef SQLITE_OS_UNIX
-
#    define SQLITE_OS_UNIX 0
-
#    undef SQLITE_OS_WIN
-
#    define SQLITE_OS_WIN 0
-
#  else
-
#    undef SQLITE_OS_OTHER
-
#  endif
-
#endif
-
#if !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_OTHER)
-
#  define SQLITE_OS_OTHER 0
-
#  ifndef SQLITE_OS_WIN
-
#    if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || \
-
        defined(__MINGW32__) || defined(__BORLANDC__)
-
#      define SQLITE_OS_WIN 1
-
#      define SQLITE_OS_UNIX 0
-
#    else
-
#      define SQLITE_OS_WIN 0
-
#      define SQLITE_OS_UNIX 1
-
#    endif
-
#  else
-
#    define SQLITE_OS_UNIX 0
-
#  endif
-
#else
-
#  ifndef SQLITE_OS_WIN
-
#    define SQLITE_OS_WIN 0
-
#  endif
-
#endif
-

-
#endif /* SQLITE_OS_SETUP_H */
-

-
/************** End of os_setup.h ********************************************/
-
/************** Continuing where we left off in os.h *************************/
-

-
/* If the SET_FULLSYNC macro is not defined above, then make it
-
** a no-op
-
*/
-
#ifndef SET_FULLSYNC
-
# define SET_FULLSYNC(x,y)
-
#endif
-

-
/* Maximum pathname length.  Note: FILENAME_MAX defined by stdio.h
-
*/
-
#ifndef SQLITE_MAX_PATHLEN
-
# define SQLITE_MAX_PATHLEN FILENAME_MAX
-
#endif
-

-
/* Maximum number of symlinks that will be resolved while trying to
-
** expand a filename in xFullPathname() in the VFS.
-
*/
-
#ifndef SQLITE_MAX_SYMLINK
-
# define SQLITE_MAX_SYMLINK 200
-
#endif
-

-
/*
-
** The default size of a disk sector
-
*/
-
#ifndef SQLITE_DEFAULT_SECTOR_SIZE
-
# define SQLITE_DEFAULT_SECTOR_SIZE 4096
-
#endif
-

-
/*
-
** Temporary files are named starting with this prefix followed by 16 random
-
** alphanumeric characters, and no file extension. They are stored in the
-
** OS's standard temporary file directory, and are deleted prior to exit.
-
** If sqlite is being embedded in another program, you may wish to change the
-
** prefix to reflect your program's name, so that if your program exits
-
** prematurely, old temporary files can be easily identified. This can be done
-
** using -DSQLITE_TEMP_FILE_PREFIX=myprefix_ on the compiler command line.
-
**
-
** 2006-10-31:  The default prefix used to be "sqlite_".  But then
-
** Mcafee started using SQLite in their anti-virus product and it
-
** started putting files with the "sqlite" name in the c:/temp folder.
-
** This annoyed many windows users.  Those users would then do a
-
** Google search for "sqlite", find the telephone numbers of the
-
** developers and call to wake them up at night and complain.
-
** For this reason, the default name prefix is changed to be "sqlite"
-
** spelled backwards.  So the temp files are still identified, but
-
** anybody smart enough to figure out the code is also likely smart
-
** enough to know that calling the developer will not help get rid
-
** of the file.
-
*/
-
#ifndef SQLITE_TEMP_FILE_PREFIX
-
# define SQLITE_TEMP_FILE_PREFIX "etilqs_"
-
#endif
-

-
/*
-
** The following values may be passed as the second argument to
-
** sqlite3OsLock(). The various locks exhibit the following semantics:
-
**
-
** SHARED:    Any number of processes may hold a SHARED lock simultaneously.
-
** RESERVED:  A single process may hold a RESERVED lock on a file at
-
**            any time. Other processes may hold and obtain new SHARED locks.
-
** PENDING:   A single process may hold a PENDING lock on a file at
-
**            any one time. Existing SHARED locks may persist, but no new
-
**            SHARED locks may be obtained by other processes.
-
** EXCLUSIVE: An EXCLUSIVE lock precludes all other locks.
-
**
-
** PENDING_LOCK may not be passed directly to sqlite3OsLock(). Instead, a
-
** process that requests an EXCLUSIVE lock may actually obtain a PENDING
-
** lock. This can be upgraded to an EXCLUSIVE lock by a subsequent call to
-
** sqlite3OsLock().
-
*/
-
#define NO_LOCK         0
-
#define SHARED_LOCK     1
-
#define RESERVED_LOCK   2
-
#define PENDING_LOCK    3
-
#define EXCLUSIVE_LOCK  4
-

-
/*
-
** File Locking Notes:  (Mostly about windows but also some info for Unix)
-
**
-
** We cannot use LockFileEx() or UnlockFileEx() on Win95/98/ME because
-
** those functions are not available.  So we use only LockFile() and
-
** UnlockFile().
-
**
-
** LockFile() prevents not just writing but also reading by other processes.
-
** A SHARED_LOCK is obtained by locking a single randomly-chosen
-
** byte out of a specific range of bytes. The lock byte is obtained at
-
** random so two separate readers can probably access the file at the
-
** same time, unless they are unlucky and choose the same lock byte.
-
** An EXCLUSIVE_LOCK is obtained by locking all bytes in the range.
-
** There can only be one writer.  A RESERVED_LOCK is obtained by locking
-
** a single byte of the file that is designated as the reserved lock byte.
-
** A PENDING_LOCK is obtained by locking a designated byte different from
-
** the RESERVED_LOCK byte.
-
**
-
** On WinNT/2K/XP systems, LockFileEx() and UnlockFileEx() are available,
-
** which means we can use reader/writer locks.  When reader/writer locks
-
** are used, the lock is placed on the same range of bytes that is used
-
** for probabilistic locking in Win95/98/ME.  Hence, the locking scheme
-
** will support two or more Win95 readers or two or more WinNT readers.
-
** But a single Win95 reader will lock out all WinNT readers and a single
-
** WinNT reader will lock out all other Win95 readers.
-
**
-
** The following #defines specify the range of bytes used for locking.
-
** SHARED_SIZE is the number of bytes available in the pool from which
-
** a random byte is selected for a shared lock.  The pool of bytes for
-
** shared locks begins at SHARED_FIRST.
-
**
-
** The same locking strategy and
-
** byte ranges are used for Unix.  This leaves open the possibility of having
-
** clients on win95, winNT, and unix all talking to the same shared file
-
** and all locking correctly.  To do so would require that samba (or whatever
-
** tool is being used for file sharing) implements locks correctly between
-
** windows and unix.  I'm guessing that isn't likely to happen, but by
-
** using the same locking range we are at least open to the possibility.
-
**
-
** Locking in windows is manditory.  For this reason, we cannot store
-
** actual data in the bytes used for locking.  The pager never allocates
-
** the pages involved in locking therefore.  SHARED_SIZE is selected so
-
** that all locks will fit on a single page even at the minimum page size.
-
** PENDING_BYTE defines the beginning of the locks.  By default PENDING_BYTE
-
** is set high so that we don't have to allocate an unused page except
-
** for very large databases.  But one should test the page skipping logic
-
** by setting PENDING_BYTE low and running the entire regression suite.
-
**
-
** Changing the value of PENDING_BYTE results in a subtly incompatible
-
** file format.  Depending on how it is changed, you might not notice
-
** the incompatibility right away, even running a full regression test.
-
** The default location of PENDING_BYTE is the first byte past the
-
** 1GB boundary.
-
**
-
*/
-
#ifdef SQLITE_OMIT_WSD
-
# define PENDING_BYTE     (0x40000000)
-
#else
-
# define PENDING_BYTE      sqlite3PendingByte
-
#endif
-
#define RESERVED_BYTE     (PENDING_BYTE+1)
-
#define SHARED_FIRST      (PENDING_BYTE+2)
-
#define SHARED_SIZE       510
-

-
/*
-
** Wrapper around OS specific sqlite3_os_init() function.
-
*/
-
SQLITE_PRIVATE int sqlite3OsInit(void);
-

-
/*
-
** Functions for accessing sqlite3_file methods
-
*/
-
SQLITE_PRIVATE void sqlite3OsClose(sqlite3_file*);
-
SQLITE_PRIVATE int sqlite3OsRead(sqlite3_file*, void*, int amt, i64 offset);
-
SQLITE_PRIVATE int sqlite3OsWrite(sqlite3_file*, const void*, int amt, i64 offset);
-
SQLITE_PRIVATE int sqlite3OsTruncate(sqlite3_file*, i64 size);
-
SQLITE_PRIVATE int sqlite3OsSync(sqlite3_file*, int);
-
SQLITE_PRIVATE int sqlite3OsFileSize(sqlite3_file*, i64 *pSize);
-
SQLITE_PRIVATE int sqlite3OsLock(sqlite3_file*, int);
-
SQLITE_PRIVATE int sqlite3OsUnlock(sqlite3_file*, int);
-
SQLITE_PRIVATE int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut);
-
SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file*,int,void*);
-
SQLITE_PRIVATE void sqlite3OsFileControlHint(sqlite3_file*,int,void*);
-
#define SQLITE_FCNTL_DB_UNCHANGED 0xca093fa0
-
SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id);
-
SQLITE_PRIVATE int sqlite3OsDeviceCharacteristics(sqlite3_file *id);
-
#ifndef SQLITE_OMIT_WAL
-
SQLITE_PRIVATE int sqlite3OsShmMap(sqlite3_file *,int,int,int,void volatile **);
-
SQLITE_PRIVATE int sqlite3OsShmLock(sqlite3_file *id, int, int, int);
-
SQLITE_PRIVATE void sqlite3OsShmBarrier(sqlite3_file *id);
-
SQLITE_PRIVATE int sqlite3OsShmUnmap(sqlite3_file *id, int);
-
#endif /* SQLITE_OMIT_WAL */
-
SQLITE_PRIVATE int sqlite3OsFetch(sqlite3_file *id, i64, int, void **);
-
SQLITE_PRIVATE int sqlite3OsUnfetch(sqlite3_file *, i64, void *);
-

-

-
/*
-
** Functions for accessing sqlite3_vfs methods
-
*/
-
SQLITE_PRIVATE int sqlite3OsOpen(sqlite3_vfs *, const char *, sqlite3_file*, int, int *);
-
SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *, const char *, int);
-
SQLITE_PRIVATE int sqlite3OsAccess(sqlite3_vfs *, const char *, int, int *pResOut);
-
SQLITE_PRIVATE int sqlite3OsFullPathname(sqlite3_vfs *, const char *, int, char *);
-
#ifndef SQLITE_OMIT_LOAD_EXTENSION
-
SQLITE_PRIVATE void *sqlite3OsDlOpen(sqlite3_vfs *, const char *);
-
SQLITE_PRIVATE void sqlite3OsDlError(sqlite3_vfs *, int, char *);
-
SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *, void *, const char *))(void);
-
SQLITE_PRIVATE void sqlite3OsDlClose(sqlite3_vfs *, void *);
-
#endif /* SQLITE_OMIT_LOAD_EXTENSION */
-
SQLITE_PRIVATE int sqlite3OsRandomness(sqlite3_vfs *, int, char *);
-
SQLITE_PRIVATE int sqlite3OsSleep(sqlite3_vfs *, int);
-
SQLITE_PRIVATE int sqlite3OsGetLastError(sqlite3_vfs*);
-
SQLITE_PRIVATE int sqlite3OsCurrentTimeInt64(sqlite3_vfs *, sqlite3_int64*);
-

-
/*
-
** Convenience functions for opening and closing files using
-
** sqlite3_malloc() to obtain space for the file-handle structure.
-
*/
-
SQLITE_PRIVATE int sqlite3OsOpenMalloc(sqlite3_vfs *, const char *, sqlite3_file **, int,int*);
-
SQLITE_PRIVATE void sqlite3OsCloseFree(sqlite3_file *);
-

-
#endif /* _SQLITE_OS_H_ */
-

-
/************** End of os.h **************************************************/
-
/************** Continuing where we left off in sqliteInt.h ******************/
/************** Include mutex.h in the middle of sqliteInt.h *****************/
/************** Begin file mutex.h *******************************************/
/*
@@ -16748,6 +16837,7 @@ struct Lookaside {
#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
  void *pStart;           /* First byte of available memory space */
  void *pEnd;             /* First byte past end of available space */
+
  void *pTrueEnd;         /* True value of pEnd, when db->pnBytesFreed!=0 */
};
struct LookasideSlot {
  LookasideSlot *pNext;    /* Next buffer in the list of free buffers */
@@ -17092,6 +17182,7 @@ struct sqlite3 {
#define SQLITE_ReleaseReg     0x00400000 /* Use OP_ReleaseReg for testing */
#define SQLITE_FlttnUnionAll  0x00800000 /* Disable the UNION ALL flattener */
   /* TH3 expects this value  ^^^^^^^^^^ See flatten04.test */
+
#define SQLITE_IndexedExpr    0x01000000 /* Pull exprs from index when able */
#define SQLITE_AllOpts        0xffffffff /* All optimizations */

/*
@@ -17664,7 +17755,7 @@ struct Table {
#ifndef SQLITE_OMIT_VIRTUALTABLE
#  define IsVirtual(X)      ((X)->eTabType==TABTYP_VTAB)
#  define ExprIsVtab(X)  \
-
    ((X)->op==TK_COLUMN && (X)->y.pTab!=0 && (X)->y.pTab->eTabType==TABTYP_VTAB)
+
   ((X)->op==TK_COLUMN && (X)->y.pTab->eTabType==TABTYP_VTAB)
#else
#  define IsVirtual(X)      0
#  define ExprIsVtab(X)     0
@@ -17881,10 +17972,22 @@ struct UnpackedRecord {
** The Index.onError field determines whether or not the indexed columns
** must be unique and what to do if they are not.  When Index.onError=OE_None,
** it means this is not a unique index.  Otherwise it is a unique index
-
** and the value of Index.onError indicate the which conflict resolution
-
** algorithm to employ whenever an attempt is made to insert a non-unique
+
** and the value of Index.onError indicates which conflict resolution
+
** algorithm to employ when an attempt is made to insert a non-unique
** element.
**
+
** The colNotIdxed bitmask is used in combination with SrcItem.colUsed
+
** for a fast test to see if an index can serve as a covering index.
+
** colNotIdxed has a 1 bit for every column of the original table that
+
** is *not* available in the index.  Thus the expression
+
** "colUsed & colNotIdxed" will be non-zero if the index is not a
+
** covering index.  The most significant bit of of colNotIdxed will always
+
** be true (note-20221022-a).  If a column beyond the 63rd column of the
+
** table is used, the "colUsed & colNotIdxed" test will always be non-zero
+
** and we have to assume either that the index is not covering, or use
+
** an alternative (slower) algorithm to determine whether or not
+
** the index is covering.
+
**
** While parsing a CREATE TABLE or CREATE INDEX statement in order to
** generate VDBE code (as opposed to parsing one read from an sqlite_schema
** table as part of parsing an existing database schema), transient instances
@@ -17920,6 +18023,8 @@ struct Index {
  unsigned bNoQuery:1;     /* Do not use this index to optimize queries */
  unsigned bAscKeyBug:1;   /* True if the bba7b69f9849b5bf bug applies */
  unsigned bHasVCol:1;     /* Index references one or more VIRTUAL columns */
+
  unsigned bHasExpr:1;     /* Index contains an expression, either a literal
+
                           ** expression, or a reference to a VIRTUAL column */
#ifdef SQLITE_ENABLE_STAT4
  int nSample;             /* Number of elements in aSample[] */
  int nSampleCol;          /* Size of IndexSample.anEq[] and so on */
@@ -17928,7 +18033,7 @@ struct Index {
  tRowcnt *aiRowEst;       /* Non-logarithmic stat1 data for this index */
  tRowcnt nRowEst0;        /* Non-logarithmic number of rows in the index */
#endif
-
  Bitmask colNotIdxed;     /* 0 for unindexed columns in pTab */
+
  Bitmask colNotIdxed;     /* Unindexed columns in pTab */
};

/*
@@ -18196,7 +18301,7 @@ struct Expr {
#define EP_Reduced    0x004000 /* Expr struct EXPR_REDUCEDSIZE bytes only */
#define EP_Win        0x008000 /* Contains window functions */
#define EP_TokenOnly  0x010000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */
-
#define EP_MemToken   0x020000 /* Need to sqlite3DbFree() Expr.zToken */
+
                   /* 0x020000 // Available for reuse */
#define EP_IfNullRow  0x040000 /* The TK_IF_NULL_ROW opcode */
#define EP_Unlikely   0x080000 /* unlikely() or likelihood() function */
#define EP_ConstFunc  0x100000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */
@@ -18381,6 +18486,14 @@ struct IdList {
** The SrcItem object represents a single term in the FROM clause of a query.
** The SrcList object is mostly an array of SrcItems.
**
+
** The jointype starts out showing the join type between the current table
+
** and the next table on the list.  The parser builds the list this way.
+
** But sqlite3SrcListShiftJoinType() later shifts the jointypes so that each
+
** jointype expresses the join between the table and the previous table.
+
**
+
** In the colUsed field, the high-order bit (bit 63) is set if the table
+
** contains more than 63 columns and the 64-th or later column is used.
+
**
** Union member validity:
**
**    u1.zIndexedBy          fg.isIndexedBy && !fg.isTabFunc
@@ -18420,14 +18533,14 @@ struct SrcItem {
    Expr *pOn;        /* fg.isUsing==0 =>  The ON clause of a join */
    IdList *pUsing;   /* fg.isUsing==1 =>  The USING clause of a join */
  } u3;
-
  Bitmask colUsed;  /* Bit N (1<<N) set if column N of pTab is used */
+
  Bitmask colUsed;  /* Bit N set if column N used. Details above for N>62 */
  union {
    char *zIndexedBy;    /* Identifier from "INDEXED BY <zIndex>" clause */
    ExprList *pFuncArg;  /* Arguments to table-valued-function */
  } u1;
  union {
    Index *pIBIndex;  /* Index structure corresponding to u1.zIndexedBy */
-
    CteUse *pCteUse;  /* CTE Usage info info fg.isCte is true */
+
    CteUse *pCteUse;  /* CTE Usage info when fg.isCte is true */
  } u2;
};

@@ -18441,23 +18554,11 @@ struct OnOrUsing {
};

/*
-
** The following structure describes the FROM clause of a SELECT statement.
-
** Each table or subquery in the FROM clause is a separate element of
-
** the SrcList.a[] array.
-
**
-
** With the addition of multiple database support, the following structure
-
** can also be used to describe a particular table such as the table that
-
** is modified by an INSERT, DELETE, or UPDATE statement.  In standard SQL,
-
** such a table must be a simple name: ID.  But in SQLite, the table can
-
** now be identified by a database name, a dot, then the table name: ID.ID.
+
** This object represents one or more tables that are the source of
+
** content for an SQL statement.  For example, a single SrcList object
+
** is used to hold the FROM clause of a SELECT statement.  SrcList also
+
** represents the target tables for DELETE, INSERT, and UPDATE statements.
**
-
** The jointype starts out showing the join type between the current table
-
** and the next table on the list.  The parser builds the list this way.
-
** But sqlite3SrcListShiftJoinType() later shifts the jointypes so that each
-
** jointype expresses the join between the table and the previous table.
-
**
-
** In the colUsed field, the high-order bit (bit 63) is set if the table
-
** contains more than 63 columns and the 64-th or later column is used.
*/
struct SrcList {
  int nSrc;        /* Number of tables or subqueries in the FROM clause */
@@ -18802,7 +18903,7 @@ struct SelectDest {
  int iSDParm2;        /* A second parameter for the eDest disposal method */
  int iSdst;           /* Base register where results are written */
  int nSdst;           /* Number of registers allocated */
-
  char *zAffSdst;      /* Affinity used when eDest==SRT_Set */
+
  char *zAffSdst;      /* Affinity used for SRT_Set, SRT_Table, and similar */
  ExprList *pOrderBy;  /* Key columns for SRT_Queue and SRT_DistQueue */
};

@@ -18868,6 +18969,28 @@ struct TriggerPrg {
#endif

/*
+
** For each index X that has as one of its arguments either an expression
+
** or the name of a virtual generated column, and if X is in scope such that
+
** the value of the expression can simply be read from the index, then
+
** there is an instance of this object on the Parse.pIdxExpr list.
+
**
+
** During code generation, while generating code to evaluate expressions,
+
** this list is consulted and if a matching expression is found, the value
+
** is read from the index rather than being recomputed.
+
*/
+
struct IndexedExpr {
+
  Expr *pExpr;            /* The expression contained in the index */
+
  int iDataCur;           /* The data cursor associated with the index */
+
  int iIdxCur;            /* The index cursor */
+
  int iIdxCol;            /* The index column that contains value of pExpr */
+
  u8 bMaybeNullRow;       /* True if we need an OP_IfNullRow check */
+
  IndexedExpr *pIENext;   /* Next in a list of all indexed expressions */
+
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
+
  const char *zIdxName;   /* Name of index, used only for bytecode comments */
+
#endif
+
};
+

+
/*
** An instance of the ParseCleanup object specifies an operation that
** should be performed after parsing to deallocation resources obtained
** during the parse and which are no longer needed.
@@ -18908,7 +19031,7 @@ struct Parse {
  u8 hasCompound;      /* Need to invoke convertCompoundSelectToSubquery() */
  u8 okConstFactor;    /* OK to factor out constants */
  u8 disableLookaside; /* Number of times lookaside has been disabled */
-
  u8 disableVtab;      /* Disable all virtual tables for this parse */
+
  u8 prepFlags;        /* SQLITE_PREPARE_* flags */
  u8 withinRJSubrtn;   /* Nesting level for RIGHT JOIN body subroutines */
#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
  u8 earlyCleanup;     /* OOM inside sqlite3ParserAddCleanup() */
@@ -18925,6 +19048,7 @@ struct Parse {
  int nLabelAlloc;     /* Number of slots in aLabel */
  int *aLabel;         /* Space to hold the labels */
  ExprList *pConstExpr;/* Constant expressions */
+
  IndexedExpr *pIdxExpr;/* List of expressions used by active indexes */
  Token constraintName;/* Name of the constraint currently being parsed */
  yDbMask writeMask;   /* Start a write transaction on these databases */
  yDbMask cookieMask;  /* Bitmask of schema verified databases */
@@ -19360,15 +19484,15 @@ struct Walker {
    struct RefSrcList *pRefSrcList;           /* sqlite3ReferencesSrcList() */
    int *aiCol;                               /* array of column indexes */
    struct IdxCover *pIdxCover;               /* Check for index coverage */
-
    struct IdxExprTrans *pIdxTrans;           /* Convert idxed expr to column */
    ExprList *pGroupBy;                       /* GROUP BY clause */
    Select *pSelect;                          /* HAVING to WHERE clause ctx */
    struct WindowRewrite *pRewrite;           /* Window rewrite context */
    struct WhereConst *pConst;                /* WHERE clause constants */
    struct RenameCtx *pRename;                /* RENAME COLUMN context */
    struct Table *pTab;                       /* Table of generated column */
+
    struct CoveringIndexCheck *pCovIdxCk;     /* Check for covering index */
    SrcItem *pSrcItem;                        /* A single FROM clause item */
-
    DbFixer *pFix;
+
    DbFixer *pFix;                            /* See sqlite3FixSelect() */
  } u;
};

@@ -19674,6 +19798,7 @@ SQLITE_PRIVATE void *sqlite3DbReallocOrFree(sqlite3 *, void *, u64);
SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *, void *, u64);
SQLITE_PRIVATE void sqlite3DbFree(sqlite3*, void*);
SQLITE_PRIVATE void sqlite3DbFreeNN(sqlite3*, void*);
+
SQLITE_PRIVATE void sqlite3DbNNFreeNN(sqlite3*, void*);
SQLITE_PRIVATE int sqlite3MallocSize(const void*);
SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3*, const void*);
SQLITE_PRIVATE void *sqlite3PageMalloc(int);
@@ -19694,12 +19819,16 @@ SQLITE_PRIVATE int sqlite3HeapNearlyFull(void);
*/
#ifdef SQLITE_USE_ALLOCA
# define sqlite3StackAllocRaw(D,N)   alloca(N)
+
# define sqlite3StackAllocRawNN(D,N) alloca(N)
# define sqlite3StackAllocZero(D,N)  memset(alloca(N), 0, N)
# define sqlite3StackFree(D,P)
+
# define sqlite3StackFreeNN(D,P)
#else
# define sqlite3StackAllocRaw(D,N)   sqlite3DbMallocRaw(D,N)
+
# define sqlite3StackAllocRawNN(D,N) sqlite3DbMallocRawNN(D,N)
# define sqlite3StackAllocZero(D,N)  sqlite3DbMallocZero(D,N)
# define sqlite3StackFree(D,P)       sqlite3DbFree(D,P)
+
# define sqlite3StackFreeNN(D,P)     sqlite3DbFreeNN(D,P)
#endif

/* Do not allow both MEMSYS5 and MEMSYS3 to be defined together.  If they
@@ -20198,6 +20327,7 @@ SQLITE_PRIVATE int sqlite3FixSelect(DbFixer*, Select*);
SQLITE_PRIVATE int sqlite3FixExpr(DbFixer*, Expr*);
SQLITE_PRIVATE int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
SQLITE_PRIVATE int sqlite3RealSameAsInt(double,sqlite3_int64);
+
SQLITE_PRIVATE i64 sqlite3RealToI64(double);
SQLITE_PRIVATE void sqlite3Int64ToText(i64,char*);
SQLITE_PRIVATE int sqlite3AtoF(const char *z, double*, int, u8);
SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*);
@@ -20243,6 +20373,7 @@ SQLITE_PRIVATE int sqlite3VarintLen(u64 v);


SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(sqlite3*, Index*);
+
SQLITE_PRIVATE char *sqlite3TableAffinityStr(sqlite3*,const Table*);
SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe*, Table*, int);
SQLITE_PRIVATE char sqlite3CompareAffinity(const Expr *pExpr, char aff2);
SQLITE_PRIVATE int sqlite3IndexAffinityOk(const Expr *pExpr, char idx_affinity);
@@ -20314,7 +20445,6 @@ SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[];
SQLITE_PRIVATE const char sqlite3StrBINARY[];
SQLITE_PRIVATE const unsigned char sqlite3StdTypeLen[];
SQLITE_PRIVATE const char sqlite3StdTypeAffinity[];
-
SQLITE_PRIVATE const char sqlite3StdTypeMap[];
SQLITE_PRIVATE const char *sqlite3StdType[];
SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[];
SQLITE_PRIVATE const unsigned char *sqlite3aLTb;
@@ -20758,6 +20888,10 @@ SQLITE_PRIVATE void sqlite3VectorErrorMsg(Parse*, Expr*);
SQLITE_PRIVATE const char **sqlite3CompileOptions(int *pnOpt);
#endif

+
#if SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL)
+
SQLITE_PRIVATE int sqlite3KvvfsInit(void);
+
#endif
+

#endif /* SQLITEINT_H */

/************** End of sqliteInt.h *******************************************/
@@ -20989,7 +21123,7 @@ SQLITE_API extern int sqlite3_open_file_count;
** autoconf-based build
*/
#if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H)
-
/* #include "config.h" */
+
/* #include "sqlite_cfg.h" */
#define SQLITECONFIG_H 1
#endif

@@ -21154,6 +21288,9 @@ static const char * const sqlite3azCompileOpt[] = {
#ifdef SQLITE_DISABLE_SKIPAHEAD_DISTINCT
  "DISABLE_SKIPAHEAD_DISTINCT",
#endif
+
#ifdef SQLITE_DQS
+
  "DQS=" CTIMEOPT_VAL(SQLITE_DQS),
+
#endif
#ifdef SQLITE_ENABLE_8_3_NAMES
  "ENABLE_8_3_NAMES=" CTIMEOPT_VAL(SQLITE_ENABLE_8_3_NAMES),
#endif
@@ -21644,9 +21781,6 @@ static const char * const sqlite3azCompileOpt[] = {
#ifdef SQLITE_OMIT_XFER_OPT
  "OMIT_XFER_OPT",
#endif
-
#ifdef SQLITE_PCACHE_SEPARATE_HEADER
-
  "PCACHE_SEPARATE_HEADER",
-
#endif
#ifdef SQLITE_PERFORMANCE_TRACE
  "PERFORMANCE_TRACE",
#endif
@@ -22126,10 +22260,6 @@ SQLITE_PRIVATE const char sqlite3StrBINARY[] = "BINARY";
**
**    sqlite3StdTypeAffinity[]    The affinity associated with each entry
**                                in sqlite3StdType[].
-
**
-
**    sqlite3StdTypeMap[]         The type value (as returned from
-
**                                sqlite3_column_type() or sqlite3_value_type())
-
**                                for each entry in sqlite3StdType[].
*/
SQLITE_PRIVATE const unsigned char sqlite3StdTypeLen[] = { 3, 4, 3, 7, 4, 4 };
SQLITE_PRIVATE const char sqlite3StdTypeAffinity[] = {
@@ -22140,14 +22270,6 @@ SQLITE_PRIVATE const char sqlite3StdTypeAffinity[] = {
  SQLITE_AFF_REAL,
  SQLITE_AFF_TEXT
};
-
SQLITE_PRIVATE const char sqlite3StdTypeMap[] = {
-
  0,
-
  SQLITE_BLOB,
-
  SQLITE_INTEGER,
-
  SQLITE_INTEGER,
-
  SQLITE_FLOAT,
-
  SQLITE_TEXT
-
};
SQLITE_PRIVATE const char *sqlite3StdType[] = {
  "ANY",
  "BLOB",
@@ -22599,7 +22721,7 @@ struct DblquoteStr {
*/
struct Vdbe {
  sqlite3 *db;            /* The database connection that owns this statement */
-
  Vdbe *pPrev,*pNext;     /* Linked list of VDBEs with the same Vdbe.db */
+
  Vdbe **ppVPrev,*pVNext; /* Linked list of VDBEs with the same Vdbe.db */
  Parse *pParse;          /* Parsing context used to create this Vdbe */
  ynVar nVar;             /* Number of entries in aVar[] */
  int nMem;               /* Number of memory locations currently allocated */
@@ -23157,6 +23279,8 @@ SQLITE_API int sqlite3_db_status(

      sqlite3BtreeEnterAll(db);
      db->pnBytesFreed = &nByte;
+
      assert( db->lookaside.pEnd==db->lookaside.pTrueEnd );
+
      db->lookaside.pEnd = db->lookaside.pStart;
      for(i=0; i<db->nDb; i++){
        Schema *pSchema = db->aDb[i].pSchema;
        if( ALWAYS(pSchema!=0) ){
@@ -23182,6 +23306,7 @@ SQLITE_API int sqlite3_db_status(
        }
      }
      db->pnBytesFreed = 0;
+
      db->lookaside.pEnd = db->lookaside.pTrueEnd;
      sqlite3BtreeLeaveAll(db);

      *pHighwater = 0;
@@ -23199,9 +23324,12 @@ SQLITE_API int sqlite3_db_status(
      int nByte = 0;              /* Used to accumulate return value */

      db->pnBytesFreed = &nByte;
-
      for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){
+
      assert( db->lookaside.pEnd==db->lookaside.pTrueEnd );
+
      db->lookaside.pEnd = db->lookaside.pStart;
+
      for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pVNext){
        sqlite3VdbeDelete(pVdbe);
      }
+
      db->lookaside.pEnd = db->lookaside.pTrueEnd;
      db->pnBytesFreed = 0;

      *pHighwater = 0;  /* IMP: R-64479-57858 */
@@ -23537,7 +23665,7 @@ static void computeJD(DateTime *p){
  p->iJD = (sqlite3_int64)((X1 + X2 + D + B - 1524.5 ) * 86400000);
  p->validJD = 1;
  if( p->validHMS ){
-
    p->iJD += p->h*3600000 + p->m*60000 + (sqlite3_int64)(p->s*1000);
+
    p->iJD += p->h*3600000 + p->m*60000 + (sqlite3_int64)(p->s*1000 + 0.5);
    if( p->validTZ ){
      p->iJD -= p->tz*60000;
      p->validYMD = 0;
@@ -24046,7 +24174,7 @@ static int parseModifier(
      */
      if( sqlite3_strnicmp(z, "weekday ", 8)==0
               && sqlite3AtoF(&z[8], &r, sqlite3Strlen30(&z[8]), SQLITE_UTF8)>0
-
               && (n=(int)r)==r && n>=0 && r<7 ){
+
               && r>=0.0 && r<7.0 && (n=(int)r)==r ){
        sqlite3_int64 Z;
        computeYMD_HMS(p);
        p->validTZ = 0;
@@ -24727,9 +24855,11 @@ SQLITE_PRIVATE int sqlite3OsFileSize(sqlite3_file *id, i64 *pSize){
}
SQLITE_PRIVATE int sqlite3OsLock(sqlite3_file *id, int lockType){
  DO_OS_MALLOC_TEST(id);
+
  assert( lockType>=SQLITE_LOCK_SHARED && lockType<=SQLITE_LOCK_EXCLUSIVE );
  return id->pMethods->xLock(id, lockType);
}
SQLITE_PRIVATE int sqlite3OsUnlock(sqlite3_file *id, int lockType){
+
  assert( lockType==SQLITE_LOCK_NONE || lockType==SQLITE_LOCK_SHARED );
  return id->pMethods->xUnlock(id, lockType);
}
SQLITE_PRIVATE int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut){
@@ -24844,6 +24974,7 @@ SQLITE_PRIVATE int sqlite3OsOpen(
  ** down into the VFS layer.  Some SQLITE_OPEN_ flags (for example,
  ** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before
  ** reaching the VFS. */
+
  assert( zPath || (flags & SQLITE_OPEN_EXCLUSIVE) );
  rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x1087f7f, pFlagsOut);
  assert( rc==SQLITE_OK || pFile->pMethods==0 );
  return rc;
@@ -29063,17 +29194,33 @@ static void mallocWithAlarm(int n, void **pp){
}

/*
+
** Maximum size of any single memory allocation.
+
**
+
** This is not a limit on the total amount of memory used.  This is
+
** a limit on the size parameter to sqlite3_malloc() and sqlite3_realloc().
+
**
+
** The upper bound is slightly less than 2GiB:  0x7ffffeff == 2,147,483,391
+
** This provides a 256-byte safety margin for defense against 32-bit
+
** signed integer overflow bugs when computing memory allocation sizes.
+
** Parnoid applications might want to reduce the maximum allocation size
+
** further for an even larger safety margin.  0x3fffffff or 0x0fffffff
+
** or even smaller would be reasonable upper bounds on the size of a memory
+
** allocations for most applications.
+
*/
+
#ifndef SQLITE_MAX_ALLOCATION_SIZE
+
# define SQLITE_MAX_ALLOCATION_SIZE  2147483391
+
#endif
+
#if SQLITE_MAX_ALLOCATION_SIZE>2147483391
+
# error Maximum size for SQLITE_MAX_ALLOCATION_SIZE is 2147483391
+
#endif
+

+
/*
** Allocate memory.  This routine is like sqlite3_malloc() except that it
** assumes the memory subsystem has already been initialized.
*/
SQLITE_PRIVATE void *sqlite3Malloc(u64 n){
  void *p;
-
  if( n==0 || n>=0x7fffff00 ){
-
    /* A memory allocation of a number of bytes which is near the maximum
-
    ** signed integer value might cause an integer overflow inside of the
-
    ** xMalloc().  Hence we limit the maximum size to 0x7fffff00, giving
-
    ** 255 bytes of overhead.  SQLite itself will never use anything near
-
    ** this amount.  The only way to reach the limit is with sqlite3_malloc() */
+
  if( n==0 || n>SQLITE_MAX_ALLOCATION_SIZE ){
    p = 0;
  }else if( sqlite3GlobalConfig.bMemstat ){
    sqlite3_mutex_enter(mem0.mutex);
@@ -29109,7 +29256,7 @@ SQLITE_API void *sqlite3_malloc64(sqlite3_uint64 n){
*/
#ifndef SQLITE_OMIT_LOOKASIDE
static int isLookaside(sqlite3 *db, const void *p){
-
  return SQLITE_WITHIN(p, db->lookaside.pStart, db->lookaside.pEnd);
+
  return SQLITE_WITHIN(p, db->lookaside.pStart, db->lookaside.pTrueEnd);
}
#else
#define isLookaside(A,B) 0
@@ -29133,18 +29280,16 @@ static int lookasideMallocSize(sqlite3 *db, const void *p){
SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, const void *p){
  assert( p!=0 );
#ifdef SQLITE_DEBUG
-
  if( db==0 || !isLookaside(db,p) ){
-
    if( db==0 ){
-
      assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
-
      assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
-
    }else{
-
      assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
-
      assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
-
    }
+
  if( db==0 ){
+
    assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
+
    assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
+
  }else if( !isLookaside(db,p) ){
+
    assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
+
    assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
  }
#endif
  if( db ){
-
    if( ((uptr)p)<(uptr)(db->lookaside.pEnd) ){
+
    if( ((uptr)p)<(uptr)(db->lookaside.pTrueEnd) ){
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
      if( ((uptr)p)>=(uptr)(db->lookaside.pMiddle) ){
        assert( sqlite3_mutex_held(db->mutex) );
@@ -29200,14 +29345,11 @@ SQLITE_PRIVATE void sqlite3DbFreeNN(sqlite3 *db, void *p){
  assert( db==0 || sqlite3_mutex_held(db->mutex) );
  assert( p!=0 );
  if( db ){
-
    if( db->pnBytesFreed ){
-
      measureAllocationSize(db, p);
-
      return;
-
    }
    if( ((uptr)p)<(uptr)(db->lookaside.pEnd) ){
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
      if( ((uptr)p)>=(uptr)(db->lookaside.pMiddle) ){
        LookasideSlot *pBuf = (LookasideSlot*)p;
+
        assert( db->pnBytesFreed==0 );
#ifdef SQLITE_DEBUG
        memset(p, 0xaa, LOOKASIDE_SMALL);  /* Trash freed content */
#endif
@@ -29218,6 +29360,7 @@ SQLITE_PRIVATE void sqlite3DbFreeNN(sqlite3 *db, void *p){
#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
      if( ((uptr)p)>=(uptr)(db->lookaside.pStart) ){
        LookasideSlot *pBuf = (LookasideSlot*)p;
+
        assert( db->pnBytesFreed==0 );
#ifdef SQLITE_DEBUG
        memset(p, 0xaa, db->lookaside.szTrue);  /* Trash freed content */
#endif
@@ -29226,6 +29369,10 @@ SQLITE_PRIVATE void sqlite3DbFreeNN(sqlite3 *db, void *p){
        return;
      }
    }
+
    if( db->pnBytesFreed ){
+
      measureAllocationSize(db, p);
+
      return;
+
    }
  }
  assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
  assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
@@ -29233,6 +29380,43 @@ SQLITE_PRIVATE void sqlite3DbFreeNN(sqlite3 *db, void *p){
  sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
  sqlite3_free(p);
}
+
SQLITE_PRIVATE void sqlite3DbNNFreeNN(sqlite3 *db, void *p){
+
  assert( db!=0 );
+
  assert( sqlite3_mutex_held(db->mutex) );
+
  assert( p!=0 );
+
  if( ((uptr)p)<(uptr)(db->lookaside.pEnd) ){
+
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
+
    if( ((uptr)p)>=(uptr)(db->lookaside.pMiddle) ){
+
      LookasideSlot *pBuf = (LookasideSlot*)p;
+
      assert( db->pnBytesFreed==0 );
+
#ifdef SQLITE_DEBUG
+
      memset(p, 0xaa, LOOKASIDE_SMALL);  /* Trash freed content */
+
#endif
+
      pBuf->pNext = db->lookaside.pSmallFree;
+
      db->lookaside.pSmallFree = pBuf;
+
      return;
+
    }
+
#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
+
    if( ((uptr)p)>=(uptr)(db->lookaside.pStart) ){
+
      LookasideSlot *pBuf = (LookasideSlot*)p;
+
      assert( db->pnBytesFreed==0 );
+
#ifdef SQLITE_DEBUG
+
      memset(p, 0xaa, db->lookaside.szTrue);  /* Trash freed content */
+
#endif
+
      pBuf->pNext = db->lookaside.pFree;
+
      db->lookaside.pFree = pBuf;
+
      return;
+
    }
+
  }
+
  if( db->pnBytesFreed ){
+
    measureAllocationSize(db, p);
+
    return;
+
  }
+
  assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
+
  assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
+
  sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
+
  sqlite3_free(p);
+
}
SQLITE_PRIVATE void sqlite3DbFree(sqlite3 *db, void *p){
  assert( db==0 || sqlite3_mutex_held(db->mutex) );
  if( p ) sqlite3DbFreeNN(db, p);
@@ -32344,16 +32528,41 @@ SQLITE_PRIVATE void sqlite3ShowWinFunc(const Window *p){ sqlite3TreeViewWinFunc(
** This structure is the current state of the generator.
*/
static SQLITE_WSD struct sqlite3PrngType {
-
  unsigned char isInit;          /* True if initialized */
-
  unsigned char i, j;            /* State variables */
-
  unsigned char s[256];          /* State variables */
+
  u32 s[16];                 /* 64 bytes of chacha20 state */
+
  u8 out[64];                /* Output bytes */
+
  u8 n;                      /* Output bytes remaining */
} sqlite3Prng;

+

+
/* The RFC-7539 ChaCha20 block function
+
*/
+
#define ROTL(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
+
#define QR(a, b, c, d) ( \
+
    a += b, d ^= a, d = ROTL(d,16), \
+
    c += d, b ^= c, b = ROTL(b,12), \
+
    a += b, d ^= a, d = ROTL(d, 8), \
+
    c += d, b ^= c, b = ROTL(b, 7))
+
static void chacha_block(u32 *out, const u32 *in){
+
  int i;
+
  u32 x[16];
+
  memcpy(x, in, 64);
+
  for(i=0; i<10; i++){
+
    QR(x[0], x[4], x[ 8], x[12]);
+
    QR(x[1], x[5], x[ 9], x[13]);
+
    QR(x[2], x[6], x[10], x[14]);
+
    QR(x[3], x[7], x[11], x[15]);
+
    QR(x[0], x[5], x[10], x[15]);
+
    QR(x[1], x[6], x[11], x[12]);
+
    QR(x[2], x[7], x[ 8], x[13]);
+
    QR(x[3], x[4], x[ 9], x[14]);
+
  }
+
  for(i=0; i<16; i++) out[i] = x[i]+in[i];
+
}
+

/*
** Return N random bytes.
*/
SQLITE_API void sqlite3_randomness(int N, void *pBuf){
-
  unsigned char t;
  unsigned char *zBuf = pBuf;

  /* The "wsdPrng" macro will resolve to the pseudo-random number generator
@@ -32383,53 +32592,46 @@ SQLITE_API void sqlite3_randomness(int N, void *pBuf){

  sqlite3_mutex_enter(mutex);
  if( N<=0 || pBuf==0 ){
-
    wsdPrng.isInit = 0;
+
    wsdPrng.s[0] = 0;
    sqlite3_mutex_leave(mutex);
    return;
  }

  /* Initialize the state of the random number generator once,
-
  ** the first time this routine is called.  The seed value does
-
  ** not need to contain a lot of randomness since we are not
-
  ** trying to do secure encryption or anything like that...
-
  **
-
  ** Nothing in this file or anywhere else in SQLite does any kind of
-
  ** encryption.  The RC4 algorithm is being used as a PRNG (pseudo-random
-
  ** number generator) not as an encryption device.
+
  ** the first time this routine is called.
  */
-
  if( !wsdPrng.isInit ){
+
  if( wsdPrng.s[0]==0 ){
    sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
-
    int i;
-
    char k[256];
-
    wsdPrng.j = 0;
-
    wsdPrng.i = 0;
+
    static const u32 chacha20_init[] = {
+
      0x61707865, 0x3320646e, 0x79622d32, 0x6b206574
+
    };
+
    memcpy(&wsdPrng.s[0], chacha20_init, 16);
    if( NEVER(pVfs==0) ){
-
      memset(k, 0, sizeof(k));
+
      memset(&wsdPrng.s[4], 0, 44);
    }else{
-
      sqlite3OsRandomness(pVfs, 256, k);
-
    }
-
    for(i=0; i<256; i++){
-
      wsdPrng.s[i] = (u8)i;
+
      sqlite3OsRandomness(pVfs, 44, (char*)&wsdPrng.s[4]);
    }
-
    for(i=0; i<256; i++){
-
      wsdPrng.j += wsdPrng.s[i] + k[i];
-
      t = wsdPrng.s[wsdPrng.j];
-
      wsdPrng.s[wsdPrng.j] = wsdPrng.s[i];
-
      wsdPrng.s[i] = t;
-
    }
-
    wsdPrng.isInit = 1;
+
    wsdPrng.s[15] = wsdPrng.s[12];
+
    wsdPrng.s[12] = 0;
+
    wsdPrng.n = 0;
  }

  assert( N>0 );
-
  do{
-
    wsdPrng.i++;
-
    t = wsdPrng.s[wsdPrng.i];
-
    wsdPrng.j += t;
-
    wsdPrng.s[wsdPrng.i] = wsdPrng.s[wsdPrng.j];
-
    wsdPrng.s[wsdPrng.j] = t;
-
    t += wsdPrng.s[wsdPrng.i];
-
    *(zBuf++) = wsdPrng.s[t];
-
  }while( --N );
+
  while( 1 /* exit by break */ ){
+
    if( N<=wsdPrng.n ){
+
      memcpy(zBuf, &wsdPrng.out[wsdPrng.n-N], N);
+
      wsdPrng.n -= N;
+
      break;
+
    }
+
    if( wsdPrng.n>0 ){
+
      memcpy(zBuf, wsdPrng.out, wsdPrng.n);
+
      N -= wsdPrng.n;
+
      zBuf += wsdPrng.n;
+
    }
+
    wsdPrng.s[12]++;
+
    chacha_block((u32*)wsdPrng.out, wsdPrng.s);
+
    wsdPrng.n = 64;
+
  }
  sqlite3_mutex_leave(mutex);
}

@@ -35287,48 +35489,48 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
    /*   5 */ "Vacuum"           OpHelp(""),
    /*   6 */ "VFilter"          OpHelp("iplan=r[P3] zplan='P4'"),
    /*   7 */ "VUpdate"          OpHelp("data=r[P3@P2]"),
-
    /*   8 */ "Goto"             OpHelp(""),
-
    /*   9 */ "Gosub"            OpHelp(""),
-
    /*  10 */ "InitCoroutine"    OpHelp(""),
-
    /*  11 */ "Yield"            OpHelp(""),
-
    /*  12 */ "MustBeInt"        OpHelp(""),
-
    /*  13 */ "Jump"             OpHelp(""),
-
    /*  14 */ "Once"             OpHelp(""),
-
    /*  15 */ "If"               OpHelp(""),
-
    /*  16 */ "IfNot"            OpHelp(""),
-
    /*  17 */ "IsNullOrType"     OpHelp("if typeof(r[P1]) IN (P3,5) goto P2"),
-
    /*  18 */ "IfNullRow"        OpHelp("if P1.nullRow then r[P3]=NULL, goto P2"),
+
    /*   8 */ "Init"             OpHelp("Start at P2"),
+
    /*   9 */ "Goto"             OpHelp(""),
+
    /*  10 */ "Gosub"            OpHelp(""),
+
    /*  11 */ "InitCoroutine"    OpHelp(""),
+
    /*  12 */ "Yield"            OpHelp(""),
+
    /*  13 */ "MustBeInt"        OpHelp(""),
+
    /*  14 */ "Jump"             OpHelp(""),
+
    /*  15 */ "Once"             OpHelp(""),
+
    /*  16 */ "If"               OpHelp(""),
+
    /*  17 */ "IfNot"            OpHelp(""),
+
    /*  18 */ "IsType"           OpHelp("if typeof(P1.P3) in P5 goto P2"),
    /*  19 */ "Not"              OpHelp("r[P2]= !r[P1]"),
-
    /*  20 */ "SeekLT"           OpHelp("key=r[P3@P4]"),
-
    /*  21 */ "SeekLE"           OpHelp("key=r[P3@P4]"),
-
    /*  22 */ "SeekGE"           OpHelp("key=r[P3@P4]"),
-
    /*  23 */ "SeekGT"           OpHelp("key=r[P3@P4]"),
-
    /*  24 */ "IfNotOpen"        OpHelp("if( !csr[P1] ) goto P2"),
-
    /*  25 */ "IfNoHope"         OpHelp("key=r[P3@P4]"),
-
    /*  26 */ "NoConflict"       OpHelp("key=r[P3@P4]"),
-
    /*  27 */ "NotFound"         OpHelp("key=r[P3@P4]"),
-
    /*  28 */ "Found"            OpHelp("key=r[P3@P4]"),
-
    /*  29 */ "SeekRowid"        OpHelp("intkey=r[P3]"),
-
    /*  30 */ "NotExists"        OpHelp("intkey=r[P3]"),
-
    /*  31 */ "Last"             OpHelp(""),
-
    /*  32 */ "IfSmaller"        OpHelp(""),
-
    /*  33 */ "SorterSort"       OpHelp(""),
-
    /*  34 */ "Sort"             OpHelp(""),
-
    /*  35 */ "Rewind"           OpHelp(""),
-
    /*  36 */ "SorterNext"       OpHelp(""),
-
    /*  37 */ "Prev"             OpHelp(""),
-
    /*  38 */ "Next"             OpHelp(""),
-
    /*  39 */ "IdxLE"            OpHelp("key=r[P3@P4]"),
-
    /*  40 */ "IdxGT"            OpHelp("key=r[P3@P4]"),
-
    /*  41 */ "IdxLT"            OpHelp("key=r[P3@P4]"),
-
    /*  42 */ "IdxGE"            OpHelp("key=r[P3@P4]"),
+
    /*  20 */ "IfNullRow"        OpHelp("if P1.nullRow then r[P3]=NULL, goto P2"),
+
    /*  21 */ "SeekLT"           OpHelp("key=r[P3@P4]"),
+
    /*  22 */ "SeekLE"           OpHelp("key=r[P3@P4]"),
+
    /*  23 */ "SeekGE"           OpHelp("key=r[P3@P4]"),
+
    /*  24 */ "SeekGT"           OpHelp("key=r[P3@P4]"),
+
    /*  25 */ "IfNotOpen"        OpHelp("if( !csr[P1] ) goto P2"),
+
    /*  26 */ "IfNoHope"         OpHelp("key=r[P3@P4]"),
+
    /*  27 */ "NoConflict"       OpHelp("key=r[P3@P4]"),
+
    /*  28 */ "NotFound"         OpHelp("key=r[P3@P4]"),
+
    /*  29 */ "Found"            OpHelp("key=r[P3@P4]"),
+
    /*  30 */ "SeekRowid"        OpHelp("intkey=r[P3]"),
+
    /*  31 */ "NotExists"        OpHelp("intkey=r[P3]"),
+
    /*  32 */ "Last"             OpHelp(""),
+
    /*  33 */ "IfSmaller"        OpHelp(""),
+
    /*  34 */ "SorterSort"       OpHelp(""),
+
    /*  35 */ "Sort"             OpHelp(""),
+
    /*  36 */ "Rewind"           OpHelp(""),
+
    /*  37 */ "SorterNext"       OpHelp(""),
+
    /*  38 */ "Prev"             OpHelp(""),
+
    /*  39 */ "Next"             OpHelp(""),
+
    /*  40 */ "IdxLE"            OpHelp("key=r[P3@P4]"),
+
    /*  41 */ "IdxGT"            OpHelp("key=r[P3@P4]"),
+
    /*  42 */ "IdxLT"            OpHelp("key=r[P3@P4]"),
    /*  43 */ "Or"               OpHelp("r[P3]=(r[P1] || r[P2])"),
    /*  44 */ "And"              OpHelp("r[P3]=(r[P1] && r[P2])"),
-
    /*  45 */ "RowSetRead"       OpHelp("r[P3]=rowset(P1)"),
-
    /*  46 */ "RowSetTest"       OpHelp("if r[P3] in rowset(P1) goto P2"),
-
    /*  47 */ "Program"          OpHelp(""),
-
    /*  48 */ "FkIfZero"         OpHelp("if fkctr[P1]==0 goto P2"),
-
    /*  49 */ "IfPos"            OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
+
    /*  45 */ "IdxGE"            OpHelp("key=r[P3@P4]"),
+
    /*  46 */ "RowSetRead"       OpHelp("r[P3]=rowset(P1)"),
+
    /*  47 */ "RowSetTest"       OpHelp("if r[P3] in rowset(P1) goto P2"),
+
    /*  48 */ "Program"          OpHelp(""),
+
    /*  49 */ "FkIfZero"         OpHelp("if fkctr[P1]==0 goto P2"),
    /*  50 */ "IsNull"           OpHelp("if r[P1]==NULL goto P2"),
    /*  51 */ "NotNull"          OpHelp("if r[P1]!=NULL goto P2"),
    /*  52 */ "Ne"               OpHelp("IF r[P3]!=r[P1]"),
@@ -35338,12 +35540,12 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
    /*  56 */ "Lt"               OpHelp("IF r[P3]<r[P1]"),
    /*  57 */ "Ge"               OpHelp("IF r[P3]>=r[P1]"),
    /*  58 */ "ElseEq"           OpHelp(""),
-
    /*  59 */ "IfNotZero"        OpHelp("if r[P1]!=0 then r[P1]--, goto P2"),
-
    /*  60 */ "DecrJumpZero"     OpHelp("if (--r[P1])==0 goto P2"),
-
    /*  61 */ "IncrVacuum"       OpHelp(""),
-
    /*  62 */ "VNext"            OpHelp(""),
-
    /*  63 */ "Filter"           OpHelp("if key(P3@P4) not in filter(P1) goto P2"),
-
    /*  64 */ "Init"             OpHelp("Start at P2"),
+
    /*  59 */ "IfPos"            OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
+
    /*  60 */ "IfNotZero"        OpHelp("if r[P1]!=0 then r[P1]--, goto P2"),
+
    /*  61 */ "DecrJumpZero"     OpHelp("if (--r[P1])==0 goto P2"),
+
    /*  62 */ "IncrVacuum"       OpHelp(""),
+
    /*  63 */ "VNext"            OpHelp(""),
+
    /*  64 */ "Filter"           OpHelp("if key(P3@P4) not in filter(P1) goto P2"),
    /*  65 */ "PureFunc"         OpHelp("r[P3]=func(r[P2@NP])"),
    /*  66 */ "Function"         OpHelp("r[P3]=func(r[P2@NP])"),
    /*  67 */ "Return"           OpHelp(""),
@@ -35472,6 +35674,981 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
#endif

/************** End of opcodes.c *********************************************/
+
/************** Begin file os_kv.c *******************************************/
+
/*
+
** 2022-09-06
+
**
+
** The author disclaims copyright to this source code.  In place of
+
** a legal notice, here is a blessing:
+
**
+
**    May you do good and not evil.
+
**    May you find forgiveness for yourself and forgive others.
+
**    May you share freely, never taking more than you give.
+
**
+
******************************************************************************
+
**
+
** This file contains an experimental VFS layer that operates on a
+
** Key/Value storage engine where both keys and values must be pure
+
** text.
+
*/
+
/* #include <sqliteInt.h> */
+
#if SQLITE_OS_KV || (SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL))
+

+
/*****************************************************************************
+
** Debugging logic
+
*/
+

+
/* SQLITE_KV_TRACE() is used for tracing calls to kvstorage routines. */
+
#if 0
+
#define SQLITE_KV_TRACE(X)  printf X
+
#else
+
#define SQLITE_KV_TRACE(X)
+
#endif
+

+
/* SQLITE_KV_LOG() is used for tracing calls to the VFS interface */
+
#if 0
+
#define SQLITE_KV_LOG(X)  printf X
+
#else
+
#define SQLITE_KV_LOG(X)
+
#endif
+

+

+
/*
+
** Forward declaration of objects used by this VFS implementation
+
*/
+
typedef struct KVVfsFile KVVfsFile;
+

+
/* A single open file.  There are only two files represented by this
+
** VFS - the database and the rollback journal.
+
*/
+
struct KVVfsFile {
+
  sqlite3_file base;              /* IO methods */
+
  const char *zClass;             /* Storage class */
+
  int isJournal;                  /* True if this is a journal file */
+
  unsigned int nJrnl;             /* Space allocated for aJrnl[] */
+
  char *aJrnl;                    /* Journal content */
+
  int szPage;                     /* Last known page size */
+
  sqlite3_int64 szDb;             /* Database file size.  -1 means unknown */
+
};
+

+
/*
+
** Methods for KVVfsFile
+
*/
+
static int kvvfsClose(sqlite3_file*);
+
static int kvvfsReadDb(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
+
static int kvvfsReadJrnl(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
+
static int kvvfsWriteDb(sqlite3_file*,const void*,int iAmt, sqlite3_int64);
+
static int kvvfsWriteJrnl(sqlite3_file*,const void*,int iAmt, sqlite3_int64);
+
static int kvvfsTruncateDb(sqlite3_file*, sqlite3_int64 size);
+
static int kvvfsTruncateJrnl(sqlite3_file*, sqlite3_int64 size);
+
static int kvvfsSyncDb(sqlite3_file*, int flags);
+
static int kvvfsSyncJrnl(sqlite3_file*, int flags);
+
static int kvvfsFileSizeDb(sqlite3_file*, sqlite3_int64 *pSize);
+
static int kvvfsFileSizeJrnl(sqlite3_file*, sqlite3_int64 *pSize);
+
static int kvvfsLock(sqlite3_file*, int);
+
static int kvvfsUnlock(sqlite3_file*, int);
+
static int kvvfsCheckReservedLock(sqlite3_file*, int *pResOut);
+
static int kvvfsFileControlDb(sqlite3_file*, int op, void *pArg);
+
static int kvvfsFileControlJrnl(sqlite3_file*, int op, void *pArg);
+
static int kvvfsSectorSize(sqlite3_file*);
+
static int kvvfsDeviceCharacteristics(sqlite3_file*);
+

+
/*
+
** Methods for sqlite3_vfs
+
*/
+
static int kvvfsOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
+
static int kvvfsDelete(sqlite3_vfs*, const char *zName, int syncDir);
+
static int kvvfsAccess(sqlite3_vfs*, const char *zName, int flags, int *);
+
static int kvvfsFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
+
static void *kvvfsDlOpen(sqlite3_vfs*, const char *zFilename);
+
static int kvvfsRandomness(sqlite3_vfs*, int nByte, char *zOut);
+
static int kvvfsSleep(sqlite3_vfs*, int microseconds);
+
static int kvvfsCurrentTime(sqlite3_vfs*, double*);
+
static int kvvfsCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
+

+
static sqlite3_vfs sqlite3OsKvvfsObject = {
+
  1,                              /* iVersion */
+
  sizeof(KVVfsFile),              /* szOsFile */
+
  1024,                           /* mxPathname */
+
  0,                              /* pNext */
+
  "kvvfs",                        /* zName */
+
  0,                              /* pAppData */
+
  kvvfsOpen,                      /* xOpen */
+
  kvvfsDelete,                    /* xDelete */
+
  kvvfsAccess,                    /* xAccess */
+
  kvvfsFullPathname,              /* xFullPathname */
+
  kvvfsDlOpen,                    /* xDlOpen */
+
  0,                              /* xDlError */
+
  0,                              /* xDlSym */
+
  0,                              /* xDlClose */
+
  kvvfsRandomness,                /* xRandomness */
+
  kvvfsSleep,                     /* xSleep */
+
  kvvfsCurrentTime,               /* xCurrentTime */
+
  0,                              /* xGetLastError */
+
  kvvfsCurrentTimeInt64           /* xCurrentTimeInt64 */
+
};
+

+
/* Methods for sqlite3_file objects referencing a database file
+
*/
+
static sqlite3_io_methods kvvfs_db_io_methods = {
+
  1,                              /* iVersion */
+
  kvvfsClose,                     /* xClose */
+
  kvvfsReadDb,                    /* xRead */
+
  kvvfsWriteDb,                   /* xWrite */
+
  kvvfsTruncateDb,                /* xTruncate */
+
  kvvfsSyncDb,                    /* xSync */
+
  kvvfsFileSizeDb,                /* xFileSize */
+
  kvvfsLock,                      /* xLock */
+
  kvvfsUnlock,                    /* xUnlock */
+
  kvvfsCheckReservedLock,         /* xCheckReservedLock */
+
  kvvfsFileControlDb,             /* xFileControl */
+
  kvvfsSectorSize,                /* xSectorSize */
+
  kvvfsDeviceCharacteristics,     /* xDeviceCharacteristics */
+
  0,                              /* xShmMap */
+
  0,                              /* xShmLock */
+
  0,                              /* xShmBarrier */
+
  0,                              /* xShmUnmap */
+
  0,                              /* xFetch */
+
  0                               /* xUnfetch */
+
};
+

+
/* Methods for sqlite3_file objects referencing a rollback journal
+
*/
+
static sqlite3_io_methods kvvfs_jrnl_io_methods = {
+
  1,                              /* iVersion */
+
  kvvfsClose,                     /* xClose */
+
  kvvfsReadJrnl,                  /* xRead */
+
  kvvfsWriteJrnl,                 /* xWrite */
+
  kvvfsTruncateJrnl,              /* xTruncate */
+
  kvvfsSyncJrnl,                  /* xSync */
+
  kvvfsFileSizeJrnl,              /* xFileSize */
+
  kvvfsLock,                      /* xLock */
+
  kvvfsUnlock,                    /* xUnlock */
+
  kvvfsCheckReservedLock,         /* xCheckReservedLock */
+
  kvvfsFileControlJrnl,           /* xFileControl */
+
  kvvfsSectorSize,                /* xSectorSize */
+
  kvvfsDeviceCharacteristics,     /* xDeviceCharacteristics */
+
  0,                              /* xShmMap */
+
  0,                              /* xShmLock */
+
  0,                              /* xShmBarrier */
+
  0,                              /* xShmUnmap */
+
  0,                              /* xFetch */
+
  0                               /* xUnfetch */
+
};
+

+
/****** Storage subsystem **************************************************/
+
#include <sys/types.h>
+
#include <sys/stat.h>
+
#include <unistd.h>
+

+
/* Forward declarations for the low-level storage engine
+
*/
+
static int kvstorageWrite(const char*, const char *zKey, const char *zData);
+
static int kvstorageDelete(const char*, const char *zKey);
+
static int kvstorageRead(const char*, const char *zKey, char *zBuf, int nBuf);
+
#define KVSTORAGE_KEY_SZ  32
+

+
/* Expand the key name with an appropriate prefix and put the result
+
** zKeyOut[].  The zKeyOut[] buffer is assumed to hold at least
+
** KVSTORAGE_KEY_SZ bytes.
+
*/
+
static void kvstorageMakeKey(
+
  const char *zClass,
+
  const char *zKeyIn,
+
  char *zKeyOut
+
){
+
  sqlite3_snprintf(KVSTORAGE_KEY_SZ, zKeyOut, "kvvfs-%s-%s", zClass, zKeyIn);
+
}
+

+
/* Write content into a key.  zClass is the particular namespace of the
+
** underlying key/value store to use - either "local" or "session".
+
**
+
** Both zKey and zData are zero-terminated pure text strings.
+
**
+
** Return the number of errors.
+
*/
+
static int kvstorageWrite(
+
  const char *zClass,
+
  const char *zKey,
+
  const char *zData
+
){
+
  FILE *fd;
+
  char zXKey[KVSTORAGE_KEY_SZ];
+
  kvstorageMakeKey(zClass, zKey, zXKey);
+
  fd = fopen(zXKey, "wb");
+
  if( fd ){
+
    SQLITE_KV_TRACE(("KVVFS-WRITE  %-15s (%d) %.50s%s\n", zXKey,
+
                 (int)strlen(zData), zData,
+
                 strlen(zData)>50 ? "..." : ""));
+
    fputs(zData, fd);
+
    fclose(fd);
+
    return 0;
+
  }else{
+
    return 1;
+
  }
+
}
+

+
/* Delete a key (with its corresponding data) from the key/value
+
** namespace given by zClass.  If the key does not previously exist,
+
** this routine is a no-op.
+
*/
+
static int kvstorageDelete(const char *zClass, const char *zKey){
+
  char zXKey[KVSTORAGE_KEY_SZ];
+
  kvstorageMakeKey(zClass, zKey, zXKey);
+
  unlink(zXKey);
+
  SQLITE_KV_TRACE(("KVVFS-DELETE %-15s\n", zXKey));
+
  return 0;
+
}
+

+
/* Read the value associated with a zKey from the key/value namespace given
+
** by zClass and put the text data associated with that key in the first
+
** nBuf bytes of zBuf[].  The value might be truncated if zBuf is not large
+
** enough to hold it all.  The value put into zBuf must always be zero
+
** terminated, even if it gets truncated because nBuf is not large enough.
+
**
+
** Return the total number of bytes in the data, without truncation, and
+
** not counting the final zero terminator.   Return -1 if the key does
+
** not exist.
+
**
+
** If nBuf<=0 then this routine simply returns the size of the data without
+
** actually reading it.
+
*/
+
static int kvstorageRead(
+
  const char *zClass,
+
  const char *zKey,
+
  char *zBuf,
+
  int nBuf
+
){
+
  FILE *fd;
+
  struct stat buf;
+
  char zXKey[KVSTORAGE_KEY_SZ];
+
  kvstorageMakeKey(zClass, zKey, zXKey);
+
  if( access(zXKey, R_OK)!=0
+
   || stat(zXKey, &buf)!=0
+
   || !S_ISREG(buf.st_mode)
+
  ){
+
    SQLITE_KV_TRACE(("KVVFS-READ   %-15s (-1)\n", zXKey));
+
    return -1;
+
  }
+
  if( nBuf<=0 ){
+
    return (int)buf.st_size;
+
  }else if( nBuf==1 ){
+
    zBuf[0] = 0;
+
    SQLITE_KV_TRACE(("KVVFS-READ   %-15s (%d)\n", zXKey,
+
                 (int)buf.st_size));
+
    return (int)buf.st_size;
+
  }
+
  if( nBuf > buf.st_size + 1 ){
+
    nBuf = buf.st_size + 1;
+
  }
+
  fd = fopen(zXKey, "rb");
+
  if( fd==0 ){
+
    SQLITE_KV_TRACE(("KVVFS-READ   %-15s (-1)\n", zXKey));
+
    return -1;
+
  }else{
+
    sqlite3_int64 n = fread(zBuf, 1, nBuf-1, fd);
+
    fclose(fd);
+
    zBuf[n] = 0;
+
    SQLITE_KV_TRACE(("KVVFS-READ   %-15s (%lld) %.50s%s\n", zXKey,
+
                 n, zBuf, n>50 ? "..." : ""));
+
    return (int)n;
+
  }
+
}
+

+
/*
+
** An internal level of indirection which enables us to replace the
+
** kvvfs i/o methods with JavaScript implementations in WASM builds.
+
** Maintenance reminder: if this struct changes in any way, the JSON
+
** rendering of its structure must be updated in
+
** sqlite3_wasm_enum_json(). There are no binary compatibility
+
** concerns, so it does not need an iVersion member. This file is
+
** necessarily always compiled together with sqlite3_wasm_enum_json(),
+
** and JS code dynamically creates the mapping of members based on
+
** that JSON description.
+
*/
+
typedef struct sqlite3_kvvfs_methods sqlite3_kvvfs_methods;
+
struct sqlite3_kvvfs_methods {
+
  int (*xRead)(const char *zClass, const char *zKey, char *zBuf, int nBuf);
+
  int (*xWrite)(const char *zClass, const char *zKey, const char *zData);
+
  int (*xDelete)(const char *zClass, const char *zKey);
+
  const int nKeySize;
+
};
+

+
/*
+
** This object holds the kvvfs I/O methods which may be swapped out
+
** for JavaScript-side implementations in WASM builds. In such builds
+
** it cannot be const, but in native builds it should be so that
+
** the compiler can hopefully optimize this level of indirection out.
+
** That said, kvvfs is intended primarily for use in WASM builds.
+
**
+
** Note that this is not explicitly flagged as static because the
+
** amalgamation build will tag it with SQLITE_PRIVATE.
+
*/
+
#ifndef SQLITE_WASM
+
const
+
#endif
+
SQLITE_PRIVATE sqlite3_kvvfs_methods sqlite3KvvfsMethods = {
+
kvstorageRead,
+
kvstorageWrite,
+
kvstorageDelete,
+
KVSTORAGE_KEY_SZ
+
};
+

+
/****** Utility subroutines ************************************************/
+

+
/*
+
** Encode binary into the text encoded used to persist on disk.
+
** The output text is stored in aOut[], which must be at least
+
** nData+1 bytes in length.
+
**
+
** Return the actual length of the encoded text, not counting the
+
** zero terminator at the end.
+
**
+
** Encoding format
+
** ---------------
+
**
+
**   *  Non-zero bytes are encoded as upper-case hexadecimal
+
**
+
**   *  A sequence of one or more zero-bytes that are not at the
+
**      beginning of the buffer are encoded as a little-endian
+
**      base-26 number using a..z.  "a" means 0.  "b" means 1,
+
**      "z" means 25.  "ab" means 26.  "ac" means 52.  And so forth.
+
**
+
**   *  Because there is no overlap between the encoding characters
+
**      of hexadecimal and base-26 numbers, it is always clear where
+
**      one stops and the next begins.
+
*/
+
static int kvvfsEncode(const char *aData, int nData, char *aOut){
+
  int i, j;
+
  const unsigned char *a = (const unsigned char*)aData;
+
  for(i=j=0; i<nData; i++){
+
    unsigned char c = a[i];
+
    if( c!=0 ){
+
      aOut[j++] = "0123456789ABCDEF"[c>>4];
+
      aOut[j++] = "0123456789ABCDEF"[c&0xf];
+
    }else{
+
      /* A sequence of 1 or more zeros is stored as a little-endian
+
      ** base-26 number using a..z as the digits. So one zero is "b".
+
      ** Two zeros is "c". 25 zeros is "z", 26 zeros is "ab", 27 is "bb",
+
      ** and so forth.
+
      */
+
      int k;
+
      for(k=1; i+k<nData && a[i+k]==0; k++){}
+
      i += k-1;
+
      while( k>0 ){
+
        aOut[j++] = 'a'+(k%26);
+
        k /= 26;
+
      }
+
    }
+
  }
+
  aOut[j] = 0;
+
  return j;
+
}
+

+
static const signed char kvvfsHexValue[256] = {
+
  -1, -1, -1, -1, -1, -1, -1, -1,   -1, -1, -1, -1, -1, -1, -1, -1,
+
  -1, -1, -1, -1, -1, -1, -1, -1,   -1, -1, -1, -1, -1, -1, -1, -1,
+
  -1, -1, -1, -1, -1, -1, -1, -1,   -1, -1, -1, -1, -1, -1, -1, -1,
+
   0,  1,  2,  3,  4,  5,  6,  7,    8,  9, -1, -1, -1, -1, -1, -1,
+
  -1, 10, 11, 12, 13, 14, 15, -1,   -1, -1, -1, -1, -1, -1, -1, -1,
+
  -1, -1, -1, -1, -1, -1, -1, -1,   -1, -1, -1, -1, -1, -1, -1, -1,
+
  -1, -1, -1, -1, -1, -1, -1, -1,   -1, -1, -1, -1, -1, -1, -1, -1,
+
  -1, -1, -1, -1, -1, -1, -1, -1,   -1, -1, -1, -1, -1, -1, -1, -1,
+

+
  -1, -1, -1, -1, -1, -1, -1, -1,   -1, -1, -1, -1, -1, -1, -1, -1,
+
  -1, -1, -1, -1, -1, -1, -1, -1,   -1, -1, -1, -1, -1, -1, -1, -1,
+
  -1, -1, -1, -1, -1, -1, -1, -1,   -1, -1, -1, -1, -1, -1, -1, -1,
+
  -1, -1, -1, -1, -1, -1, -1, -1,   -1, -1, -1, -1, -1, -1, -1, -1,
+
  -1, -1, -1, -1, -1, -1, -1, -1,   -1, -1, -1, -1, -1, -1, -1, -1,
+
  -1, -1, -1, -1, -1, -1, -1, -1,   -1, -1, -1, -1, -1, -1, -1, -1,
+
  -1, -1, -1, -1, -1, -1, -1, -1,   -1, -1, -1, -1, -1, -1, -1, -1,
+
  -1, -1, -1, -1, -1, -1, -1, -1,   -1, -1, -1, -1, -1, -1, -1, -1
+
};
+

+
/*
+
** Decode the text encoding back to binary.  The binary content is
+
** written into pOut, which must be at least nOut bytes in length.
+
**
+
** The return value is the number of bytes actually written into aOut[].
+
*/
+
static int kvvfsDecode(const char *a, char *aOut, int nOut){
+
  int i, j;
+
  int c;
+
  const unsigned char *aIn = (const unsigned char*)a;
+
  i = 0;
+
  j = 0;
+
  while( 1 ){
+
    c = kvvfsHexValue[aIn[i]];
+
    if( c<0 ){
+
      int n = 0;
+
      int mult = 1;
+
      c = aIn[i];
+
      if( c==0 ) break;
+
      while( c>='a' && c<='z' ){
+
        n += (c - 'a')*mult;
+
        mult *= 26;
+
        c = aIn[++i];
+
      }
+
      if( j+n>nOut ) return -1;
+
      memset(&aOut[j], 0, n);
+
      j += n;
+
      c = aIn[i];
+
      if( c==0 ) break;
+
    }else{
+
      aOut[j] = c<<4;
+
      c = kvvfsHexValue[aIn[++i]];
+
      if( c<0 ) break;
+
      aOut[j++] += c;
+
      i++;
+
    }
+
  }
+
  return j;
+
}
+

+
/*
+
** Decode a complete journal file.  Allocate space in pFile->aJrnl
+
** and store the decoding there.  Or leave pFile->aJrnl set to NULL
+
** if an error is encountered.
+
**
+
** The first few characters of the text encoding will be a little-endian
+
** base-26 number (digits a..z) that is the total number of bytes
+
** in the decoded journal file image.  This base-26 number is followed
+
** by a single space, then the encoding of the journal.  The space
+
** separator is required to act as a terminator for the base-26 number.
+
*/
+
static void kvvfsDecodeJournal(
+
  KVVfsFile *pFile,      /* Store decoding in pFile->aJrnl */
+
  const char *zTxt,      /* Text encoding.  Zero-terminated */
+
  int nTxt               /* Bytes in zTxt, excluding zero terminator */
+
){
+
  unsigned int n = 0;
+
  int c, i, mult;
+
  i = 0;
+
  mult = 1;
+
  while( (c = zTxt[i++])>='a' && c<='z' ){
+
    n += (zTxt[i] - 'a')*mult;
+
    mult *= 26;
+
  }
+
  sqlite3_free(pFile->aJrnl);
+
  pFile->aJrnl = sqlite3_malloc64( n );
+
  if( pFile->aJrnl==0 ){
+
    pFile->nJrnl = 0;
+
    return;
+
  }
+
  pFile->nJrnl = n;
+
  n = kvvfsDecode(zTxt+i, pFile->aJrnl, pFile->nJrnl);
+
  if( n<pFile->nJrnl ){
+
    sqlite3_free(pFile->aJrnl);
+
    pFile->aJrnl = 0;
+
    pFile->nJrnl = 0;
+
  }
+
}
+

+
/*
+
** Read or write the "sz" element, containing the database file size.
+
*/
+
static sqlite3_int64 kvvfsReadFileSize(KVVfsFile *pFile){
+
  char zData[50];
+
  zData[0] = 0;
+
  sqlite3KvvfsMethods.xRead(pFile->zClass, "sz", zData, sizeof(zData)-1);
+
  return strtoll(zData, 0, 0);
+
}
+
static int kvvfsWriteFileSize(KVVfsFile *pFile, sqlite3_int64 sz){
+
  char zData[50];
+
  sqlite3_snprintf(sizeof(zData), zData, "%lld", sz);
+
  return sqlite3KvvfsMethods.xWrite(pFile->zClass, "sz", zData);
+
}
+

+
/****** sqlite3_io_methods methods ******************************************/
+

+
/*
+
** Close an kvvfs-file.
+
*/
+
static int kvvfsClose(sqlite3_file *pProtoFile){
+
  KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
+

+
  SQLITE_KV_LOG(("xClose %s %s\n", pFile->zClass,
+
             pFile->isJournal ? "journal" : "db"));
+
  sqlite3_free(pFile->aJrnl);
+
  return SQLITE_OK;
+
}
+

+
/*
+
** Read from the -journal file.
+
*/
+
static int kvvfsReadJrnl(
+
  sqlite3_file *pProtoFile,
+
  void *zBuf,
+
  int iAmt,
+
  sqlite_int64 iOfst
+
){
+
  KVVfsFile *pFile = (KVVfsFile*)pProtoFile;
+
  assert( pFile->isJournal );
+
  SQLITE_KV_LOG(("xRead('%s-journal',%d,%lld)\n", pFile->zClass, iAmt, iOfst));
+
  if( pFile->aJrnl==0 ){
+
    int szTxt = kvstorageRead(pFile->zClass, "jrnl", 0, 0);
+
    char *aTxt;
+
    if( szTxt<=4 ){
+
      return SQLITE_IOERR;
+
    }
+
    aTxt = sqlite3_malloc64( szTxt+1 );
+
    if( aTxt==0 ) return SQLITE_NOMEM;
+
    kvstorageRead(pFile->zClass, "jrnl", aTxt, szTxt+1);
+
    kvvfsDecodeJournal(pFile, aTxt, szTxt);
+
    sqlite3_free(aTxt);
+
    if( pFile->aJrnl==0 ) return SQLITE_IOERR;
+
  }
+
  if( iOfst+iAmt>pFile->nJrnl ){
+
    return SQLITE_IOERR_SHORT_READ;
+
  }
+
  memcpy(zBuf, pFile->aJrnl+iOfst, iAmt);
+
  return SQLITE_OK;
+
}
+

+
/*
+
** Read from the database file.
+
*/
+
static int kvvfsReadDb(
+
  sqlite3_file *pProtoFile,
+
  void *zBuf,
+
  int iAmt,
+
  sqlite_int64 iOfst
+
){
+
  KVVfsFile *pFile = (KVVfsFile*)pProtoFile;
+
  unsigned int pgno;
+
  int got, n;
+
  char zKey[30];
+
  char aData[133073];
+
  assert( iOfst>=0 );
+
  assert( iAmt>=0 );
+
  SQLITE_KV_LOG(("xRead('%s-db',%d,%lld)\n", pFile->zClass, iAmt, iOfst));
+
  if( iOfst+iAmt>=512 ){
+
    if( (iOfst % iAmt)!=0 ){
+
      return SQLITE_IOERR_READ;
+
    }
+
    if( (iAmt & (iAmt-1))!=0 || iAmt<512 || iAmt>65536 ){
+
      return SQLITE_IOERR_READ;
+
    }
+
    pFile->szPage = iAmt;
+
    pgno = 1 + iOfst/iAmt;
+
  }else{
+
    pgno = 1;
+
  }
+
  sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno);
+
  got = sqlite3KvvfsMethods.xRead(pFile->zClass, zKey, aData, sizeof(aData)-1);
+
  if( got<0 ){
+
    n = 0;
+
  }else{
+
    aData[got] = 0;
+
    if( iOfst+iAmt<512 ){
+
      int k = iOfst+iAmt;
+
      aData[k*2] = 0;
+
      n = kvvfsDecode(aData, &aData[2000], sizeof(aData)-2000);
+
      if( n>=iOfst+iAmt ){
+
        memcpy(zBuf, &aData[2000+iOfst], iAmt);
+
        n = iAmt;
+
      }else{
+
        n = 0;
+
      }
+
    }else{
+
      n = kvvfsDecode(aData, zBuf, iAmt);
+
    }
+
  }
+
  if( n<iAmt ){
+
    memset(zBuf+n, 0, iAmt-n);
+
    return SQLITE_IOERR_SHORT_READ;
+
  }
+
  return SQLITE_OK;
+
}
+

+

+
/*
+
** Write into the -journal file.
+
*/
+
static int kvvfsWriteJrnl(
+
  sqlite3_file *pProtoFile,
+
  const void *zBuf,
+
  int iAmt,
+
  sqlite_int64 iOfst
+
){
+
  KVVfsFile *pFile = (KVVfsFile*)pProtoFile;
+
  sqlite3_int64 iEnd = iOfst+iAmt;
+
  SQLITE_KV_LOG(("xWrite('%s-journal',%d,%lld)\n", pFile->zClass, iAmt, iOfst));
+
  if( iEnd>=0x10000000 ) return SQLITE_FULL;
+
  if( pFile->aJrnl==0 || pFile->nJrnl<iEnd ){
+
    char *aNew = sqlite3_realloc(pFile->aJrnl, iEnd);
+
    if( aNew==0 ){
+
      return SQLITE_IOERR_NOMEM;
+
    }
+
    pFile->aJrnl = aNew;
+
    if( pFile->nJrnl<iOfst ){
+
      memset(pFile->aJrnl+pFile->nJrnl, 0, iOfst-pFile->nJrnl);
+
    }
+
    pFile->nJrnl = iEnd;
+
  }
+
  memcpy(pFile->aJrnl+iOfst, zBuf, iAmt);
+
  return SQLITE_OK;
+
}
+

+
/*
+
** Write into the database file.
+
*/
+
static int kvvfsWriteDb(
+
  sqlite3_file *pProtoFile,
+
  const void *zBuf,
+
  int iAmt,
+
  sqlite_int64 iOfst
+
){
+
  KVVfsFile *pFile = (KVVfsFile*)pProtoFile;
+
  unsigned int pgno;
+
  char zKey[30];
+
  char aData[131073];
+
  SQLITE_KV_LOG(("xWrite('%s-db',%d,%lld)\n", pFile->zClass, iAmt, iOfst));
+
  assert( iAmt>=512 && iAmt<=65536 );
+
  assert( (iAmt & (iAmt-1))==0 );
+
  assert( pFile->szPage<0 || pFile->szPage==iAmt );
+
  pFile->szPage = iAmt;
+
  pgno = 1 + iOfst/iAmt;
+
  sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno);
+
  kvvfsEncode(zBuf, iAmt, aData);
+
  if( sqlite3KvvfsMethods.xWrite(pFile->zClass, zKey, aData) ){
+
    return SQLITE_IOERR;
+
  }
+
  if( iOfst+iAmt > pFile->szDb ){
+
    pFile->szDb = iOfst + iAmt;
+
  }
+
  return SQLITE_OK;
+
}
+

+
/*
+
** Truncate an kvvfs-file.
+
*/
+
static int kvvfsTruncateJrnl(sqlite3_file *pProtoFile, sqlite_int64 size){
+
  KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
+
  SQLITE_KV_LOG(("xTruncate('%s-journal',%lld)\n", pFile->zClass, size));
+
  assert( size==0 );
+
  sqlite3KvvfsMethods.xDelete(pFile->zClass, "jrnl");
+
  sqlite3_free(pFile->aJrnl);
+
  pFile->aJrnl = 0;
+
  pFile->nJrnl = 0;
+
  return SQLITE_OK;
+
}
+
static int kvvfsTruncateDb(sqlite3_file *pProtoFile, sqlite_int64 size){
+
  KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
+
  if( pFile->szDb>size
+
   && pFile->szPage>0
+
   && (size % pFile->szPage)==0
+
  ){
+
    char zKey[50];
+
    unsigned int pgno, pgnoMax;
+
    SQLITE_KV_LOG(("xTruncate('%s-db',%lld)\n", pFile->zClass, size));
+
    pgno = 1 + size/pFile->szPage;
+
    pgnoMax = 2 + pFile->szDb/pFile->szPage;
+
    while( pgno<=pgnoMax ){
+
      sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno);
+
      sqlite3KvvfsMethods.xDelete(pFile->zClass, zKey);
+
      pgno++;
+
    }
+
    pFile->szDb = size;
+
    return kvvfsWriteFileSize(pFile, size) ? SQLITE_IOERR : SQLITE_OK;
+
  }
+
  return SQLITE_IOERR;
+
}
+

+
/*
+
** Sync an kvvfs-file.
+
*/
+
static int kvvfsSyncJrnl(sqlite3_file *pProtoFile, int flags){
+
  int i, n;
+
  KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
+
  char *zOut;
+
  SQLITE_KV_LOG(("xSync('%s-journal')\n", pFile->zClass));
+
  if( pFile->nJrnl<=0 ){
+
    return kvvfsTruncateJrnl(pProtoFile, 0);
+
  }
+
  zOut = sqlite3_malloc64( pFile->nJrnl*2 + 50 );
+
  if( zOut==0 ){
+
    return SQLITE_IOERR_NOMEM;
+
  }
+
  n = pFile->nJrnl;
+
  i = 0;
+
  do{
+
    zOut[i++] = 'a' + (n%26);
+
    n /= 26;
+
  }while( n>0 );
+
  zOut[i++] = ' ';
+
  kvvfsEncode(pFile->aJrnl, pFile->nJrnl, &zOut[i]);
+
  i = sqlite3KvvfsMethods.xWrite(pFile->zClass, "jrnl", zOut);
+
  sqlite3_free(zOut);
+
  return i ? SQLITE_IOERR : SQLITE_OK;
+
}
+
static int kvvfsSyncDb(sqlite3_file *pProtoFile, int flags){
+
  return SQLITE_OK;
+
}
+

+
/*
+
** Return the current file-size of an kvvfs-file.
+
*/
+
static int kvvfsFileSizeJrnl(sqlite3_file *pProtoFile, sqlite_int64 *pSize){
+
  KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
+
  SQLITE_KV_LOG(("xFileSize('%s-journal')\n", pFile->zClass));
+
  *pSize = pFile->nJrnl;
+
  return SQLITE_OK;
+
}
+
static int kvvfsFileSizeDb(sqlite3_file *pProtoFile, sqlite_int64 *pSize){
+
  KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
+
  SQLITE_KV_LOG(("xFileSize('%s-db')\n", pFile->zClass));
+
  if( pFile->szDb>=0 ){
+
    *pSize = pFile->szDb;
+
  }else{
+
    *pSize = kvvfsReadFileSize(pFile);
+
  }
+
  return SQLITE_OK;
+
}
+

+
/*
+
** Lock an kvvfs-file.
+
*/
+
static int kvvfsLock(sqlite3_file *pProtoFile, int eLock){
+
  KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
+
  assert( !pFile->isJournal );
+
  SQLITE_KV_LOG(("xLock(%s,%d)\n", pFile->zClass, eLock));
+

+
  if( eLock!=SQLITE_LOCK_NONE ){
+
    pFile->szDb = kvvfsReadFileSize(pFile);
+
  }
+
  return SQLITE_OK;
+
}
+

+
/*
+
** Unlock an kvvfs-file.
+
*/
+
static int kvvfsUnlock(sqlite3_file *pProtoFile, int eLock){
+
  KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
+
  assert( !pFile->isJournal );
+
  SQLITE_KV_LOG(("xUnlock(%s,%d)\n", pFile->zClass, eLock));
+
  if( eLock==SQLITE_LOCK_NONE ){
+
    pFile->szDb = -1;
+
  }
+
  return SQLITE_OK;
+
}
+

+
/*
+
** Check if another file-handle holds a RESERVED lock on an kvvfs-file.
+
*/
+
static int kvvfsCheckReservedLock(sqlite3_file *pProtoFile, int *pResOut){
+
  SQLITE_KV_LOG(("xCheckReservedLock\n"));
+
  *pResOut = 0;
+
  return SQLITE_OK;
+
}
+

+
/*
+
** File control method. For custom operations on an kvvfs-file.
+
*/
+
static int kvvfsFileControlJrnl(sqlite3_file *pProtoFile, int op, void *pArg){
+
  SQLITE_KV_LOG(("xFileControl(%d) on journal\n", op));
+
  return SQLITE_NOTFOUND;
+
}
+
static int kvvfsFileControlDb(sqlite3_file *pProtoFile, int op, void *pArg){
+
  SQLITE_KV_LOG(("xFileControl(%d) on database\n", op));
+
  if( op==SQLITE_FCNTL_SYNC ){
+
    KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
+
    int rc = SQLITE_OK;
+
    SQLITE_KV_LOG(("xSync('%s-db')\n", pFile->zClass));
+
    if( pFile->szDb>0 && 0!=kvvfsWriteFileSize(pFile, pFile->szDb) ){
+
      rc = SQLITE_IOERR;
+
    }
+
    return rc;
+
  }
+
  return SQLITE_NOTFOUND;
+
}
+

+
/*
+
** Return the sector-size in bytes for an kvvfs-file.
+
*/
+
static int kvvfsSectorSize(sqlite3_file *pFile){
+
  return 512;
+
}
+

+
/*
+
** Return the device characteristic flags supported by an kvvfs-file.
+
*/
+
static int kvvfsDeviceCharacteristics(sqlite3_file *pProtoFile){
+
  return 0;
+
}
+

+
/****** sqlite3_vfs methods *************************************************/
+

+
/*
+
** Open an kvvfs file handle.
+
*/
+
static int kvvfsOpen(
+
  sqlite3_vfs *pProtoVfs,
+
  const char *zName,
+
  sqlite3_file *pProtoFile,
+
  int flags,
+
  int *pOutFlags
+
){
+
  KVVfsFile *pFile = (KVVfsFile*)pProtoFile;
+
  if( zName==0 ) zName = "";
+
  SQLITE_KV_LOG(("xOpen(\"%s\")\n", zName));
+
  if( strcmp(zName, "local")==0
+
   || strcmp(zName, "session")==0
+
  ){
+
    pFile->isJournal = 0;
+
    pFile->base.pMethods = &kvvfs_db_io_methods;
+
  }else
+
  if( strcmp(zName, "local-journal")==0
+
   || strcmp(zName, "session-journal")==0
+
  ){
+
    pFile->isJournal = 1;
+
    pFile->base.pMethods = &kvvfs_jrnl_io_methods;
+
  }else{
+
    return SQLITE_CANTOPEN;
+
  }
+
  if( zName[0]=='s' ){
+
    pFile->zClass = "session";
+
  }else{
+
    pFile->zClass = "local";
+
  }
+
  pFile->aJrnl = 0;
+
  pFile->nJrnl = 0;
+
  pFile->szPage = -1;
+
  pFile->szDb = -1;
+
  return SQLITE_OK;
+
}
+

+
/*
+
** Delete the file located at zPath. If the dirSync argument is true,
+
** ensure the file-system modifications are synced to disk before
+
** returning.
+
*/
+
static int kvvfsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
+
  if( strcmp(zPath, "local-journal")==0 ){
+
    sqlite3KvvfsMethods.xDelete("local", "jrnl");
+
  }else
+
  if( strcmp(zPath, "session-journal")==0 ){
+
    sqlite3KvvfsMethods.xDelete("session", "jrnl");
+
  }
+
  return SQLITE_OK;
+
}
+

+
/*
+
** Test for access permissions. Return true if the requested permission
+
** is available, or false otherwise.
+
*/
+
static int kvvfsAccess(
+
  sqlite3_vfs *pProtoVfs,
+
  const char *zPath,
+
  int flags,
+
  int *pResOut
+
){
+
  SQLITE_KV_LOG(("xAccess(\"%s\")\n", zPath));
+
  if( strcmp(zPath, "local-journal")==0 ){
+
    *pResOut = sqlite3KvvfsMethods.xRead("local", "jrnl", 0, 0)>0;
+
  }else
+
  if( strcmp(zPath, "session-journal")==0 ){
+
    *pResOut = sqlite3KvvfsMethods.xRead("session", "jrnl", 0, 0)>0;
+
  }else
+
  if( strcmp(zPath, "local")==0 ){
+
    *pResOut = sqlite3KvvfsMethods.xRead("local", "sz", 0, 0)>0;
+
  }else
+
  if( strcmp(zPath, "session")==0 ){
+
    *pResOut = sqlite3KvvfsMethods.xRead("session", "sz", 0, 0)>0;
+
  }else
+
  {
+
    *pResOut = 0;
+
  }
+
  SQLITE_KV_LOG(("xAccess returns %d\n",*pResOut));
+
  return SQLITE_OK;
+
}
+

+
/*
+
** Populate buffer zOut with the full canonical pathname corresponding
+
** to the pathname in zPath. zOut is guaranteed to point to a buffer
+
** of at least (INST_MAX_PATHNAME+1) bytes.
+
*/
+
static int kvvfsFullPathname(
+
  sqlite3_vfs *pVfs,
+
  const char *zPath,
+
  int nOut,
+
  char *zOut
+
){
+
  size_t nPath;
+
#ifdef SQLITE_OS_KV_ALWAYS_LOCAL
+
  zPath = "local";
+
#endif
+
  nPath = strlen(zPath);
+
  SQLITE_KV_LOG(("xFullPathname(\"%s\")\n", zPath));
+
  if( nOut<nPath+1 ) nPath = nOut - 1;
+
  memcpy(zOut, zPath, nPath);
+
  zOut[nPath] = 0;
+
  return SQLITE_OK;
+
}
+

+
/*
+
** Open the dynamic library located at zPath and return a handle.
+
*/
+
static void *kvvfsDlOpen(sqlite3_vfs *pVfs, const char *zPath){
+
  return 0;
+
}
+

+
/*
+
** Populate the buffer pointed to by zBufOut with nByte bytes of
+
** random data.
+
*/
+
static int kvvfsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
+
  memset(zBufOut, 0, nByte);
+
  return nByte;
+
}
+

+
/*
+
** Sleep for nMicro microseconds. Return the number of microseconds
+
** actually slept.
+
*/
+
static int kvvfsSleep(sqlite3_vfs *pVfs, int nMicro){
+
  return SQLITE_OK;
+
}
+

+
/*
+
** Return the current time as a Julian Day number in *pTimeOut.
+
*/
+
static int kvvfsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
+
  sqlite3_int64 i = 0;
+
  int rc;
+
  rc = kvvfsCurrentTimeInt64(0, &i);
+
  *pTimeOut = i/86400000.0;
+
  return rc;
+
}
+
#include <sys/time.h>
+
static int kvvfsCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){
+
  static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
+
  struct timeval sNow;
+
  (void)gettimeofday(&sNow, 0);  /* Cannot fail given valid arguments */
+
  *pTimeOut = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_usec/1000;
+
  return SQLITE_OK;
+
}
+
#endif /* SQLITE_OS_KV || SQLITE_OS_UNIX */
+

+
#if SQLITE_OS_KV
+
/*
+
** This routine is called initialize the KV-vfs as the default VFS.
+
*/
+
SQLITE_API int sqlite3_os_init(void){
+
  return sqlite3_vfs_register(&sqlite3OsKvvfsObject, 1);
+
}
+
SQLITE_API int sqlite3_os_end(void){
+
  return SQLITE_OK;
+
}
+
#endif /* SQLITE_OS_KV */
+

+
#if SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL)
+
SQLITE_PRIVATE int sqlite3KvvfsInit(void){
+
  return sqlite3_vfs_register(&sqlite3OsKvvfsObject, 0);
+
}
+
#endif
+

+
/************** End of os_kv.c ***********************************************/
/************** Begin file os_unix.c *****************************************/
/*
** 2004 May 22
@@ -35562,13 +36739,13 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/*
** standard include files.
*/
-
#include <sys/types.h>
-
#include <sys/stat.h>
+
#include <sys/types.h>   /* amalgamator: keep */
+
#include <sys/stat.h>    /* amalgamator: keep */
#include <fcntl.h>
#include <sys/ioctl.h>
-
#include <unistd.h>
+
#include <unistd.h>      /* amalgamator: keep */
/* #include <time.h> */
-
#include <sys/time.h>
+
#include <sys/time.h>    /* amalgamator: keep */
#include <errno.h>
#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
# include <sys/mman.h>
@@ -43533,8 +44710,16 @@ SQLITE_API int sqlite3_os_init(void){

  /* Register all VFSes defined in the aVfs[] array */
  for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
+
#ifdef SQLITE_DEFAULT_UNIX_VFS
+
    sqlite3_vfs_register(&aVfs[i],
+
           0==strcmp(aVfs[i].zName,SQLITE_DEFAULT_UNIX_VFS));
+
#else
    sqlite3_vfs_register(&aVfs[i], i==0);
+
#endif
  }
+
#ifdef SQLITE_OS_KV_OPTIONAL
+
  sqlite3KvvfsInit();
+
#endif
  unixBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);

#ifndef SQLITE_OMIT_WAL
@@ -45497,8 +46682,9 @@ SQLITE_API int sqlite3_win32_set_directory8(
  const char *zValue  /* New value for directory being set or reset */
){
  char **ppDirectory = 0;
+
  int rc;
#ifndef SQLITE_OMIT_AUTOINIT
-
  int rc = sqlite3_initialize();
+
  rc = sqlite3_initialize();
  if( rc ) return rc;
#endif
  sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
@@ -48303,9 +49489,10 @@ static int winMakeEndInDirSep(int nBuf, char *zBuf){
}

/*
-
** If sqlite3_temp_directory is not, take the mutex and return true.
+
** If sqlite3_temp_directory is defined, take the mutex and return true.
**
-
** If sqlite3_temp_directory is NULL, omit the mutex and return false.
+
** If sqlite3_temp_directory is NULL (undefined), omit the mutex and
+
** return false.
*/
static int winTempDirDefined(void){
  sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
@@ -49341,7 +50528,8 @@ static int winFullPathname(
  char *zFull                   /* Output buffer */
){
  int rc;
-
  sqlite3_mutex *pMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR);
+
  MUTEX_LOGIC( sqlite3_mutex *pMutex; )
+
  MUTEX_LOGIC( pMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR); )
  sqlite3_mutex_enter(pMutex);
  rc = winFullPathnameNoMutex(pVfs, zRelative, nFull, zFull);
  sqlite3_mutex_leave(pMutex);
@@ -51135,12 +52323,20 @@ struct PCache {
  int sqlite3PcacheTrace = 2;       /* 0: off  1: simple  2: cache dumps */
  int sqlite3PcacheMxDump = 9999;   /* Max cache entries for pcacheDump() */
# define pcacheTrace(X) if(sqlite3PcacheTrace){sqlite3DebugPrintf X;}
-
  void pcacheDump(PCache *pCache){
-
    int N;
-
    int i, j;
-
    sqlite3_pcache_page *pLower;
+
  static void pcachePageTrace(int i, sqlite3_pcache_page *pLower){
    PgHdr *pPg;
    unsigned char *a;
+
    int j;
+
    pPg = (PgHdr*)pLower->pExtra;
+
    printf("%3d: nRef %2d flgs %02x data ", i, pPg->nRef, pPg->flags);
+
    a = (unsigned char *)pLower->pBuf;
+
    for(j=0; j<12; j++) printf("%02x", a[j]);
+
    printf(" ptr %p\n", pPg);
+
  }
+
  static void pcacheDump(PCache *pCache){
+
    int N;
+
    int i;
+
    sqlite3_pcache_page *pLower;

    if( sqlite3PcacheTrace<2 ) return;
    if( pCache->pCache==0 ) return;
@@ -51149,22 +52345,33 @@ struct PCache {
    for(i=1; i<=N; i++){
       pLower = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, i, 0);
       if( pLower==0 ) continue;
-
       pPg = (PgHdr*)pLower->pExtra;
-
       printf("%3d: nRef %2d flgs %02x data ", i, pPg->nRef, pPg->flags);
-
       a = (unsigned char *)pLower->pBuf;
-
       for(j=0; j<12; j++) printf("%02x", a[j]);
-
       printf("\n");
-
       if( pPg->pPage==0 ){
+
       pcachePageTrace(i, pLower);
+
       if( ((PgHdr*)pLower)->pPage==0 ){
         sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, pLower, 0);
       }
    }
  }
-
  #else
+
#else
# define pcacheTrace(X)
+
# define pcachePageTrace(PGNO, X)
# define pcacheDump(X)
#endif

/*
+
** Return 1 if pPg is on the dirty list for pCache.  Return 0 if not.
+
** This routine runs inside of assert() statements only.
+
*/
+
#ifdef SQLITE_DEBUG
+
static int pageOnDirtyList(PCache *pCache, PgHdr *pPg){
+
  PgHdr *p;
+
  for(p=pCache->pDirty; p; p=p->pDirtyNext){
+
    if( p==pPg ) return 1;
+
  }
+
  return 0;
+
}
+
#endif
+

+
/*
** Check invariants on a PgHdr entry.  Return true if everything is OK.
** Return false if any invariant is violated.
**
@@ -51182,8 +52389,13 @@ SQLITE_PRIVATE int sqlite3PcachePageSanity(PgHdr *pPg){
  assert( pCache!=0 );      /* Every page has an associated PCache */
  if( pPg->flags & PGHDR_CLEAN ){
    assert( (pPg->flags & PGHDR_DIRTY)==0 );/* Cannot be both CLEAN and DIRTY */
-
    assert( pCache->pDirty!=pPg );          /* CLEAN pages not on dirty list */
-
    assert( pCache->pDirtyTail!=pPg );
+
    assert( !pageOnDirtyList(pCache, pPg) );/* CLEAN pages not on dirty list */
+
  }else{
+
    assert( (pPg->flags & PGHDR_DIRTY)!=0 );/* If not CLEAN must be DIRTY */
+
    assert( pPg->pDirtyNext==0 || pPg->pDirtyNext->pDirtyPrev==pPg );
+
    assert( pPg->pDirtyPrev==0 || pPg->pDirtyPrev->pDirtyNext==pPg );
+
    assert( pPg->pDirtyPrev!=0 || pCache->pDirty==pPg );
+
    assert( pageOnDirtyList(pCache, pPg) );
  }
  /* WRITEABLE pages must also be DIRTY */
  if( pPg->flags & PGHDR_WRITEABLE ){
@@ -51457,8 +52669,9 @@ SQLITE_PRIVATE sqlite3_pcache_page *sqlite3PcacheFetch(
  assert( createFlag==0 || pCache->eCreate==eCreate );
  assert( createFlag==0 || eCreate==1+(!pCache->bPurgeable||!pCache->pDirty) );
  pRes = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate);
-
  pcacheTrace(("%p.FETCH %d%s (result: %p)\n",pCache,pgno,
+
  pcacheTrace(("%p.FETCH %d%s (result: %p) ",pCache,pgno,
               createFlag?" create":"",pRes));
+
  pcachePageTrace(pgno, pRes);
  return pRes;
}

@@ -51586,6 +52799,7 @@ SQLITE_PRIVATE void SQLITE_NOINLINE sqlite3PcacheRelease(PgHdr *p){
      pcacheUnpin(p);
    }else{
      pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT);
+
      assert( sqlite3PcachePageSanity(p) );
    }
  }
}
@@ -51629,6 +52843,7 @@ SQLITE_PRIVATE void sqlite3PcacheMakeDirty(PgHdr *p){
      pcacheTrace(("%p.DIRTY %d\n",p->pCache,p->pgno));
      assert( (p->flags & (PGHDR_DIRTY|PGHDR_CLEAN))==PGHDR_DIRTY );
      pcacheManageDirtyList(p, PCACHE_DIRTYLIST_ADD);
+
      assert( sqlite3PcachePageSanity(p) );
    }
    assert( sqlite3PcachePageSanity(p) );
  }
@@ -51691,14 +52906,24 @@ SQLITE_PRIVATE void sqlite3PcacheClearSyncFlags(PCache *pCache){
*/
SQLITE_PRIVATE void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){
  PCache *pCache = p->pCache;
+
  sqlite3_pcache_page *pOther;
  assert( p->nRef>0 );
  assert( newPgno>0 );
  assert( sqlite3PcachePageSanity(p) );
  pcacheTrace(("%p.MOVE %d -> %d\n",pCache,p->pgno,newPgno));
+
  pOther = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, newPgno, 0);
+
  if( pOther ){
+
    PgHdr *pXPage = (PgHdr*)pOther->pExtra;
+
    assert( pXPage->nRef==0 );
+
    pXPage->nRef++;
+
    pCache->nRefSum++;
+
    sqlite3PcacheDrop(pXPage);
+
  }
  sqlite3GlobalConfig.pcache2.xRekey(pCache->pCache, p->pPage, p->pgno,newPgno);
  p->pgno = newPgno;
  if( (p->flags&PGHDR_DIRTY) && (p->flags&PGHDR_NEED_SYNC) ){
    pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT);
+
    assert( sqlite3PcachePageSanity(p) );
  }
}

@@ -51996,12 +53221,13 @@ SQLITE_PRIVATE void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHd
** size can vary according to architecture, compile-time options, and
** SQLite library version number.
**
-
** If SQLITE_PCACHE_SEPARATE_HEADER is defined, then the extension is obtained
-
** using a separate memory allocation from the database page content.  This
-
** seeks to overcome the "clownshoe" problem (also called "internal
-
** fragmentation" in academic literature) of allocating a few bytes more
-
** than a power of two with the memory allocator rounding up to the next
-
** power of two, and leaving the rounded-up space unused.
+
** Historical note:  It used to be that if the SQLITE_PCACHE_SEPARATE_HEADER
+
** was defined, then the page content would be held in a separate memory
+
** allocation from the PgHdr1.  This was intended to avoid clownshoe memory
+
** allocations.  However, the btree layer needs a small (16-byte) overrun
+
** area after the page content buffer.  The header serves as that overrun
+
** area.  Therefore SQLITE_PCACHE_SEPARATE_HEADER was discontinued to avoid
+
** any possibility of a memory error.
**
** This module tracks pointers to PgHdr1 objects.  Only pcache.c communicates
** with this module.  Information is passed back and forth as PgHdr1 pointers.
@@ -52046,30 +53272,40 @@ typedef struct PGroup PGroup;

/*
** Each cache entry is represented by an instance of the following
-
** structure. Unless SQLITE_PCACHE_SEPARATE_HEADER is defined, a buffer of
-
** PgHdr1.pCache->szPage bytes is allocated directly before this structure
-
** in memory.
+
** structure. A buffer of PgHdr1.pCache->szPage bytes is allocated
+
** directly before this structure and is used to cache the page content.
+
**
+
** When reading a corrupt database file, it is possible that SQLite might
+
** read a few bytes (no more than 16 bytes) past the end of the page buffer.
+
** It will only read past the end of the page buffer, never write.  This
+
** object is positioned immediately after the page buffer to serve as an
+
** overrun area, so that overreads are harmless.
**
-
** Note: Variables isBulkLocal and isAnchor were once type "u8". That works,
+
** Variables isBulkLocal and isAnchor were once type "u8". That works,
** but causes a 2-byte gap in the structure for most architectures (since
** pointers must be either 4 or 8-byte aligned). As this structure is located
** in memory directly after the associated page data, if the database is
** corrupt, code at the b-tree layer may overread the page buffer and
** read part of this structure before the corruption is detected. This
** can cause a valgrind error if the unitialized gap is accessed. Using u16
-
** ensures there is no such gap, and therefore no bytes of unitialized memory
-
** in the structure.
+
** ensures there is no such gap, and therefore no bytes of uninitialized
+
** memory in the structure.
+
**
+
** The pLruNext and pLruPrev pointers form a double-linked circular list
+
** of all pages that are unpinned.  The PGroup.lru element (which should be
+
** the only element on the list with PgHdr1.isAnchor set to 1) forms the
+
** beginning and the end of the list.
*/
struct PgHdr1 {
-
  sqlite3_pcache_page page;      /* Base class. Must be first. pBuf & pExtra */
-
  unsigned int iKey;             /* Key value (page number) */
-
  u16 isBulkLocal;               /* This page from bulk local storage */
-
  u16 isAnchor;                  /* This is the PGroup.lru element */
-
  PgHdr1 *pNext;                 /* Next in hash table chain */
-
  PCache1 *pCache;               /* Cache that currently owns this page */
-
  PgHdr1 *pLruNext;              /* Next in LRU list of unpinned pages */
-
  PgHdr1 *pLruPrev;              /* Previous in LRU list of unpinned pages */
-
                                 /* NB: pLruPrev is only valid if pLruNext!=0 */
+
  sqlite3_pcache_page page; /* Base class. Must be first. pBuf & pExtra */
+
  unsigned int iKey;        /* Key value (page number) */
+
  u16 isBulkLocal;          /* This page from bulk local storage */
+
  u16 isAnchor;             /* This is the PGroup.lru element */
+
  PgHdr1 *pNext;            /* Next in hash table chain */
+
  PCache1 *pCache;          /* Cache that currently owns this page */
+
  PgHdr1 *pLruNext;         /* Next in circular LRU list of unpinned pages */
+
  PgHdr1 *pLruPrev;         /* Previous in LRU list of unpinned pages */
+
                            /* NB: pLruPrev is only valid if pLruNext!=0 */
};

/*
@@ -52395,25 +53631,13 @@ static PgHdr1 *pcache1AllocPage(PCache1 *pCache, int benignMalloc){
    pcache1LeaveMutex(pCache->pGroup);
#endif
    if( benignMalloc ){ sqlite3BeginBenignMalloc(); }
-
#ifdef SQLITE_PCACHE_SEPARATE_HEADER
-
    pPg = pcache1Alloc(pCache->szPage);
-
    p = sqlite3Malloc(sizeof(PgHdr1) + pCache->szExtra);
-
    if( !pPg || !p ){
-
      pcache1Free(pPg);
-
      sqlite3_free(p);
-
      pPg = 0;
-
    }
-
#else
    pPg = pcache1Alloc(pCache->szAlloc);
-
#endif
    if( benignMalloc ){ sqlite3EndBenignMalloc(); }
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
    pcache1EnterMutex(pCache->pGroup);
#endif
    if( pPg==0 ) return 0;
-
#ifndef SQLITE_PCACHE_SEPARATE_HEADER
    p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
-
#endif
    p->page.pBuf = pPg;
    p->page.pExtra = &p[1];
    p->isBulkLocal = 0;
@@ -52437,9 +53661,6 @@ static void pcache1FreePage(PgHdr1 *p){
    pCache->pFree = p;
  }else{
    pcache1Free(p->page.pBuf);
-
#ifdef SQLITE_PCACHE_SEPARATE_HEADER
-
    sqlite3_free(p);
-
#endif
  }
  (*pCache->pnPurgeable)--;
}
@@ -53080,23 +54301,26 @@ static void pcache1Rekey(
  PCache1 *pCache = (PCache1 *)p;
  PgHdr1 *pPage = (PgHdr1 *)pPg;
  PgHdr1 **pp;
-
  unsigned int h;
+
  unsigned int hOld, hNew;
  assert( pPage->iKey==iOld );
  assert( pPage->pCache==pCache );
+
  assert( iOld!=iNew );               /* The page number really is changing */

  pcache1EnterMutex(pCache->pGroup);

-
  h = iOld%pCache->nHash;
-
  pp = &pCache->apHash[h];
+
  assert( pcache1FetchNoMutex(p, iOld, 0)==pPage ); /* pPg really is iOld */
+
  hOld = iOld%pCache->nHash;
+
  pp = &pCache->apHash[hOld];
  while( (*pp)!=pPage ){
    pp = &(*pp)->pNext;
  }
  *pp = pPage->pNext;

-
  h = iNew%pCache->nHash;
+
  assert( pcache1FetchNoMutex(p, iNew, 0)==0 ); /* iNew not in cache */
+
  hNew = iNew%pCache->nHash;
  pPage->iKey = iNew;
-
  pPage->pNext = pCache->apHash[h];
-
  pCache->apHash[h] = pPage;
+
  pPage->pNext = pCache->apHash[hNew];
+
  pCache->apHash[hNew] = pPage;
  if( iNew>pCache->iMaxKey ){
    pCache->iMaxKey = iNew;
  }
@@ -53203,9 +54427,6 @@ SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int nReq){
       &&  p->isAnchor==0
    ){
      nFree += pcache1MemSize(p->page.pBuf);
-
#ifdef SQLITE_PCACHE_SEPARATE_HEADER
-
      nFree += sqlite3MemSize(p);
-
#endif
      assert( PAGE_IS_UNPINNED(p) );
      pcache1PinPage(p);
      pcache1RemoveFromHash(p, 1);
@@ -59694,6 +60915,7 @@ static int pager_open_journal(Pager *pPager){

        if( pPager->tempFile ){
          flags |= (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL);
+
          flags |= SQLITE_OPEN_EXCLUSIVE;
          nSpill = sqlite3Config.nStmtSpill;
        }else{
          flags |= SQLITE_OPEN_MAIN_JOURNAL;
@@ -61285,7 +62507,7 @@ SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager *pPager){
SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager *pPager){
  assert( assert_pager_state(pPager) );
  if( pPager->eState>=PAGER_WRITER_CACHEMOD ) return 0;
-
  if( isOpen(pPager->jfd) && pPager->journalOff>0 ) return 0;
+
  if( NEVER(isOpen(pPager->jfd) && pPager->journalOff>0) ) return 0;
  return 1;
}

@@ -66793,6 +68015,7 @@ SQLITE_PRIVATE int sqlite3BtreeHoldsAllMutexes(sqlite3 *db){
SQLITE_PRIVATE int sqlite3SchemaMutexHeld(sqlite3 *db, int iDb, Schema *pSchema){
  Btree *p;
  assert( db!=0 );
+
  if( db->pVfs==0 && db->nDb==0 ) return 1;
  if( pSchema ) iDb = sqlite3SchemaToIndex(db, pSchema);
  assert( iDb>=0 && iDb<db->nDb );
  if( !sqlite3_mutex_held(db->mutex) ) return 0;
@@ -68365,8 +69588,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
  assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE );
  assert( pPage->nOverflow==0 );
  assert( sqlite3_mutex_held(pPage->pBt->mutex) );
-
  temp = 0;
-
  src = data = pPage->aData;
+
  data = pPage->aData;
  hdr = pPage->hdrOffset;
  cellOffset = pPage->cellOffset;
  nCell = pPage->nCell;
@@ -68400,7 +69622,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
          if( iFree2+sz2 > usableSize ) return SQLITE_CORRUPT_PAGE(pPage);
          memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz));
          sz += sz2;
-
        }else if( NEVER(iFree+sz>usableSize) ){
+
        }else if( iFree+sz>usableSize ){
          return SQLITE_CORRUPT_PAGE(pPage);
        }

@@ -68420,39 +69642,38 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
  cbrk = usableSize;
  iCellLast = usableSize - 4;
  iCellStart = get2byte(&data[hdr+5]);
-
  for(i=0; i<nCell; i++){
-
    u8 *pAddr;     /* The i-th cell pointer */
-
    pAddr = &data[cellOffset + i*2];
-
    pc = get2byte(pAddr);
-
    testcase( pc==iCellFirst );
-
    testcase( pc==iCellLast );
-
    /* These conditions have already been verified in btreeInitPage()
-
    ** if PRAGMA cell_size_check=ON.
-
    */
-
    if( pc<iCellStart || pc>iCellLast ){
-
      return SQLITE_CORRUPT_PAGE(pPage);
-
    }
-
    assert( pc>=iCellStart && pc<=iCellLast );
-
    size = pPage->xCellSize(pPage, &src[pc]);
-
    cbrk -= size;
-
    if( cbrk<iCellStart || pc+size>usableSize ){
-
      return SQLITE_CORRUPT_PAGE(pPage);
-
    }
-
    assert( cbrk+size<=usableSize && cbrk>=iCellStart );
-
    testcase( cbrk+size==usableSize );
-
    testcase( pc+size==usableSize );
-
    put2byte(pAddr, cbrk);
-
    if( temp==0 ){
-
      if( cbrk==pc ) continue;
-
      temp = sqlite3PagerTempSpace(pPage->pBt->pPager);
-
      memcpy(&temp[iCellStart], &data[iCellStart], usableSize - iCellStart);
-
      src = temp;
+
  if( nCell>0 ){
+
    temp = sqlite3PagerTempSpace(pPage->pBt->pPager);
+
    memcpy(&temp[iCellStart], &data[iCellStart], usableSize - iCellStart);
+
    src = temp;
+
    for(i=0; i<nCell; i++){
+
      u8 *pAddr;     /* The i-th cell pointer */
+
      pAddr = &data[cellOffset + i*2];
+
      pc = get2byte(pAddr);
+
      testcase( pc==iCellFirst );
+
      testcase( pc==iCellLast );
+
      /* These conditions have already been verified in btreeInitPage()
+
      ** if PRAGMA cell_size_check=ON.
+
      */
+
      if( pc<iCellStart || pc>iCellLast ){
+
        return SQLITE_CORRUPT_PAGE(pPage);
+
      }
+
      assert( pc>=iCellStart && pc<=iCellLast );
+
      size = pPage->xCellSize(pPage, &src[pc]);
+
      cbrk -= size;
+
      if( cbrk<iCellStart || pc+size>usableSize ){
+
        return SQLITE_CORRUPT_PAGE(pPage);
+
      }
+
      assert( cbrk+size<=usableSize && cbrk>=iCellStart );
+
      testcase( cbrk+size==usableSize );
+
      testcase( pc+size==usableSize );
+
      put2byte(pAddr, cbrk);
+
      memcpy(&data[cbrk], &src[pc], size);
    }
-
    memcpy(&data[cbrk], &src[pc], size);
  }
  data[hdr+7] = 0;

-
 defragment_out:
+
defragment_out:
  assert( pPage->nFree>=0 );
  if( data[hdr+7]+cbrk-iCellFirst!=pPage->nFree ){
    return SQLITE_CORRUPT_PAGE(pPage);
@@ -68509,7 +69730,6 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
        ** fragmented bytes within the page. */
        memcpy(&aData[iAddr], &aData[pc], 2);
        aData[hdr+7] += (u8)x;
-
        testcase( pc+x>maxPC );
        return &aData[pc];
      }else if( x+pc > maxPC ){
        /* This slot extends off the end of the usable part of the page */
@@ -68525,9 +69745,9 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
    iAddr = pc;
    pTmp = &aData[pc];
    pc = get2byte(pTmp);
-
    if( pc<=iAddr+size ){
+
    if( pc<=iAddr ){
      if( pc ){
-
        /* The next slot in the chain is not past the end of the current slot */
+
        /* The next slot in the chain comes before the current slot */
        *pRc = SQLITE_CORRUPT_PAGE(pPg);
      }
      return 0;
@@ -68679,7 +69899,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
    iFreeBlk = 0;  /* Shortcut for the case when the freelist is empty */
  }else{
    while( (iFreeBlk = get2byte(&data[iPtr]))<iStart ){
-
      if( iFreeBlk<iPtr+4 ){
+
      if( iFreeBlk<=iPtr ){
        if( iFreeBlk==0 ) break; /* TH3: corrupt082.100 */
        return SQLITE_CORRUPT_PAGE(pPage);
      }
@@ -69161,9 +70381,7 @@ getAndInitPage_error1:
    pCur->pPage = pCur->apPage[pCur->iPage];
  }
  testcase( pgno==0 );
-
  assert( pgno!=0 || rc==SQLITE_CORRUPT
-
                  || rc==SQLITE_IOERR_NOMEM
-
                  || rc==SQLITE_NOMEM );
+
  assert( pgno!=0 || rc!=SQLITE_OK );
  return rc;
}

@@ -70599,6 +71817,9 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
          }
        }
      }else{
+
        if( pCell+4 > pPage->aData+pPage->pBt->usableSize ){
+
          return SQLITE_CORRUPT_PAGE(pPage);
+
        }
        if( get4byte(pCell)==iFrom ){
          put4byte(pCell, iTo);
          break;
@@ -72105,8 +73326,6 @@ SQLITE_PRIVATE const void *sqlite3BtreePayloadFetch(BtCursor *pCur, u32 *pAmt){
** vice-versa).
*/
static int moveToChild(BtCursor *pCur, u32 newPgno){
-
  BtShared *pBt = pCur->pBt;
-

  assert( cursorOwnsBtShared(pCur) );
  assert( pCur->eState==CURSOR_VALID );
  assert( pCur->iPage<BTCURSOR_MAX_DEPTH );
@@ -72120,7 +73339,8 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){
  pCur->apPage[pCur->iPage] = pCur->pPage;
  pCur->ix = 0;
  pCur->iPage++;
-
  return getAndInitPage(pBt, newPgno, &pCur->pPage, pCur, pCur->curPagerFlags);
+
  return getAndInitPage(pCur->pBt, newPgno, &pCur->pPage, pCur,
+
                        pCur->curPagerFlags);
}

#ifdef SQLITE_DEBUG
@@ -72226,7 +73446,7 @@ static int moveToRoot(BtCursor *pCur){
      }
      sqlite3BtreeClearCursor(pCur);
    }
-
    rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->pPage,
+
    rc = getAndInitPage(pCur->pBt, pCur->pgnoRoot, &pCur->pPage,
                        0, pCur->curPagerFlags);
    if( rc!=SQLITE_OK ){
      pCur->eState = CURSOR_INVALID;
@@ -72934,14 +74154,7 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur){

  pPage = pCur->pPage;
  idx = ++pCur->ix;
-
  if( !pPage->isInit || sqlite3FaultSim(412) ){
-
    /* The only known way for this to happen is for there to be a
-
    ** recursive SQL function that does a DELETE operation as part of a
-
    ** SELECT which deletes content out from under an active cursor
-
    ** in a corrupt database file where the table being DELETE-ed from
-
    ** has pages in common with the table being queried.  See TH3
-
    ** module cov1/btree78.test testcase 220 (2018-06-08) for an
-
    ** example. */
+
  if( NEVER(!pPage->isInit) || sqlite3FaultSim(412) ){
    return SQLITE_CORRUPT_BKPT;
  }

@@ -73117,8 +74330,8 @@ static int allocateBtreePage(
  assert( eMode==BTALLOC_ANY || (nearby>0 && IfNotOmitAV(pBt->autoVacuum)) );
  pPage1 = pBt->pPage1;
  mxPage = btreePagecount(pBt);
-
  /* EVIDENCE-OF: R-05119-02637 The 4-byte big-endian integer at offset 36
-
  ** stores stores the total number of pages on the freelist. */
+
  /* EVIDENCE-OF: R-21003-45125 The 4-byte big-endian integer at offset 36
+
  ** stores the total number of pages on the freelist. */
  n = get4byte(&pPage1->aData[36]);
  testcase( n==mxPage-1 );
  if( n>=mxPage ){
@@ -73867,12 +75080,6 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
  assert( pPage->pBt->usableSize > (u32)(ptr-data) );
  pc = get2byte(ptr);
  hdr = pPage->hdrOffset;
-
#if 0  /* Not required.  Omit for efficiency */
-
  if( pc<hdr+pPage->nCell*2 ){
-
    *pRC = SQLITE_CORRUPT_BKPT;
-
    return;
-
  }
-
#endif
  testcase( pc==(u32)get2byte(&data[hdr+5]) );
  testcase( pc+sz==pPage->pBt->usableSize );
  if( pc+sz > pPage->pBt->usableSize ){
@@ -74756,8 +75963,6 @@ static int balance_nonroot(
  Pgno pgno;                   /* Temp var to store a page number in */
  u8 abDone[NB+2];             /* True after i'th new page is populated */
  Pgno aPgno[NB+2];            /* Page numbers of new pages before shuffling */
-
  Pgno aPgOrder[NB+2];         /* Copy of aPgno[] used for sorting pages */
-
  u16 aPgFlags[NB+2];          /* flags field of new pages before shuffling */
  CellArray b;                 /* Parsed information on cells being balanced */

  memset(abDone, 0, sizeof(abDone));
@@ -75181,42 +76386,39 @@ static int balance_nonroot(
  ** of the table is closer to a linear scan through the file. That in turn
  ** helps the operating system to deliver pages from the disk more rapidly.
  **
-
  ** An O(n^2) insertion sort algorithm is used, but since n is never more
-
  ** than (NB+2) (a small constant), that should not be a problem.
+
  ** An O(N*N) sort algorithm is used, but since N is never more than NB+2
+
  ** (5), that is not a performance concern.
  **
  ** When NB==3, this one optimization makes the database about 25% faster
  ** for large insertions and deletions.
  */
  for(i=0; i<nNew; i++){
-
    aPgOrder[i] = aPgno[i] = apNew[i]->pgno;
-
    aPgFlags[i] = apNew[i]->pDbPage->flags;
-
    for(j=0; j<i; j++){
-
      if( NEVER(aPgno[j]==aPgno[i]) ){
-
        /* This branch is taken if the set of sibling pages somehow contains
-
        ** duplicate entries. This can happen if the database is corrupt.
-
        ** It would be simpler to detect this as part of the loop below, but
-
        ** we do the detection here in order to avoid populating the pager
-
        ** cache with two separate objects associated with the same
-
        ** page number.  */
-
        assert( CORRUPT_DB );
-
        rc = SQLITE_CORRUPT_BKPT;
-
        goto balance_cleanup;
-
      }
-
    }
+
    aPgno[i] = apNew[i]->pgno;
+
    assert( apNew[i]->pDbPage->flags & PGHDR_WRITEABLE );
+
    assert( apNew[i]->pDbPage->flags & PGHDR_DIRTY );
  }
-
  for(i=0; i<nNew; i++){
-
    int iBest = 0;                /* aPgno[] index of page number to use */
-
    for(j=1; j<nNew; j++){
-
      if( aPgOrder[j]<aPgOrder[iBest] ) iBest = j;
+
  for(i=0; i<nNew-1; i++){
+
    int iB = i;
+
    for(j=i+1; j<nNew; j++){
+
      if( apNew[j]->pgno < apNew[iB]->pgno ) iB = j;
    }
-
    pgno = aPgOrder[iBest];
-
    aPgOrder[iBest] = 0xffffffff;
-
    if( iBest!=i ){
-
      if( iBest>i ){
-
        sqlite3PagerRekey(apNew[iBest]->pDbPage, pBt->nPage+iBest+1, 0);
-
      }
-
      sqlite3PagerRekey(apNew[i]->pDbPage, pgno, aPgFlags[iBest]);
-
      apNew[i]->pgno = pgno;
+

+
    /* If apNew[i] has a page number that is bigger than any of the
+
    ** subsequence apNew[i] entries, then swap apNew[i] with the subsequent
+
    ** entry that has the smallest page number (which we know to be
+
    ** entry apNew[iB]).
+
    */
+
    if( iB!=i ){
+
      Pgno pgnoA = apNew[i]->pgno;
+
      Pgno pgnoB = apNew[iB]->pgno;
+
      Pgno pgnoTemp = (PENDING_BYTE/pBt->pageSize)+1;
+
      u16 fgA = apNew[i]->pDbPage->flags;
+
      u16 fgB = apNew[iB]->pDbPage->flags;
+
      sqlite3PagerRekey(apNew[i]->pDbPage, pgnoTemp, fgB);
+
      sqlite3PagerRekey(apNew[iB]->pDbPage, pgnoA, fgA);
+
      sqlite3PagerRekey(apNew[i]->pDbPage, pgnoB, fgB);
+
      apNew[i]->pgno = pgnoB;
+
      apNew[iB]->pgno = pgnoA;
    }
  }

@@ -75642,6 +76844,11 @@ static int balance(BtCursor *pCur){
      }else{
        break;
      }
+
    }else if( sqlite3PagerPageRefcount(pPage->pDbPage)>1 ){
+
      /* The page being written is not a root page, and there is currently
+
      ** more than one reference to it. This only happens if the page is one
+
      ** of its own ancestor pages. Corruption. */
+
      rc = SQLITE_CORRUPT_BKPT;
    }else{
      MemPage * const pParent = pCur->apPage[iPage-1];
      int const iIdx = pCur->aiIdx[iPage-1];
@@ -79485,6 +80692,16 @@ SQLITE_PRIVATE int sqlite3RealSameAsInt(double r1, sqlite3_int64 i){
          && i >= -2251799813685248LL && i < 2251799813685248LL);
}

+
/* Convert a floating point value to its closest integer.  Do so in
+
** a way that avoids 'outside the range of representable values' warnings
+
** from UBSAN.
+
*/
+
SQLITE_PRIVATE i64 sqlite3RealToI64(double r){
+
  if( r<=(double)SMALLEST_INT64 ) return SMALLEST_INT64;
+
  if( r>=(double)LARGEST_INT64) return LARGEST_INT64;
+
  return (i64)r;
+
}
+

/*
** Convert pMem so that it has type MEM_Real or MEM_Int.
** Invalidate any prior representations.
@@ -79506,7 +80723,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem *pMem){
    assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
    rc = sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc);
    if( ((rc==0 || rc==1) && sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<=1)
-
     || sqlite3RealSameAsInt(pMem->u.r, (ix = (i64)pMem->u.r))
+
     || sqlite3RealSameAsInt(pMem->u.r, (ix = sqlite3RealToI64(pMem->u.r)))
    ){
      pMem->u.i = ix;
      MemSetTypeFlag(pMem, MEM_Int);
@@ -79558,6 +80775,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){
      sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding);
      assert( pMem->flags & MEM_Str || pMem->db->mallocFailed );
      pMem->flags &= ~(MEM_Int|MEM_Real|MEM_IntReal|MEM_Blob|MEM_Zero);
+
      if( encoding!=SQLITE_UTF8 ) pMem->n &= ~1;
      return sqlite3VdbeChangeEncoding(pMem, encoding);
    }
  }
@@ -80693,6 +81911,9 @@ SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){
  if( (p->flags & MEM_Str)!=0 && pVal->enc==enc ){
    return p->n;
  }
+
  if( (p->flags & MEM_Str)!=0 && enc!=SQLITE_UTF8 && pVal->enc!=SQLITE_UTF8 ){
+
    return p->n;
+
  }
  if( (p->flags & MEM_Blob)!=0 ){
    if( p->flags & MEM_Zero ){
      return p->n + p->u.nZero;
@@ -80738,10 +81959,10 @@ SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse *pParse){
  memset(&p->aOp, 0, sizeof(Vdbe)-offsetof(Vdbe,aOp));
  p->db = db;
  if( db->pVdbe ){
-
    db->pVdbe->pPrev = p;
+
    db->pVdbe->ppVPrev = &p->pVNext;
  }
-
  p->pNext = db->pVdbe;
-
  p->pPrev = 0;
+
  p->pVNext = db->pVdbe;
+
  p->ppVPrev = &db->pVdbe;
  db->pVdbe = p;
  assert( p->eVdbeState==VDBE_INIT_STATE );
  p->pParse = pParse;
@@ -80823,21 +82044,28 @@ SQLITE_PRIVATE int sqlite3VdbeUsesDoubleQuotedString(
#endif

/*
-
** Swap all content between two VDBE structures.
+
** Swap byte-code between two VDBE structures.
+
**
+
** This happens after pB was previously run and returned
+
** SQLITE_SCHEMA.  The statement was then reprepared in pA.
+
** This routine transfers the new bytecode in pA over to pB
+
** so that pB can be run again.  The old pB byte code is
+
** moved back to pA so that it will be cleaned up when pA is
+
** finalized.
*/
SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){
-
  Vdbe tmp, *pTmp;
+
  Vdbe tmp, *pTmp, **ppTmp;
  char *zTmp;
  assert( pA->db==pB->db );
  tmp = *pA;
  *pA = *pB;
  *pB = tmp;
-
  pTmp = pA->pNext;
-
  pA->pNext = pB->pNext;
-
  pB->pNext = pTmp;
-
  pTmp = pA->pPrev;
-
  pA->pPrev = pB->pPrev;
-
  pB->pPrev = pTmp;
+
  pTmp = pA->pVNext;
+
  pA->pVNext = pB->pVNext;
+
  pB->pVNext = pTmp;
+
  ppTmp = pA->ppVPrev;
+
  pA->ppVPrev = pB->ppVPrev;
+
  pB->ppVPrev = ppTmp;
  zTmp = pA->zSql;
  pA->zSql = pB->zSql;
  pB->zSql = zTmp;
@@ -81158,7 +82386,7 @@ SQLITE_PRIVATE void sqlite3VdbeExplain(Parse *pParse, u8 bPush, const char *zFmt
    iThis = v->nOp;
    sqlite3VdbeAddOp4(v, OP_Explain, iThis, pParse->addrExplain, 0,
                      zMsg, P4_DYNAMIC);
-
    sqlite3ExplainBreakpoint(bPush?"PUSH":"", sqlite3VdbeGetOp(v,-1)->p4.z);
+
    sqlite3ExplainBreakpoint(bPush?"PUSH":"", sqlite3VdbeGetLastOp(v)->p4.z);
    if( bPush){
      pParse->addrExplain = iThis;
    }
@@ -81516,8 +82744,8 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
  p->readOnly = 1;
  p->bIsReader = 0;
  pOp = &p->aOp[p->nOp-1];
-
  while(1){
-

+
  assert( p->aOp[0].opcode==OP_Init );
+
  while( 1 /* Loop termates when it reaches the OP_Init opcode */ ){
    /* Only JUMP opcodes and the short list of special opcodes in the switch
    ** below need to be considered.  The mkopcodeh.tcl generator script groups
    ** all these opcodes together near the front of the opcode list.  Skip
@@ -81546,6 +82774,10 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
          p->bIsReader = 1;
          break;
        }
+
        case OP_Init: {
+
          assert( pOp->p2>=0 );
+
          goto resolve_p2_values_loop_exit;
+
        }
#ifndef SQLITE_OMIT_VIRTUALTABLE
        case OP_VUpdate: {
          if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2;
@@ -81578,11 +82810,12 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
      ** have non-negative values for P2. */
      assert( (sqlite3OpcodeProperty[pOp->opcode]&OPFLG_JUMP)==0 || pOp->p2>=0);
    }
-
    if( pOp==p->aOp ) break;
+
    assert( pOp>p->aOp );
    pOp--;
  }
+
resolve_p2_values_loop_exit:
  if( aLabel ){
-
    sqlite3DbFreeNN(p->db, pParse->aLabel);
+
    sqlite3DbNNFreeNN(p->db, pParse->aLabel);
    pParse->aLabel = 0;
  }
  pParse->nLabel = 0;
@@ -81831,15 +83064,19 @@ SQLITE_PRIVATE void sqlite3VdbeScanStatus(
** for a specific instruction.
*/
SQLITE_PRIVATE void sqlite3VdbeChangeOpcode(Vdbe *p, int addr, u8 iNewOpcode){
+
  assert( addr>=0 );
  sqlite3VdbeGetOp(p,addr)->opcode = iNewOpcode;
}
SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe *p, int addr, int val){
+
  assert( addr>=0 );
  sqlite3VdbeGetOp(p,addr)->p1 = val;
}
SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe *p, int addr, int val){
+
  assert( addr>=0 || p->db->mallocFailed );
  sqlite3VdbeGetOp(p,addr)->p2 = val;
}
SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe *p, int addr, int val){
+
  assert( addr>=0 );
  sqlite3VdbeGetOp(p,addr)->p3 = val;
}
SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u16 p5){
@@ -81848,6 +83085,18 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u16 p5){
}

/*
+
** If the previous opcode is an OP_Column that delivers results
+
** into register iDest, then add the OPFLAG_TYPEOFARG flag to that
+
** opcode.
+
*/
+
SQLITE_PRIVATE void sqlite3VdbeTypeofColumn(Vdbe *p, int iDest){
+
  VdbeOp *pOp = sqlite3VdbeGetLastOp(p);
+
  if( pOp->p3==iDest && pOp->opcode==OP_Column ){
+
    pOp->p5 |= OPFLAG_TYPEOFARG;
+
  }
+
}
+

+
/*
** Change the P2 operand of instruction addr so that it points to
** the address of the next instruction to be coded.
*/
@@ -81875,7 +83124,7 @@ SQLITE_PRIVATE void sqlite3VdbeJumpHereOrPopInst(Vdbe *p, int addr){
         || p->aOp[addr].opcode==OP_FkIfZero );
    assert( p->aOp[addr].p4type==0 );
#ifdef SQLITE_VDBE_COVERAGE
-
    sqlite3VdbeGetOp(p,-1)->iSrcLine = 0;  /* Erase VdbeCoverage() macros */
+
    sqlite3VdbeGetLastOp(p)->iSrcLine = 0;  /* Erase VdbeCoverage() macros */
#endif
    p->nOp--;
  }else{
@@ -81889,8 +83138,9 @@ SQLITE_PRIVATE void sqlite3VdbeJumpHereOrPopInst(Vdbe *p, int addr){
** the FuncDef is not ephermal, then do nothing.
*/
static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef){
+
  assert( db!=0 );
  if( (pDef->funcFlags & SQLITE_FUNC_EPHEM)!=0 ){
-
    sqlite3DbFreeNN(db, pDef);
+
    sqlite3DbNNFreeNN(db, pDef);
  }
}

@@ -81899,11 +83149,12 @@ static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef){
*/
static SQLITE_NOINLINE void freeP4Mem(sqlite3 *db, Mem *p){
  if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc);
-
  sqlite3DbFreeNN(db, p);
+
  sqlite3DbNNFreeNN(db, p);
}
static SQLITE_NOINLINE void freeP4FuncCtx(sqlite3 *db, sqlite3_context *p){
+
  assert( db!=0 );
  freeEphemeralFunction(db, p->pFunc);
-
  sqlite3DbFreeNN(db, p);
+
  sqlite3DbNNFreeNN(db, p);
}
static void freeP4(sqlite3 *db, int p4type, void *p4){
  assert( db );
@@ -81916,7 +83167,7 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){
    case P4_INT64:
    case P4_DYNAMIC:
    case P4_INTARRAY: {
-
      sqlite3DbFree(db, p4);
+
      if( p4 ) sqlite3DbNNFreeNN(db, p4);
      break;
    }
    case P4_KEYINFO: {
@@ -81955,6 +83206,7 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){
*/
static void vdbeFreeOpArray(sqlite3 *db, Op *aOp, int nOp){
  assert( nOp>=0 );
+
  assert( db!=0 );
  if( aOp ){
    Op *pOp = &aOp[nOp-1];
    while(1){  /* Exit via break */
@@ -81965,7 +83217,7 @@ static void vdbeFreeOpArray(sqlite3 *db, Op *aOp, int nOp){
      if( pOp==aOp ) break;
      pOp--;
    }
-
    sqlite3DbFreeNN(db, aOp);
+
    sqlite3DbNNFreeNN(db, aOp);
  }
}

@@ -82196,13 +83448,13 @@ SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe *p, const char *zFormat, ...){
** Set the value if the iSrcLine field for the previously coded instruction.
*/
SQLITE_PRIVATE void sqlite3VdbeSetLineNumber(Vdbe *v, int iLine){
-
  sqlite3VdbeGetOp(v,-1)->iSrcLine = iLine;
+
  sqlite3VdbeGetLastOp(v)->iSrcLine = iLine;
}
#endif /* SQLITE_VDBE_COVERAGE */

/*
-
** Return the opcode for a given address.  If the address is -1, then
-
** return the most recently inserted opcode.
+
** Return the opcode for a given address.  The address must be non-negative.
+
** See sqlite3VdbeGetLastOp() to get the most recently added opcode.
**
** If a memory allocation error has occurred prior to the calling of this
** routine, then a pointer to a dummy VdbeOp will be returned.  That opcode
@@ -82218,9 +83470,6 @@ SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
  ** zeros, which is correct.  MSVC generates a warning, nevertheless. */
  static VdbeOp dummy;  /* Ignore the MSVC warning about no initializer */
  assert( p->eVdbeState==VDBE_INIT_STATE );
-
  if( addr<0 ){
-
    addr = p->nOp - 1;
-
  }
  assert( (addr>=0 && addr<p->nOp) || p->db->mallocFailed );
  if( p->db->mallocFailed ){
    return (VdbeOp*)&dummy;
@@ -82229,6 +83478,12 @@ SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
  }
}

+
/* Return the most recently added opcode
+
*/
+
VdbeOp * sqlite3VdbeGetLastOp(Vdbe *p){
+
  return sqlite3VdbeGetOp(p, p->nOp - 1);
+
}
+

#if defined(SQLITE_ENABLE_EXPLAIN_COMMENTS)
/*
** Return an integer value for one of the parameters to the opcode pOp
@@ -82716,7 +83971,7 @@ static void releaseMemArray(Mem *p, int N){
        sqlite3VdbeMemRelease(p);
        p->flags = MEM_Undefined;
      }else if( p->szMalloc ){
-
        sqlite3DbFreeNN(db, p->zMalloc);
+
        sqlite3DbNNFreeNN(db, p->zMalloc);
        p->szMalloc = 0;
        p->flags = MEM_Undefined;
      }
@@ -83708,7 +84963,7 @@ static void checkActiveVdbeCnt(sqlite3 *db){
      if( p->readOnly==0 ) nWrite++;
      if( p->bIsReader ) nRead++;
    }
-
    p = p->pNext;
+
    p = p->pVNext;
  }
  assert( cnt==db->nVdbeActive );
  assert( nWrite==db->nVdbeWrite );
@@ -84237,10 +85492,11 @@ SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(sqlite3 *db, AuxData **pp, int iOp,
*/
static void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
  SubProgram *pSub, *pNext;
+
  assert( db!=0 );
  assert( p->db==0 || p->db==db );
  if( p->aColName ){
    releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
-
    sqlite3DbFreeNN(db, p->aColName);
+
    sqlite3DbNNFreeNN(db, p->aColName);
  }
  for(pSub=p->pProgram; pSub; pSub=pNext){
    pNext = pSub->pNext;
@@ -84249,11 +85505,11 @@ static void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
  }
  if( p->eVdbeState!=VDBE_INIT_STATE ){
    releaseMemArray(p->aVar, p->nVar);
-
    if( p->pVList ) sqlite3DbFreeNN(db, p->pVList);
-
    if( p->pFree ) sqlite3DbFreeNN(db, p->pFree);
+
    if( p->pVList ) sqlite3DbNNFreeNN(db, p->pVList);
+
    if( p->pFree ) sqlite3DbNNFreeNN(db, p->pFree);
  }
  vdbeFreeOpArray(db, p->aOp, p->nOp);
-
  sqlite3DbFree(db, p->zSql);
+
  if( p->zSql ) sqlite3DbNNFreeNN(db, p->zSql);
#ifdef SQLITE_ENABLE_NORMALIZE
  sqlite3DbFree(db, p->zNormSql);
  {
@@ -84283,20 +85539,17 @@ SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){

  assert( p!=0 );
  db = p->db;
+
  assert( db!=0 );
  assert( sqlite3_mutex_held(db->mutex) );
  sqlite3VdbeClearObject(db, p);
  if( db->pnBytesFreed==0 ){
-
    if( p->pPrev ){
-
      p->pPrev->pNext = p->pNext;
-
    }else{
-
      assert( db->pVdbe==p );
-
      db->pVdbe = p->pNext;
-
    }
-
    if( p->pNext ){
-
      p->pNext->pPrev = p->pPrev;
+
    assert( p->ppVPrev!=0 );
+
    *p->ppVPrev = p->pVNext;
+
    if( p->pVNext ){
+
      p->pVNext->ppVPrev = p->ppVPrev;
    }
  }
-
  sqlite3DbFreeNN(db, p);
+
  sqlite3DbNNFreeNN(db, p);
}

/*
@@ -85251,7 +86504,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
  assert( pPKey2->pKeyInfo->aSortFlags!=0 );
  assert( pPKey2->pKeyInfo->nKeyField>0 );
  assert( idx1<=szHdr1 || CORRUPT_DB );
-
  do{
+
  while( 1 /*exit-by-break*/ ){
    u32 serial_type;

    /* RHS is an integer */
@@ -85261,7 +86514,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
      serial_type = aKey1[idx1];
      testcase( serial_type==12 );
      if( serial_type>=10 ){
-
        rc = +1;
+
        rc = serial_type==10 ? -1 : +1;
      }else if( serial_type==0 ){
        rc = -1;
      }else if( serial_type==7 ){
@@ -85286,7 +86539,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
        ** numbers). Types 10 and 11 are currently "reserved for future
        ** use", so it doesn't really matter what the results of comparing
        ** them to numberic values are.  */
-
        rc = +1;
+
        rc = serial_type==10 ? -1 : +1;
      }else if( serial_type==0 ){
        rc = -1;
      }else{
@@ -85367,7 +86620,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
    /* RHS is null */
    else{
      serial_type = aKey1[idx1];
-
      rc = (serial_type!=0);
+
      rc = (serial_type!=0 && serial_type!=10);
    }

    if( rc!=0 ){
@@ -85389,8 +86642,13 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
    if( i==pPKey2->nField ) break;
    pRhs++;
    d1 += sqlite3VdbeSerialTypeLen(serial_type);
+
    if( d1>(unsigned)nKey1 ) break;
    idx1 += sqlite3VarintLen(serial_type);
-
  }while( idx1<(unsigned)szHdr1 && d1<=(unsigned)nKey1 );
+
    if( idx1>=(unsigned)szHdr1 ){
+
      pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
+
      return 0;  /* Corrupt index */
+
    }
+
  }

  /* No memory allocation is ever used on mem1.  Prove this using
  ** the following assert().  If the assert() fails, it indicates a
@@ -85791,7 +87049,7 @@ SQLITE_PRIVATE void sqlite3VdbeCountChanges(Vdbe *v){
*/
SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3 *db, int iCode){
  Vdbe *p;
-
  for(p = db->pVdbe; p; p=p->pNext){
+
  for(p = db->pVdbe; p; p=p->pVNext){
    p->expired = iCode+1;
  }
}
@@ -85912,13 +87170,14 @@ SQLITE_PRIVATE void sqlite3VtabImportErrmsg(Vdbe *p, sqlite3_vtab *pVtab){
** the vdbeUnpackRecord() function found in vdbeapi.c.
*/
static void vdbeFreeUnpacked(sqlite3 *db, int nField, UnpackedRecord *p){
+
  assert( db!=0 );
  if( p ){
    int i;
    for(i=0; i<nField; i++){
      Mem *pMem = &p->aMem[i];
      if( pMem->zMalloc ) sqlite3VdbeMemReleaseMalloc(pMem);
    }
-
    sqlite3DbFreeNN(db, p);
+
    sqlite3DbNNFreeNN(db, p);
  }
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
@@ -85989,7 +87248,7 @@ SQLITE_PRIVATE void sqlite3VdbePreUpdateHook(
    for(i=0; i<pCsr->nField; i++){
      sqlite3VdbeMemRelease(&preupdate.aNew[i]);
    }
-
    sqlite3DbFreeNN(db, preupdate.aNew);
+
    sqlite3DbNNFreeNN(db, preupdate.aNew);
  }
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
@@ -86106,7 +87365,9 @@ SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt){
    if( vdbeSafety(v) ) return SQLITE_MISUSE_BKPT;
    sqlite3_mutex_enter(db->mutex);
    checkProfileCallback(db, v);
-
    rc = sqlite3VdbeFinalize(v);
+
    assert( v->eVdbeState>=VDBE_READY_STATE );
+
    rc = sqlite3VdbeReset(v);
+
    sqlite3VdbeDelete(v);
    rc = sqlite3ApiExit(db, rc);
    sqlite3LeaveMutexAndCloseZombie(db);
  }
@@ -86314,6 +87575,9 @@ SQLITE_API int sqlite3_value_type(sqlite3_value* pVal){
#endif
  return aType[pVal->flags&MEM_AffMask];
}
+
SQLITE_API int sqlite3_value_encoding(sqlite3_value *pVal){
+
  return pVal->enc;
+
}

/* Return true if a parameter to xUpdate represents an unchanged column */
SQLITE_API int sqlite3_value_nochange(sqlite3_value *pVal){
@@ -87428,7 +88692,7 @@ SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){
** The error code stored in database p->db is overwritten with the return
** value in any case.
*/
-
static int vdbeUnbind(Vdbe *p, int i){
+
static int vdbeUnbind(Vdbe *p, unsigned int i){
  Mem *pVar;
  if( vdbeSafetyNotNull(p) ){
    return SQLITE_MISUSE_BKPT;
@@ -87441,12 +88705,11 @@ static int vdbeUnbind(Vdbe *p, int i){
        "bind on a busy prepared statement: [%s]", p->zSql);
    return SQLITE_MISUSE_BKPT;
  }
-
  if( i<1 || i>p->nVar ){
+
  if( i>=(unsigned int)p->nVar ){
    sqlite3Error(p->db, SQLITE_RANGE);
    sqlite3_mutex_leave(p->db->mutex);
    return SQLITE_RANGE;
  }
-
  i--;
  pVar = &p->aVar[i];
  sqlite3VdbeMemRelease(pVar);
  pVar->flags = MEM_Null;
@@ -87483,7 +88746,7 @@ static int bindText(
  Mem *pVar;
  int rc;

-
  rc = vdbeUnbind(p, i);
+
  rc = vdbeUnbind(p, (u32)(i-1));
  if( rc==SQLITE_OK ){
    if( zData!=0 ){
      pVar = &p->aVar[i-1];
@@ -87532,7 +88795,7 @@ SQLITE_API int sqlite3_bind_blob64(
SQLITE_API int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){
  int rc;
  Vdbe *p = (Vdbe *)pStmt;
-
  rc = vdbeUnbind(p, i);
+
  rc = vdbeUnbind(p, (u32)(i-1));
  if( rc==SQLITE_OK ){
    sqlite3VdbeMemSetDouble(&p->aVar[i-1], rValue);
    sqlite3_mutex_leave(p->db->mutex);
@@ -87545,7 +88808,7 @@ SQLITE_API int sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){
SQLITE_API int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){
  int rc;
  Vdbe *p = (Vdbe *)pStmt;
-
  rc = vdbeUnbind(p, i);
+
  rc = vdbeUnbind(p, (u32)(i-1));
  if( rc==SQLITE_OK ){
    sqlite3VdbeMemSetInt64(&p->aVar[i-1], iValue);
    sqlite3_mutex_leave(p->db->mutex);
@@ -87555,7 +88818,7 @@ SQLITE_API int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValu
SQLITE_API int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){
  int rc;
  Vdbe *p = (Vdbe*)pStmt;
-
  rc = vdbeUnbind(p, i);
+
  rc = vdbeUnbind(p, (u32)(i-1));
  if( rc==SQLITE_OK ){
    sqlite3_mutex_leave(p->db->mutex);
  }
@@ -87570,7 +88833,7 @@ SQLITE_API int sqlite3_bind_pointer(
){
  int rc;
  Vdbe *p = (Vdbe*)pStmt;
-
  rc = vdbeUnbind(p, i);
+
  rc = vdbeUnbind(p, (u32)(i-1));
  if( rc==SQLITE_OK ){
    sqlite3VdbeMemSetPointer(&p->aVar[i-1], pPtr, zPTtype, xDestructor);
    sqlite3_mutex_leave(p->db->mutex);
@@ -87648,7 +88911,7 @@ SQLITE_API int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_valu
SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){
  int rc;
  Vdbe *p = (Vdbe *)pStmt;
-
  rc = vdbeUnbind(p, i);
+
  rc = vdbeUnbind(p, (u32)(i-1));
  if( rc==SQLITE_OK ){
#ifndef SQLITE_OMIT_INCRBLOB
    sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n);
@@ -87808,7 +89071,7 @@ SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt){
  if( pStmt==0 ){
    pNext = (sqlite3_stmt*)pDb->pVdbe;
  }else{
-
    pNext = (sqlite3_stmt*)((Vdbe*)pStmt)->pNext;
+
    pNext = (sqlite3_stmt*)((Vdbe*)pStmt)->pVNext;
  }
  sqlite3_mutex_leave(pDb->mutex);
  return pNext;
@@ -87833,8 +89096,11 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){
    sqlite3_mutex_enter(db->mutex);
    v = 0;
    db->pnBytesFreed = (int*)&v;
+
    assert( db->lookaside.pEnd==db->lookaside.pTrueEnd );
+
    db->lookaside.pEnd = db->lookaside.pStart;
    sqlite3VdbeDelete(pVdbe);
    db->pnBytesFreed = 0;
+
    db->lookaside.pEnd = db->lookaside.pTrueEnd;
    sqlite3_mutex_leave(db->mutex);
  }else{
    v = pVdbe->aCounter[op];
@@ -88674,7 +89940,8 @@ static VdbeCursor *allocateCursor(
** return false.
*/
static int alsoAnInt(Mem *pRec, double rValue, i64 *piValue){
-
  i64 iValue = (double)rValue;
+
  i64 iValue;
+
  iValue = sqlite3RealToI64(rValue);
  if( sqlite3RealSameAsInt(rValue,iValue) ){
    *piValue = iValue;
    return 1;
@@ -88836,17 +90103,18 @@ static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){
** But it does set pMem->u.r and pMem->u.i appropriately.
*/
static u16 numericType(Mem *pMem){
-
  if( pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal) ){
+
  assert( (pMem->flags & MEM_Null)==0
+
       || pMem->db==0 || pMem->db->mallocFailed );
+
  if( pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal|MEM_Null) ){
    testcase( pMem->flags & MEM_Int );
    testcase( pMem->flags & MEM_Real );
    testcase( pMem->flags & MEM_IntReal );
-
    return pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal);
-
  }
-
  if( pMem->flags & (MEM_Str|MEM_Blob) ){
-
    testcase( pMem->flags & MEM_Str );
-
    testcase( pMem->flags & MEM_Blob );
-
    return computeNumericType(pMem);
+
    return pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal|MEM_Null);
  }
+
  assert( pMem->flags & (MEM_Str|MEM_Blob) );
+
  testcase( pMem->flags & MEM_Str );
+
  testcase( pMem->flags & MEM_Blob );
+
  return computeNumericType(pMem);
  return 0;
}

@@ -90091,7 +91359,6 @@ case OP_Subtract: /* same as TK_MINUS, in1, in2, out3 */
case OP_Multiply:              /* same as TK_STAR, in1, in2, out3 */
case OP_Divide:                /* same as TK_SLASH, in1, in2, out3 */
case OP_Remainder: {           /* same as TK_REM, in1, in2, out3 */
-
  u16 flags;      /* Combined MEM_* flags from both inputs */
  u16 type1;      /* Numeric type of left operand */
  u16 type2;      /* Numeric type of right operand */
  i64 iA;         /* Integer value of left operand */
@@ -90100,12 +91367,12 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
  double rB;      /* Real value of right operand */

  pIn1 = &aMem[pOp->p1];
-
  type1 = numericType(pIn1);
+
  type1 = pIn1->flags;
  pIn2 = &aMem[pOp->p2];
-
  type2 = numericType(pIn2);
+
  type2 = pIn2->flags;
  pOut = &aMem[pOp->p3];
-
  flags = pIn1->flags | pIn2->flags;
  if( (type1 & type2 & MEM_Int)!=0 ){
+
int_math:
    iA = pIn1->u.i;
    iB = pIn2->u.i;
    switch( pOp->opcode ){
@@ -90127,9 +91394,12 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
    }
    pOut->u.i = iB;
    MemSetTypeFlag(pOut, MEM_Int);
-
  }else if( (flags & MEM_Null)!=0 ){
+
  }else if( ((type1 | type2) & MEM_Null)!=0 ){
    goto arithmetic_result_is_null;
  }else{
+
    type1 = numericType(pIn1);
+
    type2 = numericType(pIn2);
+
    if( (type1 & type2 & MEM_Int)!=0 ) goto int_math;
fp_math:
    rA = sqlite3VdbeRealValue(pIn1);
    rB = sqlite3VdbeRealValue(pIn2);
@@ -90944,19 +92214,90 @@ case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */
  break;
}

-
/* Opcode: IsNullOrType P1 P2 P3 * *
-
** Synopsis: if typeof(r[P1]) IN (P3,5) goto P2
+
/* Opcode: IsType P1 P2 P3 P4 P5
+
** Synopsis: if typeof(P1.P3) in P5 goto P2
+
**
+
** Jump to P2 if the type of a column in a btree is one of the types specified
+
** by the P5 bitmask.
+
**
+
** P1 is normally a cursor on a btree for which the row decode cache is
+
** valid through at least column P3.  In other words, there should have been
+
** a prior OP_Column for column P3 or greater.  If the cursor is not valid,
+
** then this opcode might give spurious results.
+
** The the btree row has fewer than P3 columns, then use P4 as the
+
** datatype.
+
**
+
** If P1 is -1, then P3 is a register number and the datatype is taken
+
** from the value in that register.
+
**
+
** P5 is a bitmask of data types.  SQLITE_INTEGER is the least significant
+
** (0x01) bit. SQLITE_FLOAT is the 0x02 bit. SQLITE_TEXT is 0x04.
+
** SQLITE_BLOB is 0x08.  SQLITE_NULL is 0x10.
+
**
+
** Take the jump to address P2 if and only if the datatype of the
+
** value determined by P1 and P3 corresponds to one of the bits in the
+
** P5 bitmask.
**
-
** Jump to P2 if the value in register P1 is NULL or has a datatype P3.
-
** P3 is an integer which should be one of SQLITE_INTEGER, SQLITE_FLOAT,
-
** SQLITE_BLOB, SQLITE_NULL, or SQLITE_TEXT.
*/
-
case OP_IsNullOrType: {      /* jump, in1 */
-
  int doTheJump;
-
  pIn1 = &aMem[pOp->p1];
-
  doTheJump = (pIn1->flags & MEM_Null)!=0 || sqlite3_value_type(pIn1)==pOp->p3;
-
  VdbeBranchTaken( doTheJump, 2);
-
  if( doTheJump ) goto jump_to_p2;
+
case OP_IsType: {        /* jump */
+
  VdbeCursor *pC;
+
  u16 typeMask;
+
  u32 serialType;
+

+
  assert( pOp->p1>=(-1) && pOp->p1<p->nCursor );
+
  assert( pOp->p1>=0 || (pOp->p3>=0 && pOp->p3<=(p->nMem+1 - p->nCursor)) );
+
  if( pOp->p1>=0 ){
+
    pC = p->apCsr[pOp->p1];
+
    assert( pC!=0 );
+
    assert( pOp->p3>=0 );
+
    if( pOp->p3<pC->nHdrParsed ){
+
      serialType = pC->aType[pOp->p3];
+
      if( serialType>=12 ){
+
        if( serialType&1 ){
+
          typeMask = 0x04;   /* SQLITE_TEXT */
+
        }else{
+
          typeMask = 0x08;   /* SQLITE_BLOB */
+
        }
+
      }else{
+
        static const unsigned char aMask[] = {
+
           0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x2,
+
           0x01, 0x01, 0x10, 0x10
+
        };
+
        testcase( serialType==0 );
+
        testcase( serialType==1 );
+
        testcase( serialType==2 );
+
        testcase( serialType==3 );
+
        testcase( serialType==4 );
+
        testcase( serialType==5 );
+
        testcase( serialType==6 );
+
        testcase( serialType==7 );
+
        testcase( serialType==8 );
+
        testcase( serialType==9 );
+
        testcase( serialType==10 );
+
        testcase( serialType==11 );
+
        typeMask = aMask[serialType];
+
      }
+
    }else{
+
      typeMask = 1 << (pOp->p4.i - 1);
+
      testcase( typeMask==0x01 );
+
      testcase( typeMask==0x02 );
+
      testcase( typeMask==0x04 );
+
      testcase( typeMask==0x08 );
+
      testcase( typeMask==0x10 );
+
    }
+
  }else{
+
    assert( memIsValid(&aMem[pOp->p3]) );
+
    typeMask = 1 << (sqlite3_value_type((sqlite3_value*)&aMem[pOp->p3])-1);
+
    testcase( typeMask==0x01 );
+
    testcase( typeMask==0x02 );
+
    testcase( typeMask==0x04 );
+
    testcase( typeMask==0x08 );
+
    testcase( typeMask==0x10 );
+
  }
+
  VdbeBranchTaken( (typeMask & pOp->p5)!=0, 2);
+
  if( typeMask & pOp->p5 ){
+
    goto jump_to_p2;
+
  }
  break;
}

@@ -90999,11 +92340,14 @@ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */
** If it is, then set register P3 to NULL and jump immediately to P2.
** If P1 is not on a NULL row, then fall through without making any
** changes.
+
**
+
** If P1 is not an open cursor, then this opcode is a no-op.
*/
case OP_IfNullRow: {         /* jump */
+
  VdbeCursor *pC;
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-
  assert( p->apCsr[pOp->p1]!=0 );
-
  if( p->apCsr[pOp->p1]->nullRow ){
+
  pC = p->apCsr[pOp->p1];
+
  if( ALWAYS(pC) && pC->nullRow ){
    sqlite3VdbeMemSetNull(aMem + pOp->p3);
    goto jump_to_p2;
  }
@@ -91054,7 +92398,7 @@ case OP_Offset: { /* out3 */
** Interpret the data that cursor P1 points to as a structure built using
** the MakeRecord instruction.  (See the MakeRecord opcode for additional
** information about the format of the data.)  Extract the P2-th column
-
** from this record.  If there are less that (P2+1)
+
** from this record.  If there are less than (P2+1)
** values in the record, extract a NULL.
**
** The value extracted is stored in register P3.
@@ -91063,10 +92407,12 @@ case OP_Offset: { /* out3 */
** if the P4 argument is a P4_MEM use the value of the P4 argument as
** the result.
**
-
** If the OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG bits are set on P5 then
-
** the result is guaranteed to only be used as the argument of a length()
-
** or typeof() function, respectively.  The loading of large blobs can be
-
** skipped for length() and all content loading can be skipped for typeof().
+
** If the OPFLAG_LENGTHARG bit is set in P5 then the result is guaranteed
+
** to only be used by the length() function or the equivalent.  The content
+
** of large blobs is not loaded, thus saving CPU cycles.  If the
+
** OPFLAG_TYPEOFARG bit is set then the result will only be used by the
+
** typeof() function or the IS NULL or IS NOT NULL operators or the
+
** equivalent.  In this case, all content loading can be omitted.
*/
case OP_Column: {
  u32 p2;            /* column number to retrieve */
@@ -93005,7 +94351,13 @@ case OP_SeekGT: { /* jump, in3, group */

    r.aMem = &aMem[pOp->p3];
#ifdef SQLITE_DEBUG
-
    { int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
+
    {
+
      int i;
+
      for(i=0; i<r.nField; i++){
+
        assert( memIsValid(&r.aMem[i]) );
+
        if( i>0 ) REGISTER_TRACE(pOp->p3+i, &r.aMem[i]);
+
      }
+
    }
#endif
    r.eqSeen = 0;
    rc = sqlite3BtreeIndexMoveto(pC->uc.pCursor, &r, &res);
@@ -93068,7 +94420,7 @@ seek_not_found:
}


-
/* Opcode: SeekScan  P1 P2 * * *
+
/* Opcode: SeekScan  P1 P2 * * P5
** Synopsis: Scan-ahead up to P1 rows
**
** This opcode is a prefix opcode to OP_SeekGE.  In other words, this
@@ -93078,8 +94430,8 @@ seek_not_found:
** This opcode uses the P1 through P4 operands of the subsequent
** OP_SeekGE.  In the text that follows, the operands of the subsequent
** OP_SeekGE opcode are denoted as SeekOP.P1 through SeekOP.P4.   Only
-
** the P1 and P2 operands of this opcode are also used, and  are called
-
** This.P1 and This.P2.
+
** the P1, P2 and P5 operands of this opcode are also used, and  are called
+
** This.P1, This.P2 and This.P5.
**
** This opcode helps to optimize IN operators on a multi-column index
** where the IN operator is on the later terms of the index by avoiding
@@ -93089,29 +94441,51 @@ seek_not_found:
**
** The SeekGE.P3 and SeekGE.P4 operands identify an unpacked key which
** is the desired entry that we want the cursor SeekGE.P1 to be pointing
-
** to.  Call this SeekGE.P4/P5 row the "target".
+
** to.  Call this SeekGE.P3/P4 row the "target".
**
** If the SeekGE.P1 cursor is not currently pointing to a valid row,
** then this opcode is a no-op and control passes through into the OP_SeekGE.
**
** If the SeekGE.P1 cursor is pointing to a valid row, then that row
** might be the target row, or it might be near and slightly before the
-
** target row.  This opcode attempts to position the cursor on the target
-
** row by, perhaps by invoking sqlite3BtreeStep() on the cursor
-
** between 0 and This.P1 times.
-
**
-
** There are three possible outcomes from this opcode:<ol>
-
**
-
** <li> If after This.P1 steps, the cursor is still pointing to a place that
-
**      is earlier in the btree than the target row, then fall through
-
**      into the subsquence OP_SeekGE opcode.
-
**
-
** <li> If the cursor is successfully moved to the target row by 0 or more
-
**      sqlite3BtreeNext() calls, then jump to This.P2, which will land just
-
**      past the OP_IdxGT or OP_IdxGE opcode that follows the OP_SeekGE.
-
**
-
** <li> If the cursor ends up past the target row (indicating the the target
-
**      row does not exist in the btree) then jump to SeekOP.P2.
+
** target row, or it might be after the target row.  If the cursor is
+
** currently before the target row, then this opcode attempts to position
+
** the cursor on or after the target row by invoking sqlite3BtreeStep()
+
** on the cursor between 1 and This.P1 times.
+
**
+
** The This.P5 parameter is a flag that indicates what to do if the
+
** cursor ends up pointing at a valid row that is past the target
+
** row.  If This.P5 is false (0) then a jump is made to SeekGE.P2.  If
+
** This.P5 is true (non-zero) then a jump is made to This.P2.  The P5==0
+
** case occurs when there are no inequality constraints to the right of
+
** the IN constraing.  The jump to SeekGE.P2 ends the loop.  The P5!=0 case
+
** occurs when there are inequality constraints to the right of the IN
+
** operator.  In that case, the This.P2 will point either directly to or
+
** to setup code prior to the OP_IdxGT or OP_IdxGE opcode that checks for
+
** loop terminate.
+
**
+
** Possible outcomes from this opcode:<ol>
+
**
+
** <li> If the cursor is initally not pointed to any valid row, then
+
**      fall through into the subsequent OP_SeekGE opcode.
+
**
+
** <li> If the cursor is left pointing to a row that is before the target
+
**      row, even after making as many as This.P1 calls to
+
**      sqlite3BtreeNext(), then also fall through into OP_SeekGE.
+
**
+
** <li> If the cursor is left pointing at the target row, either because it
+
**      was at the target row to begin with or because one or more
+
**      sqlite3BtreeNext() calls moved the cursor to the target row,
+
**      then jump to This.P2..,
+
**
+
** <li> If the cursor started out before the target row and a call to
+
**      to sqlite3BtreeNext() moved the cursor off the end of the index
+
**      (indicating that the target row definitely does not exist in the
+
**      btree) then jump to SeekGE.P2, ending the loop.
+
**
+
** <li> If the cursor ends up on a valid row that is past the target row
+
**      (indicating that the target row does not exist in the btree) then
+
**      jump to SeekOP.P2 if This.P5==0 or to This.P2 if This.P5>0.
** </ol>
*/
case OP_SeekScan: {
@@ -93122,14 +94496,25 @@ case OP_SeekScan: {

  assert( pOp[1].opcode==OP_SeekGE );

-
  /* pOp->p2 points to the first instruction past the OP_IdxGT that
-
  ** follows the OP_SeekGE.  */
+
  /* If pOp->p5 is clear, then pOp->p2 points to the first instruction past the
+
  ** OP_IdxGT that follows the OP_SeekGE. Otherwise, it points to the first
+
  ** opcode past the OP_SeekGE itself.  */
  assert( pOp->p2>=(int)(pOp-aOp)+2 );
-
  assert( aOp[pOp->p2-1].opcode==OP_IdxGT || aOp[pOp->p2-1].opcode==OP_IdxGE );
-
  testcase( aOp[pOp->p2-1].opcode==OP_IdxGE );
-
  assert( pOp[1].p1==aOp[pOp->p2-1].p1 );
-
  assert( pOp[1].p2==aOp[pOp->p2-1].p2 );
-
  assert( pOp[1].p3==aOp[pOp->p2-1].p3 );
+
#ifdef SQLITE_DEBUG
+
  if( pOp->p5==0 ){
+
    /* There are no inequality constraints following the IN constraint. */
+
    assert( pOp[1].p1==aOp[pOp->p2-1].p1 );
+
    assert( pOp[1].p2==aOp[pOp->p2-1].p2 );
+
    assert( pOp[1].p3==aOp[pOp->p2-1].p3 );
+
    assert( aOp[pOp->p2-1].opcode==OP_IdxGT
+
         || aOp[pOp->p2-1].opcode==OP_IdxGE );
+
    testcase( aOp[pOp->p2-1].opcode==OP_IdxGE );
+
  }else{
+
    /* There are inequality constraints.  */
+
    assert( pOp->p2==(int)(pOp-aOp)+2 );
+
    assert( aOp[pOp->p2-1].opcode==OP_SeekGE );
+
  }
+
#endif

  assert( pOp->p1>0 );
  pC = p->apCsr[pOp[1].p1];
@@ -93163,8 +94548,9 @@ case OP_SeekScan: {
  while(1){
    rc = sqlite3VdbeIdxKeyCompare(db, pC, &r, &res);
    if( rc ) goto abort_due_to_error;
-
    if( res>0 ){
+
    if( res>0 && pOp->p5==0 ){
      seekscan_search_fail:
+
      /* Jump to SeekGE.P2, ending the loop */
#ifdef SQLITE_DEBUG
      if( db->flags&SQLITE_VdbeTrace ){
        printf("... %d steps and then skip\n", pOp->p1 - nStep);
@@ -93174,7 +94560,8 @@ case OP_SeekScan: {
      pOp++;
      goto jump_to_p2;
    }
-
    if( res==0 ){
+
    if( res>=0 ){
+
      /* Jump to This.P2, bypassing the OP_SeekGE opcode */
#ifdef SQLITE_DEBUG
      if( db->flags&SQLITE_VdbeTrace ){
        printf("... %d steps and then success\n", pOp->p1 - nStep);
@@ -93250,12 +94637,16 @@ case OP_SeekHit: {
/* Opcode: IfNotOpen P1 P2 * * *
** Synopsis: if( !csr[P1] ) goto P2
**
-
** If cursor P1 is not open, jump to instruction P2. Otherwise, fall through.
+
** If cursor P1 is not open or if P1 is set to a NULL row using the
+
** OP_NullRow opcode, then jump to instruction P2. Otherwise, fall through.
*/
case OP_IfNotOpen: {        /* jump */
+
  VdbeCursor *pCur;
+

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-
  VdbeBranchTaken(p->apCsr[pOp->p1]==0, 2);
-
  if( !p->apCsr[pOp->p1] ){
+
  pCur = p->apCsr[pOp->p1];
+
  VdbeBranchTaken(pCur==0 || pCur->nullRow, 2);
+
  if( pCur==0 || pCur->nullRow ){
    goto jump_to_p2_and_check_for_interrupt;
  }
  break;
@@ -94446,7 +95837,9 @@ case OP_SorterNext: { /* jump */

case OP_Prev:          /* jump */
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-
  assert( pOp->p5<ArraySize(p->aCounter) );
+
  assert( pOp->p5==0
+
       || pOp->p5==SQLITE_STMTSTATUS_FULLSCAN_STEP
+
       || pOp->p5==SQLITE_STMTSTATUS_AUTOINDEX);
  pC = p->apCsr[pOp->p1];
  assert( pC!=0 );
  assert( pC->deferredMoveto==0 );
@@ -94459,7 +95852,9 @@ case OP_Prev: /* jump */

case OP_Next:          /* jump */
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-
  assert( pOp->p5<ArraySize(p->aCounter) );
+
  assert( pOp->p5==0
+
       || pOp->p5==SQLITE_STMTSTATUS_FULLSCAN_STEP
+
       || pOp->p5==SQLITE_STMTSTATUS_AUTOINDEX);
  pC = p->apCsr[pOp->p1];
  assert( pC!=0 );
  assert( pC->deferredMoveto==0 );
@@ -94666,10 +96061,10 @@ case OP_IdxRowid: { /* out2 */
  ** of sqlite3VdbeCursorRestore() and sqlite3VdbeIdxRowid(). */
  rc = sqlite3VdbeCursorRestore(pC);

-
  /* sqlite3VbeCursorRestore() can only fail if the record has been deleted
-
  ** out from under the cursor.  That will never happens for an IdxRowid
-
  ** or Seek opcode */
-
  if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;
+
  /* sqlite3VdbeCursorRestore() may fail if the cursor has been disturbed
+
  ** since it was last positioned and an error (e.g. OOM or an IO error)
+
  ** occurs while trying to reposition it. */
+
  if( rc!=SQLITE_OK ) goto abort_due_to_error;

  if( !pC->nullRow ){
    rowid = 0;  /* Not needed.  Only used to silence a warning. */
@@ -95571,7 +96966,7 @@ case OP_IfPos: { /* jump, in1 */
** Synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)
**
** This opcode performs a commonly used computation associated with
-
** LIMIT and OFFSET process.  r[P1] holds the limit counter.  r[P3]
+
** LIMIT and OFFSET processing.  r[P1] holds the limit counter.  r[P3]
** holds the offset counter.  The opcode computes the combined value
** of the LIMIT and OFFSET and stores that value in r[P2].  The r[P2]
** value computed is the total number of rows that will need to be
@@ -101169,6 +102564,8 @@ SQLITE_PRIVATE int sqlite3JournalOpen(
){
  MemJournal *p = (MemJournal*)pJfd;

+
  assert( zName || nSpill<0 || (flags & SQLITE_OPEN_EXCLUSIVE) );
+

  /* Zero the file-handle object. If nSpill was passed zero, initialize
  ** it using the sqlite3OsOpen() function of the underlying VFS. In this
  ** case none of the code in this module is executed as a result of calls
@@ -101610,9 +103007,7 @@ static void resolveAlias(
        pExpr->y.pWin->pOwner = pExpr;
      }
    }
-
    sqlite3ParserAddCleanup(pParse,
-
      (void(*)(sqlite3*,void*))sqlite3ExprDelete,
-
      pDup);
+
    sqlite3ExprDeferredDelete(pParse, pDup);
  }
}

@@ -103706,9 +105101,8 @@ SQLITE_PRIVATE char sqlite3ExprAffinity(const Expr *pExpr){
  if( op==TK_REGISTER ) op = pExpr->op2;
  if( op==TK_COLUMN || op==TK_AGG_COLUMN ){
    assert( ExprUseYTab(pExpr) );
-
    if( pExpr->y.pTab ){
-
      return sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
-
    }
+
    assert( pExpr->y.pTab!=0 );
+
    return sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
  }
  if( op==TK_SELECT ){
    assert( ExprUseXSelect(pExpr) );
@@ -103826,17 +105220,14 @@ SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr){
    int op = p->op;
    if( op==TK_REGISTER ) op = p->op2;
    if( op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_TRIGGER ){
+
      int j;
      assert( ExprUseYTab(p) );
-
      if( p->y.pTab!=0 ){
-
        /* op==TK_REGISTER && p->y.pTab!=0 happens when pExpr was originally
-
        ** a TK_COLUMN but was previously evaluated and cached in a register */
-
        int j = p->iColumn;
-
        if( j>=0 ){
-
          const char *zColl = sqlite3ColumnColl(&p->y.pTab->aCol[j]);
-
          pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
-
        }
-
        break;
+
      assert( p->y.pTab!=0 );
+
      if( (j = p->iColumn)>=0 ){
+
        const char *zColl = sqlite3ColumnColl(&p->y.pTab->aCol[j]);
+
        pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
      }
+
      break;
    }
    if( op==TK_CAST || op==TK_UPLUS ){
      p = p->pLeft;
@@ -104421,7 +105812,9 @@ static void heightOfSelect(const Select *pSelect, int *pnHeight){
*/
static void exprSetHeight(Expr *p){
  int nHeight = p->pLeft ? p->pLeft->nHeight : 0;
-
  if( p->pRight && p->pRight->nHeight>nHeight ) nHeight = p->pRight->nHeight;
+
  if( NEVER(p->pRight) && p->pRight->nHeight>nHeight ){
+
    nHeight = p->pRight->nHeight;
+
  }
  if( ExprUseXSelect(p) ){
    heightOfSelect(p->x.pSelect, &nHeight);
  }else if( p->x.pList ){
@@ -104564,15 +105957,26 @@ SQLITE_PRIVATE void sqlite3ExprAttachSubtrees(
    sqlite3ExprDelete(db, pLeft);
    sqlite3ExprDelete(db, pRight);
  }else{
+
    assert( ExprUseXList(pRoot) );
+
    assert( pRoot->x.pSelect==0 );
    if( pRight ){
      pRoot->pRight = pRight;
      pRoot->flags |= EP_Propagate & pRight->flags;
+
#if SQLITE_MAX_EXPR_DEPTH>0
+
      pRoot->nHeight = pRight->nHeight+1;
+
    }else{
+
      pRoot->nHeight = 1;
+
#endif
    }
    if( pLeft ){
      pRoot->pLeft = pLeft;
      pRoot->flags |= EP_Propagate & pLeft->flags;
+
#if SQLITE_MAX_EXPR_DEPTH>0
+
      if( pLeft->nHeight>=pRoot->nHeight ){
+
        pRoot->nHeight = pLeft->nHeight+1;
+
      }
+
#endif
    }
-
    exprSetHeight(pRoot);
  }
}

@@ -104858,6 +106262,7 @@ SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n
*/
static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
  assert( p!=0 );
+
  assert( db!=0 );
  assert( !ExprUseUValue(p) || p->u.iValue>=0 );
  assert( !ExprUseYWin(p) || !ExprUseYSub(p) );
  assert( !ExprUseYWin(p) || p->y.pWin!=0 || db->mallocFailed );
@@ -104889,12 +106294,8 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
#endif
    }
  }
-
  if( ExprHasProperty(p, EP_MemToken) ){
-
    assert( !ExprHasProperty(p, EP_IntValue) );
-
    sqlite3DbFree(db, p->u.zToken);
-
  }
  if( !ExprHasProperty(p, EP_Static) ){
-
    sqlite3DbFreeNN(db, p);
+
    sqlite3DbNNFreeNN(db, p);
  }
}
SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3 *db, Expr *p){
@@ -104925,8 +106326,9 @@ SQLITE_PRIVATE void sqlite3ClearOnOrUsing(sqlite3 *db, OnOrUsing *p){
** pExpr to the pParse->pConstExpr list with a register number of 0.
*/
SQLITE_PRIVATE void sqlite3ExprDeferredDelete(Parse *pParse, Expr *pExpr){
-
  pParse->pConstExpr =
-
      sqlite3ExprListAppend(pParse, pParse->pConstExpr, pExpr);
+
  sqlite3ParserAddCleanup(pParse,
+
    (void(*)(sqlite3*,void*))sqlite3ExprDelete,
+
    pExpr);
}

/* Invoke sqlite3RenameExprUnmap() and sqlite3ExprDelete() on the
@@ -105000,7 +106402,6 @@ static int dupedExprStructSize(const Expr *p, int flags){
  }else{
    assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
    assert( !ExprHasProperty(p, EP_OuterON) );
-
    assert( !ExprHasProperty(p, EP_MemToken) );
    assert( !ExprHasVVAProperty(p, EP_NoReduce) );
    if( p->pLeft || p->x.pList ){
      nSize = EXPR_REDUCEDSIZE | EP_Reduced;
@@ -105104,7 +106505,7 @@ static Expr *exprDup(sqlite3 *db, const Expr *p, int dupFlags, u8 **pzBuffer){
    }

    /* Set the EP_Reduced, EP_TokenOnly, and EP_Static flags appropriately. */
-
    pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static|EP_MemToken);
+
    pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static);
    pNew->flags |= nStructSize & (EP_Reduced|EP_TokenOnly);
    pNew->flags |= staticFlag;
    ExprClearVVAProperties(pNew);
@@ -105680,12 +107081,13 @@ static SQLITE_NOINLINE void exprListDeleteNN(sqlite3 *db, ExprList *pList){
  int i = pList->nExpr;
  struct ExprList_item *pItem =  pList->a;
  assert( pList->nExpr>0 );
+
  assert( db!=0 );
  do{
    sqlite3ExprDelete(db, pItem->pExpr);
-
    sqlite3DbFree(db, pItem->zEName);
+
    if( pItem->zEName ) sqlite3DbNNFreeNN(db, pItem->zEName);
    pItem++;
  }while( --i>0 );
-
  sqlite3DbFreeNN(db, pList);
+
  sqlite3DbNNFreeNN(db, pList);
}
SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){
  if( pList ) exprListDeleteNN(db, pList);
@@ -106863,6 +108265,7 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN(
    sqlite3VdbeChangeP4(v, addr, (void *)pKeyInfo, P4_KEYINFO);
  }
  if( addrOnce ){
+
    sqlite3VdbeAddOp1(v, OP_NullRow, iTab);
    sqlite3VdbeJumpHere(v, addrOnce);
    /* Subroutine return */
    assert( ExprUseYSub(pExpr) );
@@ -106976,7 +108379,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
      pLimit = sqlite3PExpr(pParse, TK_NE,
                            sqlite3ExprDup(db, pSel->pLimit->pLeft, 0), pLimit);
    }
-
    sqlite3ExprDelete(db, pSel->pLimit->pLeft);
+
    sqlite3ExprDeferredDelete(pParse, pSel->pLimit->pLeft);
    pSel->pLimit->pLeft = pLimit;
  }else{
    /* If there is no pre-existing limit add a limit of 1 */
@@ -107429,10 +108832,7 @@ SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(
){
  Column *pCol;
  assert( v!=0 );
-
  if( pTab==0 ){
-
    sqlite3VdbeAddOp3(v, OP_Column, iTabCur, iCol, regOut);
-
    return;
-
  }
+
  assert( pTab!=0 );
  if( iCol<0 || iCol==pTab->iPKey ){
    sqlite3VdbeAddOp2(v, OP_Rowid, iTabCur, regOut);
    VdbeComment((v, "%s.rowid", pTab->zName));
@@ -107490,7 +108890,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(
  assert( pParse->pVdbe!=0 );
  sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pTab, iTable, iColumn, iReg);
  if( p5 ){
-
    VdbeOp *pOp = sqlite3VdbeGetOp(pParse->pVdbe,-1);
+
    VdbeOp *pOp = sqlite3VdbeGetLastOp(pParse->pVdbe);
    if( pOp->opcode==OP_Column ) pOp->p5 = p5;
  }
  return iReg;
@@ -107559,7 +108959,7 @@ static int exprCodeVector(Parse *pParse, Expr *p, int *piFreeable){
** so that a subsequent copy will not be merged into this one.
*/
static void setDoNotMergeFlagOnCopy(Vdbe *v){
-
  if( sqlite3VdbeGetOp(v, -1)->opcode==OP_Copy ){
+
  if( sqlite3VdbeGetLastOp(v)->opcode==OP_Copy ){
    sqlite3VdbeChangeP5(v, 1);  /* Tag trailing OP_Copy as not mergable */
  }
}
@@ -107682,6 +109082,53 @@ static int exprCodeInlineFunction(
  return target;
}

+
/*
+
** Check to see if pExpr is one of the indexed expressions on pParse->pIdxExpr.
+
** If it is, then resolve the expression by reading from the index and
+
** return the register into which the value has been read.  If pExpr is
+
** not an indexed expression, then return negative.
+
*/
+
static SQLITE_NOINLINE int sqlite3IndexedExprLookup(
+
  Parse *pParse,   /* The parsing context */
+
  Expr *pExpr,     /* The expression to potentially bypass */
+
  int target       /* Where to store the result of the expression */
+
){
+
  IndexedExpr *p;
+
  Vdbe *v;
+
  for(p=pParse->pIdxExpr; p; p=p->pIENext){
+
    int iDataCur = p->iDataCur;
+
    if( iDataCur<0 ) continue;
+
    if( pParse->iSelfTab ){
+
      if( p->iDataCur!=pParse->iSelfTab-1 ) continue;
+
      iDataCur = -1;
+
    }
+
    if( sqlite3ExprCompare(0, pExpr, p->pExpr, iDataCur)!=0 ) continue;
+
    v = pParse->pVdbe;
+
    assert( v!=0 );
+
    if( p->bMaybeNullRow ){
+
      /* If the index is on a NULL row due to an outer join, then we
+
      ** cannot extract the value from the index.  The value must be
+
      ** computed using the original expression. */
+
      int addr = sqlite3VdbeCurrentAddr(v);
+
      sqlite3VdbeAddOp3(v, OP_IfNullRow, p->iIdxCur, addr+3, target);
+
      VdbeCoverage(v);
+
      sqlite3VdbeAddOp3(v, OP_Column, p->iIdxCur, p->iIdxCol, target);
+
      VdbeComment((v, "%s expr-column %d", p->zIdxName, p->iIdxCol));
+
      sqlite3VdbeGoto(v, 0);
+
      p = pParse->pIdxExpr;
+
      pParse->pIdxExpr = 0;
+
      sqlite3ExprCode(pParse, pExpr, target);
+
      pParse->pIdxExpr = p;
+
      sqlite3VdbeJumpHere(v, addr+2);
+
    }else{
+
      sqlite3VdbeAddOp3(v, OP_Column, p->iIdxCur, p->iIdxCol, target);
+
      VdbeComment((v, "%s expr-column %d", p->zIdxName, p->iIdxCol));
+
    }
+
    return target;
+
  }
+
  return -1;  /* Not found */
+
}
+


/*
** Generate code into the current Vdbe to evaluate the given
@@ -107710,6 +109157,11 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
expr_code_doover:
  if( pExpr==0 ){
    op = TK_NULL;
+
  }else if( pParse->pIdxExpr!=0
+
   && !ExprHasProperty(pExpr, EP_Leaf)
+
   && (r1 = sqlite3IndexedExprLookup(pParse, pExpr, target))>=0
+
  ){
+
    return r1;
  }else{
    assert( !ExprHasVVAProperty(pExpr,EP_Immutable) );
    op = pExpr->op;
@@ -107730,7 +109182,7 @@ expr_code_doover:
                              pCol->iSorterColumn, target);
        if( pCol->iColumn<0 ){
          VdbeComment((v,"%s.rowid",pTab->zName));
-
        }else{
+
        }else if( ALWAYS(pTab!=0) ){
          VdbeComment((v,"%s.%s",
              pTab->zName, pTab->aCol[pCol->iColumn].zCnName));
          if( pTab->aCol[pCol->iColumn].affinity==SQLITE_AFF_REAL ){
@@ -107755,11 +109207,8 @@ expr_code_doover:
        int aff;
        iReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft,target);
        assert( ExprUseYTab(pExpr) );
-
        if( pExpr->y.pTab ){
-
          aff = sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
-
        }else{
-
          aff = pExpr->affExpr;
-
        }
+
        assert( pExpr->y.pTab!=0 );
+
        aff = sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
        if( aff>SQLITE_AFF_BLOB ){
          static const char zAff[] = "B\000C\000D\000E";
          assert( SQLITE_AFF_BLOB=='A' );
@@ -107821,12 +109270,10 @@ expr_code_doover:
        }
      }
      assert( ExprUseYTab(pExpr) );
+
      assert( pExpr->y.pTab!=0 );
      iReg = sqlite3ExprCodeGetColumn(pParse, pExpr->y.pTab,
                               pExpr->iColumn, iTab, target,
                               pExpr->op2);
-
      if( pExpr->y.pTab==0 && pExpr->affExpr==SQLITE_AFF_REAL ){
-
        sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg);
-
      }
      return iReg;
    }
    case TK_INTEGER: {
@@ -108325,6 +109772,21 @@ expr_code_doover:
    case TK_IF_NULL_ROW: {
      int addrINR;
      u8 okConstFactor = pParse->okConstFactor;
+
      AggInfo *pAggInfo = pExpr->pAggInfo;
+
      if( pAggInfo ){
+
        assert( pExpr->iAgg>=0 && pExpr->iAgg<pAggInfo->nColumn );
+
        if( !pAggInfo->directMode ){
+
          inReg = pAggInfo->aCol[pExpr->iAgg].iMem;
+
          break;
+
        }
+
        if( pExpr->pAggInfo->useSortingIdx ){
+
          sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdxPTab,
+
                            pAggInfo->aCol[pExpr->iAgg].iSorterColumn,
+
                            target);
+
          inReg = target;
+
          break;
+
        }
+
      }
      addrINR = sqlite3VdbeAddOp1(v, OP_IfNullRow, pExpr->iTable);
      /* Temporarily disable factoring of constant expressions, since
      ** even though expressions may appear to be constant, they are not
@@ -108666,7 +110128,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeExprList(
      if( inReg!=target+i ){
        VdbeOp *pOp;
        if( copyOp==OP_Copy
-
         && (pOp=sqlite3VdbeGetOp(v, -1))->opcode==OP_Copy
+
         && (pOp=sqlite3VdbeGetLastOp(v))->opcode==OP_Copy
         && pOp->p1+pOp->p3+1==inReg
         && pOp->p2+pOp->p3+1==target+i
         && pOp->p5==0  /* The do-not-merge flag must be clear */
@@ -108865,6 +110327,7 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int
      assert( TK_ISNULL==OP_IsNull );   testcase( op==TK_ISNULL );
      assert( TK_NOTNULL==OP_NotNull ); testcase( op==TK_NOTNULL );
      r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
+
      sqlite3VdbeTypeofColumn(v, r1);
      sqlite3VdbeAddOp2(v, op, r1, dest);
      VdbeCoverageIf(v, op==TK_ISNULL);
      VdbeCoverageIf(v, op==TK_NOTNULL);
@@ -109039,6 +110502,7 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int
    case TK_ISNULL:
    case TK_NOTNULL: {
      r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
+
      sqlite3VdbeTypeofColumn(v, r1);
      sqlite3VdbeAddOp2(v, op, r1, dest);
      testcase( op==TK_ISNULL );   VdbeCoverageIf(v, op==TK_ISNULL);
      testcase( op==TK_NOTNULL );  VdbeCoverageIf(v, op==TK_NOTNULL);
@@ -109192,7 +110656,13 @@ SQLITE_PRIVATE int sqlite3ExprCompare(
    if( pB->op==TK_COLLATE && sqlite3ExprCompare(pParse, pA,pB->pLeft,iTab)<2 ){
      return 1;
    }
-
    return 2;
+
    if( pA->op==TK_AGG_COLUMN && pB->op==TK_COLUMN
+
     && pB->iTable<0 && pA->iTable==iTab
+
    ){
+
      /* fall through */
+
    }else{
+
      return 2;
+
    }
  }
  assert( !ExprHasProperty(pA, EP_IntValue) );
  assert( !ExprHasProperty(pB, EP_IntValue) );
@@ -109494,10 +110964,10 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
      assert( pLeft->op!=TK_COLUMN || ExprUseYTab(pLeft) );
      assert( pRight->op!=TK_COLUMN || ExprUseYTab(pRight) );
      if( (pLeft->op==TK_COLUMN
-
           && pLeft->y.pTab!=0
+
           && ALWAYS(pLeft->y.pTab!=0)
           && IsVirtual(pLeft->y.pTab))
       || (pRight->op==TK_COLUMN
-
           && pRight->y.pTab!=0
+
           && ALWAYS(pRight->y.pTab!=0)
           && IsVirtual(pRight->y.pTab))
      ){
        return WRC_Prune;
@@ -109702,6 +111172,7 @@ static int exprRefToSrcList(Walker *pWalker, Expr *pExpr){
SQLITE_PRIVATE int sqlite3ReferencesSrcList(Parse *pParse, Expr *pExpr, SrcList *pSrcList){
  Walker w;
  struct RefSrcList x;
+
  assert( pParse->db!=0 );
  memset(&w, 0, sizeof(w));
  memset(&x, 0, sizeof(x));
  w.xExprCallback = exprRefToSrcList;
@@ -109718,7 +111189,7 @@ SQLITE_PRIVATE int sqlite3ReferencesSrcList(Parse *pParse, Expr *pExpr, SrcList
    sqlite3WalkExpr(&w, pExpr->y.pWin->pFilter);
  }
#endif
-
  sqlite3DbFree(pParse->db, x.aiExclude);
+
  if( x.aiExclude ) sqlite3DbNNFreeNN(pParse->db, x.aiExclude);
  if( w.eCode & 0x01 ){
    return 1;
  }else if( w.eCode ){
@@ -109749,8 +111220,8 @@ static int agginfoPersistExprCb(Walker *pWalker, Expr *pExpr){
    int iAgg = pExpr->iAgg;
    Parse *pParse = pWalker->pParse;
    sqlite3 *db = pParse->db;
-
    assert( pExpr->op==TK_AGG_COLUMN || pExpr->op==TK_AGG_FUNCTION );
-
    if( pExpr->op==TK_AGG_COLUMN ){
+
    if( pExpr->op!=TK_AGG_FUNCTION ){
+
      assert( pExpr->op==TK_AGG_COLUMN || pExpr->op==TK_IF_NULL_ROW );
      assert( iAgg>=0 && iAgg<pAggInfo->nColumn );
      if( pAggInfo->aCol[iAgg].pCExpr==pExpr ){
        pExpr = sqlite3ExprDup(db, pExpr, 0);
@@ -109760,6 +111231,7 @@ static int agginfoPersistExprCb(Walker *pWalker, Expr *pExpr){
        }
      }
    }else{
+
      assert( pExpr->op==TK_AGG_FUNCTION );
      assert( iAgg>=0 && iAgg<pAggInfo->nFunc );
      if( pAggInfo->aFunc[iAgg].pFExpr==pExpr ){
        pExpr = sqlite3ExprDup(db, pExpr, 0);
@@ -109830,10 +111302,12 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){

  assert( pNC->ncFlags & NC_UAggInfo );
  switch( pExpr->op ){
+
    case TK_IF_NULL_ROW:
    case TK_AGG_COLUMN:
    case TK_COLUMN: {
      testcase( pExpr->op==TK_AGG_COLUMN );
      testcase( pExpr->op==TK_COLUMN );
+
      testcase( pExpr->op==TK_IF_NULL_ROW );
      /* Check to see if the column is in one of the tables in the FROM
      ** clause of the aggregate query */
      if( ALWAYS(pSrcList!=0) ){
@@ -109851,8 +111325,10 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
            int k;
            pCol = pAggInfo->aCol;
            for(k=0; k<pAggInfo->nColumn; k++, pCol++){
-
              if( pCol->iTable==pExpr->iTable &&
-
                  pCol->iColumn==pExpr->iColumn ){
+
              if( pCol->iTable==pExpr->iTable
+
               && pCol->iColumn==pExpr->iColumn
+
               && pExpr->op!=TK_IF_NULL_ROW
+
              ){
                break;
              }
            }
@@ -109867,15 +111343,17 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
              pCol->iMem = ++pParse->nMem;
              pCol->iSorterColumn = -1;
              pCol->pCExpr = pExpr;
-
              if( pAggInfo->pGroupBy ){
+
              if( pAggInfo->pGroupBy && pExpr->op!=TK_IF_NULL_ROW ){
                int j, n;
                ExprList *pGB = pAggInfo->pGroupBy;
                struct ExprList_item *pTerm = pGB->a;
                n = pGB->nExpr;
                for(j=0; j<n; j++, pTerm++){
                  Expr *pE = pTerm->pExpr;
-
                  if( pE->op==TK_COLUMN && pE->iTable==pExpr->iTable &&
-
                      pE->iColumn==pExpr->iColumn ){
+
                  if( pE->op==TK_COLUMN
+
                   && pE->iTable==pExpr->iTable
+
                   && pE->iColumn==pExpr->iColumn
+
                  ){
                    pCol->iSorterColumn = j;
                    break;
                  }
@@ -109892,7 +111370,9 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
            */
            ExprSetVVAProperty(pExpr, EP_NoReduce);
            pExpr->pAggInfo = pAggInfo;
-
            pExpr->op = TK_AGG_COLUMN;
+
            if( pExpr->op==TK_COLUMN ){
+
              pExpr->op = TK_AGG_COLUMN;
+
            }
            pExpr->iAgg = (i16)k;
            break;
          } /* endif pExpr->iTable==pItem->iCursor */
@@ -113312,6 +114792,7 @@ static void analyzeVdbeCommentIndexWithColumnName(
  if( NEVER(i==XN_ROWID) ){
    VdbeComment((v,"%s.rowid",pIdx->zName));
  }else if( i==XN_EXPR ){
+
    assert( pIdx->bHasExpr );
    VdbeComment((v,"%s.expr(%d)",pIdx->zName, k));
  }else{
    VdbeComment((v,"%s.%s", pIdx->zName, pIdx->pTable->aCol[i].zCnName));
@@ -115314,6 +116795,7 @@ SQLITE_PRIVATE int sqlite3DbMaskAllZero(yDbMask m){
SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
  sqlite3 *db;
  Vdbe *v;
+
  int iDb, i;

  assert( pParse->pToplevel==0 );
  db = pParse->db;
@@ -115343,7 +116825,6 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
    if( pParse->bReturning ){
      Returning *pReturning = pParse->u1.pReturning;
      int addrRewind;
-
      int i;
      int reg;

      if( pReturning->nRetCol ){
@@ -115380,76 +116861,69 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
    ** transaction on each used database and to verify the schema cookie
    ** on each used database.
    */
-
    if( db->mallocFailed==0
-
     && (DbMaskNonZero(pParse->cookieMask) || pParse->pConstExpr)
-
    ){
-
      int iDb, i;
-
      assert( sqlite3VdbeGetOp(v, 0)->opcode==OP_Init );
-
      sqlite3VdbeJumpHere(v, 0);
-
      assert( db->nDb>0 );
-
      iDb = 0;
-
      do{
-
        Schema *pSchema;
-
        if( DbMaskTest(pParse->cookieMask, iDb)==0 ) continue;
-
        sqlite3VdbeUsesBtree(v, iDb);
-
        pSchema = db->aDb[iDb].pSchema;
-
        sqlite3VdbeAddOp4Int(v,
-
          OP_Transaction,                    /* Opcode */
-
          iDb,                               /* P1 */
-
          DbMaskTest(pParse->writeMask,iDb), /* P2 */
-
          pSchema->schema_cookie,            /* P3 */
-
          pSchema->iGeneration               /* P4 */
-
        );
-
        if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1);
-
        VdbeComment((v,
-
              "usesStmtJournal=%d", pParse->mayAbort && pParse->isMultiWrite));
-
      }while( ++iDb<db->nDb );
+
    assert( pParse->nErr>0 || sqlite3VdbeGetOp(v, 0)->opcode==OP_Init );
+
    sqlite3VdbeJumpHere(v, 0);
+
    assert( db->nDb>0 );
+
    iDb = 0;
+
    do{
+
      Schema *pSchema;
+
      if( DbMaskTest(pParse->cookieMask, iDb)==0 ) continue;
+
      sqlite3VdbeUsesBtree(v, iDb);
+
      pSchema = db->aDb[iDb].pSchema;
+
      sqlite3VdbeAddOp4Int(v,
+
        OP_Transaction,                    /* Opcode */
+
        iDb,                               /* P1 */
+
        DbMaskTest(pParse->writeMask,iDb), /* P2 */
+
        pSchema->schema_cookie,            /* P3 */
+
        pSchema->iGeneration               /* P4 */
+
      );
+
      if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1);
+
      VdbeComment((v,
+
            "usesStmtJournal=%d", pParse->mayAbort && pParse->isMultiWrite));
+
    }while( ++iDb<db->nDb );
#ifndef SQLITE_OMIT_VIRTUALTABLE
-
      for(i=0; i<pParse->nVtabLock; i++){
-
        char *vtab = (char *)sqlite3GetVTable(db, pParse->apVtabLock[i]);
-
        sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB);
-
      }
-
      pParse->nVtabLock = 0;
+
    for(i=0; i<pParse->nVtabLock; i++){
+
      char *vtab = (char *)sqlite3GetVTable(db, pParse->apVtabLock[i]);
+
      sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB);
+
    }
+
    pParse->nVtabLock = 0;
#endif

-
      /* Once all the cookies have been verified and transactions opened,
-
      ** obtain the required table-locks. This is a no-op unless the
-
      ** shared-cache feature is enabled.
-
      */
-
      codeTableLocks(pParse);
+
    /* Once all the cookies have been verified and transactions opened,
+
    ** obtain the required table-locks. This is a no-op unless the
+
    ** shared-cache feature is enabled.
+
    */
+
    codeTableLocks(pParse);

-
      /* Initialize any AUTOINCREMENT data structures required.
-
      */
-
      sqlite3AutoincrementBegin(pParse);
+
    /* Initialize any AUTOINCREMENT data structures required.
+
    */
+
    sqlite3AutoincrementBegin(pParse);

-
      /* Code constant expressions that where factored out of inner loops.
-
      **
-
      ** The pConstExpr list might also contain expressions that we simply
-
      ** want to keep around until the Parse object is deleted.  Such
-
      ** expressions have iConstExprReg==0.  Do not generate code for
-
      ** those expressions, of course.
-
      */
-
      if( pParse->pConstExpr ){
-
        ExprList *pEL = pParse->pConstExpr;
-
        pParse->okConstFactor = 0;
-
        for(i=0; i<pEL->nExpr; i++){
-
          int iReg = pEL->a[i].u.iConstExprReg;
-
          if( iReg>0 ){
-
            sqlite3ExprCode(pParse, pEL->a[i].pExpr, iReg);
-
          }
-
        }
+
    /* Code constant expressions that where factored out of inner loops.
+
    **
+
    ** The pConstExpr list might also contain expressions that we simply
+
    ** want to keep around until the Parse object is deleted.  Such
+
    ** expressions have iConstExprReg==0.  Do not generate code for
+
    ** those expressions, of course.
+
    */
+
    if( pParse->pConstExpr ){
+
      ExprList *pEL = pParse->pConstExpr;
+
      pParse->okConstFactor = 0;
+
      for(i=0; i<pEL->nExpr; i++){
+
        int iReg = pEL->a[i].u.iConstExprReg;
+
        sqlite3ExprCode(pParse, pEL->a[i].pExpr, iReg);
      }
+
    }

-
      if( pParse->bReturning ){
-
        Returning *pRet = pParse->u1.pReturning;
-
        if( pRet->nRetCol ){
-
          sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRet->iRetCur, pRet->nRetCol);
-
        }
+
    if( pParse->bReturning ){
+
      Returning *pRet = pParse->u1.pReturning;
+
      if( pRet->nRetCol ){
+
        sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRet->iRetCur, pRet->nRetCol);
      }
-

-
      /* Finally, jump back to the beginning of the executable code. */
-
      sqlite3VdbeGoto(v, 1);
    }
+

+
    /* Finally, jump back to the beginning of the executable code. */
+
    sqlite3VdbeGoto(v, 1);
  }

  /* Get the VDBE program ready for execution
@@ -115634,7 +117108,7 @@ SQLITE_PRIVATE Table *sqlite3LocateTable(
    /* If zName is the not the name of a table in the schema created using
    ** CREATE, then check to see if it is the name of an virtual table that
    ** can be an eponymous virtual table. */
-
    if( pParse->disableVtab==0 && db->init.busy==0 ){
+
    if( (pParse->prepFlags & SQLITE_PREPARE_NO_VTAB)==0 && db->init.busy==0 ){
      Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName);
      if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
        pMod = sqlite3PragmaVtabRegister(db, zName);
@@ -115647,7 +117121,7 @@ SQLITE_PRIVATE Table *sqlite3LocateTable(
#endif
    if( flags & LOCATE_NOERR ) return 0;
    pParse->checkSchema = 1;
-
  }else if( IsVirtual(p) && pParse->disableVtab ){
+
  }else if( IsVirtual(p) && (pParse->prepFlags & SQLITE_PREPARE_NO_VTAB)!=0 ){
    p = 0;
  }

@@ -115956,16 +117430,17 @@ SQLITE_PRIVATE void sqlite3DeleteColumnNames(sqlite3 *db, Table *pTable){
  int i;
  Column *pCol;
  assert( pTable!=0 );
+
  assert( db!=0 );
  if( (pCol = pTable->aCol)!=0 ){
    for(i=0; i<pTable->nCol; i++, pCol++){
      assert( pCol->zCnName==0 || pCol->hName==sqlite3StrIHash(pCol->zCnName) );
      sqlite3DbFree(db, pCol->zCnName);
    }
-
    sqlite3DbFree(db, pTable->aCol);
+
    sqlite3DbNNFreeNN(db, pTable->aCol);
    if( IsOrdinaryTable(pTable) ){
      sqlite3ExprListDelete(db, pTable->u.tab.pDfltList);
    }
-
    if( db==0 || db->pnBytesFreed==0 ){
+
    if( db->pnBytesFreed==0 ){
      pTable->aCol = 0;
      pTable->nCol = 0;
      if( IsOrdinaryTable(pTable) ){
@@ -116002,7 +117477,8 @@ static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){
  ** a Table object that was going to be marked ephemeral. So do not check
  ** that no lookaside memory is used in this case either. */
  int nLookaside = 0;
-
  if( db && !db->mallocFailed && (pTable->tabFlags & TF_Ephemeral)==0 ){
+
  assert( db!=0 );
+
  if( !db->mallocFailed && (pTable->tabFlags & TF_Ephemeral)==0 ){
    nLookaside = sqlite3LookasideUsed(db, 0);
  }
#endif
@@ -116012,7 +117488,7 @@ static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){
    pNext = pIndex->pNext;
    assert( pIndex->pSchema==pTable->pSchema
         || (IsVirtual(pTable) && pIndex->idxType!=SQLITE_IDXTYPE_APPDEF) );
-
    if( (db==0 || db->pnBytesFreed==0) && !IsVirtual(pTable) ){
+
    if( db->pnBytesFreed==0 && !IsVirtual(pTable) ){
      char *zName = pIndex->zName;
      TESTONLY ( Index *pOld = ) sqlite3HashInsert(
         &pIndex->pSchema->idxHash, zName, 0
@@ -116049,8 +117525,9 @@ static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){
}
SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
  /* Do not delete the table until the reference count reaches zero. */
+
  assert( db!=0 );
  if( !pTable ) return;
-
  if( ((!db || db->pnBytesFreed==0) && (--pTable->nTabRef)>0) ) return;
+
  if( db->pnBytesFreed==0 && (--pTable->nTabRef)>0 ) return;
  deleteTable(db, pTable);
}

@@ -117454,7 +118931,8 @@ static int isDupColumn(Index *pIdx, int nKey, Index *pPk, int iCol){
/* Recompute the colNotIdxed field of the Index.
**
** colNotIdxed is a bitmask that has a 0 bit representing each indexed
-
** columns that are within the first 63 columns of the table.  The
+
** columns that are within the first 63 columns of the table and a 1 for
+
** all other bits (all columns that are not in the index).  The
** high-order bit of colNotIdxed is always 1.  All unindexed columns
** of the table have a 1.
**
@@ -117482,7 +118960,7 @@ static void recomputeColumnsNotIndexed(Index *pIdx){
    }
  }
  pIdx->colNotIdxed = ~m;
-
  assert( (pIdx->colNotIdxed>>63)==1 );
+
  assert( (pIdx->colNotIdxed>>63)==1 );  /* See note-20221022-a */
}

/*
@@ -118223,7 +119701,7 @@ create_view_fail:
** the columns of the view in the pTable structure.  Return the number
** of errors.  If an error is seen leave an error message in pParse->zErrMsg.
*/
-
SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
+
static SQLITE_NOINLINE int viewGetColumnNames(Parse *pParse, Table *pTable){
  Table *pSelTab;   /* A fake table from which we get the result set */
  Select *pSel;     /* Copy of the SELECT that implements the view */
  int nErr = 0;     /* Number of errors encountered */
@@ -118248,9 +119726,10 @@ SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){

#ifndef SQLITE_OMIT_VIEW
  /* A positive nCol means the columns names for this view are
-
  ** already known.
+
  ** already known.  This routine is not called unless either the
+
  ** table is virtual or nCol is zero.
  */
-
  if( pTable->nCol>0 ) return 0;
+
  assert( pTable->nCol<=0 );

  /* A negative nCol is a special marker meaning that we are currently
  ** trying to compute the column names.  If we enter this routine with
@@ -118346,6 +119825,11 @@ SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
#endif /* SQLITE_OMIT_VIEW */
  return nErr;
}
+
SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
+
  assert( pTable!=0 );
+
  if( !IsVirtual(pTable) && pTable->nCol>0 ) return 0;
+
  return viewGetColumnNames(pParse, pTable);
+
}
#endif /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */

#ifndef SQLITE_OMIT_VIEW
@@ -119211,7 +120695,7 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
    }
    if( !IN_RENAME_OBJECT ){
      if( !db->init.busy ){
-
        if( sqlite3FindTable(db, zName, 0)!=0 ){
+
        if( sqlite3FindTable(db, zName, pDb->zDbSName)!=0 ){
          sqlite3ErrorMsg(pParse, "there is already a table named %s", zName);
          goto exit_create_index;
        }
@@ -119364,6 +120848,7 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
      j = XN_EXPR;
      pIndex->aiColumn[i] = XN_EXPR;
      pIndex->uniqNotNull = 0;
+
      pIndex->bHasExpr = 1;
    }else{
      j = pCExpr->iColumn;
      assert( j<=0x7fff );
@@ -119375,6 +120860,7 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
        }
        if( pTab->aCol[j].colFlags & COLFLAG_VIRTUAL ){
          pIndex->bHasVCol = 1;
+
          pIndex->bHasExpr = 1;
        }
      }
      pIndex->aiColumn[i] = (i16)j;
@@ -119864,12 +121350,13 @@ SQLITE_PRIVATE IdList *sqlite3IdListAppend(Parse *pParse, IdList *pList, Token *
*/
SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3 *db, IdList *pList){
  int i;
+
  assert( db!=0 );
  if( pList==0 ) return;
  assert( pList->eU4!=EU4_EXPR ); /* EU4_EXPR mode is not currently used */
  for(i=0; i<pList->nId; i++){
    sqlite3DbFree(db, pList->a[i].zName);
  }
-
  sqlite3DbFreeNN(db, pList);
+
  sqlite3DbNNFreeNN(db, pList);
}

/*
@@ -120072,11 +121559,12 @@ SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){
SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
  int i;
  SrcItem *pItem;
+
  assert( db!=0 );
  if( pList==0 ) return;
  for(pItem=pList->a, i=0; i<pList->nSrc; i++, pItem++){
-
    if( pItem->zDatabase ) sqlite3DbFreeNN(db, pItem->zDatabase);
-
    sqlite3DbFree(db, pItem->zName);
-
    if( pItem->zAlias ) sqlite3DbFreeNN(db, pItem->zAlias);
+
    if( pItem->zDatabase ) sqlite3DbNNFreeNN(db, pItem->zDatabase);
+
    if( pItem->zName ) sqlite3DbNNFreeNN(db, pItem->zName);
+
    if( pItem->zAlias ) sqlite3DbNNFreeNN(db, pItem->zAlias);
    if( pItem->fg.isIndexedBy ) sqlite3DbFree(db, pItem->u1.zIndexedBy);
    if( pItem->fg.isTabFunc ) sqlite3ExprListDelete(db, pItem->u1.pFuncArg);
    sqlite3DeleteTable(db, pItem->pTab);
@@ -120087,7 +121575,7 @@ SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
      sqlite3ExprDelete(db, pItem->u3.pOn);
    }
  }
-
  sqlite3DbFreeNN(db, pList);
+
  sqlite3DbNNFreeNN(db, pList);
}

/*
@@ -121339,19 +122827,21 @@ SQLITE_PRIVATE void sqlite3SchemaClear(void *p){
  Hash temp2;
  HashElem *pElem;
  Schema *pSchema = (Schema *)p;
+
  sqlite3 xdb;

+
  memset(&xdb, 0, sizeof(xdb));
  temp1 = pSchema->tblHash;
  temp2 = pSchema->trigHash;
  sqlite3HashInit(&pSchema->trigHash);
  sqlite3HashClear(&pSchema->idxHash);
  for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
-
    sqlite3DeleteTrigger(0, (Trigger*)sqliteHashData(pElem));
+
    sqlite3DeleteTrigger(&xdb, (Trigger*)sqliteHashData(pElem));
  }
  sqlite3HashClear(&temp2);
  sqlite3HashInit(&pSchema->tblHash);
  for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){
    Table *pTab = sqliteHashData(pElem);
-
    sqlite3DeleteTable(0, pTab);
+
    sqlite3DeleteTable(&xdb, pTab);
  }
  sqlite3HashClear(&temp1);
  sqlite3HashClear(&pSchema->fkeyHash);
@@ -121450,18 +122940,42 @@ SQLITE_PRIVATE void sqlite3CodeChangeCount(Vdbe *v, int regCounter, const char *
**   1) It is a virtual table and no implementation of the xUpdate method
**      has been provided
**
-
**   2) It is a system table (i.e. sqlite_schema), this call is not
+
**   2) A trigger is currently being coded and the table is a virtual table
+
**      that is SQLITE_VTAB_DIRECTONLY or if PRAGMA trusted_schema=OFF and
+
**      the table is not SQLITE_VTAB_INNOCUOUS.
+
**
+
**   3) It is a system table (i.e. sqlite_schema), this call is not
**      part of a nested parse and writable_schema pragma has not
**      been specified
**
-
**   3) The table is a shadow table, the database connection is in
+
**   4) The table is a shadow table, the database connection is in
**      defensive mode, and the current sqlite3_prepare()
**      is for a top-level SQL statement.
*/
+
static int vtabIsReadOnly(Parse *pParse, Table *pTab){
+
  if( sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0 ){
+
    return 1;
+
  }
+

+
  /* Within triggers:
+
  **   *  Do not allow DELETE, INSERT, or UPDATE of SQLITE_VTAB_DIRECTONLY
+
  **      virtual tables
+
  **   *  Only allow DELETE, INSERT, or UPDATE of non-SQLITE_VTAB_INNOCUOUS
+
  **      virtual tables if PRAGMA trusted_schema=ON.
+
  */
+
  if( pParse->pToplevel!=0
+
   && pTab->u.vtab.p->eVtabRisk >
+
           ((pParse->db->flags & SQLITE_TrustedSchema)!=0)
+
  ){
+
    sqlite3ErrorMsg(pParse, "unsafe use of virtual table \"%s\"",
+
      pTab->zName);
+
  }
+
  return 0;
+
}
static int tabIsReadOnly(Parse *pParse, Table *pTab){
  sqlite3 *db;
  if( IsVirtual(pTab) ){
-
    return sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0;
+
    return vtabIsReadOnly(pParse, pTab);
  }
  if( (pTab->tabFlags & (TF_Readonly|TF_Shadow))==0 ) return 0;
  db = pParse->db;
@@ -121473,9 +122987,11 @@ static int tabIsReadOnly(Parse *pParse, Table *pTab){
}

/*
-
** Check to make sure the given table is writable.  If it is not
-
** writable, generate an error message and return 1.  If it is
-
** writable return 0;
+
** Check to make sure the given table is writable.
+
**
+
** If pTab is not writable  ->  generate an error message and return 1.
+
** If pTab is writable but other errors have occurred -> return 1.
+
** If pTab is writable and no prior errors -> return 0;
*/
SQLITE_PRIVATE int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
  if( tabIsReadOnly(pParse, pTab) ){
@@ -121836,9 +123352,10 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
    }
    for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
      assert( pIdx->pSchema==pTab->pSchema );
-
      sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
      if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
-
        sqlite3VdbeChangeP3(v, -1, memCnt ? memCnt : -1);
+
        sqlite3VdbeAddOp3(v, OP_Clear, pIdx->tnum, iDb, memCnt ? memCnt : -1);
+
      }else{
+
        sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
      }
    }
  }else
@@ -122038,7 +123555,7 @@ delete_from_cleanup:
  sqlite3ExprListDelete(db, pOrderBy);
  sqlite3ExprDelete(db, pLimit);
#endif
-
  sqlite3DbFree(db, aToOpen);
+
  if( aToOpen ) sqlite3DbNNFreeNN(db, aToOpen);
  return;
}
/* Make sure "isView" and other macros defined above are undefined. Otherwise
@@ -123121,7 +124638,7 @@ static int patternCompare(
      ** c but in the other case and search the input string for either
      ** c or cx.
      */
-
      if( c<=0x80 ){
+
      if( c<0x80 ){
        char zStop[3];
        int bMatch;
        if( noCase ){
@@ -123204,7 +124721,13 @@ static int patternCompare(
** non-zero if there is no match.
*/
SQLITE_API int sqlite3_strglob(const char *zGlobPattern, const char *zString){
-
  return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, '[');
+
  if( zString==0 ){
+
    return zGlobPattern!=0;
+
  }else if( zGlobPattern==0 ){
+
    return 1;
+
  }else {
+
    return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, '[');
+
  }
}

/*
@@ -123212,7 +124735,13 @@ SQLITE_API int sqlite3_strglob(const char *zGlobPattern, const char *zString){
** a miss - like strcmp().
*/
SQLITE_API int sqlite3_strlike(const char *zPattern, const char *zStr, unsigned int esc){
-
  return patternCompare((u8*)zPattern, (u8*)zStr, &likeInfoNorm, esc);
+
  if( zStr==0 ){
+
    return zPattern!=0;
+
  }else if( zPattern==0 ){
+
    return 1;
+
  }else{
+
    return patternCompare((u8*)zPattern, (u8*)zStr, &likeInfoNorm, esc);
+
  }
}

/*
@@ -126206,11 +127735,12 @@ SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *db, Table *pTab){
  FKey *pNext;                    /* Copy of pFKey->pNextFrom */

  assert( IsOrdinaryTable(pTab) );
+
  assert( db!=0 );
  for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pNext){
    assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pTab->pSchema) );

    /* Remove the FK from the fkeyHash hash table. */
-
    if( !db || db->pnBytesFreed==0 ){
+
    if( db->pnBytesFreed==0 ){
      if( pFKey->pPrevTo ){
        pFKey->pPrevTo->pNextTo = pFKey->pNextTo;
      }else{
@@ -126340,6 +127870,7 @@ SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(sqlite3 *db, Index *pIdx){
        aff = SQLITE_AFF_INTEGER;
      }else{
        assert( x==XN_EXPR );
+
        assert( pIdx->bHasExpr );
        assert( pIdx->aColExpr!=0 );
        aff = sqlite3ExprAffinity(pIdx->aColExpr->a[n].pExpr);
      }
@@ -126354,6 +127885,28 @@ SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(sqlite3 *db, Index *pIdx){
}

/*
+
** Compute an affinity string for a table.   Space is obtained
+
** from sqlite3DbMalloc().  The caller is responsible for freeing
+
** the space when done.
+
*/
+
SQLITE_PRIVATE char *sqlite3TableAffinityStr(sqlite3 *db, const Table *pTab){
+
  char *zColAff;
+
  zColAff = (char *)sqlite3DbMallocRaw(db, pTab->nCol+1);
+
  if( zColAff ){
+
    int i, j;
+
    for(i=j=0; i<pTab->nCol; i++){
+
      if( (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ){
+
        zColAff[j++] = pTab->aCol[i].affinity;
+
      }
+
    }
+
    do{
+
      zColAff[j--] = 0;
+
    }while( j>=0 && zColAff[j]<=SQLITE_AFF_BLOB );
+
  }
+
  return zColAff;
+
}
+

+
/*
** Make changes to the evolving bytecode to do affinity transformations
** of values that are about to be gathered into a row for table pTab.
**
@@ -126394,7 +127947,7 @@ SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(sqlite3 *db, Index *pIdx){
** Apply the type checking to that array of registers.
*/
SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){
-
  int i, j;
+
  int i;
  char *zColAff;
  if( pTab->tabFlags & TF_Strict ){
    if( iReg==0 ){
@@ -126403,7 +127956,7 @@ SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){
      ** OP_MakeRecord is found */
      VdbeOp *pPrev;
      sqlite3VdbeAppendP4(v, pTab, P4_TABLE);
-
      pPrev = sqlite3VdbeGetOp(v, -1);
+
      pPrev = sqlite3VdbeGetLastOp(v);
      assert( pPrev!=0 );
      assert( pPrev->opcode==OP_MakeRecord || sqlite3VdbeDb(v)->mallocFailed );
      pPrev->opcode = OP_TypeCheck;
@@ -126417,22 +127970,11 @@ SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){
  }
  zColAff = pTab->zColAff;
  if( zColAff==0 ){
-
    sqlite3 *db = sqlite3VdbeDb(v);
-
    zColAff = (char *)sqlite3DbMallocRaw(0, pTab->nCol+1);
+
    zColAff = sqlite3TableAffinityStr(0, pTab);
    if( !zColAff ){
-
      sqlite3OomFault(db);
+
      sqlite3OomFault(sqlite3VdbeDb(v));
      return;
    }
-

-
    for(i=j=0; i<pTab->nCol; i++){
-
      assert( pTab->aCol[i].affinity!=0 || sqlite3VdbeParser(v)->nErr>0 );
-
      if( (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ){
-
        zColAff[j++] = pTab->aCol[i].affinity;
-
      }
-
    }
-
    do{
-
      zColAff[j--] = 0;
-
    }while( j>=0 && zColAff[j]<=SQLITE_AFF_BLOB );
    pTab->zColAff = zColAff;
  }
  assert( zColAff!=0 );
@@ -126441,7 +127983,7 @@ SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){
    if( iReg ){
      sqlite3VdbeAddOp4(v, OP_Affinity, iReg, i, 0, zColAff, i);
    }else{
-
      assert( sqlite3VdbeGetOp(v, -1)->opcode==OP_MakeRecord
+
      assert( sqlite3VdbeGetLastOp(v)->opcode==OP_MakeRecord
              || sqlite3VdbeDb(v)->mallocFailed );
      sqlite3VdbeChangeP4(v, -1, zColAff, i);
    }
@@ -126527,7 +128069,7 @@ SQLITE_PRIVATE void sqlite3ComputeGeneratedColumns(
  */
  sqlite3TableAffinity(pParse->pVdbe, pTab, iRegStore);
  if( (pTab->tabFlags & TF_HasStored)!=0 ){
-
    pOp = sqlite3VdbeGetOp(pParse->pVdbe,-1);
+
    pOp = sqlite3VdbeGetLastOp(pParse->pVdbe);
    if( pOp->opcode==OP_Affinity ){
      /* Change the OP_Affinity argument to '@' (NONE) for all stored
      ** columns.  '@' is the no-op affinity and those columns have not
@@ -127433,7 +128975,12 @@ SQLITE_PRIVATE void sqlite3Insert(
        sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+k, iRegStore);
      }
    }else{
-
      sqlite3ExprCode(pParse, pList->a[k].pExpr, iRegStore);
+
      Expr *pX = pList->a[k].pExpr;
+
      int y = sqlite3ExprCodeTarget(pParse, pX, iRegStore);
+
      if( y!=iRegStore ){
+
        sqlite3VdbeAddOp2(v,
+
          ExprHasProperty(pX, EP_Subquery) ? OP_Copy : OP_SCopy, y, iRegStore);
+
      }
    }
  }

@@ -127570,7 +129117,9 @@ SQLITE_PRIVATE void sqlite3Insert(
      sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur,
          regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace, 0, pUpsert
      );
-
      sqlite3FkCheck(pParse, pTab, 0, regIns, 0, 0);
+
      if( db->flags & SQLITE_ForeignKeys ){
+
        sqlite3FkCheck(pParse, pTab, 0, regIns, 0, 0);
+
      }

      /* Set the OPFLAG_USESEEKRESULT flag if either (a) there are no REPLACE
      ** constraints or (b) there are no triggers and this table is not a
@@ -127654,7 +129203,7 @@ insert_cleanup:
  sqlite3UpsertDelete(db, pUpsert);
  sqlite3SelectDelete(db, pSelect);
  sqlite3IdListDelete(db, pColumn);
-
  sqlite3DbFree(db, aRegIdx);
+
  if( aRegIdx ) sqlite3DbNNFreeNN(db, aRegIdx);
}

/* Make sure "isView" and other macros defined above are undefined. Otherwise
@@ -129881,9 +131430,9 @@ struct sqlite3_api_routines {
  const char *(*filename_journal)(const char*);
  const char *(*filename_wal)(const char*);
  /* Version 3.32.0 and later */
-
  char *(*create_filename)(const char*,const char*,const char*,
+
  const char *(*create_filename)(const char*,const char*,const char*,
                           int,const char**);
-
  void (*free_filename)(char*);
+
  void (*free_filename)(const char*);
  sqlite3_file *(*database_file_object)(const char*);
  /* Version 3.34.0 and later */
  int (*txn_state)(sqlite3*,const char*);
@@ -129907,6 +131456,8 @@ struct sqlite3_api_routines {
  unsigned char *(*serialize)(sqlite3*,const char *,sqlite3_int64*,
                              unsigned int);
  const char *(*db_name)(sqlite3*,int);
+
  /* Version 3.40.0 and later */
+
  int (*value_encoding)(sqlite3_value*);
};

/*
@@ -130231,6 +131782,8 @@ typedef int (*sqlite3_loadext_entry)(
#define sqlite3_serialize              sqlite3_api->serialize
#endif
#define sqlite3_db_name                sqlite3_api->db_name
+
/* Version 3.40.0 and later */
+
#define sqlite3_value_encoding         sqlite3_api->value_encoding
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */

#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
@@ -130743,7 +132296,9 @@ static const sqlite3_api_routines sqlite3Apis = {
  0,
  0,
#endif
-
  sqlite3_db_name
+
  sqlite3_db_name,
+
  /* Version 3.40.0 and later */
+
  sqlite3_value_type
};

/* True if x is the directory separator character
@@ -133543,15 +135098,24 @@ SQLITE_PRIVATE void sqlite3Pragma(
      for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
        Table *pTab = sqliteHashData(x);
        Index *pIdx, *pPk;
-
        Index *pPrior = 0;
+
        Index *pPrior = 0;      /* Previous index */
        int loopTop;
        int iDataCur, iIdxCur;
        int r1 = -1;
-
        int bStrict;
+
        int bStrict;            /* True for a STRICT table */
+
        int r2;                 /* Previous key for WITHOUT ROWID tables */
+
        int mxCol;              /* Maximum non-virtual column number */

        if( !IsOrdinaryTable(pTab) ) continue;
        if( pObjTab && pObjTab!=pTab ) continue;
-
        pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
+
        if( isQuick || HasRowid(pTab) ){
+
          pPk = 0;
+
          r2 = 0;
+
        }else{
+
          pPk = sqlite3PrimaryKeyIndex(pTab);
+
          r2 = sqlite3GetTempRange(pParse, pPk->nKeyCol);
+
          sqlite3VdbeAddOp3(v, OP_Null, 1, r2, r2+pPk->nKeyCol-1);
+
        }
        sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0,
                                   1, 0, &iDataCur, &iIdxCur);
        /* reg[7] counts the number of entries in the table.
@@ -133565,52 +135129,157 @@ SQLITE_PRIVATE void sqlite3Pragma(
        assert( sqlite3NoTempsInRange(pParse,1,7+j) );
        sqlite3VdbeAddOp2(v, OP_Rewind, iDataCur, 0); VdbeCoverage(v);
        loopTop = sqlite3VdbeAddOp2(v, OP_AddImm, 7, 1);
+

+
        /* Fetch the right-most column from the table.  This will cause
+
        ** the entire record header to be parsed and sanity checked.  It
+
        ** will also prepopulate the cursor column cache that is used
+
        ** by the OP_IsType code, so it is a required step.
+
        */
+
        mxCol = pTab->nCol-1;
+
        while( mxCol>=0
+
            && ((pTab->aCol[mxCol].colFlags & COLFLAG_VIRTUAL)!=0
+
                || pTab->iPKey==mxCol) ) mxCol--;
+
        if( mxCol>=0 ){
+
          sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, mxCol, 3);
+
          sqlite3VdbeTypeofColumn(v, 3);
+
        }
+

        if( !isQuick ){
-
          /* Sanity check on record header decoding */
-
          sqlite3VdbeAddOp3(v, OP_Column, iDataCur, pTab->nNVCol-1,3);
-
          sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
-
          VdbeComment((v, "(right-most column)"));
+
          if( pPk ){
+
            /* Verify WITHOUT ROWID keys are in ascending order */
+
            int a1;
+
            char *zErr;
+
            a1 = sqlite3VdbeAddOp4Int(v, OP_IdxGT, iDataCur, 0,r2,pPk->nKeyCol);
+
            VdbeCoverage(v);
+
            sqlite3VdbeAddOp1(v, OP_IsNull, r2); VdbeCoverage(v);
+
            zErr = sqlite3MPrintf(db,
+
                   "row not in PRIMARY KEY order for %s",
+
                    pTab->zName);
+
            sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
+
            integrityCheckResultRow(v);
+
            sqlite3VdbeJumpHere(v, a1);
+
            sqlite3VdbeJumpHere(v, a1+1);
+
            for(j=0; j<pPk->nKeyCol; j++){
+
              sqlite3ExprCodeLoadIndexColumn(pParse, pPk, iDataCur, j, r2+j);
+
            }
+
          }
        }
-
        /* Verify that all NOT NULL columns really are NOT NULL.  At the
-
        ** same time verify the type of the content of STRICT tables */
+
        /* Verify datatypes for all columns:
+
        **
+
        **   (1) NOT NULL columns may not contain a NULL
+
        **   (2) Datatype must be exact for non-ANY columns in STRICT tables
+
        **   (3) Datatype for TEXT columns in non-STRICT tables must be
+
        **       NULL, TEXT, or BLOB.
+
        **   (4) Datatype for numeric columns in non-STRICT tables must not
+
        **       be a TEXT value that can be losslessly converted to numeric.
+
        */
        bStrict = (pTab->tabFlags & TF_Strict)!=0;
        for(j=0; j<pTab->nCol; j++){
          char *zErr;
-
          Column *pCol = pTab->aCol + j;
-
          int doError, jmp2;
+
          Column *pCol = pTab->aCol + j;  /* The column to be checked */
+
          int labelError;               /* Jump here to report an error */
+
          int labelOk;                  /* Jump here if all looks ok */
+
          int p1, p3, p4;               /* Operands to the OP_IsType opcode */
+
          int doTypeCheck;              /* Check datatypes (besides NOT NULL) */
+

          if( j==pTab->iPKey ) continue;
-
          if( pCol->notNull==0 && !bStrict ) continue;
-
          doError = bStrict ? sqlite3VdbeMakeLabel(pParse) : 0;
-
          sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3);
-
          if( sqlite3VdbeGetOp(v,-1)->opcode==OP_Column ){
-
            sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
+
          if( bStrict ){
+
            doTypeCheck = pCol->eCType>COLTYPE_ANY;
+
          }else{
+
            doTypeCheck = pCol->affinity>SQLITE_AFF_BLOB;
          }
+
          if( pCol->notNull==0 && !doTypeCheck ) continue;
+

+
          /* Compute the operands that will be needed for OP_IsType */
+
          p4 = SQLITE_NULL;
+
          if( pCol->colFlags & COLFLAG_VIRTUAL ){
+
            sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3);
+
            p1 = -1;
+
            p3 = 3;
+
          }else{
+
            if( pCol->iDflt ){
+
              sqlite3_value *pDfltValue = 0;
+
              sqlite3ValueFromExpr(db, sqlite3ColumnExpr(pTab,pCol), ENC(db),
+
                                   pCol->affinity, &pDfltValue);
+
              if( pDfltValue ){
+
                p4 = sqlite3_value_type(pDfltValue);
+
                sqlite3ValueFree(pDfltValue);
+
              }
+
            }
+
            p1 = iDataCur;
+
            if( !HasRowid(pTab) ){
+
              testcase( j!=sqlite3TableColumnToStorage(pTab, j) );
+
              p3 = sqlite3TableColumnToIndex(sqlite3PrimaryKeyIndex(pTab), j);
+
            }else{
+
              p3 = sqlite3TableColumnToStorage(pTab,j);
+
              testcase( p3!=j);
+
            }
+
          }
+

+
          labelError = sqlite3VdbeMakeLabel(pParse);
+
          labelOk = sqlite3VdbeMakeLabel(pParse);
          if( pCol->notNull ){
-
            jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v);
+
            /* (1) NOT NULL columns may not contain a NULL */
+
            int jmp2 = sqlite3VdbeAddOp4Int(v, OP_IsType, p1, labelOk, p3, p4);
+
            sqlite3VdbeChangeP5(v, 0x0f);
+
            VdbeCoverage(v);
            zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
                                pCol->zCnName);
            sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
-
            if( bStrict && pCol->eCType!=COLTYPE_ANY ){
-
              sqlite3VdbeGoto(v, doError);
+
            if( doTypeCheck ){
+
              sqlite3VdbeGoto(v, labelError);
+
              sqlite3VdbeJumpHere(v, jmp2);
            }else{
-
              integrityCheckResultRow(v);
+
              /* VDBE byte code will fall thru */
            }
-
            sqlite3VdbeJumpHere(v, jmp2);
          }
-
          if( (pTab->tabFlags & TF_Strict)!=0
-
           && pCol->eCType!=COLTYPE_ANY
-
          ){
-
            jmp2 = sqlite3VdbeAddOp3(v, OP_IsNullOrType, 3, 0,
-
                                     sqlite3StdTypeMap[pCol->eCType-1]);
+
          if( bStrict && doTypeCheck ){
+
            /* (2) Datatype must be exact for non-ANY columns in STRICT tables*/
+
            static unsigned char aStdTypeMask[] = {
+
               0x1f,    /* ANY */
+
               0x18,    /* BLOB */
+
               0x11,    /* INT */
+
               0x11,    /* INTEGER */
+
               0x13,    /* REAL */
+
               0x14     /* TEXT */
+
            };
+
            sqlite3VdbeAddOp4Int(v, OP_IsType, p1, labelOk, p3, p4);
+
            assert( pCol->eCType>=1 && pCol->eCType<=sizeof(aStdTypeMask) );
+
            sqlite3VdbeChangeP5(v, aStdTypeMask[pCol->eCType-1]);
            VdbeCoverage(v);
            zErr = sqlite3MPrintf(db, "non-%s value in %s.%s",
                                  sqlite3StdType[pCol->eCType-1],
                                  pTab->zName, pTab->aCol[j].zCnName);
            sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
-
            sqlite3VdbeResolveLabel(v, doError);
-
            integrityCheckResultRow(v);
-
            sqlite3VdbeJumpHere(v, jmp2);
+
          }else if( !bStrict && pCol->affinity==SQLITE_AFF_TEXT ){
+
            /* (3) Datatype for TEXT columns in non-STRICT tables must be
+
            **     NULL, TEXT, or BLOB. */
+
            sqlite3VdbeAddOp4Int(v, OP_IsType, p1, labelOk, p3, p4);
+
            sqlite3VdbeChangeP5(v, 0x1c); /* NULL, TEXT, or BLOB */
+
            VdbeCoverage(v);
+
            zErr = sqlite3MPrintf(db, "NUMERIC value in %s.%s",
+
                                  pTab->zName, pTab->aCol[j].zCnName);
+
            sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
+
          }else if( !bStrict && pCol->affinity>=SQLITE_AFF_NUMERIC ){
+
            /* (4) Datatype for numeric columns in non-STRICT tables must not
+
            **     be a TEXT value that can be converted to numeric. */
+
            sqlite3VdbeAddOp4Int(v, OP_IsType, p1, labelOk, p3, p4);
+
            sqlite3VdbeChangeP5(v, 0x1b); /* NULL, INT, FLOAT, or BLOB */
+
            VdbeCoverage(v);
+
            if( p1>=0 ){
+
              sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3);
+
            }
+
            sqlite3VdbeAddOp4(v, OP_Affinity, 3, 1, 0, "C", P4_STATIC);
+
            sqlite3VdbeAddOp4Int(v, OP_IsType, -1, labelOk, 3, p4);
+
            sqlite3VdbeChangeP5(v, 0x1c); /* NULL, TEXT, or BLOB */
+
            VdbeCoverage(v);
+
            zErr = sqlite3MPrintf(db, "TEXT value in %s.%s",
+
                                  pTab->zName, pTab->aCol[j].zCnName);
+
            sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
          }
+
          sqlite3VdbeResolveLabel(v, labelError);
+
          integrityCheckResultRow(v);
+
          sqlite3VdbeResolveLabel(v, labelOk);
        }
        /* Verify CHECK constraints */
        if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
@@ -133698,6 +135367,9 @@ SQLITE_PRIVATE void sqlite3Pragma(
            integrityCheckResultRow(v);
            sqlite3VdbeJumpHere(v, addr);
          }
+
          if( pPk ){
+
            sqlite3ReleaseTempRange(pParse, r2, pPk->nKeyCol);
+
          }
        }
      }
    }
@@ -133848,6 +135520,11 @@ SQLITE_PRIVATE void sqlite3Pragma(
      aOp[1].p2 = iCookie;
      aOp[1].p3 = sqlite3Atoi(zRight);
      aOp[1].p5 = 1;
+
      if( iCookie==BTREE_SCHEMA_VERSION && (db->flags & SQLITE_Defensive)!=0 ){
+
        /* Do not allow the use of PRAGMA schema_version=VALUE in defensive
+
        ** mode.  Change the OP_SetCookie opcode into a no-op.  */
+
        aOp[1].opcode = OP_Noop;
+
      }
    }else{
      /* Read the specified cookie value */
      static const VdbeOpList readCookie[] = {
@@ -135096,15 +136773,15 @@ SQLITE_PRIVATE void sqlite3ParseObjectReset(Parse *pParse){
  assert( db->pParse==pParse );
  assert( pParse->nested==0 );
#ifndef SQLITE_OMIT_SHARED_CACHE
-
  sqlite3DbFree(db, pParse->aTableLock);
+
  if( pParse->aTableLock ) sqlite3DbNNFreeNN(db, pParse->aTableLock);
#endif
  while( pParse->pCleanup ){
    ParseCleanup *pCleanup = pParse->pCleanup;
    pParse->pCleanup = pCleanup->pNext;
    pCleanup->xCleanup(db, pCleanup->pPtr);
-
    sqlite3DbFreeNN(db, pCleanup);
+
    sqlite3DbNNFreeNN(db, pCleanup);
  }
-
  sqlite3DbFree(db, pParse->aLabel);
+
  if( pParse->aLabel ) sqlite3DbNNFreeNN(db, pParse->aLabel);
  if( pParse->pConstExpr ){
    sqlite3ExprListDelete(db, pParse->pConstExpr);
  }
@@ -135227,7 +136904,7 @@ static int sqlite3Prepare(
    sParse.disableLookaside++;
    DisableLookaside;
  }
-
  sParse.disableVtab = (prepFlags & SQLITE_PREPARE_NO_VTAB)!=0;
+
  sParse.prepFlags = prepFlags & 0xff;

  /* Check to verify that it is possible to get a read lock on all
  ** database schemas.  The inability to get a read lock indicates that
@@ -135268,7 +136945,9 @@ static int sqlite3Prepare(
    }
  }

-
  sqlite3VtabUnlockList(db);
+
#ifndef SQLITE_OMIT_VIRTUALTABLE
+
  if( db->pDisconnect ) sqlite3VtabUnlockList(db);
+
#endif

  if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){
    char *zSqlCopy;
@@ -135663,6 +137342,7 @@ struct SortCtx {
** If bFree==0, Leave the first Select object unfreed
*/
static void clearSelect(sqlite3 *db, Select *p, int bFree){
+
  assert( db!=0 );
  while( p ){
    Select *pPrior = p->pPrior;
    sqlite3ExprListDelete(db, p->pEList);
@@ -135682,7 +137362,7 @@ static void clearSelect(sqlite3 *db, Select *p, int bFree){
      sqlite3WindowUnlinkFromSelect(p->pWin);
    }
#endif
-
    if( bFree ) sqlite3DbFreeNN(db, p);
+
    if( bFree ) sqlite3DbNNFreeNN(db, p);
    p = pPrior;
    bFree = 1;
  }
@@ -136873,6 +138553,9 @@ static void selectInnerLoop(
      testcase( eDest==SRT_Fifo );
      testcase( eDest==SRT_DistFifo );
      sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1+nPrefixReg);
+
      if( pDest->zAffSdst ){
+
        sqlite3VdbeChangeP4(v, -1, pDest->zAffSdst, nResultCol);
+
      }
#ifndef SQLITE_OMIT_CTE
      if( eDest==SRT_DistFifo ){
        /* If the destination is DistFifo, then cursor (iParm+1) is open
@@ -137088,9 +138771,10 @@ SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){
*/
SQLITE_PRIVATE void sqlite3KeyInfoUnref(KeyInfo *p){
  if( p ){
+
    assert( p->db!=0 );
    assert( p->nRef>0 );
    p->nRef--;
-
    if( p->nRef==0 ) sqlite3DbFreeNN(p->db, p);
+
    if( p->nRef==0 ) sqlite3DbNNFreeNN(p->db, p);
  }
}

@@ -137410,9 +139094,6 @@ static void generateSortTail(
** Return a pointer to a string containing the 'declaration type' of the
** expression pExpr. The string may be treated as static by the caller.
**
-
** Also try to estimate the size of the returned value and return that
-
** result in *pEstWidth.
-
**
** The declaration type is the exact datatype definition extracted from the
** original CREATE TABLE statement if the expression is a column. The
** declaration type for a ROWID field is INTEGER. Exactly when an expression
@@ -139278,8 +140959,8 @@ static int multiSelectOrderBy(
  */
  sqlite3VdbeResolveLabel(v, labelEnd);

-
  /* Reassemble the compound query so that it will be freed correctly
-
  ** by the calling function */
+
  /* Make arrangements to free the 2nd and subsequent arms of the compound
+
  ** after the parse has finished */
  if( pSplit->pPrior ){
    sqlite3ParserAddCleanup(pParse,
       (void(*)(sqlite3*,void*))sqlite3SelectDelete, pSplit->pPrior);
@@ -139312,7 +140993,7 @@ static int multiSelectOrderBy(
** the left operands of a RIGHT JOIN.  In either case, we need to potentially
** bypass the substituted expression with OP_IfNullRow.
**
-
** Suppose the original expression integer constant.  Even though the table
+
** Suppose the original expression is an integer constant. Even though the table
** has the nullRow flag set, because the expression is an integer constant,
** it will not be NULLed out.  So instead, we insert an OP_IfNullRow opcode
** that checks to see if the nullRow flag is set on the table.  If the nullRow
@@ -139338,6 +141019,7 @@ typedef struct SubstContext {
  int iNewTable;            /* New table number */
  int isOuterJoin;          /* Add TK_IF_NULL_ROW opcodes on each replacement */
  ExprList *pEList;         /* Replacement expressions */
+
  ExprList *pCList;         /* Collation sequences for replacement expr */
} SubstContext;

/* Forward Declarations */
@@ -139379,9 +141061,10 @@ static Expr *substExpr(
#endif
    {
      Expr *pNew;
-
      Expr *pCopy = pSubst->pEList->a[pExpr->iColumn].pExpr;
+
      int iColumn = pExpr->iColumn;
+
      Expr *pCopy = pSubst->pEList->a[iColumn].pExpr;
      Expr ifNullRow;
-
      assert( pSubst->pEList!=0 && pExpr->iColumn<pSubst->pEList->nExpr );
+
      assert( pSubst->pEList!=0 && iColumn<pSubst->pEList->nExpr );
      assert( pExpr->pRight==0 );
      if( sqlite3ExprIsVector(pCopy) ){
        sqlite3VectorErrorMsg(pSubst->pParse, pCopy);
@@ -139392,6 +141075,7 @@ static Expr *substExpr(
          ifNullRow.op = TK_IF_NULL_ROW;
          ifNullRow.pLeft = pCopy;
          ifNullRow.iTable = pSubst->iNewTable;
+
          ifNullRow.iColumn = -99;
          ifNullRow.flags = EP_IfNullRow;
          pCopy = &ifNullRow;
        }
@@ -139418,11 +141102,16 @@ static Expr *substExpr(

        /* Ensure that the expression now has an implicit collation sequence,
        ** just as it did when it was a column of a view or sub-query. */
-
        if( pExpr->op!=TK_COLUMN && pExpr->op!=TK_COLLATE ){
-
          CollSeq *pColl = sqlite3ExprCollSeq(pSubst->pParse, pExpr);
-
          pExpr = sqlite3ExprAddCollateString(pSubst->pParse, pExpr,
-
              (pColl ? pColl->zName : "BINARY")
+
        {
+
          CollSeq *pNat = sqlite3ExprCollSeq(pSubst->pParse, pExpr);
+
          CollSeq *pColl = sqlite3ExprCollSeq(pSubst->pParse,
+
                pSubst->pCList->a[iColumn].pExpr
          );
+
          if( pNat!=pColl || (pExpr->op!=TK_COLUMN && pExpr->op!=TK_COLLATE) ){
+
            pExpr = sqlite3ExprAddCollateString(pSubst->pParse, pExpr,
+
                (pColl ? pColl->zName : "BINARY")
+
            );
+
          }
        }
        ExprClearProperty(pExpr, EP_Collate);
      }
@@ -139615,6 +141304,18 @@ static void renumberCursors(
}
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */

+
/*
+
** If pSel is not part of a compound SELECT, return a pointer to its
+
** expression list. Otherwise, return a pointer to the expression list
+
** of the leftmost SELECT in the compound.
+
*/
+
static ExprList *findLeftmostExprlist(Select *pSel){
+
  while( pSel->pPrior ){
+
    pSel = pSel->pPrior;
+
  }
+
  return pSel->pEList;
+
}
+

#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
/*
** This routine attempts to flatten subqueries as a performance optimization.
@@ -139659,7 +141360,8 @@ static void renumberCursors(
**        (3a) the subquery may not be a join and
**        (3b) the FROM clause of the subquery may not contain a virtual
**             table and
-
**        (3c) the outer query may not be an aggregate.
+
**        (**) Was: "The outer query may not have a GROUP BY." This case
+
**             is now managed correctly
**        (3d) the outer query may not be DISTINCT.
**        See also (26) for restrictions on RIGHT JOIN.
**
@@ -139716,6 +141418,8 @@ static void renumberCursors(
**        (17g) either the subquery is the first element of the outer
**              query or there are no RIGHT or FULL JOINs in any arm
**              of the subquery.  (This is a duplicate of condition (27b).)
+
**        (17h) The corresponding result set expressions in all arms of the
+
**              compound must have the same affinity.
**
**        The parent and sub-query may contain WHERE clauses. Subject to
**        rules (11), (13) and (14), they may also contain ORDER BY,
@@ -139767,19 +141471,13 @@ static void renumberCursors(
**        See also (3) for restrictions on LEFT JOIN.
**
**  (27)  The subquery may not contain a FULL or RIGHT JOIN unless it
-
**        is the first element of the parent query.  This must be the
-
**        the case if:
-
**        (27a) the subquery is not compound query, and
+
**        is the first element of the parent query.  Two subcases:
+
**        (27a) the subquery is not a compound query.
**        (27b) the subquery is a compound query and the RIGHT JOIN occurs
**              in any arm of the compound query.  (See also (17g).)
**
**  (28)  The subquery is not a MATERIALIZED CTE.
**
-
**  (29)  Either the subquery is not the right-hand operand of a join with an
-
**        ON or USING clause nor the right-hand operand of a NATURAL JOIN, or
-
**        the right-most table within the FROM clause of the subquery
-
**        is not part of an outer join.
-
**
**
** In this routine, the "p" parameter is a pointer to the outer query.
** The subquery is p->pSrc->a[iFrom].  isAgg is true if the outer query
@@ -139871,16 +141569,10 @@ static int flattenSubquery(
  **
  ** which is not at all the same thing.
  **
-
  ** If the subquery is the right operand of a LEFT JOIN, then the outer
-
  ** query cannot be an aggregate. (3c)  This is an artifact of the way
-
  ** aggregates are processed - there is no mechanism to determine if
-
  ** the LEFT JOIN table should be all-NULL.
-
  **
  ** See also tickets #306, #350, and #3300.
  */
  if( (pSubitem->fg.jointype & (JT_OUTER|JT_LTORJ))!=0 ){
    if( pSubSrc->nSrc>1                        /* (3a) */
-
     || isAgg                                  /* (3c) */
     || IsVirtual(pSubSrc->a[0].pTab)          /* (3b) */
     || (p->selFlags & SF_Distinct)!=0         /* (3d) */
     || (pSubitem->fg.jointype & JT_RIGHT)!=0  /* (26) */
@@ -139889,15 +141581,6 @@ static int flattenSubquery(
    }
    isOuterJoin = 1;
  }
-
#ifdef SQLITE_EXTRA_IFNULLROW
-
  else if( iFrom>0 && !isAgg ){
-
    /* Setting isOuterJoin to -1 causes OP_IfNullRow opcodes to be generated for
-
    ** every reference to any result column from subquery in a join, even
-
    ** though they are not necessary.  This will stress-test the OP_IfNullRow
-
    ** opcode. */
-
    isOuterJoin = -1;
-
  }
-
#endif

  assert( pSubSrc->nSrc>0 );  /* True by restriction (7) */
  if( iFrom>0 && (pSubSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){
@@ -139907,41 +141590,13 @@ static int flattenSubquery(
    return 0;       /* (28) */
  }

-
  /* Restriction (29):
-
  **
-
  ** We do not want two constraints on the same term of the flattened
-
  ** query where one constraint has EP_InnerON and the other is EP_OuterON.
-
  ** To prevent this, one or the other of the following conditions must be
-
  ** false:
-
  **
-
  **   (29a)  The right-most entry in the FROM clause of the subquery
-
  **          must not be part of an outer join.
-
  **
-
  **   (29b)  The subquery itself must not be the right operand of a
-
  **          NATURAL join or a join that as an ON or USING clause.
-
  **
-
  ** These conditions are sufficient to keep an EP_OuterON from being
-
  ** flattened into an EP_InnerON.  Restrictions (3a) and (27a) prevent
-
  ** an EP_InnerON from being flattened into an EP_OuterON.
-
  */
-
  if( pSubSrc->nSrc>=2
-
   && (pSubSrc->a[pSubSrc->nSrc-1].fg.jointype & JT_OUTER)!=0
-
  ){
-
    if( (pSubitem->fg.jointype & JT_NATURAL)!=0
-
     || pSubitem->fg.isUsing
-
     || NEVER(pSubitem->u3.pOn!=0) /* ON clause already shifted into WHERE */
-
     || pSubitem->fg.isOn
-
    ){
-
      return 0;
-
    }
-
  }
-

  /* Restriction (17): If the sub-query is a compound SELECT, then it must
  ** use only the UNION ALL operator. And none of the simple select queries
  ** that make up the compound SELECT are allowed to be aggregate or distinct
  ** queries.
  */
  if( pSub->pPrior ){
+
    int ii;
    if( pSub->pOrderBy ){
      return 0;  /* Restriction (20) */
    }
@@ -139974,7 +141629,6 @@ static int flattenSubquery(

    /* Restriction (18). */
    if( p->pOrderBy ){
-
      int ii;
      for(ii=0; ii<p->pOrderBy->nExpr; ii++){
        if( p->pOrderBy->a[ii].u.x.iOrderByCol==0 ) return 0;
      }
@@ -139983,6 +141637,21 @@ static int flattenSubquery(
    /* Restriction (23) */
    if( (p->selFlags & SF_Recursive) ) return 0;

+
    /* Restriction (17h) */
+
    for(ii=0; ii<pSub->pEList->nExpr; ii++){
+
      char aff;
+
      assert( pSub->pEList->a[ii].pExpr!=0 );
+
      aff = sqlite3ExprAffinity(pSub->pEList->a[ii].pExpr);
+
      for(pSub1=pSub->pPrior; pSub1; pSub1=pSub1->pPrior){
+
        assert( pSub1->pEList!=0 );
+
        assert( pSub1->pEList->nExpr>ii );
+
        assert( pSub1->pEList->a[ii].pExpr!=0 );
+
        if( sqlite3ExprAffinity(pSub1->pEList->a[ii].pExpr)!=aff ){
+
          return 0;
+
        }
+
      }
+
    }
+

    if( pSrc->nSrc>1 ){
      if( pParse->nSelect>500 ) return 0;
      if( OptimizationDisabled(db, SQLITE_FlttnUnionAll) ) return 0;
@@ -140216,6 +141885,7 @@ static int flattenSubquery(
      x.iNewTable = iNewParent;
      x.isOuterJoin = isOuterJoin;
      x.pEList = pSub->pEList;
+
      x.pCList = findLeftmostExprlist(pSub);
      substSelect(&x, pParent, 0);
    }

@@ -140235,7 +141905,7 @@ static int flattenSubquery(
      pSub->pLimit = 0;
    }

-
    /* Recompute the SrcList_item.colUsed masks for the flattened
+
    /* Recompute the SrcItem.colUsed masks for the flattened
    ** tables. */
    for(i=0; i<nSubSrc; i++){
      recomputeColumnsUsed(pParent, &pSrc->a[i+iFrom]);
@@ -140625,6 +142295,13 @@ static int pushDownWindowCheck(Parse *pParse, Select *pSubq, Expr *pExpr){
**       be materialized.  (This restriction is implemented in the calling
**       routine.)
**
+
**   (8) The subquery may not be a compound that uses UNION, INTERSECT,
+
**       or EXCEPT.  (We could, perhaps, relax this restriction to allow
+
**       this case if none of the comparisons operators between left and
+
**       right arms of the compound use a collation other than BINARY.
+
**       But it is a lot of work to check that case for an obscure and
+
**       minor optimization, so we omit it for now.)
+
**
** Return 0 if no changes are made and non-zero if one or more WHERE clause
** terms are duplicated into the subquery.
*/
@@ -140644,6 +142321,10 @@ static int pushDownWhereTerms(
  if( pSubq->pPrior ){
    Select *pSel;
    for(pSel=pSubq; pSel; pSel=pSel->pPrior){
+
      u8 op = pSel->op;
+
      assert( op==TK_ALL || op==TK_SELECT
+
           || op==TK_UNION || op==TK_INTERSECT || op==TK_EXCEPT );
+
      if( op!=TK_ALL && op!=TK_SELECT ) return 0;  /* restriction (8) */
      if( pSel->pWin ) return 0;    /* restriction (6b) */
    }
  }else{
@@ -140698,6 +142379,7 @@ static int pushDownWhereTerms(
      x.iNewTable = pSrc->iCursor;
      x.isOuterJoin = 0;
      x.pEList = pSubq->pEList;
+
      x.pCList = findLeftmostExprlist(pSubq);
      pNew = substExpr(&x, pNew);
#ifndef SQLITE_OMIT_WINDOWFUNC
      if( pSubq->pWin && 0==pushDownWindowCheck(pParse, pSubq, pNew) ){
@@ -141222,9 +142904,9 @@ SQLITE_PRIVATE void sqlite3SelectPopWith(Walker *pWalker, Select *p){
#endif

/*
-
** The SrcList_item structure passed as the second argument represents a
+
** The SrcItem structure passed as the second argument represents a
** sub-query in the FROM clause of a SELECT statement. This function
-
** allocates and populates the SrcList_item.pTab object. If successful,
+
** allocates and populates the SrcItem.pTab object. If successful,
** SQLITE_OK is returned. Otherwise, if an OOM error is encountered,
** SQLITE_NOMEM.
*/
@@ -142057,7 +143739,7 @@ static void havingToWhere(Parse *pParse, Select *p){

/*
** Check to see if the pThis entry of pTabList is a self-join of a prior view.
-
** If it is, then return the SrcList_item for the prior view.  If it is not,
+
** If it is, then return the SrcItem for the prior view.  If it is not,
** then return 0.
*/
static SrcItem *isSelfJoinView(
@@ -142675,7 +144357,10 @@ SQLITE_PRIVATE int sqlite3Select(
      }
      sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
      ExplainQueryPlan((pParse, 1, "MATERIALIZE %!S", pItem));
+
      dest.zAffSdst = sqlite3TableAffinityStr(db, pItem->pTab);
      sqlite3Select(pParse, pSub, &dest);
+
      sqlite3DbFree(db, dest.zAffSdst);
+
      dest.zAffSdst = 0;
      pItem->pTab->nRowLogEst = pSub->nSelectRow;
      if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
      sqlite3VdbeAddOp2(v, OP_Return, pItem->regReturn, topAddr+1);
@@ -142795,7 +144480,7 @@ SQLITE_PRIVATE int sqlite3Select(
  if( (p->selFlags & SF_FixedLimit)==0 ){
    p->nSelectRow = 320;  /* 4 billion rows */
  }
-
  computeLimitRegisters(pParse, p, iEnd);
+
  if( p->pLimit ) computeLimitRegisters(pParse, p, iEnd);
  if( p->iLimit==0 && sSort.addrSortIndex>=0 ){
    sqlite3VdbeChangeOpcode(v, sSort.addrSortIndex, OP_SorterOpen);
    sSort.sortFlags |= SORTFLAG_UseSorter;
@@ -143017,8 +144702,13 @@ SQLITE_PRIVATE int sqlite3Select(
        sqlite3TreeViewExprList(0, pMinMaxOrderBy, 0, "ORDERBY");
      }
      for(ii=0; ii<pAggInfo->nColumn; ii++){
-
        sqlite3DebugPrintf("agg-column[%d] iMem=%d\n",
-
            ii, pAggInfo->aCol[ii].iMem);
+
        struct AggInfo_col *pCol = &pAggInfo->aCol[ii];
+
        sqlite3DebugPrintf(
+
           "agg-column[%d] pTab=%s iTable=%d iColumn=%d iMem=%d"
+
           " iSorterColumn=%d\n",
+
           ii, pCol->pTab ? pCol->pTab->zName : "NULL",
+
           pCol->iTable, pCol->iColumn, pCol->iMem,
+
           pCol->iSorterColumn);
        sqlite3TreeViewExpr(0, pAggInfo->aCol[ii].pCExpr, 0);
      }
      for(ii=0; ii<pAggInfo->nFunc; ii++){
@@ -143096,7 +144786,7 @@ SQLITE_PRIVATE int sqlite3Select(
      sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
      SELECTTRACE(1,pParse,p,("WhereBegin\n"));
      pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, pDistinct,
-
          0, (sDistinct.isTnct==2 ? WHERE_DISTINCTBY : WHERE_GROUPBY)
+
          p, (sDistinct.isTnct==2 ? WHERE_DISTINCTBY : WHERE_GROUPBY)
          |  (orderByGrp ? WHERE_SORTBYGROUP : 0) | distFlag, 0
      );
      if( pWInfo==0 ){
@@ -143139,15 +144829,15 @@ SQLITE_PRIVATE int sqlite3Select(
        regBase = sqlite3GetTempRange(pParse, nCol);
        sqlite3ExprCodeExprList(pParse, pGroupBy, regBase, 0, 0);
        j = nGroupBy;
+
        pAggInfo->directMode = 1;
        for(i=0; i<pAggInfo->nColumn; i++){
          struct AggInfo_col *pCol = &pAggInfo->aCol[i];
          if( pCol->iSorterColumn>=j ){
-
            int r1 = j + regBase;
-
            sqlite3ExprCodeGetColumnOfTable(v,
-
                               pCol->pTab, pCol->iTable, pCol->iColumn, r1);
+
            sqlite3ExprCode(pParse, pCol->pCExpr, j + regBase);
            j++;
          }
        }
+
        pAggInfo->directMode = 0;
        regRecord = sqlite3GetTempReg(pParse);
        sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regRecord);
        sqlite3VdbeAddOp2(v, OP_SorterInsert, pAggInfo->sortingIdx, regRecord);
@@ -143395,7 +145085,7 @@ SQLITE_PRIVATE int sqlite3Select(

        SELECTTRACE(1,pParse,p,("WhereBegin\n"));
        pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMaxOrderBy,
-
                                   pDistinct, 0, minMaxFlag|distFlag, 0);
+
                                   pDistinct, p, minMaxFlag|distFlag, 0);
        if( pWInfo==0 ){
          goto select_end;
        }
@@ -144039,6 +145729,23 @@ SQLITE_PRIVATE void sqlite3FinishTrigger(
    Vdbe *v;
    char *z;

+
    /* If this is a new CREATE TABLE statement, and if shadow tables
+
    ** are read-only, and the trigger makes a change to a shadow table,
+
    ** then raise an error - do not allow the trigger to be created. */
+
    if( sqlite3ReadOnlyShadowTables(db) ){
+
      TriggerStep *pStep;
+
      for(pStep=pTrig->step_list; pStep; pStep=pStep->pNext){
+
        if( pStep->zTarget!=0
+
         && sqlite3ShadowTableName(db, pStep->zTarget)
+
        ){
+
          sqlite3ErrorMsg(pParse,
+
            "trigger \"%s\" may not write to shadow table \"%s\"",
+
            pTrig->zName, pStep->zTarget);
+
          goto triggerfinish_cleanup;
+
        }
+
      }
+
    }
+

    /* Make an entry in the sqlite_schema table */
    v = sqlite3GetVdbe(pParse);
    if( v==0 ) goto triggerfinish_cleanup;
@@ -144862,7 +146569,7 @@ static TriggerPrg *codeRowTrigger(
  sSubParse.zAuthContext = pTrigger->zName;
  sSubParse.eTriggerOp = pTrigger->op;
  sSubParse.nQueryLoop = pParse->nQueryLoop;
-
  sSubParse.disableVtab = pParse->disableVtab;
+
  sSubParse.prepFlags = pParse->prepFlags;

  v = sqlite3GetVdbe(&sSubParse);
  if( v ){
@@ -145208,11 +146915,14 @@ static void updateVirtualTable(
** it has been converted into REAL.
*/
SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
+
  Column *pCol;
  assert( pTab!=0 );
-
  if( !IsView(pTab) ){
+
  assert( pTab->nCol>i );
+
  pCol = &pTab->aCol[i];
+
  if( pCol->iDflt ){
    sqlite3_value *pValue = 0;
    u8 enc = ENC(sqlite3VdbeDb(v));
-
    Column *pCol = &pTab->aCol[i];
+
    assert( !IsView(pTab) );
    VdbeComment((v, "%s.%s", pTab->zName, pCol->zCnName));
    assert( i<pTab->nCol );
    sqlite3ValueFromExpr(sqlite3VdbeDb(v),
@@ -145223,7 +146933,7 @@ SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
    }
  }
#ifndef SQLITE_OMIT_FLOATING_POINT
-
  if( pTab->aCol[i].affinity==SQLITE_AFF_REAL && !IsVirtual(pTab) ){
+
  if( pCol->affinity==SQLITE_AFF_REAL && !IsVirtual(pTab) ){
    sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg);
  }
#endif
@@ -146663,6 +148373,7 @@ SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget(
        if( pIdx->aiColumn[ii]==XN_EXPR ){
          assert( pIdx->aColExpr!=0 );
          assert( pIdx->aColExpr->nExpr>ii );
+
          assert( pIdx->bHasExpr );
          pExpr = pIdx->aColExpr->a[ii].pExpr;
          if( pExpr->op!=TK_COLLATE ){
            sCol[0].pLeft = pExpr;
@@ -146976,6 +148687,7 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3RunVacuum(
  int nDb;                /* Number of attached databases */
  const char *zDbMain;    /* Schema name of database to vacuum */
  const char *zOut;       /* Name of output file */
+
  u32 pgflags = PAGER_SYNCHRONOUS_OFF; /* sync flags for output db */

  if( !db->autoCommit ){
    sqlite3SetString(pzErrMsg, db, "cannot VACUUM from within a transaction");
@@ -147047,12 +148759,17 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3RunVacuum(
      goto end_of_vacuum;
    }
    db->mDbFlags |= DBFLAG_VacuumInto;
+

+
    /* For a VACUUM INTO, the pager-flags are set to the same values as
+
    ** they are for the database being vacuumed, except that PAGER_CACHESPILL
+
    ** is always set. */
+
    pgflags = db->aDb[iDb].safety_level | (db->flags & PAGER_FLAGS_MASK);
  }
  nRes = sqlite3BtreeGetRequestedReserve(pMain);

  sqlite3BtreeSetCacheSize(pTemp, db->aDb[iDb].pSchema->cache_size);
  sqlite3BtreeSetSpillSize(pTemp, sqlite3BtreeSetSpillSize(pMain,0));
-
  sqlite3BtreeSetPagerFlags(pTemp, PAGER_SYNCHRONOUS_OFF|PAGER_CACHESPILL);
+
  sqlite3BtreeSetPagerFlags(pTemp, pgflags|PAGER_CACHESPILL);

  /* Begin a transaction and take an exclusive lock on the main database
  ** file. This is done before the sqlite3BtreeGetPageSize(pMain) call below,
@@ -147565,7 +149282,8 @@ SQLITE_PRIVATE void sqlite3VtabUnlockList(sqlite3 *db){
*/
SQLITE_PRIVATE void sqlite3VtabClear(sqlite3 *db, Table *p){
  assert( IsVirtual(p) );
-
  if( !db || db->pnBytesFreed==0 ) vtabDisconnectAll(0, p);
+
  assert( db!=0 );
+
  if( db->pnBytesFreed==0 ) vtabDisconnectAll(0, p);
  if( p->u.vtab.azArg ){
    int i;
    for(i=0; i<p->u.vtab.nArg; i++){
@@ -148365,7 +150083,7 @@ SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(
  if( pExpr->op!=TK_COLUMN ) return pDef;
  assert( ExprUseYTab(pExpr) );
  pTab = pExpr->y.pTab;
-
  if( pTab==0 ) return pDef;
+
  if( NEVER(pTab==0) ) return pDef;
  if( !IsVirtual(pTab) ) return pDef;
  pVtab = sqlite3GetVTable(db, pTab)->pVtab;
  assert( pVtab!=0 );
@@ -148972,7 +150690,7 @@ struct WhereAndInfo {
** between VDBE cursor numbers and bits of the bitmasks in WhereTerm.
**
** The VDBE cursor numbers are small integers contained in
-
** SrcList_item.iCursor and Expr.iTable fields.  For any given WHERE
+
** SrcItem.iCursor and Expr.iTable fields.  For any given WHERE
** clause, the cursor numbers might not begin with 0 and they might
** contain gaps in the numbering sequence.  But we want to make maximum
** use of the bits in our bitmasks.  This structure provides a mapping
@@ -149044,20 +150762,6 @@ struct WhereLoopBuilder {
#endif

/*
-
** Each instance of this object records a change to a single node
-
** in an expression tree to cause that node to point to a column
-
** of an index rather than an expression or a virtual column.  All
-
** such transformations need to be undone at the end of WHERE clause
-
** processing.
-
*/
-
typedef struct WhereExprMod WhereExprMod;
-
struct WhereExprMod {
-
  WhereExprMod *pNext;  /* Next translation on a list of them all */
-
  Expr *pExpr;          /* The Expr node that was transformed */
-
  Expr orig;            /* Original value of the Expr node */
-
};
-

-
/*
** The WHERE clause processing routine has two halves.  The
** first part does the start of the WHERE loop and the second
** half does the tail of the WHERE loop.  An instance of
@@ -149072,10 +150776,10 @@ struct WhereInfo {
  SrcList *pTabList;        /* List of tables in the join */
  ExprList *pOrderBy;       /* The ORDER BY clause or NULL */
  ExprList *pResultSet;     /* Result set of the query */
+
#if WHERETRACE_ENABLED
  Expr *pWhere;             /* The complete WHERE clause */
-
#ifndef SQLITE_OMIT_VIRTUALTABLE
-
  Select *pLimit;           /* Used to access LIMIT expr/registers for vtabs */
#endif
+
  Select *pSelect;          /* The entire SELECT statement containing WHERE */
  int aiCurOnePass[2];      /* OP_OpenWrite cursors for the ONEPASS opt */
  int iContinue;            /* Jump here to continue with next record */
  int iBreak;               /* Jump here to break out of the loop */
@@ -149094,7 +150798,6 @@ struct WhereInfo {
  int iTop;                 /* The very beginning of the WHERE loop */
  int iEndWhere;            /* End of the WHERE clause itself */
  WhereLoop *pLoops;        /* List of all WhereLoop objects */
-
  WhereExprMod *pExprMods;  /* Expression modifications */
  WhereMemBlock *pMemToFree;/* Memory to free when this object destroyed */
  Bitmask revMask;          /* Mask of ORDER BY terms that need reversing */
  WhereClause sWC;          /* Decomposition of the WHERE clause */
@@ -149242,6 +150945,7 @@ SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(Parse*, SrcItem*, WhereClause*);
#define WHERE_BLOOMFILTER  0x00400000  /* Consider using a Bloom-filter */
#define WHERE_SELFCULL     0x00800000  /* nOut reduced by extra WHERE terms */
#define WHERE_OMIT_OFFSET  0x01000000  /* Set offset counter to zero */
+
#define WHERE_VIEWSCAN     0x02000000  /* A full-scan of a VIEW or subquery */

#endif /* !defined(SQLITE_WHEREINT_H) */

@@ -150121,7 +151825,7 @@ static void whereLikeOptimizationStringFixup(
  if( pTerm->wtFlags & TERM_LIKEOPT ){
    VdbeOp *pOp;
    assert( pLevel->iLikeRepCntr>0 );
-
    pOp = sqlite3VdbeGetOp(v, -1);
+
    pOp = sqlite3VdbeGetLastOp(v);
    assert( pOp!=0 );
    assert( pOp->opcode==OP_String8
            || pTerm->pWC->pWInfo->pParse->db->mallocFailed );
@@ -150445,143 +152149,6 @@ static void codeExprOrVector(Parse *pParse, Expr *p, int iReg, int nReg){
  }
}

-
/* An instance of the IdxExprTrans object carries information about a
-
** mapping from an expression on table columns into a column in an index
-
** down through the Walker.
-
*/
-
typedef struct IdxExprTrans {
-
  Expr *pIdxExpr;    /* The index expression */
-
  int iTabCur;       /* The cursor of the corresponding table */
-
  int iIdxCur;       /* The cursor for the index */
-
  int iIdxCol;       /* The column for the index */
-
  int iTabCol;       /* The column for the table */
-
  WhereInfo *pWInfo; /* Complete WHERE clause information */
-
  sqlite3 *db;       /* Database connection (for malloc()) */
-
} IdxExprTrans;
-

-
/*
-
** Preserve pExpr on the WhereETrans list of the WhereInfo.
-
*/
-
static void preserveExpr(IdxExprTrans *pTrans, Expr *pExpr){
-
  WhereExprMod *pNew;
-
  pNew = sqlite3DbMallocRaw(pTrans->db, sizeof(*pNew));
-
  if( pNew==0 ) return;
-
  pNew->pNext = pTrans->pWInfo->pExprMods;
-
  pTrans->pWInfo->pExprMods = pNew;
-
  pNew->pExpr = pExpr;
-
  memcpy(&pNew->orig, pExpr, sizeof(*pExpr));
-
}
-

-
/* The walker node callback used to transform matching expressions into
-
** a reference to an index column for an index on an expression.
-
**
-
** If pExpr matches, then transform it into a reference to the index column
-
** that contains the value of pExpr.
-
*/
-
static int whereIndexExprTransNode(Walker *p, Expr *pExpr){
-
  IdxExprTrans *pX = p->u.pIdxTrans;
-
  if( sqlite3ExprCompare(0, pExpr, pX->pIdxExpr, pX->iTabCur)==0 ){
-
    pExpr = sqlite3ExprSkipCollate(pExpr);
-
    preserveExpr(pX, pExpr);
-
    pExpr->affExpr = sqlite3ExprAffinity(pExpr);
-
    pExpr->op = TK_COLUMN;
-
    pExpr->iTable = pX->iIdxCur;
-
    pExpr->iColumn = pX->iIdxCol;
-
    testcase( ExprHasProperty(pExpr, EP_Unlikely) );
-
    ExprClearProperty(pExpr, EP_Skip|EP_Unlikely|EP_WinFunc|EP_Subrtn);
-
    pExpr->y.pTab = 0;
-
    return WRC_Prune;
-
  }else{
-
    return WRC_Continue;
-
  }
-
}
-

-
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
-
/* A walker node callback that translates a column reference to a table
-
** into a corresponding column reference of an index.
-
*/
-
static int whereIndexExprTransColumn(Walker *p, Expr *pExpr){
-
  if( pExpr->op==TK_COLUMN ){
-
    IdxExprTrans *pX = p->u.pIdxTrans;
-
    if( pExpr->iTable==pX->iTabCur && pExpr->iColumn==pX->iTabCol ){
-
      assert( ExprUseYTab(pExpr) && pExpr->y.pTab!=0 );
-
      preserveExpr(pX, pExpr);
-
      pExpr->affExpr = sqlite3TableColumnAffinity(pExpr->y.pTab,pExpr->iColumn);
-
      pExpr->iTable = pX->iIdxCur;
-
      pExpr->iColumn = pX->iIdxCol;
-
      pExpr->y.pTab = 0;
-
    }
-
  }
-
  return WRC_Continue;
-
}
-
#endif /* SQLITE_OMIT_GENERATED_COLUMNS */
-

-
/*
-
** For an indexes on expression X, locate every instance of expression X
-
** in pExpr and change that subexpression into a reference to the appropriate
-
** column of the index.
-
**
-
** 2019-10-24: Updated to also translate references to a VIRTUAL column in
-
** the table into references to the corresponding (stored) column of the
-
** index.
-
*/
-
static void whereIndexExprTrans(
-
  Index *pIdx,      /* The Index */
-
  int iTabCur,      /* Cursor of the table that is being indexed */
-
  int iIdxCur,      /* Cursor of the index itself */
-
  WhereInfo *pWInfo /* Transform expressions in this WHERE clause */
-
){
-
  int iIdxCol;               /* Column number of the index */
-
  ExprList *aColExpr;        /* Expressions that are indexed */
-
  Table *pTab;
-
  Walker w;
-
  IdxExprTrans x;
-
  aColExpr = pIdx->aColExpr;
-
  if( aColExpr==0 && !pIdx->bHasVCol ){
-
    /* The index does not reference any expressions or virtual columns
-
    ** so no translations are needed. */
-
    return;
-
  }
-
  pTab = pIdx->pTable;
-
  memset(&w, 0, sizeof(w));
-
  w.u.pIdxTrans = &x;
-
  x.iTabCur = iTabCur;
-
  x.iIdxCur = iIdxCur;
-
  x.pWInfo = pWInfo;
-
  x.db = pWInfo->pParse->db;
-
  for(iIdxCol=0; iIdxCol<pIdx->nColumn; iIdxCol++){
-
    i16 iRef = pIdx->aiColumn[iIdxCol];
-
    if( iRef==XN_EXPR ){
-
      assert( aColExpr!=0 && aColExpr->a[iIdxCol].pExpr!=0 );
-
      x.pIdxExpr = aColExpr->a[iIdxCol].pExpr;
-
      if( sqlite3ExprIsConstant(x.pIdxExpr) ) continue;
-
      w.xExprCallback = whereIndexExprTransNode;
-
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
-
    }else if( iRef>=0
-
       && (pTab->aCol[iRef].colFlags & COLFLAG_VIRTUAL)!=0
-
       && ((pTab->aCol[iRef].colFlags & COLFLAG_HASCOLL)==0
-
           || sqlite3StrICmp(sqlite3ColumnColl(&pTab->aCol[iRef]),
-
                                               sqlite3StrBINARY)==0)
-
    ){
-
      /* Check to see if there are direct references to generated columns
-
      ** that are contained in the index.  Pulling the generated column
-
      ** out of the index is an optimization only - the main table is always
-
      ** available if the index cannot be used.  To avoid unnecessary
-
      ** complication, omit this optimization if the collating sequence for
-
      ** the column is non-standard */
-
      x.iTabCol = iRef;
-
      w.xExprCallback = whereIndexExprTransColumn;
-
#endif /* SQLITE_OMIT_GENERATED_COLUMNS */
-
    }else{
-
      continue;
-
    }
-
    x.iIdxCol = iIdxCol;
-
    sqlite3WalkExpr(&w, pWInfo->pWhere);
-
    sqlite3WalkExprList(&w, pWInfo->pOrderBy);
-
    sqlite3WalkExprList(&w, pWInfo->pResultSet);
-
  }
-
}
-

/*
** The pTruth expression is always true because it is the WHERE clause
** a partial index that is driving a query loop.  Look through all of the
@@ -150650,6 +152217,8 @@ static SQLITE_NOINLINE void filterPullDown(
      testcase( pTerm->wtFlags & TERM_VIRTUAL );
      regRowid = sqlite3GetTempReg(pParse);
      regRowid = codeEqualityTerm(pParse, pTerm, pLevel, 0, 0, regRowid);
+
      sqlite3VdbeAddOp2(pParse->pVdbe, OP_MustBeInt, regRowid, addrNxt);
+
      VdbeCoverage(pParse->pVdbe);
      sqlite3VdbeAddOp4Int(pParse->pVdbe, OP_Filter, pLevel->regFilter,
                           addrNxt, regRowid, 1);
      VdbeCoverage(pParse->pVdbe);
@@ -150801,9 +152370,9 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
         && pLoop->u.vtab.bOmitOffset
        ){
          assert( pTerm->eOperator==WO_AUX );
-
          assert( pWInfo->pLimit!=0 );
-
          assert( pWInfo->pLimit->iOffset>0 );
-
          sqlite3VdbeAddOp2(v, OP_Integer, 0, pWInfo->pLimit->iOffset);
+
          assert( pWInfo->pSelect!=0 );
+
          assert( pWInfo->pSelect->iOffset>0 );
+
          sqlite3VdbeAddOp2(v, OP_Integer, 0, pWInfo->pSelect->iOffset);
          VdbeComment((v,"Zero OFFSET counter"));
        }
      }
@@ -150911,6 +152480,8 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
    if( iRowidReg!=iReleaseReg ) sqlite3ReleaseTempReg(pParse, iReleaseReg);
    addrNxt = pLevel->addrNxt;
    if( pLevel->regFilter ){
+
      sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt);
+
      VdbeCoverage(v);
      sqlite3VdbeAddOp4Int(v, OP_Filter, pLevel->regFilter, addrNxt,
                           iRowidReg, 1);
      VdbeCoverage(v);
@@ -151262,6 +152833,11 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
        ** guess. */
        addrSeekScan = sqlite3VdbeAddOp1(v, OP_SeekScan,
                                         (pIdx->aiRowLogEst[0]+9)/10);
+
        if( pRangeStart ){
+
          sqlite3VdbeChangeP5(v, 1);
+
          sqlite3VdbeChangeP2(v, addrSeekScan, sqlite3VdbeCurrentAddr(v)+1);
+
          addrSeekScan = 0;
+
        }
        VdbeCoverage(v);
      }
      sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
@@ -151337,8 +152913,8 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
      }
      nConstraint++;
    }
-
    sqlite3DbFree(db, zStartAff);
-
    sqlite3DbFree(db, zEndAff);
+
    if( zStartAff ) sqlite3DbNNFreeNN(db, zStartAff);
+
    if( zEndAff ) sqlite3DbNNFreeNN(db, zEndAff);

    /* Top of the loop body */
    if( pLevel->p2==0 ) pLevel->p2 = sqlite3VdbeCurrentAddr(v);
@@ -151400,27 +152976,6 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
    }

    if( pLevel->iLeftJoin==0 ){
-
      /* If pIdx is an index on one or more expressions, then look through
-
      ** all the expressions in pWInfo and try to transform matching expressions
-
      ** into reference to index columns.  Also attempt to translate references
-
      ** to virtual columns in the table into references to (stored) columns
-
      ** of the index.
-
      **
-
      ** Do not do this for the RHS of a LEFT JOIN. This is because the
-
      ** expression may be evaluated after OP_NullRow has been executed on
-
      ** the cursor. In this case it is important to do the full evaluation,
-
      ** as the result of the expression may not be NULL, even if all table
-
      ** column values are.  https://www.sqlite.org/src/info/7fa8049685b50b5a
-
      **
-
      ** Also, do not do this when processing one index an a multi-index
-
      ** OR clause, since the transformation will become invalid once we
-
      ** move forward to the next index.
-
      ** https://sqlite.org/src/info/4e8e4857d32d401f
-
      */
-
      if( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN))==0 ){
-
        whereIndexExprTrans(pIdx, iCur, iIdxCur, pWInfo);
-
      }
-

      /* If a partial index is driving the loop, try to eliminate WHERE clause
      ** terms from the query that must be true due to the WHERE clause of
      ** the partial index.
@@ -151533,7 +153088,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
      int nNotReady;                 /* The number of notReady tables */
      SrcItem *origSrc;              /* Original list of tables */
      nNotReady = pWInfo->nLevel - iLevel - 1;
-
      pOrTab = sqlite3StackAllocRaw(db,
+
      pOrTab = sqlite3DbMallocRawNN(db,
                            sizeof(*pOrTab)+ nNotReady*sizeof(pOrTab->a[0]));
      if( pOrTab==0 ) return notReady;
      pOrTab->nAlloc = (u8)(nNotReady + 1);
@@ -151786,7 +153341,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
    assert( pLevel->op==OP_Return );
    pLevel->p2 = sqlite3VdbeCurrentAddr(v);

-
    if( pWInfo->nLevel>1 ){ sqlite3StackFree(db, pOrTab); }
+
    if( pWInfo->nLevel>1 ){ sqlite3DbFreeNN(db, pOrTab); }
    if( !untestedTerms ) disableTerm(pLevel, pTerm);
  }else
#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
@@ -152414,7 +153969,7 @@ static int isLikeOrGlob(
        if( pLeft->op!=TK_COLUMN
         || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT
         || (ALWAYS( ExprUseYTab(pLeft) )
-
             && pLeft->y.pTab
+
             && ALWAYS(pLeft->y.pTab)
             && IsVirtual(pLeft->y.pTab))  /* Might be numeric */
        ){
          int isNum;
@@ -152531,8 +154086,7 @@ static int isAuxiliaryVtabOperator(
    **       MATCH(expression,vtab_column)
    */
    pCol = pList->a[1].pExpr;
-
    assert( pCol->op!=TK_COLUMN || ExprUseYTab(pCol) );
-
    testcase( pCol->op==TK_COLUMN && pCol->y.pTab==0 );
+
    assert( pCol->op!=TK_COLUMN || (ExprUseYTab(pCol) && pCol->y.pTab!=0) );
    if( ExprIsVtab(pCol) ){
      for(i=0; i<ArraySize(aOp); i++){
        assert( !ExprHasProperty(pExpr, EP_IntValue) );
@@ -152557,7 +154111,7 @@ static int isAuxiliaryVtabOperator(
    */
    pCol = pList->a[0].pExpr;
    assert( pCol->op!=TK_COLUMN || ExprUseYTab(pCol) );
-
    testcase( pCol->op==TK_COLUMN && pCol->y.pTab==0 );
+
    assert( pCol->op!=TK_COLUMN || (ExprUseYTab(pCol) && pCol->y.pTab!=0) );
    if( ExprIsVtab(pCol) ){
      sqlite3_vtab *pVtab;
      sqlite3_module *pMod;
@@ -152582,13 +154136,12 @@ static int isAuxiliaryVtabOperator(
    int res = 0;
    Expr *pLeft = pExpr->pLeft;
    Expr *pRight = pExpr->pRight;
-
    assert( pLeft->op!=TK_COLUMN || ExprUseYTab(pLeft) );
-
    testcase( pLeft->op==TK_COLUMN && pLeft->y.pTab==0 );
+
    assert( pLeft->op!=TK_COLUMN || (ExprUseYTab(pLeft) && pLeft->y.pTab!=0) );
    if( ExprIsVtab(pLeft) ){
      res++;
    }
-
    assert( pRight==0 || pRight->op!=TK_COLUMN || ExprUseYTab(pRight) );
-
    testcase( pRight && pRight->op==TK_COLUMN && pRight->y.pTab==0 );
+
    assert( pRight==0 || pRight->op!=TK_COLUMN
+
            || (ExprUseYTab(pRight) && pRight->y.pTab!=0) );
    if( pRight && ExprIsVtab(pRight) ){
      res++;
      SWAP(Expr*, pLeft, pRight);
@@ -153137,6 +154690,7 @@ static SQLITE_NOINLINE int exprMightBeIndexed2(
    if( pIdx->aColExpr==0 ) continue;
    for(i=0; i<pIdx->nKeyCol; i++){
      if( pIdx->aiColumn[i]!=XN_EXPR ) continue;
+
      assert( pIdx->bHasExpr );
      if( sqlite3ExprCompareSkip(pExpr, pIdx->aColExpr->a[i].pExpr, iCur)==0 ){
        aiCurCol[0] = iCur;
        aiCurCol[1] = XN_EXPR;
@@ -153750,9 +155304,9 @@ static void whereAddLimitExpr(
** exist only so that they may be passed to the xBestIndex method of the
** single virtual table in the FROM clause of the SELECT.
*/
-
SQLITE_PRIVATE void sqlite3WhereAddLimit(WhereClause *pWC, Select *p){
-
  assert( p==0 || (p->pGroupBy==0 && (p->selFlags & SF_Aggregate)==0) );
-
  if( (p && p->pLimit)                                          /* 1 */
+
SQLITE_PRIVATE void SQLITE_NOINLINE sqlite3WhereAddLimit(WhereClause *pWC, Select *p){
+
  assert( p!=0 && p->pLimit!=0 );                 /* 1 -- checked by caller */
+
  if( p->pGroupBy==0
   && (p->selFlags & (SF_Distinct|SF_Aggregate))==0             /* 2 */
   && (p->pSrc->nSrc==1 && IsVirtual(p->pSrc->a[0].pTab))       /* 3 */
  ){
@@ -154745,6 +156299,43 @@ static void whereTraceIndexInfoOutputs(sqlite3_index_info *p){
#define whereTraceIndexInfoOutputs(A)
#endif

+
/*
+
** We know that pSrc is an operand of an outer join.  Return true if
+
** pTerm is a constraint that is compatible with that join.
+
**
+
** pTerm must be EP_OuterON if pSrc is the right operand of an
+
** outer join.  pTerm can be either EP_OuterON or EP_InnerON if pSrc
+
** is the left operand of a RIGHT join.
+
**
+
** See https://sqlite.org/forum/forumpost/206d99a16dd9212f
+
** for an example of a WHERE clause constraints that may not be used on
+
** the right table of a RIGHT JOIN because the constraint implies a
+
** not-NULL condition on the left table of the RIGHT JOIN.
+
*/
+
static int constraintCompatibleWithOuterJoin(
+
  const WhereTerm *pTerm,       /* WHERE clause term to check */
+
  const SrcItem *pSrc           /* Table we are trying to access */
+
){
+
  assert( (pSrc->fg.jointype&(JT_LEFT|JT_LTORJ|JT_RIGHT))!=0 ); /* By caller */
+
  testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_LEFT );
+
  testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_LTORJ );
+
  testcase( ExprHasProperty(pTerm->pExpr, EP_OuterON) )
+
  testcase( ExprHasProperty(pTerm->pExpr, EP_InnerON) );
+
  if( !ExprHasProperty(pTerm->pExpr, EP_OuterON|EP_InnerON)
+
   || pTerm->pExpr->w.iJoin != pSrc->iCursor
+
  ){
+
    return 0;
+
  }
+
  if( (pSrc->fg.jointype & (JT_LEFT|JT_RIGHT))!=0
+
   && ExprHasProperty(pTerm->pExpr, EP_InnerON)
+
  ){
+
    return 0;
+
  }
+
  return 1;
+
}
+

+

+

#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
/*
** Return TRUE if the WHERE clause term pTerm is of a form where it
@@ -154760,16 +156351,10 @@ static int termCanDriveIndex(
  if( pTerm->leftCursor!=pSrc->iCursor ) return 0;
  if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) return 0;
  assert( (pSrc->fg.jointype & JT_RIGHT)==0 );
-
  if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0 ){
-
    testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_LEFT );
-
    testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_LTORJ );
-
    testcase( ExprHasProperty(pTerm->pExpr, EP_OuterON) )
-
    testcase( ExprHasProperty(pTerm->pExpr, EP_InnerON) );
-
    if( !ExprHasProperty(pTerm->pExpr, EP_OuterON|EP_InnerON)
-
     || pTerm->pExpr->w.iJoin != pSrc->iCursor
-
    ){
-
      return 0;  /* See tag-20191211-001 */
-
    }
+
  if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0
+
   && !constraintCompatibleWithOuterJoin(pTerm,pSrc)
+
  ){
+
    return 0;  /* See https://sqlite.org/forum/forumpost/51e6959f61 */
  }
  if( (pTerm->prereqRight & notReady)!=0 ) return 0;
  assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
@@ -155181,22 +156766,10 @@ static sqlite3_index_info *allocateIndexInfo(
    assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
    assert( pTerm->u.x.leftColumn>=XN_ROWID );
    assert( pTerm->u.x.leftColumn<pTab->nCol );
-

-
    /* tag-20191211-002: WHERE-clause constraints are not useful to the
-
    ** right-hand table of a LEFT JOIN nor to the either table of a
-
    ** RIGHT JOIN.  See tag-20191211-001 for the
-
    ** equivalent restriction for ordinary tables. */
-
    if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0 ){
-
      testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_LEFT );
-
      testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_RIGHT );
-
      testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_LTORJ );
-
      testcase( ExprHasProperty(pTerm->pExpr, EP_OuterON) );
-
      testcase( ExprHasProperty(pTerm->pExpr, EP_InnerON) );
-
      if( !ExprHasProperty(pTerm->pExpr, EP_OuterON|EP_InnerON)
-
       || pTerm->pExpr->w.iJoin != pSrc->iCursor
-
      ){
-
        continue;
-
      }
+
    if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0
+
     && !constraintCompatibleWithOuterJoin(pTerm,pSrc)
+
    ){
+
      continue;
    }
    nTerm++;
    pTerm->wtFlags |= TERM_OK;
@@ -155569,7 +157142,7 @@ static int whereKeyStats(
    ** is larger than all samples in the array. */
    tRowcnt iUpper, iGap;
    if( i>=pIdx->nSample ){
-
      iUpper = sqlite3LogEstToInt(pIdx->aiRowLogEst[0]);
+
      iUpper = pIdx->nRowEst0;
    }else{
      iUpper = aSample[i].anLt[iCol];
    }
@@ -156198,12 +157771,18 @@ static void whereLoopClearUnion(sqlite3 *db, WhereLoop *p){
}

/*
-
** Deallocate internal memory used by a WhereLoop object
+
** Deallocate internal memory used by a WhereLoop object.  Leave the
+
** object in an initialized state, as if it had been newly allocated.
*/
static void whereLoopClear(sqlite3 *db, WhereLoop *p){
-
  if( p->aLTerm!=p->aLTermSpace ) sqlite3DbFreeNN(db, p->aLTerm);
+
  if( p->aLTerm!=p->aLTermSpace ){
+
    sqlite3DbFreeNN(db, p->aLTerm);
+
    p->aLTerm = p->aLTermSpace;
+
    p->nLSlot = ArraySize(p->aLTermSpace);
+
  }
  whereLoopClearUnion(db, p);
-
  whereLoopInit(p);
+
  p->nLTerm = 0;
+
  p->wsFlags = 0;
}

/*
@@ -156227,7 +157806,9 @@ static int whereLoopResize(sqlite3 *db, WhereLoop *p, int n){
*/
static int whereLoopXfer(sqlite3 *db, WhereLoop *pTo, WhereLoop *pFrom){
  whereLoopClearUnion(db, pTo);
-
  if( whereLoopResize(db, pTo, pFrom->nLTerm) ){
+
  if( pFrom->nLTerm > pTo->nLSlot
+
   && whereLoopResize(db, pTo, pFrom->nLTerm)
+
  ){
    memset(pTo, 0, WHERE_LOOP_XFER_SZ);
    return SQLITE_NOMEM_BKPT;
  }
@@ -156245,8 +157826,9 @@ static int whereLoopXfer(sqlite3 *db, WhereLoop *pTo, WhereLoop *pFrom){
** Delete a WhereLoop object
*/
static void whereLoopDelete(sqlite3 *db, WhereLoop *p){
+
  assert( db!=0 );
  whereLoopClear(db, p);
-
  sqlite3DbFreeNN(db, p);
+
  sqlite3DbNNFreeNN(db, p);
}

/*
@@ -156254,30 +157836,19 @@ static void whereLoopDelete(sqlite3 *db, WhereLoop *p){
*/
static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
  assert( pWInfo!=0 );
+
  assert( db!=0 );
  sqlite3WhereClauseClear(&pWInfo->sWC);
  while( pWInfo->pLoops ){
    WhereLoop *p = pWInfo->pLoops;
    pWInfo->pLoops = p->pNextLoop;
    whereLoopDelete(db, p);
  }
-
  assert( pWInfo->pExprMods==0 );
  while( pWInfo->pMemToFree ){
    WhereMemBlock *pNext = pWInfo->pMemToFree->pNext;
-
    sqlite3DbFreeNN(db, pWInfo->pMemToFree);
+
    sqlite3DbNNFreeNN(db, pWInfo->pMemToFree);
    pWInfo->pMemToFree = pNext;
  }
-
  sqlite3DbFreeNN(db, pWInfo);
-
}
-

-
/* Undo all Expr node modifications
-
*/
-
static void whereUndoExprMods(WhereInfo *pWInfo){
-
  while( pWInfo->pExprMods ){
-
    WhereExprMod *p = pWInfo->pExprMods;
-
    pWInfo->pExprMods = p->pNext;
-
    memcpy(p->pExpr, &p->orig, sizeof(p->orig));
-
    sqlite3DbFree(pWInfo->pParse->db, p);
-
  }
+
  sqlite3DbNNFreeNN(db, pWInfo);
}

/*
@@ -156844,32 +158415,11 @@ static int whereLoopAddBtreeIndex(
    ** to mix with a lower range bound from some other source */
    if( pTerm->wtFlags & TERM_LIKEOPT && pTerm->eOperator==WO_LT ) continue;

-
    /* tag-20191211-001:  Do not allow constraints from the WHERE clause to
-
    ** be used by the right table of a LEFT JOIN nor by the left table of a
-
    ** RIGHT JOIN.  Only constraints in the ON clause are allowed.
-
    ** See tag-20191211-002 for the vtab equivalent.
-
    **
-
    ** 2022-06-06: See https://sqlite.org/forum/forumpost/206d99a16dd9212f
-
    ** for an example of a WHERE clause constraints that may not be used on
-
    ** the right table of a RIGHT JOIN because the constraint implies a
-
    ** not-NULL condition on the left table of the RIGHT JOIN.
-
    **
-
    ** 2022-06-10: The same condition applies to termCanDriveIndex() above.
-
    ** https://sqlite.org/forum/forumpost/51e6959f61
-
    */
-
    if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0 ){
-
      testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_LEFT );
-
      testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_RIGHT );
-
      testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_LTORJ );
-
      testcase( ExprHasProperty(pTerm->pExpr, EP_OuterON) )
-
      testcase( ExprHasProperty(pTerm->pExpr, EP_InnerON) );
-
      if( !ExprHasProperty(pTerm->pExpr, EP_OuterON|EP_InnerON)
-
       || pTerm->pExpr->w.iJoin != pSrc->iCursor
-
      ){
-
        continue;
-
      }
+
    if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0
+
     && !constraintCompatibleWithOuterJoin(pTerm,pSrc)
+
    ){
+
      continue;
    }
-

    if( IsUniqueIndex(pProbe) && saved_nEq==pProbe->nKeyCol-1 ){
      pBuilder->bldFlags1 |= SQLITE_BLDF1_UNIQUE;
    }else{
@@ -156880,7 +158430,11 @@ static int whereLoopAddBtreeIndex(
    pNew->u.btree.nBtm = saved_nBtm;
    pNew->u.btree.nTop = saved_nTop;
    pNew->nLTerm = saved_nLTerm;
-
    if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */
+
    if( pNew->nLTerm>=pNew->nLSlot
+
     && whereLoopResize(db, pNew, pNew->nLTerm+1)
+
    ){
+
       break; /* OOM while trying to enlarge the pNew->aLTerm array */
+
    }
    pNew->aLTerm[pNew->nLTerm++] = pTerm;
    pNew->prereq = (saved_prereq | pTerm->prereqRight) & ~pNew->maskSelf;

@@ -156973,38 +158527,39 @@ static int whereLoopAddBtreeIndex(
      if( scan.iEquiv>1 ) pNew->wsFlags |= WHERE_TRANSCONS;
    }else if( eOp & WO_ISNULL ){
      pNew->wsFlags |= WHERE_COLUMN_NULL;
-
    }else if( eOp & (WO_GT|WO_GE) ){
-
      testcase( eOp & WO_GT );
-
      testcase( eOp & WO_GE );
-
      pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT;
-
      pNew->u.btree.nBtm = whereRangeVectorLen(
-
          pParse, pSrc->iCursor, pProbe, saved_nEq, pTerm
-
      );
-
      pBtm = pTerm;
-
      pTop = 0;
-
      if( pTerm->wtFlags & TERM_LIKEOPT ){
-
        /* Range constraints that come from the LIKE optimization are
-
        ** always used in pairs. */
-
        pTop = &pTerm[1];
-
        assert( (pTop-(pTerm->pWC->a))<pTerm->pWC->nTerm );
-
        assert( pTop->wtFlags & TERM_LIKEOPT );
-
        assert( pTop->eOperator==WO_LT );
-
        if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */
-
        pNew->aLTerm[pNew->nLTerm++] = pTop;
-
        pNew->wsFlags |= WHERE_TOP_LIMIT;
-
        pNew->u.btree.nTop = 1;
-
      }
-
    }else{
-
      assert( eOp & (WO_LT|WO_LE) );
-
      testcase( eOp & WO_LT );
-
      testcase( eOp & WO_LE );
-
      pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_TOP_LIMIT;
-
      pNew->u.btree.nTop = whereRangeVectorLen(
+
    }else{
+
      int nVecLen = whereRangeVectorLen(
          pParse, pSrc->iCursor, pProbe, saved_nEq, pTerm
      );
-
      pTop = pTerm;
-
      pBtm = (pNew->wsFlags & WHERE_BTM_LIMIT)!=0 ?
-
                     pNew->aLTerm[pNew->nLTerm-2] : 0;
+
      if( eOp & (WO_GT|WO_GE) ){
+
        testcase( eOp & WO_GT );
+
        testcase( eOp & WO_GE );
+
        pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT;
+
        pNew->u.btree.nBtm = nVecLen;
+
        pBtm = pTerm;
+
        pTop = 0;
+
        if( pTerm->wtFlags & TERM_LIKEOPT ){
+
          /* Range constraints that come from the LIKE optimization are
+
          ** always used in pairs. */
+
          pTop = &pTerm[1];
+
          assert( (pTop-(pTerm->pWC->a))<pTerm->pWC->nTerm );
+
          assert( pTop->wtFlags & TERM_LIKEOPT );
+
          assert( pTop->eOperator==WO_LT );
+
          if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */
+
          pNew->aLTerm[pNew->nLTerm++] = pTop;
+
          pNew->wsFlags |= WHERE_TOP_LIMIT;
+
          pNew->u.btree.nTop = 1;
+
        }
+
      }else{
+
        assert( eOp & (WO_LT|WO_LE) );
+
        testcase( eOp & WO_LT );
+
        testcase( eOp & WO_LE );
+
        pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_TOP_LIMIT;
+
        pNew->u.btree.nTop = nVecLen;
+
        pTop = pTerm;
+
        pBtm = (pNew->wsFlags & WHERE_BTM_LIMIT)!=0 ?
+
                       pNew->aLTerm[pNew->nLTerm-2] : 0;
+
      }
    }

    /* At this point pNew->nOut is set to the number of rows expected to
@@ -157249,6 +158804,94 @@ static int whereUsablePartialIndex(
}

/*
+
** Structure passed to the whereIsCoveringIndex Walker callback.
+
*/
+
struct CoveringIndexCheck {
+
  Index *pIdx;       /* The index */
+
  int iTabCur;       /* Cursor number for the corresponding table */
+
};
+

+
/*
+
** Information passed in is pWalk->u.pCovIdxCk.  Call is pCk.
+
**
+
** If the Expr node references the table with cursor pCk->iTabCur, then
+
** make sure that column is covered by the index pCk->pIdx.  We know that
+
** all columns less than 63 (really BMS-1) are covered, so we don't need
+
** to check them.  But we do need to check any column at 63 or greater.
+
**
+
** If the index does not cover the column, then set pWalk->eCode to
+
** non-zero and return WRC_Abort to stop the search.
+
**
+
** If this node does not disprove that the index can be a covering index,
+
** then just return WRC_Continue, to continue the search.
+
*/
+
static int whereIsCoveringIndexWalkCallback(Walker *pWalk, Expr *pExpr){
+
  int i;                  /* Loop counter */
+
  const Index *pIdx;      /* The index of interest */
+
  const i16 *aiColumn;    /* Columns contained in the index */
+
  u16 nColumn;            /* Number of columns in the index */
+
  if( pExpr->op!=TK_COLUMN && pExpr->op!=TK_AGG_COLUMN ) return WRC_Continue;
+
  if( pExpr->iColumn<(BMS-1) ) return WRC_Continue;
+
  if( pExpr->iTable!=pWalk->u.pCovIdxCk->iTabCur ) return WRC_Continue;
+
  pIdx = pWalk->u.pCovIdxCk->pIdx;
+
  aiColumn = pIdx->aiColumn;
+
  nColumn = pIdx->nColumn;
+
  for(i=0; i<nColumn; i++){
+
    if( aiColumn[i]==pExpr->iColumn ) return WRC_Continue;
+
  }
+
  pWalk->eCode = 1;
+
  return WRC_Abort;
+
}
+

+

+
/*
+
** pIdx is an index that covers all of the low-number columns used by
+
** pWInfo->pSelect (columns from 0 through 62).  But there are columns
+
** in pWInfo->pSelect beyond 62.  This routine tries to answer the question
+
** of whether pIdx covers *all* columns in the query.
+
**
+
** Return 0 if pIdx is a covering index.   Return non-zero if pIdx is
+
** not a covering index or if we are unable to determine if pIdx is a
+
** covering index.
+
**
+
** This routine is an optimization.  It is always safe to return non-zero.
+
** But returning zero when non-zero should have been returned can lead to
+
** incorrect bytecode and assertion faults.
+
*/
+
static SQLITE_NOINLINE u32 whereIsCoveringIndex(
+
  WhereInfo *pWInfo,     /* The WHERE clause context */
+
  Index *pIdx,           /* Index that is being tested */
+
  int iTabCur            /* Cursor for the table being indexed */
+
){
+
  int i;
+
  struct CoveringIndexCheck ck;
+
  Walker w;
+
  if( pWInfo->pSelect==0 ){
+
    /* We don't have access to the full query, so we cannot check to see
+
    ** if pIdx is covering.  Assume it is not. */
+
    return 1;
+
  }
+
  for(i=0; i<pIdx->nColumn; i++){
+
    if( pIdx->aiColumn[i]>=BMS-1 ) break;
+
  }
+
  if( i>=pIdx->nColumn ){
+
    /* pIdx does not index any columns greater than 62, but we know from
+
    ** colMask that columns greater than 62 are used, so this is not a
+
    ** covering index */
+
    return 1;
+
  }
+
  ck.pIdx = pIdx;
+
  ck.iTabCur = iTabCur;
+
  memset(&w, 0, sizeof(w));
+
  w.xExprCallback = whereIsCoveringIndexWalkCallback;
+
  w.xSelectCallback = sqlite3SelectWalkNoop;
+
  w.u.pCovIdxCk = &ck;
+
  w.eCode = 0;
+
  sqlite3WalkSelect(&w, pWInfo->pSelect);
+
  return w.eCode;
+
}
+

+
/*
** Add all WhereLoop objects for a single table of the join where the table
** is identified by pBuilder->pNew->iTab.  That table is guaranteed to be
** a b-tree table, not a virtual table.
@@ -157450,6 +159093,9 @@ static int whereLoopAddBtree(
#else
      pNew->rRun = rSize + 16;
#endif
+
      if( IsView(pTab) || (pTab->tabFlags & TF_Ephemeral)!=0 ){
+
        pNew->wsFlags |= WHERE_VIEWSCAN;
+
      }
      ApplyCostMultiplier(pNew->rRun, pTab->costMult);
      whereLoopOutputAdjust(pWC, pNew, rSize);
      rc = whereLoopInsert(pBuilder, pNew);
@@ -157462,6 +159108,9 @@ static int whereLoopAddBtree(
        m = 0;
      }else{
        m = pSrc->colUsed & pProbe->colNotIdxed;
+
        if( m==TOPBIT ){
+
          m = whereIsCoveringIndex(pWInfo, pProbe, pSrc->iCursor);
+
        }
        pNew->wsFlags = (m==0) ? (WHERE_IDX_ONLY|WHERE_INDEXED) : WHERE_INDEXED;
      }

@@ -158176,7 +159825,13 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){

  /* Loop over the tables in the join, from left to right */
  pNew = pBuilder->pNew;
-
  whereLoopInit(pNew);
+

+
  /* Verify that pNew has already been initialized */
+
  assert( pNew->nLTerm==0 );
+
  assert( pNew->wsFlags==0 );
+
  assert( pNew->nLSlot>=ArraySize(pNew->aLTermSpace) );
+
  assert( pNew->aLTerm!=0 );
+

  pBuilder->iPlanLimit = SQLITE_QUERY_PLANNER_LIMIT;
  for(iTab=0, pItem=pTabList->a; pItem<pEnd; iTab++, pItem++){
    Bitmask mUnusable = 0;
@@ -158681,7 +160336,6 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
  int mxChoice;             /* Maximum number of simultaneous paths tracked */
  int nLoop;                /* Number of terms in the join */
  Parse *pParse;            /* Parsing context */
-
  sqlite3 *db;              /* The database connection */
  int iLoop;                /* Loop counter over the terms of the join */
  int ii, jj;               /* Loop counters */
  int mxI = 0;              /* Index of next entry to replace */
@@ -158700,7 +160354,6 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
  int nSpace;               /* Bytes of space allocated at pSpace */

  pParse = pWInfo->pParse;
-
  db = pParse->db;
  nLoop = pWInfo->nLevel;
  /* TUNING: For simple queries, only the best path is tracked.
  ** For 2-way joins, the 5 best paths are followed.
@@ -158723,7 +160376,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
  /* Allocate and initialize space for aTo, aFrom and aSortCost[] */
  nSpace = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2;
  nSpace += sizeof(LogEst) * nOrderBy;
-
  pSpace = sqlite3DbMallocRawNN(db, nSpace);
+
  pSpace = sqlite3StackAllocRawNN(pParse->db, nSpace);
  if( pSpace==0 ) return SQLITE_NOMEM_BKPT;
  aTo = (WherePath*)pSpace;
  aFrom = aTo+mxChoice;
@@ -158773,9 +160426,9 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
        LogEst nOut;                      /* Rows visited by (pFrom+pWLoop) */
        LogEst rCost;                     /* Cost of path (pFrom+pWLoop) */
        LogEst rUnsorted;                 /* Unsorted cost of (pFrom+pWLoop) */
-
        i8 isOrdered = pFrom->isOrdered;  /* isOrdered for (pFrom+pWLoop) */
+
        i8 isOrdered;                     /* isOrdered for (pFrom+pWLoop) */
        Bitmask maskNew;                  /* Mask of src visited by (..) */
-
        Bitmask revMask = 0;              /* Mask of rev-order loops for (..) */
+
        Bitmask revMask;                  /* Mask of rev-order loops for (..) */

        if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue;
        if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue;
@@ -158794,7 +160447,9 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
        rUnsorted = sqlite3LogEstAdd(rUnsorted, pFrom->rUnsorted);
        nOut = pFrom->nRow + pWLoop->nOut;
        maskNew = pFrom->maskLoop | pWLoop->maskSelf;
+
        isOrdered = pFrom->isOrdered;
        if( isOrdered<0 ){
+
          revMask = 0;
          isOrdered = wherePathSatisfiesOrderBy(pWInfo,
                       pWInfo->pOrderBy, pFrom, pWInfo->wctrlFlags,
                       iLoop, pWLoop, &revMask);
@@ -158822,6 +160477,13 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
          rUnsorted -= 2;  /* TUNING:  Slight bias in favor of no-sort plans */
        }

+
        /* TUNING:  A full-scan of a VIEW or subquery in the outer loop
+
        ** is not so bad. */
+
        if( iLoop==0 && (pWLoop->wsFlags & WHERE_VIEWSCAN)!=0 ){
+
          rCost += -10;
+
          nOut += -30;
+
        }
+

        /* Check to see if pWLoop should be added to the set of
        ** mxChoice best-so-far paths.
        **
@@ -158972,7 +160634,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){

  if( nFrom==0 ){
    sqlite3ErrorMsg(pParse, "no query solution");
-
    sqlite3DbFreeNN(db, pSpace);
+
    sqlite3StackFreeNN(pParse->db, pSpace);
    return SQLITE_ERROR;
  }

@@ -159054,7 +160716,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
  pWInfo->nRowOut = pFrom->nRow;

  /* Free temporary memory and return success */
-
  sqlite3DbFreeNN(db, pSpace);
+
  sqlite3StackFreeNN(pParse->db, pSpace);
  return SQLITE_OK;
}

@@ -159354,6 +161016,77 @@ static SQLITE_NOINLINE void whereCheckIfBloomFilterIsUseful(
}

/*
+
** This is an sqlite3ParserAddCleanup() callback that is invoked to
+
** free the Parse->pIdxExpr list when the Parse object is destroyed.
+
*/
+
static void whereIndexedExprCleanup(sqlite3 *db, void *pObject){
+
  Parse *pParse = (Parse*)pObject;
+
  while( pParse->pIdxExpr!=0 ){
+
    IndexedExpr *p = pParse->pIdxExpr;
+
    pParse->pIdxExpr = p->pIENext;
+
    sqlite3ExprDelete(db, p->pExpr);
+
    sqlite3DbFreeNN(db, p);
+
  }
+
}
+

+
/*
+
** The index pIdx is used by a query and contains one or more expressions.
+
** In other words pIdx is an index on an expression.  iIdxCur is the cursor
+
** number for the index and iDataCur is the cursor number for the corresponding
+
** table.
+
**
+
** This routine adds IndexedExpr entries to the Parse->pIdxExpr field for
+
** each of the expressions in the index so that the expression code generator
+
** will know to replace occurrences of the indexed expression with
+
** references to the corresponding column of the index.
+
*/
+
static SQLITE_NOINLINE void whereAddIndexedExpr(
+
  Parse *pParse,     /* Add IndexedExpr entries to pParse->pIdxExpr */
+
  Index *pIdx,       /* The index-on-expression that contains the expressions */
+
  int iIdxCur,       /* Cursor number for pIdx */
+
  SrcItem *pTabItem  /* The FROM clause entry for the table */
+
){
+
  int i;
+
  IndexedExpr *p;
+
  Table *pTab;
+
  assert( pIdx->bHasExpr );
+
  pTab = pIdx->pTable;
+
  for(i=0; i<pIdx->nColumn; i++){
+
    Expr *pExpr;
+
    int j = pIdx->aiColumn[i];
+
    int bMaybeNullRow;
+
    if( j==XN_EXPR ){
+
      pExpr = pIdx->aColExpr->a[i].pExpr;
+
      testcase( pTabItem->fg.jointype & JT_LEFT );
+
      testcase( pTabItem->fg.jointype & JT_RIGHT );
+
      testcase( pTabItem->fg.jointype & JT_LTORJ );
+
      bMaybeNullRow = (pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0;
+
    }else if( j>=0 && (pTab->aCol[j].colFlags & COLFLAG_VIRTUAL)!=0 ){
+
      pExpr = sqlite3ColumnExpr(pTab, &pTab->aCol[j]);
+
      bMaybeNullRow = 0;
+
    }else{
+
      continue;
+
    }
+
    if( sqlite3ExprIsConstant(pExpr) ) continue;
+
    p = sqlite3DbMallocRaw(pParse->db,  sizeof(IndexedExpr));
+
    if( p==0 ) break;
+
    p->pIENext = pParse->pIdxExpr;
+
    p->pExpr = sqlite3ExprDup(pParse->db, pExpr, 0);
+
    p->iDataCur = pTabItem->iCursor;
+
    p->iIdxCur = iIdxCur;
+
    p->iIdxCol = i;
+
    p->bMaybeNullRow = bMaybeNullRow;
+
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
+
    p->zIdxName = pIdx->zName;
+
#endif
+
    pParse->pIdxExpr = p;
+
    if( p->pIENext==0 ){
+
      sqlite3ParserAddCleanup(pParse, whereIndexedExprCleanup, pParse);
+
    }
+
  }
+
}
+

+
/*
** Generate the beginning of the loop used for WHERE clause processing.
** The return value is a pointer to an opaque structure that contains
** information needed to terminate the loop.  Later, the calling routine
@@ -159447,7 +161180,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
  Expr *pWhere,           /* The WHERE clause */
  ExprList *pOrderBy,     /* An ORDER BY (or GROUP BY) clause, or NULL */
  ExprList *pResultSet,   /* Query result set.  Req'd for DISTINCT */
-
  Select *pLimit,         /* Use this LIMIT/OFFSET clause, if any */
+
  Select *pSelect,        /* The entire SELECT statement */
  u16 wctrlFlags,         /* The WHERE_* flags defined in sqliteInt.h */
  int iAuxArg             /* If WHERE_OR_SUBCLAUSE is set, index cursor number
                          ** If WHERE_USE_LIMIT, then the limit amount */
@@ -159516,7 +161249,9 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
  pWInfo->pParse = pParse;
  pWInfo->pTabList = pTabList;
  pWInfo->pOrderBy = pOrderBy;
+
#if WHERETRACE_ENABLED
  pWInfo->pWhere = pWhere;
+
#endif
  pWInfo->pResultSet = pResultSet;
  pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1;
  pWInfo->nLevel = nTabList;
@@ -159524,9 +161259,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
  pWInfo->wctrlFlags = wctrlFlags;
  pWInfo->iLimit = iAuxArg;
  pWInfo->savedNQueryLoop = pParse->nQueryLoop;
-
#ifndef SQLITE_OMIT_VIRTUALTABLE
-
  pWInfo->pLimit = pLimit;
-
#endif
+
  pWInfo->pSelect = pSelect;
  memset(&pWInfo->nOBSat, 0,
         offsetof(WhereInfo,sWC) - offsetof(WhereInfo,nOBSat));
  memset(&pWInfo->a[0], 0, sizeof(WhereLoop)+nTabList*sizeof(WhereLevel));
@@ -159595,7 +161328,9 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(

  /* Analyze all of the subexpressions. */
  sqlite3WhereExprAnalyze(pTabList, &pWInfo->sWC);
-
  sqlite3WhereAddLimit(&pWInfo->sWC, pLimit);
+
  if( pSelect && pSelect->pLimit ){
+
    sqlite3WhereAddLimit(&pWInfo->sWC, pSelect);
+
  }
  if( pParse->nErr ) goto whereBeginError;

  /* Special case: WHERE terms that do not refer to any tables in the join
@@ -159898,6 +161633,9 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
        op = OP_ReopenIdx;
      }else{
        iIndexCur = pParse->nTab++;
+
        if( pIx->bHasExpr && OptimizationEnabled(db, SQLITE_IndexedExpr) ){
+
          whereAddIndexedExpr(pParse, pIx, iIndexCur, pTabItem);
+
        }
      }
      pLevel->iIdxCur = iIndexCur;
      assert( pIx!=0 );
@@ -160020,8 +161758,6 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
  /* Jump here if malloc fails */
whereBeginError:
  if( pWInfo ){
-
    testcase( pWInfo->pExprMods!=0 );
-
    whereUndoExprMods(pWInfo);
    pParse->nQueryLoop = pWInfo->savedNQueryLoop;
    whereInfoFree(db, pWInfo);
  }
@@ -160240,7 +161976,6 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
  }

  assert( pWInfo->nLevel<=pTabList->nSrc );
-
  if( pWInfo->pExprMods ) whereUndoExprMods(pWInfo);
  for(i=0, pLevel=pWInfo->a; i<pWInfo->nLevel; i++, pLevel++){
    int k, last;
    VdbeOp *pOp, *pLastOp;
@@ -160294,6 +162029,16 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
      }else{
        last = pWInfo->iEndWhere;
      }
+
      if( pIdx->bHasExpr ){
+
        IndexedExpr *p = pParse->pIdxExpr;
+
        while( p ){
+
          if( p->iIdxCur==pLevel->iIdxCur ){
+
            p->iDataCur = -1;
+
            p->iIdxCur = -1;
+
          }
+
          p = p->pIENext;
+
        }
+
      }
      k = pLevel->addrBody + 1;
#ifdef SQLITE_DEBUG
      if( db->flags & SQLITE_VdbeAddopTrace ){
@@ -161287,7 +163032,6 @@ static ExprList *exprListAppendList(
    for(i=0; i<pAppend->nExpr; i++){
      sqlite3 *db = pParse->db;
      Expr *pDup = sqlite3ExprDup(db, pAppend->a[i].pExpr, 0);
-
      assert( pDup==0 || !ExprHasProperty(pDup, EP_MemToken) );
      if( db->mallocFailed ){
        sqlite3ExprDelete(db, pDup);
        break;
@@ -162558,10 +164302,9 @@ static void windowCodeRangeTest(

    /* This block runs if reg1 is not NULL, but reg2 is. */
    sqlite3VdbeJumpHere(v, addr);
-
    sqlite3VdbeAddOp2(v, OP_IsNull, reg2, lbl); VdbeCoverage(v);
-
    if( op==OP_Gt || op==OP_Ge ){
-
      sqlite3VdbeChangeP2(v, -1, addrDone);
-
    }
+
    sqlite3VdbeAddOp2(v, OP_IsNull, reg2,
+
                      (op==OP_Gt || op==OP_Ge) ? addrDone : lbl);
+
    VdbeCoverage(v);
  }

  /* Register reg1 currently contains csr1.peerVal (the peer-value from csr1).
@@ -170138,7 +171881,7 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql){
  if( pParse->pNewTrigger && !IN_RENAME_OBJECT ){
    sqlite3DeleteTrigger(db, pParse->pNewTrigger);
  }
-
  if( pParse->pVList ) sqlite3DbFreeNN(db, pParse->pVList);
+
  if( pParse->pVList ) sqlite3DbNNFreeNN(db, pParse->pVList);
  db->pParse = pParentParse;
  assert( nErr==0 || pParse->rc!=SQLITE_OK );
  return nErr;
@@ -171494,18 +173237,19 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
    db->lookaside.bMalloced = pBuf==0 ?1:0;
    db->lookaside.nSlot = nBig+nSm;
  }else{
-
    db->lookaside.pStart = db;
+
    db->lookaside.pStart = 0;
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
    db->lookaside.pSmallInit = 0;
    db->lookaside.pSmallFree = 0;
-
    db->lookaside.pMiddle = db;
+
    db->lookaside.pMiddle = 0;
#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
-
    db->lookaside.pEnd = db;
+
    db->lookaside.pEnd = 0;
    db->lookaside.bDisable = 1;
    db->lookaside.sz = 0;
    db->lookaside.bMalloced = 0;
    db->lookaside.nSlot = 0;
  }
+
  db->lookaside.pTrueEnd = db->lookaside.pEnd;
  assert( sqlite3LookasideUsed(db,0)==0 );
#endif /* SQLITE_OMIT_LOOKASIDE */
  return SQLITE_OK;
@@ -171584,6 +173328,7 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3 *db){
SQLITE_API int sqlite3_db_config(sqlite3 *db, int op, ...){
  va_list ap;
  int rc;
+
  sqlite3_mutex_enter(db->mutex);
  va_start(ap, op);
  switch( op ){
    case SQLITE_DBCONFIG_MAINDBNAME: {
@@ -171649,6 +173394,7 @@ SQLITE_API int sqlite3_db_config(sqlite3 *db, int op, ...){
    }
  }
  va_end(ap);
+
  sqlite3_mutex_leave(db->mutex);
  return rc;
}

@@ -174019,6 +175765,19 @@ static int openDatabase(
    goto opendb_out;
  }

+
#if SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL)
+
  /* Process magic filenames ":localStorage:" and ":sessionStorage:" */
+
  if( zFilename && zFilename[0]==':' ){
+
    if( strcmp(zFilename, ":localStorage:")==0 ){
+
      zFilename = "file:local?vfs=kvvfs";
+
      flags |= SQLITE_OPEN_URI;
+
    }else if( strcmp(zFilename, ":sessionStorage:")==0 ){
+
      zFilename = "file:session?vfs=kvvfs";
+
      flags |= SQLITE_OPEN_URI;
+
    }
+
  }
+
#endif /* SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL) */
+

  /* Parse the filename/URI argument
  **
  ** Only allow sensible combinations of bits in the flags argument.
@@ -174049,6 +175808,12 @@ static int openDatabase(
    sqlite3_free(zErrMsg);
    goto opendb_out;
  }
+
  assert( db->pVfs!=0 );
+
#if SQLITE_OS_KV || defined(SQLITE_OS_KV_OPTIONAL)
+
  if( sqlite3_stricmp(db->pVfs->zName, "kvvfs")==0 ){
+
    db->temp_store = 2;
+
  }
+
#endif

  /* Open the backend database driver */
  rc = sqlite3BtreeOpen(db->pVfs, zOpen, db, &db->aDb[0].pBt, 0,
@@ -175158,7 +176923,7 @@ static char *appendText(char *p, const char *z){
** Memory layout must be compatible with that generated by the pager
** and expected by sqlite3_uri_parameter() and databaseName().
*/
-
SQLITE_API char *sqlite3_create_filename(
+
SQLITE_API const char *sqlite3_create_filename(
  const char *zDatabase,
  const char *zJournal,
  const char *zWal,
@@ -175194,10 +176959,10 @@ SQLITE_API char *sqlite3_create_filename(
** error to call this routine with any parameter other than a pointer
** previously obtained from sqlite3_create_filename() or a NULL pointer.
*/
-
SQLITE_API void sqlite3_free_filename(char *p){
+
SQLITE_API void sqlite3_free_filename(const char *p){
  if( p==0 ) return;
-
  p = (char*)databaseName(p);
-
  sqlite3_free(p - 4);
+
  p = databaseName(p);
+
  sqlite3_free((char*)p - 4);
}


@@ -175448,8 +177213,8 @@ SQLITE_API int sqlite3_snapshot_open(
*/
SQLITE_API int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb){
  int rc = SQLITE_ERROR;
-
  int iDb;
#ifndef SQLITE_OMIT_WAL
+
  int iDb;

#ifdef SQLITE_ENABLE_API_ARMOR
  if( !sqlite3SafetyCheckOk(db) ){
@@ -177004,7 +178769,7 @@ struct Fts3MultiSegReader {
  int nAdvance;                   /* How many seg-readers to advance */
  Fts3SegFilter *pFilter;         /* Pointer to filter object */
  char *aBuffer;                  /* Buffer to merge doclists in */
-
  int nBuffer;                    /* Allocated size of aBuffer[] in bytes */
+
  i64 nBuffer;                    /* Allocated size of aBuffer[] in bytes */

  int iColFilter;                 /* If >=0, filter for this column */
  int bRestart;
@@ -179700,7 +181465,7 @@ static int fts3TermSelectMerge(
    **
    ** Similar padding is added in the fts3DoclistOrMerge() function.
    */
-
    pTS->aaOutput[0] = sqlite3_malloc(nDoclist + FTS3_VARINT_MAX + 1);
+
    pTS->aaOutput[0] = sqlite3_malloc64((i64)nDoclist + FTS3_VARINT_MAX + 1);
    pTS->anOutput[0] = nDoclist;
    if( pTS->aaOutput[0] ){
      memcpy(pTS->aaOutput[0], aDoclist, nDoclist);
@@ -181557,7 +183322,7 @@ static int fts3EvalIncrPhraseNext(
      if( bEof==0 ){
        int nList = 0;
        int nByte = a[p->nToken-1].nList;
-
        char *aDoclist = sqlite3_malloc(nByte+FTS3_BUFFER_PADDING);
+
        char *aDoclist = sqlite3_malloc64((i64)nByte+FTS3_BUFFER_PADDING);
        if( !aDoclist ) return SQLITE_NOMEM;
        memcpy(aDoclist, a[p->nToken-1].pList, nByte+1);
        memset(&aDoclist[nByte], 0, FTS3_BUFFER_PADDING);
@@ -185793,7 +187558,7 @@ static int porterNext(
      if( n>c->nAllocated ){
        char *pNew;
        c->nAllocated = n+20;
-
        pNew = sqlite3_realloc(c->zToken, c->nAllocated);
+
        pNew = sqlite3_realloc64(c->zToken, c->nAllocated);
        if( !pNew ) return SQLITE_NOMEM;
        c->zToken = pNew;
      }
@@ -186545,7 +188310,7 @@ static int simpleNext(
      if( n>c->nTokenAllocated ){
        char *pNew;
        c->nTokenAllocated = n+20;
-
        pNew = sqlite3_realloc(c->pToken, c->nTokenAllocated);
+
        pNew = sqlite3_realloc64(c->pToken, c->nTokenAllocated);
        if( !pNew ) return SQLITE_NOMEM;
        c->pToken = pNew;
      }
@@ -187707,7 +189472,7 @@ static int fts3PendingListAppendVarint(

  /* Allocate or grow the PendingList as required. */
  if( !p ){
-
    p = sqlite3_malloc(sizeof(*p) + 100);
+
    p = sqlite3_malloc64(sizeof(*p) + 100);
    if( !p ){
      return SQLITE_NOMEM;
    }
@@ -187716,14 +189481,14 @@ static int fts3PendingListAppendVarint(
    p->nData = 0;
  }
  else if( p->nData+FTS3_VARINT_MAX+1>p->nSpace ){
-
    int nNew = p->nSpace * 2;
-
    p = sqlite3_realloc(p, sizeof(*p) + nNew);
+
    i64 nNew = p->nSpace * 2;
+
    p = sqlite3_realloc64(p, sizeof(*p) + nNew);
    if( !p ){
      sqlite3_free(*pp);
      *pp = 0;
      return SQLITE_NOMEM;
    }
-
    p->nSpace = nNew;
+
    p->nSpace = (int)nNew;
    p->aData = (char *)&p[1];
  }

@@ -188280,7 +190045,7 @@ SQLITE_PRIVATE int sqlite3Fts3ReadBlock(
    int nByte = sqlite3_blob_bytes(p->pSegments);
    *pnBlob = nByte;
    if( paBlob ){
-
      char *aByte = sqlite3_malloc(nByte + FTS3_NODE_PADDING);
+
      char *aByte = sqlite3_malloc64((i64)nByte + FTS3_NODE_PADDING);
      if( !aByte ){
        rc = SQLITE_NOMEM;
      }else{
@@ -188397,7 +190162,7 @@ static int fts3SegReaderNext(
        int nTerm = fts3HashKeysize(pElem);
        if( (nTerm+1)>pReader->nTermAlloc ){
          sqlite3_free(pReader->zTerm);
-
          pReader->zTerm = (char*)sqlite3_malloc((nTerm+1)*2);
+
          pReader->zTerm = (char*)sqlite3_malloc64(((i64)nTerm+1)*2);
          if( !pReader->zTerm ) return SQLITE_NOMEM;
          pReader->nTermAlloc = (nTerm+1)*2;
        }
@@ -188405,7 +190170,7 @@ static int fts3SegReaderNext(
        pReader->zTerm[nTerm] = '\0';
        pReader->nTerm = nTerm;

-
        aCopy = (char*)sqlite3_malloc(nCopy);
+
        aCopy = (char*)sqlite3_malloc64(nCopy);
        if( !aCopy ) return SQLITE_NOMEM;
        memcpy(aCopy, pList->aData, nCopy);
        pReader->nNode = pReader->nDoclist = nCopy;
@@ -188692,7 +190457,7 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderNew(
    nExtra = nRoot + FTS3_NODE_PADDING;
  }

-
  pReader = (Fts3SegReader *)sqlite3_malloc(sizeof(Fts3SegReader) + nExtra);
+
  pReader = (Fts3SegReader *)sqlite3_malloc64(sizeof(Fts3SegReader) + nExtra);
  if( !pReader ){
    return SQLITE_NOMEM;
  }
@@ -188784,7 +190549,7 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderPending(
        if( nElem==nAlloc ){
          Fts3HashElem **aElem2;
          nAlloc += 16;
-
          aElem2 = (Fts3HashElem **)sqlite3_realloc(
+
          aElem2 = (Fts3HashElem **)sqlite3_realloc64(
              aElem, nAlloc*sizeof(Fts3HashElem *)
          );
          if( !aElem2 ){
@@ -189118,7 +190883,7 @@ static int fts3NodeAddTerm(
        ** this is not expected to be a serious problem.
        */
        assert( pTree->aData==(char *)&pTree[1] );
-
        pTree->aData = (char *)sqlite3_malloc(nReq);
+
        pTree->aData = (char *)sqlite3_malloc64(nReq);
        if( !pTree->aData ){
          return SQLITE_NOMEM;
        }
@@ -189136,7 +190901,7 @@ static int fts3NodeAddTerm(

      if( isCopyTerm ){
        if( pTree->nMalloc<nTerm ){
-
          char *zNew = sqlite3_realloc(pTree->zMalloc, nTerm*2);
+
          char *zNew = sqlite3_realloc64(pTree->zMalloc, (i64)nTerm*2);
          if( !zNew ){
            return SQLITE_NOMEM;
          }
@@ -189162,7 +190927,7 @@ static int fts3NodeAddTerm(
  ** now. Instead, the term is inserted into the parent of pTree. If pTree
  ** has no parent, one is created here.
  */
-
  pNew = (SegmentNode *)sqlite3_malloc(sizeof(SegmentNode) + p->nNodeSize);
+
  pNew = (SegmentNode *)sqlite3_malloc64(sizeof(SegmentNode) + p->nNodeSize);
  if( !pNew ){
    return SQLITE_NOMEM;
  }
@@ -189300,7 +191065,7 @@ static int fts3SegWriterAdd(
){
  int nPrefix;                    /* Size of term prefix in bytes */
  int nSuffix;                    /* Size of term suffix in bytes */
-
  int nReq;                       /* Number of bytes required on leaf page */
+
  i64 nReq;                       /* Number of bytes required on leaf page */
  int nData;
  SegmentWriter *pWriter = *ppWriter;

@@ -189309,13 +191074,13 @@ static int fts3SegWriterAdd(
    sqlite3_stmt *pStmt;

    /* Allocate the SegmentWriter structure */
-
    pWriter = (SegmentWriter *)sqlite3_malloc(sizeof(SegmentWriter));
+
    pWriter = (SegmentWriter *)sqlite3_malloc64(sizeof(SegmentWriter));
    if( !pWriter ) return SQLITE_NOMEM;
    memset(pWriter, 0, sizeof(SegmentWriter));
    *ppWriter = pWriter;

    /* Allocate a buffer in which to accumulate data */
-
    pWriter->aData = (char *)sqlite3_malloc(p->nNodeSize);
+
    pWriter->aData = (char *)sqlite3_malloc64(p->nNodeSize);
    if( !pWriter->aData ) return SQLITE_NOMEM;
    pWriter->nSize = p->nNodeSize;

@@ -189390,7 +191155,7 @@ static int fts3SegWriterAdd(
  ** the buffer to make it large enough.
  */
  if( nReq>pWriter->nSize ){
-
    char *aNew = sqlite3_realloc(pWriter->aData, nReq);
+
    char *aNew = sqlite3_realloc64(pWriter->aData, nReq);
    if( !aNew ) return SQLITE_NOMEM;
    pWriter->aData = aNew;
    pWriter->nSize = nReq;
@@ -189415,7 +191180,7 @@ static int fts3SegWriterAdd(
  */
  if( isCopyTerm ){
    if( nTerm>pWriter->nMalloc ){
-
      char *zNew = sqlite3_realloc(pWriter->zMalloc, nTerm*2);
+
      char *zNew = sqlite3_realloc64(pWriter->zMalloc, (i64)nTerm*2);
      if( !zNew ){
        return SQLITE_NOMEM;
      }
@@ -189723,12 +191488,12 @@ static void fts3ColumnFilter(
static int fts3MsrBufferData(
  Fts3MultiSegReader *pMsr,       /* Multi-segment-reader handle */
  char *pList,
-
  int nList
+
  i64 nList
){
  if( nList>pMsr->nBuffer ){
    char *pNew;
    pMsr->nBuffer = nList*2;
-
    pNew = (char *)sqlite3_realloc(pMsr->aBuffer, pMsr->nBuffer);
+
    pNew = (char *)sqlite3_realloc64(pMsr->aBuffer, pMsr->nBuffer);
    if( !pNew ) return SQLITE_NOMEM;
    pMsr->aBuffer = pNew;
  }
@@ -189784,7 +191549,7 @@ SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext(
      fts3SegReaderSort(pMsr->apSegment, nMerge, j, xCmp);

      if( nList>0 && fts3SegReaderIsPending(apSegment[0]) ){
-
        rc = fts3MsrBufferData(pMsr, pList, nList+1);
+
        rc = fts3MsrBufferData(pMsr, pList, (i64)nList+1);
        if( rc!=SQLITE_OK ) return rc;
        assert( (pMsr->aBuffer[nList] & 0xFE)==0x00 );
        pList = pMsr->aBuffer;
@@ -189921,11 +191686,11 @@ SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr){
  return SQLITE_OK;
}

-
static int fts3GrowSegReaderBuffer(Fts3MultiSegReader *pCsr, int nReq){
+
static int fts3GrowSegReaderBuffer(Fts3MultiSegReader *pCsr, i64 nReq){
  if( nReq>pCsr->nBuffer ){
    char *aNew;
    pCsr->nBuffer = nReq*2;
-
    aNew = sqlite3_realloc(pCsr->aBuffer, pCsr->nBuffer);
+
    aNew = sqlite3_realloc64(pCsr->aBuffer, pCsr->nBuffer);
    if( !aNew ){
      return SQLITE_NOMEM;
    }
@@ -190016,7 +191781,8 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(
    ){
      pCsr->nDoclist = apSegment[0]->nDoclist;
      if( fts3SegReaderIsPending(apSegment[0]) ){
-
        rc = fts3MsrBufferData(pCsr, apSegment[0]->aDoclist, pCsr->nDoclist);
+
        rc = fts3MsrBufferData(pCsr, apSegment[0]->aDoclist,
+
                               (i64)pCsr->nDoclist);
        pCsr->aDoclist = pCsr->aBuffer;
      }else{
        pCsr->aDoclist = apSegment[0]->aDoclist;
@@ -190069,7 +191835,8 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(

          nByte = sqlite3Fts3VarintLen(iDelta) + (isRequirePos?nList+1:0);

-
          rc = fts3GrowSegReaderBuffer(pCsr, nByte+nDoclist+FTS3_NODE_PADDING);
+
          rc = fts3GrowSegReaderBuffer(pCsr,
+
                                   (i64)nByte+nDoclist+FTS3_NODE_PADDING);
          if( rc ) return rc;

          if( isFirst ){
@@ -190095,7 +191862,7 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(
        fts3SegReaderSort(apSegment, nMerge, j, xCmp);
      }
      if( nDoclist>0 ){
-
        rc = fts3GrowSegReaderBuffer(pCsr, nDoclist+FTS3_NODE_PADDING);
+
        rc = fts3GrowSegReaderBuffer(pCsr, (i64)nDoclist+FTS3_NODE_PADDING);
        if( rc ) return rc;
        memset(&pCsr->aBuffer[nDoclist], 0, FTS3_NODE_PADDING);
        pCsr->aDoclist = pCsr->aBuffer;
@@ -190808,7 +192575,7 @@ struct NodeReader {
static void blobGrowBuffer(Blob *pBlob, int nMin, int *pRc){
  if( *pRc==SQLITE_OK && nMin>pBlob->nAlloc ){
    int nAlloc = nMin;
-
    char *a = (char *)sqlite3_realloc(pBlob->a, nAlloc);
+
    char *a = (char *)sqlite3_realloc64(pBlob->a, nAlloc);
    if( a ){
      pBlob->nAlloc = nAlloc;
      pBlob->a = a;
@@ -191605,7 +193372,7 @@ static int fts3RepackSegdirLevel(
      if( nIdx>=nAlloc ){
        int *aNew;
        nAlloc += 16;
-
        aNew = sqlite3_realloc(aIdx, nAlloc*sizeof(int));
+
        aNew = sqlite3_realloc64(aIdx, nAlloc*sizeof(int));
        if( !aNew ){
          rc = SQLITE_NOMEM;
          break;
@@ -191979,7 +193746,7 @@ SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){

  /* Allocate space for the cursor, filter and writer objects */
  const int nAlloc = sizeof(*pCsr) + sizeof(*pFilter) + sizeof(*pWriter);
-
  pWriter = (IncrmergeWriter *)sqlite3_malloc(nAlloc);
+
  pWriter = (IncrmergeWriter *)sqlite3_malloc64(nAlloc);
  if( !pWriter ) return SQLITE_NOMEM;
  pFilter = (Fts3SegFilter *)&pWriter[1];
  pCsr = (Fts3MultiSegReader *)&pFilter[1];
@@ -192615,7 +194382,7 @@ SQLITE_PRIVATE int sqlite3Fts3DeferredTokenList(
    return SQLITE_OK;
  }

-
  pRet = (char *)sqlite3_malloc(p->pList->nData);
+
  pRet = (char *)sqlite3_malloc64(p->pList->nData);
  if( !pRet ) return SQLITE_NOMEM;

  nSkip = sqlite3Fts3GetVarint(p->pList->aData, &dummy);
@@ -192635,7 +194402,7 @@ SQLITE_PRIVATE int sqlite3Fts3DeferToken(
  int iCol                        /* Column that token must appear in (or -1) */
){
  Fts3DeferredToken *pDeferred;
-
  pDeferred = sqlite3_malloc(sizeof(*pDeferred));
+
  pDeferred = sqlite3_malloc64(sizeof(*pDeferred));
  if( !pDeferred ){
    return SQLITE_NOMEM;
  }
@@ -201350,7 +203117,7 @@ static int rtreeUpdate(
  rtreeReference(pRtree);
  assert(nData>=1);

-
  cell.iRowid = 0;  /* Used only to suppress a compiler warning */
+
  memset(&cell, 0, sizeof(cell));

  /* Constraint handling. A write operation on an r-tree table may return
  ** SQLITE_CONSTRAINT for two reasons:
@@ -204817,8 +206584,9 @@ static void icuRegexpFunc(sqlite3_context *p, int nArg, sqlite3_value **apArg){

    if( U_SUCCESS(status) ){
      sqlite3_set_auxdata(p, 0, pExpr, icuRegexpDelete);
-
    }else{
-
      assert(!pExpr);
+
      pExpr = sqlite3_get_auxdata(p, 0);
+
    }
+
    if( !pExpr ){
      icuFunctionError(p, "uregex_open", status);
      return;
    }
@@ -205976,6 +207744,34 @@ SQLITE_API void sqlite3rbu_bp_progress(sqlite3rbu *pRbu, int *pnOne, int*pnTwo);
SQLITE_API int sqlite3rbu_state(sqlite3rbu *pRbu);

/*
+
** As part of applying an RBU update or performing an RBU vacuum operation,
+
** the system must at one point move the *-oal file to the equivalent *-wal
+
** path. Normally, it does this by invoking POSIX function rename(2) directly.
+
** Except on WINCE platforms, where it uses win32 API MoveFileW(). This
+
** function may be used to register a callback that the RBU module will invoke
+
** instead of one of these APIs.
+
**
+
** If a callback is registered with an RBU handle, it invokes it instead
+
** of rename(2) when it needs to move a file within the file-system. The
+
** first argument passed to the xRename() callback is a copy of the second
+
** argument (pArg) passed to this function. The second is the full path
+
** to the file to move and the third the full path to which it should be
+
** moved. The callback function should return SQLITE_OK to indicate
+
** success. If an error occurs, it should return an SQLite error code.
+
** In this case the RBU operation will be abandoned and the error returned
+
** to the RBU user.
+
**
+
** Passing a NULL pointer in place of the xRename argument to this function
+
** restores the default behaviour.
+
*/
+
SQLITE_API void sqlite3rbu_rename_handler(
+
  sqlite3rbu *pRbu,
+
  void *pArg,
+
  int (*xRename)(void *pArg, const char *zOld, const char *zNew)
+
);
+

+

+
/*
** Create an RBU VFS named zName that accesses the underlying file-system
** via existing VFS zParent. Or, if the zParent parameter is passed NULL,
** then the new RBU VFS uses the default system VFS to access the file-system.
@@ -206342,6 +208138,8 @@ struct sqlite3rbu {
  int nPagePerSector;             /* Pages per sector for pTargetFd */
  i64 iOalSz;
  i64 nPhaseOneStep;
+
  void *pRenameArg;
+
  int (*xRename)(void*, const char*, const char*);

  /* The following state variables are used as part of the incremental
  ** checkpoint stage (eStage==RBU_STAGE_CKPT). See comments surrounding
@@ -208730,7 +210528,7 @@ static void rbuOpenDatabase(sqlite3rbu *p, sqlite3 *dbMain, int *pbRetry){
    sqlite3_file_control(p->dbRbu, "main", SQLITE_FCNTL_RBUCNT, (void*)p);
    if( p->zState==0 ){
      const char *zFile = sqlite3_db_filename(p->dbRbu, "main");
-
      p->zState = rbuMPrintf(p, "file://%s-vacuum?modeof=%s", zFile, zFile);
+
      p->zState = rbuMPrintf(p, "file:///%s-vacuum?modeof=%s", zFile, zFile);
    }
  }

@@ -209190,32 +210988,7 @@ static void rbuMoveOalFile(sqlite3rbu *p){
    }

    if( p->rc==SQLITE_OK ){
-
#if defined(_WIN32_WCE)
-
      {
-
        LPWSTR zWideOal;
-
        LPWSTR zWideWal;
-

-
        zWideOal = rbuWinUtf8ToUnicode(zOal);
-
        if( zWideOal ){
-
          zWideWal = rbuWinUtf8ToUnicode(zWal);
-
          if( zWideWal ){
-
            if( MoveFileW(zWideOal, zWideWal) ){
-
              p->rc = SQLITE_OK;
-
            }else{
-
              p->rc = SQLITE_IOERR;
-
            }
-
            sqlite3_free(zWideWal);
-
          }else{
-
            p->rc = SQLITE_IOERR_NOMEM;
-
          }
-
          sqlite3_free(zWideOal);
-
        }else{
-
          p->rc = SQLITE_IOERR_NOMEM;
-
        }
-
      }
-
#else
-
      p->rc = rename(zOal, zWal) ? SQLITE_IOERR : SQLITE_OK;
-
#endif
+
      p->rc = p->xRename(p->pRenameArg, zOal, zWal);
    }

    if( p->rc!=SQLITE_OK
@@ -209954,6 +211727,7 @@ static sqlite3rbu *openRbuHandle(

    /* Create the custom VFS. */
    memset(p, 0, sizeof(sqlite3rbu));
+
    sqlite3rbu_rename_handler(p, 0, 0);
    rbuCreateVfs(p);

    /* Open the target, RBU and state databases */
@@ -210345,6 +212119,54 @@ SQLITE_API int sqlite3rbu_savestate(sqlite3rbu *p){
  return rc;
}

+
/*
+
** Default xRename callback for RBU.
+
*/
+
static int xDefaultRename(void *pArg, const char *zOld, const char *zNew){
+
  int rc = SQLITE_OK;
+
#if defined(_WIN32_WCE)
+
  {
+
    LPWSTR zWideOld;
+
    LPWSTR zWideNew;
+

+
    zWideOld = rbuWinUtf8ToUnicode(zOld);
+
    if( zWideOld ){
+
      zWideNew = rbuWinUtf8ToUnicode(zNew);
+
      if( zWideNew ){
+
        if( MoveFileW(zWideOld, zWideNew) ){
+
          rc = SQLITE_OK;
+
        }else{
+
          rc = SQLITE_IOERR;
+
        }
+
        sqlite3_free(zWideNew);
+
      }else{
+
        rc = SQLITE_IOERR_NOMEM;
+
      }
+
      sqlite3_free(zWideOld);
+
    }else{
+
      rc = SQLITE_IOERR_NOMEM;
+
    }
+
  }
+
#else
+
  rc = rename(zOld, zNew) ? SQLITE_IOERR : SQLITE_OK;
+
#endif
+
  return rc;
+
}
+

+
SQLITE_API void sqlite3rbu_rename_handler(
+
  sqlite3rbu *pRbu,
+
  void *pArg,
+
  int (*xRename)(void *pArg, const char *zOld, const char *zNew)
+
){
+
  if( xRename ){
+
    pRbu->xRename = xRename;
+
    pRbu->pRenameArg = pArg;
+
  }else{
+
    pRbu->xRename = xDefaultRename;
+
    pRbu->pRenameArg = 0;
+
  }
+
}
+

/**************************************************************************
** Beginning of RBU VFS shim methods. The VFS shim modifies the behaviour
** of a standard VFS in the following ways:
@@ -212475,12 +214297,18 @@ static int dbpageColumn(
    }
    case 1: {           /* data */
      DbPage *pDbPage = 0;
-
      rc = sqlite3PagerGet(pCsr->pPager, pCsr->pgno, (DbPage**)&pDbPage, 0);
-
      if( rc==SQLITE_OK ){
-
        sqlite3_result_blob(ctx, sqlite3PagerGetData(pDbPage), pCsr->szPage,
-
                            SQLITE_TRANSIENT);
+
      if( pCsr->pgno==((PENDING_BYTE/pCsr->szPage)+1) ){
+
        /* The pending byte page. Assume it is zeroed out. Attempting to
+
        ** request this page from the page is an SQLITE_CORRUPT error. */
+
        sqlite3_result_zeroblob(ctx, pCsr->szPage);
+
      }else{
+
        rc = sqlite3PagerGet(pCsr->pPager, pCsr->pgno, (DbPage**)&pDbPage, 0);
+
        if( rc==SQLITE_OK ){
+
          sqlite3_result_blob(ctx, sqlite3PagerGetData(pDbPage), pCsr->szPage,
+
              SQLITE_TRANSIENT);
+
        }
+
        sqlite3PagerUnref(pDbPage);
      }
-
      sqlite3PagerUnref(pDbPage);
      break;
    }
    default: {          /* schema */
@@ -212489,7 +214317,7 @@ static int dbpageColumn(
      break;
    }
  }
-
  return SQLITE_OK;
+
  return rc;
}

static int dbpageRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
@@ -212549,11 +214377,12 @@ static int dbpageUpdate(
  pPager = sqlite3BtreePager(pBt);
  rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pDbPage, 0);
  if( rc==SQLITE_OK ){
-
    rc = sqlite3PagerWrite(pDbPage);
-
    if( rc==SQLITE_OK ){
-
      memcpy(sqlite3PagerGetData(pDbPage),
-
             sqlite3_value_blob(argv[3]),
-
             szPage);
+
    const void *pData = sqlite3_value_blob(argv[3]);
+
    assert( pData!=0 || pTab->db->mallocFailed );
+
    if( pData
+
     && (rc = sqlite3PagerWrite(pDbPage))==SQLITE_OK
+
    ){
+
      memcpy(sqlite3PagerGetData(pDbPage), pData, szPage);
    }
  }
  sqlite3PagerUnref(pDbPage);
@@ -212573,11 +214402,12 @@ static int dbpageBegin(sqlite3_vtab *pVtab){
  DbpageTable *pTab = (DbpageTable *)pVtab;
  sqlite3 *db = pTab->db;
  int i;
-
  for(i=0; i<db->nDb; i++){
+
  int rc = SQLITE_OK;
+
  for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
    Btree *pBt = db->aDb[i].pBt;
-
    if( pBt ) sqlite3BtreeBeginTrans(pBt, 1, 0);
+
    if( pBt ) rc = sqlite3BtreeBeginTrans(pBt, 1, 0);
  }
-
  return SQLITE_OK;
+
  return rc;
}


@@ -219301,7 +221131,7 @@ static void sqlite3Fts5BufferAppendPrintf(int *, Fts5Buffer*, char *zFmt, ...);
static char *sqlite3Fts5Mprintf(int *pRc, const char *zFmt, ...);

#define fts5BufferZero(x)             sqlite3Fts5BufferZero(x)
-
#define fts5BufferAppendVarint(a,b,c) sqlite3Fts5BufferAppendVarint(a,b,c)
+
#define fts5BufferAppendVarint(a,b,c) sqlite3Fts5BufferAppendVarint(a,b,(i64)c)
#define fts5BufferFree(a)             sqlite3Fts5BufferFree(a)
#define fts5BufferAppendBlob(a,b,c,d) sqlite3Fts5BufferAppendBlob(a,b,c,d)
#define fts5BufferSet(a,b,c,d)        sqlite3Fts5BufferSet(a,b,c,d)
@@ -231178,7 +233008,9 @@ static void fts5WriteAppendRowid(
      fts5BufferAppendVarint(&p->rc, &pPage->buf, iRowid);
    }else{
      assert_nc( p->rc || iRowid>pWriter->iPrevRowid );
-
      fts5BufferAppendVarint(&p->rc, &pPage->buf, iRowid - pWriter->iPrevRowid);
+
      fts5BufferAppendVarint(&p->rc, &pPage->buf,
+
          (u64)iRowid - (u64)pWriter->iPrevRowid
+
      );
    }
    pWriter->iPrevRowid = iRowid;
    pWriter->bFirstRowidInDoclist = 0;
@@ -231942,7 +233774,7 @@ static int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge){

static void fts5AppendRowid(
  Fts5Index *p,
-
  i64 iDelta,
+
  u64 iDelta,
  Fts5Iter *pUnused,
  Fts5Buffer *pBuf
){
@@ -231952,7 +233784,7 @@ static void fts5AppendRowid(

static void fts5AppendPoslist(
  Fts5Index *p,
-
  i64 iDelta,
+
  u64 iDelta,
  Fts5Iter *pMulti,
  Fts5Buffer *pBuf
){
@@ -232027,10 +233859,10 @@ static void fts5MergeAppendDocid(
}
#endif

-
#define fts5MergeAppendDocid(pBuf, iLastRowid, iRowid) {       \
-
  assert( (pBuf)->n!=0 || (iLastRowid)==0 );                   \
-
  fts5BufferSafeAppendVarint((pBuf), (iRowid) - (iLastRowid)); \
-
  (iLastRowid) = (iRowid);                                     \
+
#define fts5MergeAppendDocid(pBuf, iLastRowid, iRowid) {                 \
+
  assert( (pBuf)->n!=0 || (iLastRowid)==0 );                             \
+
  fts5BufferSafeAppendVarint((pBuf), (u64)(iRowid) - (u64)(iLastRowid)); \
+
  (iLastRowid) = (iRowid);                                               \
}

/*
@@ -232301,7 +234133,7 @@ static void fts5SetupPrefixIter(
  int nMerge = 1;

  void (*xMerge)(Fts5Index*, Fts5Buffer*, int, Fts5Buffer*);
-
  void (*xAppend)(Fts5Index*, i64, Fts5Iter*, Fts5Buffer*);
+
  void (*xAppend)(Fts5Index*, u64, Fts5Iter*, Fts5Buffer*);
  if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){
    xMerge = fts5MergeRowidLists;
    xAppend = fts5AppendRowid;
@@ -232340,7 +234172,7 @@ static void fts5SetupPrefixIter(
        Fts5SegIter *pSeg = &p1->aSeg[ p1->aFirst[1].iFirst ];
        p1->xSetOutputs(p1, pSeg);
        if( p1->base.nData ){
-
          xAppend(p, p1->base.iRowid-iLastRowid, p1, &doclist);
+
          xAppend(p, (u64)p1->base.iRowid-(u64)iLastRowid, p1, &doclist);
          iLastRowid = p1->base.iRowid;
        }
      }
@@ -232388,7 +234220,7 @@ static void fts5SetupPrefixIter(
        iLastRowid = 0;
      }

-
      xAppend(p, p1->base.iRowid-iLastRowid, p1, &doclist);
+
      xAppend(p, (u64)p1->base.iRowid-(u64)iLastRowid, p1, &doclist);
      iLastRowid = p1->base.iRowid;
    }

@@ -233367,6 +235199,7 @@ static int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum, int bUseCksum

    /* If this is a new term, query for it. Update cksum3 with the results. */
    fts5TestTerm(p, &term, z, n, cksum2, &cksum3);
+
    if( p->rc ) break;

    if( eDetail==FTS5_DETAIL_NONE ){
      if( 0==fts5MultiIterIsEmpty(p, pIter) ){
@@ -236704,7 +238537,7 @@ static void fts5SourceIdFunc(
){
  assert( nArg==0 );
  UNUSED_PARAM2(nArg, apUnused);
-
  sqlite3_result_text(pCtx, "fts5: 2022-09-05 11:02:23 4635f4a69c8c2a8df242b384a992aea71224e39a2ccab42d8c0b0602f1e826e8", -1, SQLITE_TRANSIENT);
+
  sqlite3_result_text(pCtx, "fts5: 2022-11-16 12:10:08 89c459e766ea7e9165d0beeb124708b955a4950d0f4792f457465d71b158d318", -1, SQLITE_TRANSIENT);
}

/*
modified external/sqlite/sqlite3.h
@@ -146,9 +146,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-
#define SQLITE_VERSION        "3.39.3"
-
#define SQLITE_VERSION_NUMBER 3039003
-
#define SQLITE_SOURCE_ID      "2022-09-05 11:02:23 4635f4a69c8c2a8df242b384a992aea71224e39a2ccab42d8c0b0602f1e826e8"
+
#define SQLITE_VERSION        "3.40.0"
+
#define SQLITE_VERSION_NUMBER 3040000
+
#define SQLITE_SOURCE_ID      "2022-11-16 12:10:08 89c459e766ea7e9165d0beeb124708b955a4950d0f4792f457465d71b158d318"

/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -670,13 +670,17 @@ SQLITE_API int sqlite3_exec(
**
** SQLite uses one of these integer values as the second
** argument to calls it makes to the xLock() and xUnlock() methods
-
** of an [sqlite3_io_methods] object.
+
** of an [sqlite3_io_methods] object.  These values are ordered from
+
** lest restrictive to most restrictive.
+
**
+
** The argument to xLock() is always SHARED or higher.  The argument to
+
** xUnlock is either SHARED or NONE.
*/
-
#define SQLITE_LOCK_NONE          0
-
#define SQLITE_LOCK_SHARED        1
-
#define SQLITE_LOCK_RESERVED      2
-
#define SQLITE_LOCK_PENDING       3
-
#define SQLITE_LOCK_EXCLUSIVE     4
+
#define SQLITE_LOCK_NONE          0       /* xUnlock() only */
+
#define SQLITE_LOCK_SHARED        1       /* xLock() or xUnlock() */
+
#define SQLITE_LOCK_RESERVED      2       /* xLock() only */
+
#define SQLITE_LOCK_PENDING       3       /* xLock() only */
+
#define SQLITE_LOCK_EXCLUSIVE     4       /* xLock() only */

/*
** CAPI3REF: Synchronization Type Flags
@@ -754,7 +758,14 @@ struct sqlite3_file {
** <li> [SQLITE_LOCK_PENDING], or
** <li> [SQLITE_LOCK_EXCLUSIVE].
** </ul>
-
** xLock() increases the lock. xUnlock() decreases the lock.
+
** xLock() upgrades the database file lock.  In other words, xLock() moves the
+
** database file lock in the direction NONE toward EXCLUSIVE. The argument to
+
** xLock() is always on of SHARED, RESERVED, PENDING, or EXCLUSIVE, never
+
** SQLITE_LOCK_NONE.  If the database file lock is already at or above the
+
** requested lock, then the call to xLock() is a no-op.
+
** xUnlock() downgrades the database file lock to either SHARED or NONE.
+
*  If the lock is already at or below the requested lock state, then the call
+
** to xUnlock() is a no-op.
** The xCheckReservedLock() method checks whether any database connection,
** either in this process or in some other process, is holding a RESERVED,
** PENDING, or EXCLUSIVE lock on the file.  It returns true
@@ -859,9 +870,8 @@ struct sqlite3_io_methods {
** opcode causes the xFileControl method to write the current state of
** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED],
** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE])
-
** into an integer that the pArg argument points to. This capability
-
** is used during testing and is only available when the SQLITE_TEST
-
** compile-time option is used.
+
** into an integer that the pArg argument points to.
+
** This capability is only available if SQLite is compiled with [SQLITE_DEBUG].
**
** <li>[[SQLITE_FCNTL_SIZE_HINT]]
** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS
@@ -1254,6 +1264,26 @@ typedef struct sqlite3_mutex sqlite3_mutex;
typedef struct sqlite3_api_routines sqlite3_api_routines;

/*
+
** CAPI3REF: File Name
+
**
+
** Type [sqlite3_filename] is used by SQLite to pass filenames to the
+
** xOpen method of a [VFS]. It may be cast to (const char*) and treated
+
** as a normal, nul-terminated, UTF-8 buffer containing the filename, but
+
** may also be passed to special APIs such as:
+
**
+
** <ul>
+
** <li>  sqlite3_filename_database()
+
** <li>  sqlite3_filename_journal()
+
** <li>  sqlite3_filename_wal()
+
** <li>  sqlite3_uri_parameter()
+
** <li>  sqlite3_uri_boolean()
+
** <li>  sqlite3_uri_int64()
+
** <li>  sqlite3_uri_key()
+
** </ul>
+
*/
+
typedef const char *sqlite3_filename;
+

+
/*
** CAPI3REF: OS Interface Object
**
** An instance of the sqlite3_vfs object defines the interface between
@@ -1431,7 +1461,7 @@ struct sqlite3_vfs {
  sqlite3_vfs *pNext;      /* Next registered VFS */
  const char *zName;       /* Name of this virtual file system */
  void *pAppData;          /* Pointer to application-specific data */
-
  int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*,
+
  int (*xOpen)(sqlite3_vfs*, sqlite3_filename zName, sqlite3_file*,
               int flags, int *pOutFlags);
  int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir);
  int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut);
@@ -2309,6 +2339,7 @@ struct sqlite3_mem_methods {
** <ul>
** <li> The [PRAGMA writable_schema=ON] statement.
** <li> The [PRAGMA journal_mode=OFF] statement.
+
** <li> The [PRAGMA schema_version=N] statement.
** <li> Writes to the [sqlite_dbpage] virtual table.
** <li> Direct writes to [shadow tables].
** </ul>
@@ -3424,6 +3455,9 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** <dd>The database is opened [shared cache] enabled, overriding
** the default shared cache setting provided by
** [sqlite3_enable_shared_cache()].)^
+
** The [use of shared cache mode is discouraged] and hence shared cache
+
** capabilities may be omitted from many builds of SQLite.  In such cases,
+
** this option is a no-op.
**
** ^(<dt>[SQLITE_OPEN_PRIVATECACHE]</dt>
** <dd>The database is opened [shared cache] disabled, overriding
@@ -3439,7 +3473,7 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** to return an extended result code.</dd>
**
** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt>
-
** <dd>The database filename is not allowed to be a symbolic link</dd>
+
** <dd>The database filename is not allowed to contain a symbolic link</dd>
** </dl>)^
**
** If the 3rd parameter to sqlite3_open_v2() is not one of the
@@ -3698,10 +3732,10 @@ SQLITE_API int sqlite3_open_v2(
**
** See the [URI filename] documentation for additional information.
*/
-
SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam);
-
SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault);
-
SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64);
-
SQLITE_API const char *sqlite3_uri_key(const char *zFilename, int N);
+
SQLITE_API const char *sqlite3_uri_parameter(sqlite3_filename z, const char *zParam);
+
SQLITE_API int sqlite3_uri_boolean(sqlite3_filename z, const char *zParam, int bDefault);
+
SQLITE_API sqlite3_int64 sqlite3_uri_int64(sqlite3_filename, const char*, sqlite3_int64);
+
SQLITE_API const char *sqlite3_uri_key(sqlite3_filename z, int N);

/*
** CAPI3REF:  Translate filenames
@@ -3730,9 +3764,9 @@ SQLITE_API const char *sqlite3_uri_key(const char *zFilename, int N);
** return value from [sqlite3_db_filename()], then the result is
** undefined and is likely a memory access violation.
*/
-
SQLITE_API const char *sqlite3_filename_database(const char*);
-
SQLITE_API const char *sqlite3_filename_journal(const char*);
-
SQLITE_API const char *sqlite3_filename_wal(const char*);
+
SQLITE_API const char *sqlite3_filename_database(sqlite3_filename);
+
SQLITE_API const char *sqlite3_filename_journal(sqlite3_filename);
+
SQLITE_API const char *sqlite3_filename_wal(sqlite3_filename);

/*
** CAPI3REF:  Database File Corresponding To A Journal
@@ -3798,14 +3832,14 @@ SQLITE_API sqlite3_file *sqlite3_database_file_object(const char*);
** then the corresponding [sqlite3_module.xClose() method should also be
** invoked prior to calling sqlite3_free_filename(Y).
*/
-
SQLITE_API char *sqlite3_create_filename(
+
SQLITE_API sqlite3_filename sqlite3_create_filename(
  const char *zDatabase,
  const char *zJournal,
  const char *zWal,
  int nParam,
  const char **azParam
);
-
SQLITE_API void sqlite3_free_filename(char*);
+
SQLITE_API void sqlite3_free_filename(sqlite3_filename);

/*
** CAPI3REF: Error Codes And Messages
@@ -5508,6 +5542,16 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
** then the conversion is performed.  Otherwise no conversion occurs.
** The [SQLITE_INTEGER | datatype] after conversion is returned.)^
**
+
** ^(The sqlite3_value_encoding(X) interface returns one of [SQLITE_UTF8],
+
** [SQLITE_UTF16BE], or [SQLITE_UTF16LE] according to the current encoding
+
** of the value X, assuming that X has type TEXT.)^  If sqlite3_value_type(X)
+
** returns something other than SQLITE_TEXT, then the return value from
+
** sqlite3_value_encoding(X) is meaningless.  ^Calls to
+
** sqlite3_value_text(X), sqlite3_value_text16(X), sqlite3_value_text16be(X),
+
** sqlite3_value_text16le(X), sqlite3_value_bytes(X), or
+
** sqlite3_value_bytes16(X) might change the encoding of the value X and
+
** thus change the return from subsequent calls to sqlite3_value_encoding(X).
+
**
** ^Within the [xUpdate] method of a [virtual table], the
** sqlite3_value_nochange(X) interface returns true if and only if
** the column corresponding to X is unchanged by the UPDATE operation
@@ -5572,6 +5616,7 @@ SQLITE_API int sqlite3_value_type(sqlite3_value*);
SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*);
SQLITE_API int sqlite3_value_nochange(sqlite3_value*);
SQLITE_API int sqlite3_value_frombind(sqlite3_value*);
+
SQLITE_API int sqlite3_value_encoding(sqlite3_value*);

/*
** CAPI3REF: Finding The Subtype Of SQL Values
@@ -5625,7 +5670,7 @@ SQLITE_API void sqlite3_value_free(sqlite3_value*);
**
** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer
** when first called if N is less than or equal to zero or if a memory
-
** allocate error occurs.
+
** allocation error occurs.
**
** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is
** determined by the N parameter on first successful call.  Changing the
@@ -5830,9 +5875,10 @@ typedef void (*sqlite3_destructor_type)(void*);
** of [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE].
** ^SQLite takes the text result from the application from
** the 2nd parameter of the sqlite3_result_text* interfaces.
-
** ^If the 3rd parameter to the sqlite3_result_text* interfaces
-
** is negative, then SQLite takes result text from the 2nd parameter
-
** through the first zero character.
+
** ^If the 3rd parameter to any of the sqlite3_result_text* interfaces
+
** other than sqlite3_result_text64() is negative, then SQLite computes
+
** the string length itself by searching the 2nd parameter for the first
+
** zero character.
** ^If the 3rd parameter to the sqlite3_result_text* interfaces
** is non-negative, then as many bytes (not characters) of the text
** pointed to by the 2nd parameter are taken as the application-defined
@@ -6328,7 +6374,7 @@ SQLITE_API const char *sqlite3_db_name(sqlite3 *db, int N);
** <li> [sqlite3_filename_wal()]
** </ul>
*/
-
SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
+
SQLITE_API sqlite3_filename sqlite3_db_filename(sqlite3 *db, const char *zDbName);

/*
** CAPI3REF: Determine if a database is read-only
@@ -6465,7 +6511,7 @@ SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
** function C that is invoked prior to each autovacuum of the database
** file.  ^The callback is passed a copy of the generic data pointer (P),
** the schema-name of the attached database that is being autovacuumed,
-
** the the size of the database file in pages, the number of free pages,
+
** the size of the database file in pages, the number of free pages,
** and the number of bytes per page, respectively.  The callback should
** return the number of free pages that should be removed by the
** autovacuum.  ^If the callback returns zero, then no autovacuum happens.
@@ -6586,6 +6632,11 @@ SQLITE_API void *sqlite3_update_hook(
** to the same database. Sharing is enabled if the argument is true
** and disabled if the argument is false.)^
**
+
** This interface is omitted if SQLite is compiled with
+
** [-DSQLITE_OMIT_SHARED_CACHE].  The [-DSQLITE_OMIT_SHARED_CACHE]
+
** compile-time option is recommended because the
+
** [use of shared cache mode is discouraged].
+
**
** ^Cache sharing is enabled and disabled for an entire process.
** This is a change as of SQLite [version 3.5.0] ([dateof:3.5.0]).
** In prior versions of SQLite,
@@ -6684,7 +6735,7 @@ SQLITE_API int sqlite3_db_release_memory(sqlite3*);
** ^The soft heap limit may not be greater than the hard heap limit.
** ^If the hard heap limit is enabled and if sqlite3_soft_heap_limit(N)
** is invoked with a value of N that is greater than the hard heap limit,
-
** the the soft heap limit is set to the value of the hard heap limit.
+
** the soft heap limit is set to the value of the hard heap limit.
** ^The soft heap limit is automatically enabled whenever the hard heap
** limit is enabled. ^When sqlite3_hard_heap_limit64(N) is invoked and
** the soft heap limit is outside the range of 1..N, then the soft heap
@@ -8979,7 +9030,7 @@ typedef struct sqlite3_backup sqlite3_backup;
** if the application incorrectly accesses the destination [database connection]
** and so no error code is reported, but the operations may malfunction
** nevertheless.  Use of the destination database connection while a
-
** backup is in progress might also also cause a mutex deadlock.
+
** backup is in progress might also cause a mutex deadlock.
**
** If running in [shared cache mode], the application must
** guarantee that the shared cache used by the destination database
@@ -9407,7 +9458,7 @@ SQLITE_API int sqlite3_wal_checkpoint_v2(
*/
#define SQLITE_CHECKPOINT_PASSIVE  0  /* Do as much as possible w/o blocking */
#define SQLITE_CHECKPOINT_FULL     1  /* Wait for writers, then checkpoint */
-
#define SQLITE_CHECKPOINT_RESTART  2  /* Like FULL but wait for for readers */
+
#define SQLITE_CHECKPOINT_RESTART  2  /* Like FULL but wait for readers */
#define SQLITE_CHECKPOINT_TRUNCATE 3  /* Like RESTART but also truncate WAL */

/*